cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

zd1301_demod.c (12759B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * ZyDAS ZD1301 driver (demodulator)
      4 *
      5 * Copyright (C) 2015 Antti Palosaari <crope@iki.fi>
      6 */
      7
      8#include "zd1301_demod.h"
      9
     10static u8 zd1301_demod_gain = 0x38;
     11module_param_named(gain, zd1301_demod_gain, byte, 0644);
     12MODULE_PARM_DESC(gain, "gain (value: 0x00 - 0x70, default: 0x38)");
     13
     14struct zd1301_demod_dev {
     15	struct platform_device *pdev;
     16	struct dvb_frontend frontend;
     17	struct i2c_adapter adapter;
     18	u8 gain;
     19};
     20
     21static int zd1301_demod_wreg(struct zd1301_demod_dev *dev, u16 reg, u8 val)
     22{
     23	struct platform_device *pdev = dev->pdev;
     24	struct zd1301_demod_platform_data *pdata = pdev->dev.platform_data;
     25
     26	return pdata->reg_write(pdata->reg_priv, reg, val);
     27}
     28
     29static int zd1301_demod_rreg(struct zd1301_demod_dev *dev, u16 reg, u8 *val)
     30{
     31	struct platform_device *pdev = dev->pdev;
     32	struct zd1301_demod_platform_data *pdata = pdev->dev.platform_data;
     33
     34	return pdata->reg_read(pdata->reg_priv, reg, val);
     35}
     36
     37static int zd1301_demod_set_frontend(struct dvb_frontend *fe)
     38{
     39	struct zd1301_demod_dev *dev = fe->demodulator_priv;
     40	struct platform_device *pdev = dev->pdev;
     41	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
     42	int ret;
     43	u32 if_frequency;
     44	u8 r6a50_val;
     45
     46	dev_dbg(&pdev->dev, "frequency=%u bandwidth_hz=%u\n",
     47		c->frequency, c->bandwidth_hz);
     48
     49	/* Program tuner */
     50	if (fe->ops.tuner_ops.set_params &&
     51	    fe->ops.tuner_ops.get_if_frequency) {
     52		ret = fe->ops.tuner_ops.set_params(fe);
     53		if (ret)
     54			goto err;
     55		ret = fe->ops.tuner_ops.get_if_frequency(fe, &if_frequency);
     56		if (ret)
     57			goto err;
     58	} else {
     59		ret = -EINVAL;
     60		goto err;
     61	}
     62
     63	dev_dbg(&pdev->dev, "if_frequency=%u\n", if_frequency);
     64	if (if_frequency != 36150000) {
     65		ret = -EINVAL;
     66		goto err;
     67	}
     68
     69	switch (c->bandwidth_hz) {
     70	case 6000000:
     71		r6a50_val = 0x78;
     72		break;
     73	case 7000000:
     74		r6a50_val = 0x68;
     75		break;
     76	case 8000000:
     77		r6a50_val = 0x58;
     78		break;
     79	default:
     80		ret = -EINVAL;
     81		goto err;
     82	}
     83
     84	ret = zd1301_demod_wreg(dev, 0x6a60, 0x11);
     85	if (ret)
     86		goto err;
     87	ret = zd1301_demod_wreg(dev, 0x6a47, 0x46);
     88	if (ret)
     89		goto err;
     90	ret = zd1301_demod_wreg(dev, 0x6a48, 0x46);
     91	if (ret)
     92		goto err;
     93	ret = zd1301_demod_wreg(dev, 0x6a4a, 0x15);
     94	if (ret)
     95		goto err;
     96	ret = zd1301_demod_wreg(dev, 0x6a4b, 0x63);
     97	if (ret)
     98		goto err;
     99	ret = zd1301_demod_wreg(dev, 0x6a5b, 0x99);
    100	if (ret)
    101		goto err;
    102	ret = zd1301_demod_wreg(dev, 0x6a3b, 0x10);
    103	if (ret)
    104		goto err;
    105	ret = zd1301_demod_wreg(dev, 0x6806, 0x01);
    106	if (ret)
    107		goto err;
    108	ret = zd1301_demod_wreg(dev, 0x6a41, 0x08);
    109	if (ret)
    110		goto err;
    111	ret = zd1301_demod_wreg(dev, 0x6a42, 0x46);
    112	if (ret)
    113		goto err;
    114	ret = zd1301_demod_wreg(dev, 0x6a44, 0x14);
    115	if (ret)
    116		goto err;
    117	ret = zd1301_demod_wreg(dev, 0x6a45, 0x67);
    118	if (ret)
    119		goto err;
    120	ret = zd1301_demod_wreg(dev, 0x6a38, 0x00);
    121	if (ret)
    122		goto err;
    123	ret = zd1301_demod_wreg(dev, 0x6a4c, 0x52);
    124	if (ret)
    125		goto err;
    126	ret = zd1301_demod_wreg(dev, 0x6a49, 0x2a);
    127	if (ret)
    128		goto err;
    129	ret = zd1301_demod_wreg(dev, 0x6840, 0x2e);
    130	if (ret)
    131		goto err;
    132	ret = zd1301_demod_wreg(dev, 0x6a50, r6a50_val);
    133	if (ret)
    134		goto err;
    135	ret = zd1301_demod_wreg(dev, 0x6a38, 0x07);
    136	if (ret)
    137		goto err;
    138
    139	return 0;
    140err:
    141	dev_dbg(&pdev->dev, "failed=%d\n", ret);
    142	return ret;
    143}
    144
    145static int zd1301_demod_sleep(struct dvb_frontend *fe)
    146{
    147	struct zd1301_demod_dev *dev = fe->demodulator_priv;
    148	struct platform_device *pdev = dev->pdev;
    149	int ret;
    150
    151	dev_dbg(&pdev->dev, "\n");
    152
    153	ret = zd1301_demod_wreg(dev, 0x6a43, 0x70);
    154	if (ret)
    155		goto err;
    156	ret = zd1301_demod_wreg(dev, 0x684e, 0x00);
    157	if (ret)
    158		goto err;
    159	ret = zd1301_demod_wreg(dev, 0x6849, 0x00);
    160	if (ret)
    161		goto err;
    162	ret = zd1301_demod_wreg(dev, 0x68e2, 0xd7);
    163	if (ret)
    164		goto err;
    165	ret = zd1301_demod_wreg(dev, 0x68e0, 0x39);
    166	if (ret)
    167		goto err;
    168	ret = zd1301_demod_wreg(dev, 0x6840, 0x21);
    169	if (ret)
    170		goto err;
    171
    172	return 0;
    173err:
    174	dev_dbg(&pdev->dev, "failed=%d\n", ret);
    175	return ret;
    176}
    177
    178static int zd1301_demod_init(struct dvb_frontend *fe)
    179{
    180	struct zd1301_demod_dev *dev = fe->demodulator_priv;
    181	struct platform_device *pdev = dev->pdev;
    182	int ret;
    183
    184	dev_dbg(&pdev->dev, "\n");
    185
    186	ret = zd1301_demod_wreg(dev, 0x6840, 0x26);
    187	if (ret)
    188		goto err;
    189	ret = zd1301_demod_wreg(dev, 0x68e0, 0xff);
    190	if (ret)
    191		goto err;
    192	ret = zd1301_demod_wreg(dev, 0x68e2, 0xd8);
    193	if (ret)
    194		goto err;
    195	ret = zd1301_demod_wreg(dev, 0x6849, 0x4e);
    196	if (ret)
    197		goto err;
    198	ret = zd1301_demod_wreg(dev, 0x684e, 0x01);
    199	if (ret)
    200		goto err;
    201	ret = zd1301_demod_wreg(dev, 0x6a43, zd1301_demod_gain);
    202	if (ret)
    203		goto err;
    204
    205	return 0;
    206err:
    207	dev_dbg(&pdev->dev, "failed=%d\n", ret);
    208	return ret;
    209}
    210
    211static int zd1301_demod_get_tune_settings(struct dvb_frontend *fe,
    212					  struct dvb_frontend_tune_settings *settings)
    213{
    214	struct zd1301_demod_dev *dev = fe->demodulator_priv;
    215	struct platform_device *pdev = dev->pdev;
    216
    217	dev_dbg(&pdev->dev, "\n");
    218
    219	/* ~180ms seems to be enough */
    220	settings->min_delay_ms = 400;
    221
    222	return 0;
    223}
    224
    225static int zd1301_demod_read_status(struct dvb_frontend *fe,
    226				    enum fe_status *status)
    227{
    228	struct zd1301_demod_dev *dev = fe->demodulator_priv;
    229	struct platform_device *pdev = dev->pdev;
    230	int ret;
    231	u8 u8tmp;
    232
    233	ret = zd1301_demod_rreg(dev, 0x6a24, &u8tmp);
    234	if (ret)
    235		goto err;
    236	if (u8tmp > 0x00 && u8tmp < 0x20)
    237		*status = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI |
    238			  FE_HAS_SYNC | FE_HAS_LOCK;
    239	else
    240		*status = 0;
    241
    242	dev_dbg(&pdev->dev, "lock byte=%02x\n", u8tmp);
    243
    244	/*
    245	 * Interesting registers here are:
    246	 * 0x6a05: get some gain value
    247	 * 0x6a06: get about same gain value than set to 0x6a43
    248	 * 0x6a07: get some gain value
    249	 * 0x6a43: set gain value by driver
    250	 * 0x6a24: get demod lock bits (FSM stage?)
    251	 *
    252	 * Driver should implement some kind of algorithm to calculate suitable
    253	 * value for register 0x6a43, based likely values from register 0x6a05
    254	 * and 0x6a07. Looks like gain register 0x6a43 value could be from
    255	 * range 0x00 - 0x70.
    256	 */
    257
    258	if (dev->gain != zd1301_demod_gain) {
    259		dev->gain = zd1301_demod_gain;
    260
    261		ret = zd1301_demod_wreg(dev, 0x6a43, dev->gain);
    262		if (ret)
    263			goto err;
    264	}
    265
    266	return 0;
    267err:
    268	dev_dbg(&pdev->dev, "failed=%d\n", ret);
    269	return ret;
    270}
    271
    272static const struct dvb_frontend_ops zd1301_demod_ops = {
    273	.delsys = {SYS_DVBT},
    274	.info = {
    275		.name = "ZyDAS ZD1301",
    276		.caps = FE_CAN_FEC_1_2 |
    277			FE_CAN_FEC_2_3 |
    278			FE_CAN_FEC_3_4 |
    279			FE_CAN_FEC_5_6 |
    280			FE_CAN_FEC_7_8 |
    281			FE_CAN_FEC_AUTO |
    282			FE_CAN_QPSK |
    283			FE_CAN_QAM_16 |
    284			FE_CAN_QAM_64 |
    285			FE_CAN_QAM_AUTO |
    286			FE_CAN_TRANSMISSION_MODE_AUTO |
    287			FE_CAN_GUARD_INTERVAL_AUTO |
    288			FE_CAN_HIERARCHY_AUTO |
    289			FE_CAN_MUTE_TS
    290	},
    291
    292	.sleep = zd1301_demod_sleep,
    293	.init = zd1301_demod_init,
    294	.set_frontend = zd1301_demod_set_frontend,
    295	.get_tune_settings = zd1301_demod_get_tune_settings,
    296	.read_status = zd1301_demod_read_status,
    297};
    298
    299struct dvb_frontend *zd1301_demod_get_dvb_frontend(struct platform_device *pdev)
    300{
    301	struct zd1301_demod_dev *dev = platform_get_drvdata(pdev);
    302
    303	dev_dbg(&pdev->dev, "\n");
    304
    305	return &dev->frontend;
    306}
    307EXPORT_SYMBOL(zd1301_demod_get_dvb_frontend);
    308
    309static int zd1301_demod_i2c_master_xfer(struct i2c_adapter *adapter,
    310					struct i2c_msg msg[], int num)
    311{
    312	struct zd1301_demod_dev *dev = i2c_get_adapdata(adapter);
    313	struct platform_device *pdev = dev->pdev;
    314	int ret, i;
    315	unsigned long timeout;
    316	u8 u8tmp;
    317
    318	#define I2C_XFER_TIMEOUT 5
    319	#define ZD1301_IS_I2C_XFER_WRITE_READ(_msg, _num) \
    320		(_num == 2 && !(_msg[0].flags & I2C_M_RD) && (_msg[1].flags & I2C_M_RD))
    321	#define ZD1301_IS_I2C_XFER_WRITE(_msg, _num) \
    322		(_num == 1 && !(_msg[0].flags & I2C_M_RD))
    323	#define ZD1301_IS_I2C_XFER_READ(_msg, _num) \
    324		(_num == 1 && (_msg[0].flags & I2C_M_RD))
    325	if (ZD1301_IS_I2C_XFER_WRITE_READ(msg, num)) {
    326		dev_dbg(&pdev->dev, "write&read msg[0].len=%u msg[1].len=%u\n",
    327			msg[0].len, msg[1].len);
    328		if (msg[0].len > 1 || msg[1].len > 8) {
    329			ret = -EOPNOTSUPP;
    330			goto err;
    331		}
    332
    333		ret = zd1301_demod_wreg(dev, 0x6811, 0x80);
    334		if (ret)
    335			goto err;
    336		ret = zd1301_demod_wreg(dev, 0x6812, 0x05);
    337		if (ret)
    338			goto err;
    339		ret = zd1301_demod_wreg(dev, 0x6813, msg[1].addr << 1);
    340		if (ret)
    341			goto err;
    342		ret = zd1301_demod_wreg(dev, 0x6801, msg[0].buf[0]);
    343		if (ret)
    344			goto err;
    345		ret = zd1301_demod_wreg(dev, 0x6802, 0x00);
    346		if (ret)
    347			goto err;
    348		ret = zd1301_demod_wreg(dev, 0x6803, 0x06);
    349		if (ret)
    350			goto err;
    351		ret = zd1301_demod_wreg(dev, 0x6805, 0x00);
    352		if (ret)
    353			goto err;
    354		ret = zd1301_demod_wreg(dev, 0x6804, msg[1].len);
    355		if (ret)
    356			goto err;
    357
    358		/* Poll xfer ready */
    359		timeout = jiffies + msecs_to_jiffies(I2C_XFER_TIMEOUT);
    360		for (u8tmp = 1; !time_after(jiffies, timeout) && u8tmp;) {
    361			usleep_range(500, 800);
    362
    363			ret = zd1301_demod_rreg(dev, 0x6804, &u8tmp);
    364			if (ret)
    365				goto err;
    366		}
    367
    368		for (i = 0; i < msg[1].len; i++) {
    369			ret = zd1301_demod_rreg(dev, 0x0600 + i, &msg[1].buf[i]);
    370			if (ret)
    371				goto err;
    372		}
    373	} else if (ZD1301_IS_I2C_XFER_WRITE(msg, num)) {
    374		dev_dbg(&pdev->dev, "write msg[0].len=%u\n", msg[0].len);
    375		if (msg[0].len > 1 + 8) {
    376			ret = -EOPNOTSUPP;
    377			goto err;
    378		}
    379
    380		ret = zd1301_demod_wreg(dev, 0x6811, 0x80);
    381		if (ret)
    382			goto err;
    383		ret = zd1301_demod_wreg(dev, 0x6812, 0x01);
    384		if (ret)
    385			goto err;
    386		ret = zd1301_demod_wreg(dev, 0x6813, msg[0].addr << 1);
    387		if (ret)
    388			goto err;
    389		ret = zd1301_demod_wreg(dev, 0x6800, msg[0].buf[0]);
    390		if (ret)
    391			goto err;
    392		ret = zd1301_demod_wreg(dev, 0x6802, 0x00);
    393		if (ret)
    394			goto err;
    395		ret = zd1301_demod_wreg(dev, 0x6803, 0x06);
    396		if (ret)
    397			goto err;
    398
    399		for (i = 0; i < msg[0].len - 1; i++) {
    400			ret = zd1301_demod_wreg(dev, 0x0600 + i, msg[0].buf[1 + i]);
    401			if (ret)
    402				goto err;
    403		}
    404
    405		ret = zd1301_demod_wreg(dev, 0x6805, 0x80);
    406		if (ret)
    407			goto err;
    408		ret = zd1301_demod_wreg(dev, 0x6804, msg[0].len - 1);
    409		if (ret)
    410			goto err;
    411
    412		/* Poll xfer ready */
    413		timeout = jiffies + msecs_to_jiffies(I2C_XFER_TIMEOUT);
    414		for (u8tmp = 1; !time_after(jiffies, timeout) && u8tmp;) {
    415			usleep_range(500, 800);
    416
    417			ret = zd1301_demod_rreg(dev, 0x6804, &u8tmp);
    418			if (ret)
    419				goto err;
    420		}
    421	} else {
    422		dev_dbg(&pdev->dev, "unknown msg[0].len=%u\n", msg[0].len);
    423		ret = -EOPNOTSUPP;
    424		goto err;
    425	}
    426
    427	return num;
    428err:
    429	dev_dbg(&pdev->dev, "failed=%d\n", ret);
    430	return ret;
    431}
    432
    433static u32 zd1301_demod_i2c_functionality(struct i2c_adapter *adapter)
    434{
    435	return I2C_FUNC_I2C;
    436}
    437
    438static const struct i2c_algorithm zd1301_demod_i2c_algorithm = {
    439	.master_xfer   = zd1301_demod_i2c_master_xfer,
    440	.functionality = zd1301_demod_i2c_functionality,
    441};
    442
    443struct i2c_adapter *zd1301_demod_get_i2c_adapter(struct platform_device *pdev)
    444{
    445	struct zd1301_demod_dev *dev = platform_get_drvdata(pdev);
    446
    447	dev_dbg(&pdev->dev, "\n");
    448
    449	return &dev->adapter;
    450}
    451EXPORT_SYMBOL(zd1301_demod_get_i2c_adapter);
    452
    453/* Platform driver interface */
    454static int zd1301_demod_probe(struct platform_device *pdev)
    455{
    456	struct zd1301_demod_dev *dev;
    457	struct zd1301_demod_platform_data *pdata = pdev->dev.platform_data;
    458	int ret;
    459
    460	dev_dbg(&pdev->dev, "\n");
    461
    462	if (!pdata) {
    463		ret = -EINVAL;
    464		dev_err(&pdev->dev, "cannot proceed without platform data\n");
    465		goto err;
    466	}
    467	if (!pdev->dev.parent->driver) {
    468		ret = -EINVAL;
    469		dev_dbg(&pdev->dev, "no parent device\n");
    470		goto err;
    471	}
    472
    473	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
    474	if (!dev) {
    475		ret = -ENOMEM;
    476		goto err;
    477	}
    478
    479	/* Setup the state */
    480	dev->pdev = pdev;
    481	dev->gain = zd1301_demod_gain;
    482
    483	/* Sleep */
    484	ret = zd1301_demod_wreg(dev, 0x6840, 0x21);
    485	if (ret)
    486		goto err_kfree;
    487	ret = zd1301_demod_wreg(dev, 0x6a38, 0x07);
    488	if (ret)
    489		goto err_kfree;
    490
    491	/* Create I2C adapter */
    492	strscpy(dev->adapter.name, "ZyDAS ZD1301 demod",
    493		sizeof(dev->adapter.name));
    494	dev->adapter.algo = &zd1301_demod_i2c_algorithm;
    495	dev->adapter.algo_data = NULL;
    496	dev->adapter.dev.parent = pdev->dev.parent;
    497	i2c_set_adapdata(&dev->adapter, dev);
    498	ret = i2c_add_adapter(&dev->adapter);
    499	if (ret) {
    500		dev_err(&pdev->dev, "I2C adapter add failed %d\n", ret);
    501		goto err_kfree;
    502	}
    503
    504	/* Create dvb frontend */
    505	memcpy(&dev->frontend.ops, &zd1301_demod_ops, sizeof(dev->frontend.ops));
    506	dev->frontend.demodulator_priv = dev;
    507	platform_set_drvdata(pdev, dev);
    508	dev_info(&pdev->dev, "ZyDAS ZD1301 demod attached\n");
    509
    510	return 0;
    511err_kfree:
    512	kfree(dev);
    513err:
    514	dev_dbg(&pdev->dev, "failed=%d\n", ret);
    515	return ret;
    516}
    517
    518static int zd1301_demod_remove(struct platform_device *pdev)
    519{
    520	struct zd1301_demod_dev *dev = platform_get_drvdata(pdev);
    521
    522	dev_dbg(&pdev->dev, "\n");
    523
    524	i2c_del_adapter(&dev->adapter);
    525	kfree(dev);
    526
    527	return 0;
    528}
    529
    530static struct platform_driver zd1301_demod_driver = {
    531	.driver = {
    532		.name                = "zd1301_demod",
    533		.suppress_bind_attrs = true,
    534	},
    535	.probe          = zd1301_demod_probe,
    536	.remove         = zd1301_demod_remove,
    537};
    538module_platform_driver(zd1301_demod_driver);
    539
    540MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
    541MODULE_DESCRIPTION("ZyDAS ZD1301 demodulator driver");
    542MODULE_LICENSE("GPL");