1c942fddfSThomas 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 
zd1301_demod_wreg(struct zd1301_demod_dev * dev,u16 reg,u8 val)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 
zd1301_demod_rreg(struct zd1301_demod_dev * dev,u16 reg,u8 * val)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 
zd1301_demod_set_frontend(struct dvb_frontend * fe)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 
zd1301_demod_sleep(struct dvb_frontend * fe)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 
zd1301_demod_init(struct dvb_frontend * fe)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 
zd1301_demod_get_tune_settings(struct dvb_frontend * fe,struct dvb_frontend_tune_settings * settings)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 
zd1301_demod_read_status(struct dvb_frontend * fe,enum fe_status * status)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 
zd1301_demod_get_dvb_frontend(struct platform_device * pdev)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 
zd1301_demod_i2c_master_xfer(struct i2c_adapter * adapter,struct i2c_msg msg[],int num)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 
zd1301_demod_i2c_functionality(struct i2c_adapter * adapter)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 
zd1301_demod_get_i2c_adapter(struct platform_device * pdev)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 */
zd1301_demod_probe(struct platform_device * pdev)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 
zd1301_demod_remove(struct platform_device * pdev)518*f5b11862SUwe Kleine-König static void 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 
52847d65372SAntti Palosaari static struct platform_driver zd1301_demod_driver = {
52947d65372SAntti Palosaari 	.driver = {
53047d65372SAntti Palosaari 		.name                = "zd1301_demod",
53147d65372SAntti Palosaari 		.suppress_bind_attrs = true,
53247d65372SAntti Palosaari 	},
53347d65372SAntti Palosaari 	.probe          = zd1301_demod_probe,
534*f5b11862SUwe Kleine-König 	.remove_new     = zd1301_demod_remove,
53547d65372SAntti Palosaari };
53647d65372SAntti Palosaari module_platform_driver(zd1301_demod_driver);
53747d65372SAntti Palosaari 
53847d65372SAntti Palosaari MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
53947d65372SAntti Palosaari MODULE_DESCRIPTION("ZyDAS ZD1301 demodulator driver");
54047d65372SAntti Palosaari MODULE_LICENSE("GPL");
541