brintos

brintos / linux-shallow public Read only

0
0
Text · 12.4 KiB · 17f6e37 Raw
541 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*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	else240		*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 value247	 * 0x6a06: get about same gain value than set to 0x6a43248	 * 0x6a07: get some gain value249	 * 0x6a43: set gain value by driver250	 * 0x6a24: get demod lock bits (FSM stage?)251	 *252	 * Driver should implement some kind of algorithm to calculate suitable253	 * value for register 0x6a43, based likely values from register 0x6a05254	 * and 0x6a07. Looks like gain register 0x6a43 value could be from255	 * 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_TS290	},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 5319	#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 void 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 528static struct platform_driver zd1301_demod_driver = {529	.driver = {530		.name                = "zd1301_demod",531		.suppress_bind_attrs = true,532	},533	.probe          = zd1301_demod_probe,534	.remove_new     = zd1301_demod_remove,535};536module_platform_driver(zd1301_demod_driver);537 538MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");539MODULE_DESCRIPTION("ZyDAS ZD1301 demodulator driver");540MODULE_LICENSE("GPL");541