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