1*c942fddfSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 247d65372SAntti Palosaari /* 347d65372SAntti Palosaari * ZyDAS ZD1301 driver (demodulator) 447d65372SAntti Palosaari * 547d65372SAntti Palosaari * Copyright (C) 2015 Antti Palosaari <crope@iki.fi> 647d65372SAntti Palosaari */ 747d65372SAntti Palosaari 847d65372SAntti Palosaari #include "zd1301_demod.h" 947d65372SAntti Palosaari 1047d65372SAntti Palosaari static u8 zd1301_demod_gain = 0x38; 1147d65372SAntti Palosaari module_param_named(gain, zd1301_demod_gain, byte, 0644); 1247d65372SAntti Palosaari MODULE_PARM_DESC(gain, "gain (value: 0x00 - 0x70, default: 0x38)"); 1347d65372SAntti Palosaari 1447d65372SAntti Palosaari struct zd1301_demod_dev { 1547d65372SAntti Palosaari struct platform_device *pdev; 1647d65372SAntti Palosaari struct dvb_frontend frontend; 1747d65372SAntti Palosaari struct i2c_adapter adapter; 1847d65372SAntti Palosaari u8 gain; 1947d65372SAntti Palosaari }; 2047d65372SAntti Palosaari 2147d65372SAntti Palosaari static int zd1301_demod_wreg(struct zd1301_demod_dev *dev, u16 reg, u8 val) 2247d65372SAntti Palosaari { 2347d65372SAntti Palosaari struct platform_device *pdev = dev->pdev; 2447d65372SAntti Palosaari struct zd1301_demod_platform_data *pdata = pdev->dev.platform_data; 2547d65372SAntti Palosaari 2647d65372SAntti Palosaari return pdata->reg_write(pdata->reg_priv, reg, val); 2747d65372SAntti Palosaari } 2847d65372SAntti Palosaari 2947d65372SAntti Palosaari static int zd1301_demod_rreg(struct zd1301_demod_dev *dev, u16 reg, u8 *val) 3047d65372SAntti Palosaari { 3147d65372SAntti Palosaari struct platform_device *pdev = dev->pdev; 3247d65372SAntti Palosaari struct zd1301_demod_platform_data *pdata = pdev->dev.platform_data; 3347d65372SAntti Palosaari 3447d65372SAntti Palosaari return pdata->reg_read(pdata->reg_priv, reg, val); 3547d65372SAntti Palosaari } 3647d65372SAntti Palosaari 3747d65372SAntti Palosaari static int zd1301_demod_set_frontend(struct dvb_frontend *fe) 3847d65372SAntti Palosaari { 3947d65372SAntti Palosaari struct zd1301_demod_dev *dev = fe->demodulator_priv; 4047d65372SAntti Palosaari struct platform_device *pdev = dev->pdev; 4147d65372SAntti Palosaari struct dtv_frontend_properties *c = &fe->dtv_property_cache; 4247d65372SAntti Palosaari int ret; 4347d65372SAntti Palosaari u32 if_frequency; 4447d65372SAntti Palosaari u8 r6a50_val; 4547d65372SAntti Palosaari 4647d65372SAntti Palosaari dev_dbg(&pdev->dev, "frequency=%u bandwidth_hz=%u\n", 4747d65372SAntti Palosaari c->frequency, c->bandwidth_hz); 4847d65372SAntti Palosaari 4947d65372SAntti Palosaari /* Program tuner */ 5047d65372SAntti Palosaari if (fe->ops.tuner_ops.set_params && 5147d65372SAntti Palosaari fe->ops.tuner_ops.get_if_frequency) { 5247d65372SAntti Palosaari ret = fe->ops.tuner_ops.set_params(fe); 5347d65372SAntti Palosaari if (ret) 5447d65372SAntti Palosaari goto err; 5547d65372SAntti Palosaari ret = fe->ops.tuner_ops.get_if_frequency(fe, &if_frequency); 5647d65372SAntti Palosaari if (ret) 5747d65372SAntti Palosaari goto err; 5847d65372SAntti Palosaari } else { 5947d65372SAntti Palosaari ret = -EINVAL; 6047d65372SAntti Palosaari goto err; 6147d65372SAntti Palosaari } 6247d65372SAntti Palosaari 6347d65372SAntti Palosaari dev_dbg(&pdev->dev, "if_frequency=%u\n", if_frequency); 6447d65372SAntti Palosaari if (if_frequency != 36150000) { 6547d65372SAntti Palosaari ret = -EINVAL; 6647d65372SAntti Palosaari goto err; 6747d65372SAntti Palosaari } 6847d65372SAntti Palosaari 6947d65372SAntti Palosaari switch (c->bandwidth_hz) { 7047d65372SAntti Palosaari case 6000000: 7147d65372SAntti Palosaari r6a50_val = 0x78; 7247d65372SAntti Palosaari break; 7347d65372SAntti Palosaari case 7000000: 7447d65372SAntti Palosaari r6a50_val = 0x68; 7547d65372SAntti Palosaari break; 7647d65372SAntti Palosaari case 8000000: 7747d65372SAntti Palosaari r6a50_val = 0x58; 7847d65372SAntti Palosaari break; 7947d65372SAntti Palosaari default: 8047d65372SAntti Palosaari ret = -EINVAL; 8147d65372SAntti Palosaari goto err; 8247d65372SAntti Palosaari } 8347d65372SAntti Palosaari 8447d65372SAntti Palosaari ret = zd1301_demod_wreg(dev, 0x6a60, 0x11); 8547d65372SAntti Palosaari if (ret) 8647d65372SAntti Palosaari goto err; 8747d65372SAntti Palosaari ret = zd1301_demod_wreg(dev, 0x6a47, 0x46); 8847d65372SAntti Palosaari if (ret) 8947d65372SAntti Palosaari goto err; 9047d65372SAntti Palosaari ret = zd1301_demod_wreg(dev, 0x6a48, 0x46); 9147d65372SAntti Palosaari if (ret) 9247d65372SAntti Palosaari goto err; 9347d65372SAntti Palosaari ret = zd1301_demod_wreg(dev, 0x6a4a, 0x15); 9447d65372SAntti Palosaari if (ret) 9547d65372SAntti Palosaari goto err; 9647d65372SAntti Palosaari ret = zd1301_demod_wreg(dev, 0x6a4b, 0x63); 9747d65372SAntti Palosaari if (ret) 9847d65372SAntti Palosaari goto err; 9947d65372SAntti Palosaari ret = zd1301_demod_wreg(dev, 0x6a5b, 0x99); 10047d65372SAntti Palosaari if (ret) 10147d65372SAntti Palosaari goto err; 10247d65372SAntti Palosaari ret = zd1301_demod_wreg(dev, 0x6a3b, 0x10); 10347d65372SAntti Palosaari if (ret) 10447d65372SAntti Palosaari goto err; 10547d65372SAntti Palosaari ret = zd1301_demod_wreg(dev, 0x6806, 0x01); 10647d65372SAntti Palosaari if (ret) 10747d65372SAntti Palosaari goto err; 10847d65372SAntti Palosaari ret = zd1301_demod_wreg(dev, 0x6a41, 0x08); 10947d65372SAntti Palosaari if (ret) 11047d65372SAntti Palosaari goto err; 11147d65372SAntti Palosaari ret = zd1301_demod_wreg(dev, 0x6a42, 0x46); 11247d65372SAntti Palosaari if (ret) 11347d65372SAntti Palosaari goto err; 11447d65372SAntti Palosaari ret = zd1301_demod_wreg(dev, 0x6a44, 0x14); 11547d65372SAntti Palosaari if (ret) 11647d65372SAntti Palosaari goto err; 11747d65372SAntti Palosaari ret = zd1301_demod_wreg(dev, 0x6a45, 0x67); 11847d65372SAntti Palosaari if (ret) 11947d65372SAntti Palosaari goto err; 12047d65372SAntti Palosaari ret = zd1301_demod_wreg(dev, 0x6a38, 0x00); 12147d65372SAntti Palosaari if (ret) 12247d65372SAntti Palosaari goto err; 12347d65372SAntti Palosaari ret = zd1301_demod_wreg(dev, 0x6a4c, 0x52); 12447d65372SAntti Palosaari if (ret) 12547d65372SAntti Palosaari goto err; 12647d65372SAntti Palosaari ret = zd1301_demod_wreg(dev, 0x6a49, 0x2a); 12747d65372SAntti Palosaari if (ret) 12847d65372SAntti Palosaari goto err; 12947d65372SAntti Palosaari ret = zd1301_demod_wreg(dev, 0x6840, 0x2e); 13047d65372SAntti Palosaari if (ret) 13147d65372SAntti Palosaari goto err; 13247d65372SAntti Palosaari ret = zd1301_demod_wreg(dev, 0x6a50, r6a50_val); 13347d65372SAntti Palosaari if (ret) 13447d65372SAntti Palosaari goto err; 13547d65372SAntti Palosaari ret = zd1301_demod_wreg(dev, 0x6a38, 0x07); 13647d65372SAntti Palosaari if (ret) 13747d65372SAntti Palosaari goto err; 13847d65372SAntti Palosaari 13947d65372SAntti Palosaari return 0; 14047d65372SAntti Palosaari err: 14147d65372SAntti Palosaari dev_dbg(&pdev->dev, "failed=%d\n", ret); 14247d65372SAntti Palosaari return ret; 14347d65372SAntti Palosaari } 14447d65372SAntti Palosaari 14547d65372SAntti Palosaari static int zd1301_demod_sleep(struct dvb_frontend *fe) 14647d65372SAntti Palosaari { 14747d65372SAntti Palosaari struct zd1301_demod_dev *dev = fe->demodulator_priv; 14847d65372SAntti Palosaari struct platform_device *pdev = dev->pdev; 14947d65372SAntti Palosaari int ret; 15047d65372SAntti Palosaari 15147d65372SAntti Palosaari dev_dbg(&pdev->dev, "\n"); 15247d65372SAntti Palosaari 15347d65372SAntti Palosaari ret = zd1301_demod_wreg(dev, 0x6a43, 0x70); 15447d65372SAntti Palosaari if (ret) 15547d65372SAntti Palosaari goto err; 15647d65372SAntti Palosaari ret = zd1301_demod_wreg(dev, 0x684e, 0x00); 15747d65372SAntti Palosaari if (ret) 15847d65372SAntti Palosaari goto err; 15947d65372SAntti Palosaari ret = zd1301_demod_wreg(dev, 0x6849, 0x00); 16047d65372SAntti Palosaari if (ret) 16147d65372SAntti Palosaari goto err; 16247d65372SAntti Palosaari ret = zd1301_demod_wreg(dev, 0x68e2, 0xd7); 16347d65372SAntti Palosaari if (ret) 16447d65372SAntti Palosaari goto err; 16547d65372SAntti Palosaari ret = zd1301_demod_wreg(dev, 0x68e0, 0x39); 16647d65372SAntti Palosaari if (ret) 16747d65372SAntti Palosaari goto err; 16847d65372SAntti Palosaari ret = zd1301_demod_wreg(dev, 0x6840, 0x21); 16947d65372SAntti Palosaari if (ret) 17047d65372SAntti Palosaari goto err; 17147d65372SAntti Palosaari 17247d65372SAntti Palosaari return 0; 17347d65372SAntti Palosaari err: 17447d65372SAntti Palosaari dev_dbg(&pdev->dev, "failed=%d\n", ret); 17547d65372SAntti Palosaari return ret; 17647d65372SAntti Palosaari } 17747d65372SAntti Palosaari 17847d65372SAntti Palosaari static int zd1301_demod_init(struct dvb_frontend *fe) 17947d65372SAntti Palosaari { 18047d65372SAntti Palosaari struct zd1301_demod_dev *dev = fe->demodulator_priv; 18147d65372SAntti Palosaari struct platform_device *pdev = dev->pdev; 18247d65372SAntti Palosaari int ret; 18347d65372SAntti Palosaari 18447d65372SAntti Palosaari dev_dbg(&pdev->dev, "\n"); 18547d65372SAntti Palosaari 18647d65372SAntti Palosaari ret = zd1301_demod_wreg(dev, 0x6840, 0x26); 18747d65372SAntti Palosaari if (ret) 18847d65372SAntti Palosaari goto err; 18947d65372SAntti Palosaari ret = zd1301_demod_wreg(dev, 0x68e0, 0xff); 19047d65372SAntti Palosaari if (ret) 19147d65372SAntti Palosaari goto err; 19247d65372SAntti Palosaari ret = zd1301_demod_wreg(dev, 0x68e2, 0xd8); 19347d65372SAntti Palosaari if (ret) 19447d65372SAntti Palosaari goto err; 19547d65372SAntti Palosaari ret = zd1301_demod_wreg(dev, 0x6849, 0x4e); 19647d65372SAntti Palosaari if (ret) 19747d65372SAntti Palosaari goto err; 19847d65372SAntti Palosaari ret = zd1301_demod_wreg(dev, 0x684e, 0x01); 19947d65372SAntti Palosaari if (ret) 20047d65372SAntti Palosaari goto err; 20147d65372SAntti Palosaari ret = zd1301_demod_wreg(dev, 0x6a43, zd1301_demod_gain); 20247d65372SAntti Palosaari if (ret) 20347d65372SAntti Palosaari goto err; 20447d65372SAntti Palosaari 20547d65372SAntti Palosaari return 0; 20647d65372SAntti Palosaari err: 20747d65372SAntti Palosaari dev_dbg(&pdev->dev, "failed=%d\n", ret); 20847d65372SAntti Palosaari return ret; 20947d65372SAntti Palosaari } 21047d65372SAntti Palosaari 21147d65372SAntti Palosaari static int zd1301_demod_get_tune_settings(struct dvb_frontend *fe, 21247d65372SAntti Palosaari struct dvb_frontend_tune_settings *settings) 21347d65372SAntti Palosaari { 21447d65372SAntti Palosaari struct zd1301_demod_dev *dev = fe->demodulator_priv; 21547d65372SAntti Palosaari struct platform_device *pdev = dev->pdev; 21647d65372SAntti Palosaari 21747d65372SAntti Palosaari dev_dbg(&pdev->dev, "\n"); 21847d65372SAntti Palosaari 21947d65372SAntti Palosaari /* ~180ms seems to be enough */ 22047d65372SAntti Palosaari settings->min_delay_ms = 400; 22147d65372SAntti Palosaari 22247d65372SAntti Palosaari return 0; 22347d65372SAntti Palosaari } 22447d65372SAntti Palosaari 22547d65372SAntti Palosaari static int zd1301_demod_read_status(struct dvb_frontend *fe, 22647d65372SAntti Palosaari enum fe_status *status) 22747d65372SAntti Palosaari { 22847d65372SAntti Palosaari struct zd1301_demod_dev *dev = fe->demodulator_priv; 22947d65372SAntti Palosaari struct platform_device *pdev = dev->pdev; 23047d65372SAntti Palosaari int ret; 23147d65372SAntti Palosaari u8 u8tmp; 23247d65372SAntti Palosaari 23347d65372SAntti Palosaari ret = zd1301_demod_rreg(dev, 0x6a24, &u8tmp); 23447d65372SAntti Palosaari if (ret) 23547d65372SAntti Palosaari goto err; 23647d65372SAntti Palosaari if (u8tmp > 0x00 && u8tmp < 0x20) 23747d65372SAntti Palosaari *status = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI | 23847d65372SAntti Palosaari FE_HAS_SYNC | FE_HAS_LOCK; 23947d65372SAntti Palosaari else 24047d65372SAntti Palosaari *status = 0; 24147d65372SAntti Palosaari 24247d65372SAntti Palosaari dev_dbg(&pdev->dev, "lock byte=%02x\n", u8tmp); 24347d65372SAntti Palosaari 24447d65372SAntti Palosaari /* 24547d65372SAntti Palosaari * Interesting registers here are: 24647d65372SAntti Palosaari * 0x6a05: get some gain value 24747d65372SAntti Palosaari * 0x6a06: get about same gain value than set to 0x6a43 24847d65372SAntti Palosaari * 0x6a07: get some gain value 24947d65372SAntti Palosaari * 0x6a43: set gain value by driver 25047d65372SAntti Palosaari * 0x6a24: get demod lock bits (FSM stage?) 25147d65372SAntti Palosaari * 25247d65372SAntti Palosaari * Driver should implement some kind of algorithm to calculate suitable 25347d65372SAntti Palosaari * value for register 0x6a43, based likely values from register 0x6a05 25447d65372SAntti Palosaari * and 0x6a07. Looks like gain register 0x6a43 value could be from 25547d65372SAntti Palosaari * range 0x00 - 0x70. 25647d65372SAntti Palosaari */ 25747d65372SAntti Palosaari 25847d65372SAntti Palosaari if (dev->gain != zd1301_demod_gain) { 25947d65372SAntti Palosaari dev->gain = zd1301_demod_gain; 26047d65372SAntti Palosaari 26147d65372SAntti Palosaari ret = zd1301_demod_wreg(dev, 0x6a43, dev->gain); 26247d65372SAntti Palosaari if (ret) 26347d65372SAntti Palosaari goto err; 26447d65372SAntti Palosaari } 26547d65372SAntti Palosaari 26647d65372SAntti Palosaari return 0; 26747d65372SAntti Palosaari err: 26847d65372SAntti Palosaari dev_dbg(&pdev->dev, "failed=%d\n", ret); 26947d65372SAntti Palosaari return ret; 27047d65372SAntti Palosaari } 27147d65372SAntti Palosaari 27247d65372SAntti Palosaari static const struct dvb_frontend_ops zd1301_demod_ops = { 27347d65372SAntti Palosaari .delsys = {SYS_DVBT}, 27447d65372SAntti Palosaari .info = { 27547d65372SAntti Palosaari .name = "ZyDAS ZD1301", 27647d65372SAntti Palosaari .caps = FE_CAN_FEC_1_2 | 27747d65372SAntti Palosaari FE_CAN_FEC_2_3 | 27847d65372SAntti Palosaari FE_CAN_FEC_3_4 | 27947d65372SAntti Palosaari FE_CAN_FEC_5_6 | 28047d65372SAntti Palosaari FE_CAN_FEC_7_8 | 28147d65372SAntti Palosaari FE_CAN_FEC_AUTO | 28247d65372SAntti Palosaari FE_CAN_QPSK | 28347d65372SAntti Palosaari FE_CAN_QAM_16 | 28447d65372SAntti Palosaari FE_CAN_QAM_64 | 28547d65372SAntti Palosaari FE_CAN_QAM_AUTO | 28647d65372SAntti Palosaari FE_CAN_TRANSMISSION_MODE_AUTO | 28747d65372SAntti Palosaari FE_CAN_GUARD_INTERVAL_AUTO | 28847d65372SAntti Palosaari FE_CAN_HIERARCHY_AUTO | 28947d65372SAntti Palosaari FE_CAN_MUTE_TS 29047d65372SAntti Palosaari }, 29147d65372SAntti Palosaari 29247d65372SAntti Palosaari .sleep = zd1301_demod_sleep, 29347d65372SAntti Palosaari .init = zd1301_demod_init, 29447d65372SAntti Palosaari .set_frontend = zd1301_demod_set_frontend, 29547d65372SAntti Palosaari .get_tune_settings = zd1301_demod_get_tune_settings, 29647d65372SAntti Palosaari .read_status = zd1301_demod_read_status, 29747d65372SAntti Palosaari }; 29847d65372SAntti Palosaari 29947d65372SAntti Palosaari struct dvb_frontend *zd1301_demod_get_dvb_frontend(struct platform_device *pdev) 30047d65372SAntti Palosaari { 30147d65372SAntti Palosaari struct zd1301_demod_dev *dev = platform_get_drvdata(pdev); 30247d65372SAntti Palosaari 30347d65372SAntti Palosaari dev_dbg(&pdev->dev, "\n"); 30447d65372SAntti Palosaari 30547d65372SAntti Palosaari return &dev->frontend; 30647d65372SAntti Palosaari } 30747d65372SAntti Palosaari EXPORT_SYMBOL(zd1301_demod_get_dvb_frontend); 30847d65372SAntti Palosaari 30947d65372SAntti Palosaari static int zd1301_demod_i2c_master_xfer(struct i2c_adapter *adapter, 31047d65372SAntti Palosaari struct i2c_msg msg[], int num) 31147d65372SAntti Palosaari { 31247d65372SAntti Palosaari struct zd1301_demod_dev *dev = i2c_get_adapdata(adapter); 31347d65372SAntti Palosaari struct platform_device *pdev = dev->pdev; 31447d65372SAntti Palosaari int ret, i; 31547d65372SAntti Palosaari unsigned long timeout; 31647d65372SAntti Palosaari u8 u8tmp; 31747d65372SAntti Palosaari 31847d65372SAntti Palosaari #define I2C_XFER_TIMEOUT 5 31947d65372SAntti Palosaari #define ZD1301_IS_I2C_XFER_WRITE_READ(_msg, _num) \ 32047d65372SAntti Palosaari (_num == 2 && !(_msg[0].flags & I2C_M_RD) && (_msg[1].flags & I2C_M_RD)) 32147d65372SAntti Palosaari #define ZD1301_IS_I2C_XFER_WRITE(_msg, _num) \ 32247d65372SAntti Palosaari (_num == 1 && !(_msg[0].flags & I2C_M_RD)) 32347d65372SAntti Palosaari #define ZD1301_IS_I2C_XFER_READ(_msg, _num) \ 32447d65372SAntti Palosaari (_num == 1 && (_msg[0].flags & I2C_M_RD)) 32547d65372SAntti Palosaari if (ZD1301_IS_I2C_XFER_WRITE_READ(msg, num)) { 32647d65372SAntti Palosaari dev_dbg(&pdev->dev, "write&read msg[0].len=%u msg[1].len=%u\n", 32747d65372SAntti Palosaari msg[0].len, msg[1].len); 32847d65372SAntti Palosaari if (msg[0].len > 1 || msg[1].len > 8) { 32947d65372SAntti Palosaari ret = -EOPNOTSUPP; 33047d65372SAntti Palosaari goto err; 33147d65372SAntti Palosaari } 33247d65372SAntti Palosaari 33347d65372SAntti Palosaari ret = zd1301_demod_wreg(dev, 0x6811, 0x80); 33447d65372SAntti Palosaari if (ret) 33547d65372SAntti Palosaari goto err; 33647d65372SAntti Palosaari ret = zd1301_demod_wreg(dev, 0x6812, 0x05); 33747d65372SAntti Palosaari if (ret) 33847d65372SAntti Palosaari goto err; 33947d65372SAntti Palosaari ret = zd1301_demod_wreg(dev, 0x6813, msg[1].addr << 1); 34047d65372SAntti Palosaari if (ret) 34147d65372SAntti Palosaari goto err; 34247d65372SAntti Palosaari ret = zd1301_demod_wreg(dev, 0x6801, msg[0].buf[0]); 34347d65372SAntti Palosaari if (ret) 34447d65372SAntti Palosaari goto err; 34547d65372SAntti Palosaari ret = zd1301_demod_wreg(dev, 0x6802, 0x00); 34647d65372SAntti Palosaari if (ret) 34747d65372SAntti Palosaari goto err; 34847d65372SAntti Palosaari ret = zd1301_demod_wreg(dev, 0x6803, 0x06); 34947d65372SAntti Palosaari if (ret) 35047d65372SAntti Palosaari goto err; 35147d65372SAntti Palosaari ret = zd1301_demod_wreg(dev, 0x6805, 0x00); 35247d65372SAntti Palosaari if (ret) 35347d65372SAntti Palosaari goto err; 35447d65372SAntti Palosaari ret = zd1301_demod_wreg(dev, 0x6804, msg[1].len); 35547d65372SAntti Palosaari if (ret) 35647d65372SAntti Palosaari goto err; 35747d65372SAntti Palosaari 35847d65372SAntti Palosaari /* Poll xfer ready */ 35947d65372SAntti Palosaari timeout = jiffies + msecs_to_jiffies(I2C_XFER_TIMEOUT); 36047d65372SAntti Palosaari for (u8tmp = 1; !time_after(jiffies, timeout) && u8tmp;) { 36147d65372SAntti Palosaari usleep_range(500, 800); 36247d65372SAntti Palosaari 36347d65372SAntti Palosaari ret = zd1301_demod_rreg(dev, 0x6804, &u8tmp); 36447d65372SAntti Palosaari if (ret) 36547d65372SAntti Palosaari goto err; 36647d65372SAntti Palosaari } 36747d65372SAntti Palosaari 36847d65372SAntti Palosaari for (i = 0; i < msg[1].len; i++) { 36947d65372SAntti Palosaari ret = zd1301_demod_rreg(dev, 0x0600 + i, &msg[1].buf[i]); 37047d65372SAntti Palosaari if (ret) 37147d65372SAntti Palosaari goto err; 37247d65372SAntti Palosaari } 37347d65372SAntti Palosaari } else if (ZD1301_IS_I2C_XFER_WRITE(msg, num)) { 37447d65372SAntti Palosaari dev_dbg(&pdev->dev, "write msg[0].len=%u\n", msg[0].len); 37547d65372SAntti Palosaari if (msg[0].len > 1 + 8) { 37647d65372SAntti Palosaari ret = -EOPNOTSUPP; 37747d65372SAntti Palosaari goto err; 37847d65372SAntti Palosaari } 37947d65372SAntti Palosaari 38047d65372SAntti Palosaari ret = zd1301_demod_wreg(dev, 0x6811, 0x80); 38147d65372SAntti Palosaari if (ret) 38247d65372SAntti Palosaari goto err; 38347d65372SAntti Palosaari ret = zd1301_demod_wreg(dev, 0x6812, 0x01); 38447d65372SAntti Palosaari if (ret) 38547d65372SAntti Palosaari goto err; 38647d65372SAntti Palosaari ret = zd1301_demod_wreg(dev, 0x6813, msg[0].addr << 1); 38747d65372SAntti Palosaari if (ret) 38847d65372SAntti Palosaari goto err; 38947d65372SAntti Palosaari ret = zd1301_demod_wreg(dev, 0x6800, msg[0].buf[0]); 39047d65372SAntti Palosaari if (ret) 39147d65372SAntti Palosaari goto err; 39247d65372SAntti Palosaari ret = zd1301_demod_wreg(dev, 0x6802, 0x00); 39347d65372SAntti Palosaari if (ret) 39447d65372SAntti Palosaari goto err; 39547d65372SAntti Palosaari ret = zd1301_demod_wreg(dev, 0x6803, 0x06); 39647d65372SAntti Palosaari if (ret) 39747d65372SAntti Palosaari goto err; 39847d65372SAntti Palosaari 39947d65372SAntti Palosaari for (i = 0; i < msg[0].len - 1; i++) { 40047d65372SAntti Palosaari ret = zd1301_demod_wreg(dev, 0x0600 + i, msg[0].buf[1 + i]); 40147d65372SAntti Palosaari if (ret) 40247d65372SAntti Palosaari goto err; 40347d65372SAntti Palosaari } 40447d65372SAntti Palosaari 40547d65372SAntti Palosaari ret = zd1301_demod_wreg(dev, 0x6805, 0x80); 40647d65372SAntti Palosaari if (ret) 40747d65372SAntti Palosaari goto err; 40847d65372SAntti Palosaari ret = zd1301_demod_wreg(dev, 0x6804, msg[0].len - 1); 40947d65372SAntti Palosaari if (ret) 41047d65372SAntti Palosaari goto err; 41147d65372SAntti Palosaari 41247d65372SAntti Palosaari /* Poll xfer ready */ 41347d65372SAntti Palosaari timeout = jiffies + msecs_to_jiffies(I2C_XFER_TIMEOUT); 41447d65372SAntti Palosaari for (u8tmp = 1; !time_after(jiffies, timeout) && u8tmp;) { 41547d65372SAntti Palosaari usleep_range(500, 800); 41647d65372SAntti Palosaari 41747d65372SAntti Palosaari ret = zd1301_demod_rreg(dev, 0x6804, &u8tmp); 41847d65372SAntti Palosaari if (ret) 41947d65372SAntti Palosaari goto err; 42047d65372SAntti Palosaari } 42147d65372SAntti Palosaari } else { 42247d65372SAntti Palosaari dev_dbg(&pdev->dev, "unknown msg[0].len=%u\n", msg[0].len); 42347d65372SAntti Palosaari ret = -EOPNOTSUPP; 42447d65372SAntti Palosaari goto err; 42547d65372SAntti Palosaari } 42647d65372SAntti Palosaari 42747d65372SAntti Palosaari return num; 42847d65372SAntti Palosaari err: 42947d65372SAntti Palosaari dev_dbg(&pdev->dev, "failed=%d\n", ret); 43047d65372SAntti Palosaari return ret; 43147d65372SAntti Palosaari } 43247d65372SAntti Palosaari 43347d65372SAntti Palosaari static u32 zd1301_demod_i2c_functionality(struct i2c_adapter *adapter) 43447d65372SAntti Palosaari { 43547d65372SAntti Palosaari return I2C_FUNC_I2C; 43647d65372SAntti Palosaari } 43747d65372SAntti Palosaari 438c51df136SGustavo A. R. Silva static const struct i2c_algorithm zd1301_demod_i2c_algorithm = { 43947d65372SAntti Palosaari .master_xfer = zd1301_demod_i2c_master_xfer, 44047d65372SAntti Palosaari .functionality = zd1301_demod_i2c_functionality, 44147d65372SAntti Palosaari }; 44247d65372SAntti Palosaari 44347d65372SAntti Palosaari struct i2c_adapter *zd1301_demod_get_i2c_adapter(struct platform_device *pdev) 44447d65372SAntti Palosaari { 44547d65372SAntti Palosaari struct zd1301_demod_dev *dev = platform_get_drvdata(pdev); 44647d65372SAntti Palosaari 44747d65372SAntti Palosaari dev_dbg(&pdev->dev, "\n"); 44847d65372SAntti Palosaari 44947d65372SAntti Palosaari return &dev->adapter; 45047d65372SAntti Palosaari } 45147d65372SAntti Palosaari EXPORT_SYMBOL(zd1301_demod_get_i2c_adapter); 45247d65372SAntti Palosaari 45347d65372SAntti Palosaari /* Platform driver interface */ 45447d65372SAntti Palosaari static int zd1301_demod_probe(struct platform_device *pdev) 45547d65372SAntti Palosaari { 45647d65372SAntti Palosaari struct zd1301_demod_dev *dev; 45747d65372SAntti Palosaari struct zd1301_demod_platform_data *pdata = pdev->dev.platform_data; 45847d65372SAntti Palosaari int ret; 45947d65372SAntti Palosaari 46047d65372SAntti Palosaari dev_dbg(&pdev->dev, "\n"); 46147d65372SAntti Palosaari 46247d65372SAntti Palosaari if (!pdata) { 46347d65372SAntti Palosaari ret = -EINVAL; 46447d65372SAntti Palosaari dev_err(&pdev->dev, "cannot proceed without platform data\n"); 46547d65372SAntti Palosaari goto err; 46647d65372SAntti Palosaari } 46747d65372SAntti Palosaari if (!pdev->dev.parent->driver) { 46847d65372SAntti Palosaari ret = -EINVAL; 46947d65372SAntti Palosaari dev_dbg(&pdev->dev, "no parent device\n"); 47047d65372SAntti Palosaari goto err; 47147d65372SAntti Palosaari } 47247d65372SAntti Palosaari 47347d65372SAntti Palosaari dev = kzalloc(sizeof(*dev), GFP_KERNEL); 47447d65372SAntti Palosaari if (!dev) { 47547d65372SAntti Palosaari ret = -ENOMEM; 47647d65372SAntti Palosaari goto err; 47747d65372SAntti Palosaari } 47847d65372SAntti Palosaari 47947d65372SAntti Palosaari /* Setup the state */ 48047d65372SAntti Palosaari dev->pdev = pdev; 48147d65372SAntti Palosaari dev->gain = zd1301_demod_gain; 48247d65372SAntti Palosaari 48347d65372SAntti Palosaari /* Sleep */ 48447d65372SAntti Palosaari ret = zd1301_demod_wreg(dev, 0x6840, 0x21); 48547d65372SAntti Palosaari if (ret) 48647d65372SAntti Palosaari goto err_kfree; 48747d65372SAntti Palosaari ret = zd1301_demod_wreg(dev, 0x6a38, 0x07); 48847d65372SAntti Palosaari if (ret) 48947d65372SAntti Palosaari goto err_kfree; 49047d65372SAntti Palosaari 49147d65372SAntti Palosaari /* Create I2C adapter */ 492c0decac1SMauro Carvalho Chehab strscpy(dev->adapter.name, "ZyDAS ZD1301 demod", 493c0decac1SMauro Carvalho Chehab sizeof(dev->adapter.name)); 49447d65372SAntti Palosaari dev->adapter.algo = &zd1301_demod_i2c_algorithm; 49547d65372SAntti Palosaari dev->adapter.algo_data = NULL; 49647d65372SAntti Palosaari dev->adapter.dev.parent = pdev->dev.parent; 49747d65372SAntti Palosaari i2c_set_adapdata(&dev->adapter, dev); 49847d65372SAntti Palosaari ret = i2c_add_adapter(&dev->adapter); 49947d65372SAntti Palosaari if (ret) { 50047d65372SAntti Palosaari dev_err(&pdev->dev, "I2C adapter add failed %d\n", ret); 50147d65372SAntti Palosaari goto err_kfree; 50247d65372SAntti Palosaari } 50347d65372SAntti Palosaari 50447d65372SAntti Palosaari /* Create dvb frontend */ 50547d65372SAntti Palosaari memcpy(&dev->frontend.ops, &zd1301_demod_ops, sizeof(dev->frontend.ops)); 50647d65372SAntti Palosaari dev->frontend.demodulator_priv = dev; 50747d65372SAntti Palosaari platform_set_drvdata(pdev, dev); 50847d65372SAntti Palosaari dev_info(&pdev->dev, "ZyDAS ZD1301 demod attached\n"); 50947d65372SAntti Palosaari 51047d65372SAntti Palosaari return 0; 51147d65372SAntti Palosaari err_kfree: 51247d65372SAntti Palosaari kfree(dev); 51347d65372SAntti Palosaari err: 51447d65372SAntti Palosaari dev_dbg(&pdev->dev, "failed=%d\n", ret); 51547d65372SAntti Palosaari return ret; 51647d65372SAntti Palosaari } 51747d65372SAntti Palosaari 51847d65372SAntti Palosaari static int zd1301_demod_remove(struct platform_device *pdev) 51947d65372SAntti Palosaari { 52047d65372SAntti Palosaari struct zd1301_demod_dev *dev = platform_get_drvdata(pdev); 52147d65372SAntti Palosaari 52247d65372SAntti Palosaari dev_dbg(&pdev->dev, "\n"); 52347d65372SAntti Palosaari 52447d65372SAntti Palosaari i2c_del_adapter(&dev->adapter); 52547d65372SAntti Palosaari kfree(dev); 52647d65372SAntti Palosaari 52747d65372SAntti Palosaari return 0; 52847d65372SAntti Palosaari } 52947d65372SAntti Palosaari 53047d65372SAntti Palosaari static struct platform_driver zd1301_demod_driver = { 53147d65372SAntti Palosaari .driver = { 53247d65372SAntti Palosaari .name = "zd1301_demod", 53347d65372SAntti Palosaari .suppress_bind_attrs = true, 53447d65372SAntti Palosaari }, 53547d65372SAntti Palosaari .probe = zd1301_demod_probe, 53647d65372SAntti Palosaari .remove = zd1301_demod_remove, 53747d65372SAntti Palosaari }; 53847d65372SAntti Palosaari module_platform_driver(zd1301_demod_driver); 53947d65372SAntti Palosaari 54047d65372SAntti Palosaari MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); 54147d65372SAntti Palosaari MODULE_DESCRIPTION("ZyDAS ZD1301 demodulator driver"); 54247d65372SAntti Palosaari MODULE_LICENSE("GPL"); 543