xref: /OK3568_Linux_fs/kernel/drivers/media/dvb-frontends/tda10071.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * NXP TDA10071 + Conexant CX24118A DVB-S/S2 demodulator + tuner driver
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Copyright (C) 2011 Antti Palosaari <crope@iki.fi>
6*4882a593Smuzhiyun  */
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun #include "tda10071_priv.h"
9*4882a593Smuzhiyun 
10*4882a593Smuzhiyun static const struct dvb_frontend_ops tda10071_ops;
11*4882a593Smuzhiyun 
12*4882a593Smuzhiyun /*
13*4882a593Smuzhiyun  * XXX: regmap_update_bits() does not fit our needs as it does not support
14*4882a593Smuzhiyun  * partially volatile registers. Also it performs register read even mask is as
15*4882a593Smuzhiyun  * wide as register value.
16*4882a593Smuzhiyun  */
17*4882a593Smuzhiyun /* write single register with mask */
tda10071_wr_reg_mask(struct tda10071_dev * dev,u8 reg,u8 val,u8 mask)18*4882a593Smuzhiyun static int tda10071_wr_reg_mask(struct tda10071_dev *dev,
19*4882a593Smuzhiyun 				u8 reg, u8 val, u8 mask)
20*4882a593Smuzhiyun {
21*4882a593Smuzhiyun 	int ret;
22*4882a593Smuzhiyun 	u8 tmp;
23*4882a593Smuzhiyun 
24*4882a593Smuzhiyun 	/* no need for read if whole reg is written */
25*4882a593Smuzhiyun 	if (mask != 0xff) {
26*4882a593Smuzhiyun 		ret = regmap_bulk_read(dev->regmap, reg, &tmp, 1);
27*4882a593Smuzhiyun 		if (ret)
28*4882a593Smuzhiyun 			return ret;
29*4882a593Smuzhiyun 
30*4882a593Smuzhiyun 		val &= mask;
31*4882a593Smuzhiyun 		tmp &= ~mask;
32*4882a593Smuzhiyun 		val |= tmp;
33*4882a593Smuzhiyun 	}
34*4882a593Smuzhiyun 
35*4882a593Smuzhiyun 	return regmap_bulk_write(dev->regmap, reg, &val, 1);
36*4882a593Smuzhiyun }
37*4882a593Smuzhiyun 
38*4882a593Smuzhiyun /* execute firmware command */
tda10071_cmd_execute(struct tda10071_dev * dev,struct tda10071_cmd * cmd)39*4882a593Smuzhiyun static int tda10071_cmd_execute(struct tda10071_dev *dev,
40*4882a593Smuzhiyun 	struct tda10071_cmd *cmd)
41*4882a593Smuzhiyun {
42*4882a593Smuzhiyun 	struct i2c_client *client = dev->client;
43*4882a593Smuzhiyun 	int ret, i;
44*4882a593Smuzhiyun 	unsigned int uitmp;
45*4882a593Smuzhiyun 
46*4882a593Smuzhiyun 	if (!dev->warm) {
47*4882a593Smuzhiyun 		ret = -EFAULT;
48*4882a593Smuzhiyun 		goto error;
49*4882a593Smuzhiyun 	}
50*4882a593Smuzhiyun 
51*4882a593Smuzhiyun 	mutex_lock(&dev->cmd_execute_mutex);
52*4882a593Smuzhiyun 
53*4882a593Smuzhiyun 	/* write cmd and args for firmware */
54*4882a593Smuzhiyun 	ret = regmap_bulk_write(dev->regmap, 0x00, cmd->args, cmd->len);
55*4882a593Smuzhiyun 	if (ret)
56*4882a593Smuzhiyun 		goto error_mutex_unlock;
57*4882a593Smuzhiyun 
58*4882a593Smuzhiyun 	/* start cmd execution */
59*4882a593Smuzhiyun 	ret = regmap_write(dev->regmap, 0x1f, 1);
60*4882a593Smuzhiyun 	if (ret)
61*4882a593Smuzhiyun 		goto error_mutex_unlock;
62*4882a593Smuzhiyun 
63*4882a593Smuzhiyun 	/* wait cmd execution terminate */
64*4882a593Smuzhiyun 	for (i = 1000, uitmp = 1; i && uitmp; i--) {
65*4882a593Smuzhiyun 		ret = regmap_read(dev->regmap, 0x1f, &uitmp);
66*4882a593Smuzhiyun 		if (ret)
67*4882a593Smuzhiyun 			goto error_mutex_unlock;
68*4882a593Smuzhiyun 
69*4882a593Smuzhiyun 		usleep_range(200, 5000);
70*4882a593Smuzhiyun 	}
71*4882a593Smuzhiyun 
72*4882a593Smuzhiyun 	mutex_unlock(&dev->cmd_execute_mutex);
73*4882a593Smuzhiyun 	dev_dbg(&client->dev, "loop=%d\n", i);
74*4882a593Smuzhiyun 
75*4882a593Smuzhiyun 	if (i == 0) {
76*4882a593Smuzhiyun 		ret = -ETIMEDOUT;
77*4882a593Smuzhiyun 		goto error;
78*4882a593Smuzhiyun 	}
79*4882a593Smuzhiyun 
80*4882a593Smuzhiyun 	return ret;
81*4882a593Smuzhiyun error_mutex_unlock:
82*4882a593Smuzhiyun 	mutex_unlock(&dev->cmd_execute_mutex);
83*4882a593Smuzhiyun error:
84*4882a593Smuzhiyun 	dev_dbg(&client->dev, "failed=%d\n", ret);
85*4882a593Smuzhiyun 	return ret;
86*4882a593Smuzhiyun }
87*4882a593Smuzhiyun 
tda10071_set_tone(struct dvb_frontend * fe,enum fe_sec_tone_mode fe_sec_tone_mode)88*4882a593Smuzhiyun static int tda10071_set_tone(struct dvb_frontend *fe,
89*4882a593Smuzhiyun 	enum fe_sec_tone_mode fe_sec_tone_mode)
90*4882a593Smuzhiyun {
91*4882a593Smuzhiyun 	struct tda10071_dev *dev = fe->demodulator_priv;
92*4882a593Smuzhiyun 	struct i2c_client *client = dev->client;
93*4882a593Smuzhiyun 	struct tda10071_cmd cmd;
94*4882a593Smuzhiyun 	int ret;
95*4882a593Smuzhiyun 	u8 tone;
96*4882a593Smuzhiyun 
97*4882a593Smuzhiyun 	if (!dev->warm) {
98*4882a593Smuzhiyun 		ret = -EFAULT;
99*4882a593Smuzhiyun 		goto error;
100*4882a593Smuzhiyun 	}
101*4882a593Smuzhiyun 
102*4882a593Smuzhiyun 	dev_dbg(&client->dev, "tone_mode=%d\n", fe_sec_tone_mode);
103*4882a593Smuzhiyun 
104*4882a593Smuzhiyun 	switch (fe_sec_tone_mode) {
105*4882a593Smuzhiyun 	case SEC_TONE_ON:
106*4882a593Smuzhiyun 		tone = 1;
107*4882a593Smuzhiyun 		break;
108*4882a593Smuzhiyun 	case SEC_TONE_OFF:
109*4882a593Smuzhiyun 		tone = 0;
110*4882a593Smuzhiyun 		break;
111*4882a593Smuzhiyun 	default:
112*4882a593Smuzhiyun 		dev_dbg(&client->dev, "invalid fe_sec_tone_mode\n");
113*4882a593Smuzhiyun 		ret = -EINVAL;
114*4882a593Smuzhiyun 		goto error;
115*4882a593Smuzhiyun 	}
116*4882a593Smuzhiyun 
117*4882a593Smuzhiyun 	cmd.args[0] = CMD_LNB_PCB_CONFIG;
118*4882a593Smuzhiyun 	cmd.args[1] = 0;
119*4882a593Smuzhiyun 	cmd.args[2] = 0x00;
120*4882a593Smuzhiyun 	cmd.args[3] = 0x00;
121*4882a593Smuzhiyun 	cmd.args[4] = tone;
122*4882a593Smuzhiyun 	cmd.len = 5;
123*4882a593Smuzhiyun 	ret = tda10071_cmd_execute(dev, &cmd);
124*4882a593Smuzhiyun 	if (ret)
125*4882a593Smuzhiyun 		goto error;
126*4882a593Smuzhiyun 
127*4882a593Smuzhiyun 	return ret;
128*4882a593Smuzhiyun error:
129*4882a593Smuzhiyun 	dev_dbg(&client->dev, "failed=%d\n", ret);
130*4882a593Smuzhiyun 	return ret;
131*4882a593Smuzhiyun }
132*4882a593Smuzhiyun 
tda10071_set_voltage(struct dvb_frontend * fe,enum fe_sec_voltage fe_sec_voltage)133*4882a593Smuzhiyun static int tda10071_set_voltage(struct dvb_frontend *fe,
134*4882a593Smuzhiyun 	enum fe_sec_voltage fe_sec_voltage)
135*4882a593Smuzhiyun {
136*4882a593Smuzhiyun 	struct tda10071_dev *dev = fe->demodulator_priv;
137*4882a593Smuzhiyun 	struct i2c_client *client = dev->client;
138*4882a593Smuzhiyun 	struct tda10071_cmd cmd;
139*4882a593Smuzhiyun 	int ret;
140*4882a593Smuzhiyun 	u8 voltage;
141*4882a593Smuzhiyun 
142*4882a593Smuzhiyun 	if (!dev->warm) {
143*4882a593Smuzhiyun 		ret = -EFAULT;
144*4882a593Smuzhiyun 		goto error;
145*4882a593Smuzhiyun 	}
146*4882a593Smuzhiyun 
147*4882a593Smuzhiyun 	dev_dbg(&client->dev, "voltage=%d\n", fe_sec_voltage);
148*4882a593Smuzhiyun 
149*4882a593Smuzhiyun 	switch (fe_sec_voltage) {
150*4882a593Smuzhiyun 	case SEC_VOLTAGE_13:
151*4882a593Smuzhiyun 		voltage = 0;
152*4882a593Smuzhiyun 		break;
153*4882a593Smuzhiyun 	case SEC_VOLTAGE_18:
154*4882a593Smuzhiyun 		voltage = 1;
155*4882a593Smuzhiyun 		break;
156*4882a593Smuzhiyun 	case SEC_VOLTAGE_OFF:
157*4882a593Smuzhiyun 		voltage = 0;
158*4882a593Smuzhiyun 		break;
159*4882a593Smuzhiyun 	default:
160*4882a593Smuzhiyun 		dev_dbg(&client->dev, "invalid fe_sec_voltage\n");
161*4882a593Smuzhiyun 		ret = -EINVAL;
162*4882a593Smuzhiyun 		goto error;
163*4882a593Smuzhiyun 	}
164*4882a593Smuzhiyun 
165*4882a593Smuzhiyun 	cmd.args[0] = CMD_LNB_SET_DC_LEVEL;
166*4882a593Smuzhiyun 	cmd.args[1] = 0;
167*4882a593Smuzhiyun 	cmd.args[2] = voltage;
168*4882a593Smuzhiyun 	cmd.len = 3;
169*4882a593Smuzhiyun 	ret = tda10071_cmd_execute(dev, &cmd);
170*4882a593Smuzhiyun 	if (ret)
171*4882a593Smuzhiyun 		goto error;
172*4882a593Smuzhiyun 
173*4882a593Smuzhiyun 	return ret;
174*4882a593Smuzhiyun error:
175*4882a593Smuzhiyun 	dev_dbg(&client->dev, "failed=%d\n", ret);
176*4882a593Smuzhiyun 	return ret;
177*4882a593Smuzhiyun }
178*4882a593Smuzhiyun 
tda10071_diseqc_send_master_cmd(struct dvb_frontend * fe,struct dvb_diseqc_master_cmd * diseqc_cmd)179*4882a593Smuzhiyun static int tda10071_diseqc_send_master_cmd(struct dvb_frontend *fe,
180*4882a593Smuzhiyun 	struct dvb_diseqc_master_cmd *diseqc_cmd)
181*4882a593Smuzhiyun {
182*4882a593Smuzhiyun 	struct tda10071_dev *dev = fe->demodulator_priv;
183*4882a593Smuzhiyun 	struct i2c_client *client = dev->client;
184*4882a593Smuzhiyun 	struct tda10071_cmd cmd;
185*4882a593Smuzhiyun 	int ret, i;
186*4882a593Smuzhiyun 	unsigned int uitmp;
187*4882a593Smuzhiyun 
188*4882a593Smuzhiyun 	if (!dev->warm) {
189*4882a593Smuzhiyun 		ret = -EFAULT;
190*4882a593Smuzhiyun 		goto error;
191*4882a593Smuzhiyun 	}
192*4882a593Smuzhiyun 
193*4882a593Smuzhiyun 	dev_dbg(&client->dev, "msg_len=%d\n", diseqc_cmd->msg_len);
194*4882a593Smuzhiyun 
195*4882a593Smuzhiyun 	if (diseqc_cmd->msg_len < 3 || diseqc_cmd->msg_len > 6) {
196*4882a593Smuzhiyun 		ret = -EINVAL;
197*4882a593Smuzhiyun 		goto error;
198*4882a593Smuzhiyun 	}
199*4882a593Smuzhiyun 
200*4882a593Smuzhiyun 	/* wait LNB TX */
201*4882a593Smuzhiyun 	for (i = 500, uitmp = 0; i && !uitmp; i--) {
202*4882a593Smuzhiyun 		ret = regmap_read(dev->regmap, 0x47, &uitmp);
203*4882a593Smuzhiyun 		if (ret)
204*4882a593Smuzhiyun 			goto error;
205*4882a593Smuzhiyun 		uitmp = (uitmp >> 0) & 1;
206*4882a593Smuzhiyun 		usleep_range(10000, 20000);
207*4882a593Smuzhiyun 	}
208*4882a593Smuzhiyun 
209*4882a593Smuzhiyun 	dev_dbg(&client->dev, "loop=%d\n", i);
210*4882a593Smuzhiyun 
211*4882a593Smuzhiyun 	if (i == 0) {
212*4882a593Smuzhiyun 		ret = -ETIMEDOUT;
213*4882a593Smuzhiyun 		goto error;
214*4882a593Smuzhiyun 	}
215*4882a593Smuzhiyun 
216*4882a593Smuzhiyun 	ret = regmap_update_bits(dev->regmap, 0x47, 0x01, 0x00);
217*4882a593Smuzhiyun 	if (ret)
218*4882a593Smuzhiyun 		goto error;
219*4882a593Smuzhiyun 
220*4882a593Smuzhiyun 	cmd.args[0] = CMD_LNB_SEND_DISEQC;
221*4882a593Smuzhiyun 	cmd.args[1] = 0;
222*4882a593Smuzhiyun 	cmd.args[2] = 0;
223*4882a593Smuzhiyun 	cmd.args[3] = 0;
224*4882a593Smuzhiyun 	cmd.args[4] = 2;
225*4882a593Smuzhiyun 	cmd.args[5] = 0;
226*4882a593Smuzhiyun 	cmd.args[6] = diseqc_cmd->msg_len;
227*4882a593Smuzhiyun 	memcpy(&cmd.args[7], diseqc_cmd->msg, diseqc_cmd->msg_len);
228*4882a593Smuzhiyun 	cmd.len = 7 + diseqc_cmd->msg_len;
229*4882a593Smuzhiyun 	ret = tda10071_cmd_execute(dev, &cmd);
230*4882a593Smuzhiyun 	if (ret)
231*4882a593Smuzhiyun 		goto error;
232*4882a593Smuzhiyun 
233*4882a593Smuzhiyun 	return ret;
234*4882a593Smuzhiyun error:
235*4882a593Smuzhiyun 	dev_dbg(&client->dev, "failed=%d\n", ret);
236*4882a593Smuzhiyun 	return ret;
237*4882a593Smuzhiyun }
238*4882a593Smuzhiyun 
tda10071_diseqc_recv_slave_reply(struct dvb_frontend * fe,struct dvb_diseqc_slave_reply * reply)239*4882a593Smuzhiyun static int tda10071_diseqc_recv_slave_reply(struct dvb_frontend *fe,
240*4882a593Smuzhiyun 	struct dvb_diseqc_slave_reply *reply)
241*4882a593Smuzhiyun {
242*4882a593Smuzhiyun 	struct tda10071_dev *dev = fe->demodulator_priv;
243*4882a593Smuzhiyun 	struct i2c_client *client = dev->client;
244*4882a593Smuzhiyun 	struct tda10071_cmd cmd;
245*4882a593Smuzhiyun 	int ret, i;
246*4882a593Smuzhiyun 	unsigned int uitmp;
247*4882a593Smuzhiyun 
248*4882a593Smuzhiyun 	if (!dev->warm) {
249*4882a593Smuzhiyun 		ret = -EFAULT;
250*4882a593Smuzhiyun 		goto error;
251*4882a593Smuzhiyun 	}
252*4882a593Smuzhiyun 
253*4882a593Smuzhiyun 	dev_dbg(&client->dev, "\n");
254*4882a593Smuzhiyun 
255*4882a593Smuzhiyun 	/* wait LNB RX */
256*4882a593Smuzhiyun 	for (i = 500, uitmp = 0; i && !uitmp; i--) {
257*4882a593Smuzhiyun 		ret = regmap_read(dev->regmap, 0x47, &uitmp);
258*4882a593Smuzhiyun 		if (ret)
259*4882a593Smuzhiyun 			goto error;
260*4882a593Smuzhiyun 		uitmp = (uitmp >> 1) & 1;
261*4882a593Smuzhiyun 		usleep_range(10000, 20000);
262*4882a593Smuzhiyun 	}
263*4882a593Smuzhiyun 
264*4882a593Smuzhiyun 	dev_dbg(&client->dev, "loop=%d\n", i);
265*4882a593Smuzhiyun 
266*4882a593Smuzhiyun 	if (i == 0) {
267*4882a593Smuzhiyun 		ret = -ETIMEDOUT;
268*4882a593Smuzhiyun 		goto error;
269*4882a593Smuzhiyun 	}
270*4882a593Smuzhiyun 
271*4882a593Smuzhiyun 	/* reply len */
272*4882a593Smuzhiyun 	ret = regmap_read(dev->regmap, 0x46, &uitmp);
273*4882a593Smuzhiyun 	if (ret)
274*4882a593Smuzhiyun 		goto error;
275*4882a593Smuzhiyun 
276*4882a593Smuzhiyun 	reply->msg_len = uitmp & 0x1f; /* [4:0] */
277*4882a593Smuzhiyun 	if (reply->msg_len > sizeof(reply->msg))
278*4882a593Smuzhiyun 		reply->msg_len = sizeof(reply->msg); /* truncate API max */
279*4882a593Smuzhiyun 
280*4882a593Smuzhiyun 	/* read reply */
281*4882a593Smuzhiyun 	cmd.args[0] = CMD_LNB_UPDATE_REPLY;
282*4882a593Smuzhiyun 	cmd.args[1] = 0;
283*4882a593Smuzhiyun 	cmd.len = 2;
284*4882a593Smuzhiyun 	ret = tda10071_cmd_execute(dev, &cmd);
285*4882a593Smuzhiyun 	if (ret)
286*4882a593Smuzhiyun 		goto error;
287*4882a593Smuzhiyun 
288*4882a593Smuzhiyun 	ret = regmap_bulk_read(dev->regmap, cmd.len, reply->msg,
289*4882a593Smuzhiyun 			       reply->msg_len);
290*4882a593Smuzhiyun 	if (ret)
291*4882a593Smuzhiyun 		goto error;
292*4882a593Smuzhiyun 
293*4882a593Smuzhiyun 	return ret;
294*4882a593Smuzhiyun error:
295*4882a593Smuzhiyun 	dev_dbg(&client->dev, "failed=%d\n", ret);
296*4882a593Smuzhiyun 	return ret;
297*4882a593Smuzhiyun }
298*4882a593Smuzhiyun 
tda10071_diseqc_send_burst(struct dvb_frontend * fe,enum fe_sec_mini_cmd fe_sec_mini_cmd)299*4882a593Smuzhiyun static int tda10071_diseqc_send_burst(struct dvb_frontend *fe,
300*4882a593Smuzhiyun 	enum fe_sec_mini_cmd fe_sec_mini_cmd)
301*4882a593Smuzhiyun {
302*4882a593Smuzhiyun 	struct tda10071_dev *dev = fe->demodulator_priv;
303*4882a593Smuzhiyun 	struct i2c_client *client = dev->client;
304*4882a593Smuzhiyun 	struct tda10071_cmd cmd;
305*4882a593Smuzhiyun 	int ret, i;
306*4882a593Smuzhiyun 	unsigned int uitmp;
307*4882a593Smuzhiyun 	u8 burst;
308*4882a593Smuzhiyun 
309*4882a593Smuzhiyun 	if (!dev->warm) {
310*4882a593Smuzhiyun 		ret = -EFAULT;
311*4882a593Smuzhiyun 		goto error;
312*4882a593Smuzhiyun 	}
313*4882a593Smuzhiyun 
314*4882a593Smuzhiyun 	dev_dbg(&client->dev, "fe_sec_mini_cmd=%d\n", fe_sec_mini_cmd);
315*4882a593Smuzhiyun 
316*4882a593Smuzhiyun 	switch (fe_sec_mini_cmd) {
317*4882a593Smuzhiyun 	case SEC_MINI_A:
318*4882a593Smuzhiyun 		burst = 0;
319*4882a593Smuzhiyun 		break;
320*4882a593Smuzhiyun 	case SEC_MINI_B:
321*4882a593Smuzhiyun 		burst = 1;
322*4882a593Smuzhiyun 		break;
323*4882a593Smuzhiyun 	default:
324*4882a593Smuzhiyun 		dev_dbg(&client->dev, "invalid fe_sec_mini_cmd\n");
325*4882a593Smuzhiyun 		ret = -EINVAL;
326*4882a593Smuzhiyun 		goto error;
327*4882a593Smuzhiyun 	}
328*4882a593Smuzhiyun 
329*4882a593Smuzhiyun 	/* wait LNB TX */
330*4882a593Smuzhiyun 	for (i = 500, uitmp = 0; i && !uitmp; i--) {
331*4882a593Smuzhiyun 		ret = regmap_read(dev->regmap, 0x47, &uitmp);
332*4882a593Smuzhiyun 		if (ret)
333*4882a593Smuzhiyun 			goto error;
334*4882a593Smuzhiyun 		uitmp = (uitmp >> 0) & 1;
335*4882a593Smuzhiyun 		usleep_range(10000, 20000);
336*4882a593Smuzhiyun 	}
337*4882a593Smuzhiyun 
338*4882a593Smuzhiyun 	dev_dbg(&client->dev, "loop=%d\n", i);
339*4882a593Smuzhiyun 
340*4882a593Smuzhiyun 	if (i == 0) {
341*4882a593Smuzhiyun 		ret = -ETIMEDOUT;
342*4882a593Smuzhiyun 		goto error;
343*4882a593Smuzhiyun 	}
344*4882a593Smuzhiyun 
345*4882a593Smuzhiyun 	ret = regmap_update_bits(dev->regmap, 0x47, 0x01, 0x00);
346*4882a593Smuzhiyun 	if (ret)
347*4882a593Smuzhiyun 		goto error;
348*4882a593Smuzhiyun 
349*4882a593Smuzhiyun 	cmd.args[0] = CMD_LNB_SEND_TONEBURST;
350*4882a593Smuzhiyun 	cmd.args[1] = 0;
351*4882a593Smuzhiyun 	cmd.args[2] = burst;
352*4882a593Smuzhiyun 	cmd.len = 3;
353*4882a593Smuzhiyun 	ret = tda10071_cmd_execute(dev, &cmd);
354*4882a593Smuzhiyun 	if (ret)
355*4882a593Smuzhiyun 		goto error;
356*4882a593Smuzhiyun 
357*4882a593Smuzhiyun 	return ret;
358*4882a593Smuzhiyun error:
359*4882a593Smuzhiyun 	dev_dbg(&client->dev, "failed=%d\n", ret);
360*4882a593Smuzhiyun 	return ret;
361*4882a593Smuzhiyun }
362*4882a593Smuzhiyun 
tda10071_read_status(struct dvb_frontend * fe,enum fe_status * status)363*4882a593Smuzhiyun static int tda10071_read_status(struct dvb_frontend *fe, enum fe_status *status)
364*4882a593Smuzhiyun {
365*4882a593Smuzhiyun 	struct tda10071_dev *dev = fe->demodulator_priv;
366*4882a593Smuzhiyun 	struct i2c_client *client = dev->client;
367*4882a593Smuzhiyun 	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
368*4882a593Smuzhiyun 	struct tda10071_cmd cmd;
369*4882a593Smuzhiyun 	int ret;
370*4882a593Smuzhiyun 	unsigned int uitmp;
371*4882a593Smuzhiyun 	u8 buf[8];
372*4882a593Smuzhiyun 
373*4882a593Smuzhiyun 	*status = 0;
374*4882a593Smuzhiyun 
375*4882a593Smuzhiyun 	if (!dev->warm) {
376*4882a593Smuzhiyun 		ret = 0;
377*4882a593Smuzhiyun 		goto error;
378*4882a593Smuzhiyun 	}
379*4882a593Smuzhiyun 
380*4882a593Smuzhiyun 	ret = regmap_read(dev->regmap, 0x39, &uitmp);
381*4882a593Smuzhiyun 	if (ret)
382*4882a593Smuzhiyun 		goto error;
383*4882a593Smuzhiyun 
384*4882a593Smuzhiyun 	/* 0x39[0] tuner PLL */
385*4882a593Smuzhiyun 	if (uitmp & 0x02) /* demod PLL */
386*4882a593Smuzhiyun 		*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER;
387*4882a593Smuzhiyun 	if (uitmp & 0x04) /* viterbi or LDPC*/
388*4882a593Smuzhiyun 		*status |= FE_HAS_VITERBI;
389*4882a593Smuzhiyun 	if (uitmp & 0x08) /* RS or BCH */
390*4882a593Smuzhiyun 		*status |= FE_HAS_SYNC | FE_HAS_LOCK;
391*4882a593Smuzhiyun 
392*4882a593Smuzhiyun 	dev->fe_status = *status;
393*4882a593Smuzhiyun 
394*4882a593Smuzhiyun 	/* signal strength */
395*4882a593Smuzhiyun 	if (dev->fe_status & FE_HAS_SIGNAL) {
396*4882a593Smuzhiyun 		cmd.args[0] = CMD_GET_AGCACC;
397*4882a593Smuzhiyun 		cmd.args[1] = 0;
398*4882a593Smuzhiyun 		cmd.len = 2;
399*4882a593Smuzhiyun 		ret = tda10071_cmd_execute(dev, &cmd);
400*4882a593Smuzhiyun 		if (ret)
401*4882a593Smuzhiyun 			goto error;
402*4882a593Smuzhiyun 
403*4882a593Smuzhiyun 		/* input power estimate dBm */
404*4882a593Smuzhiyun 		ret = regmap_read(dev->regmap, 0x50, &uitmp);
405*4882a593Smuzhiyun 		if (ret)
406*4882a593Smuzhiyun 			goto error;
407*4882a593Smuzhiyun 
408*4882a593Smuzhiyun 		c->strength.stat[0].scale = FE_SCALE_DECIBEL;
409*4882a593Smuzhiyun 		c->strength.stat[0].svalue = (int) (uitmp - 256) * 1000;
410*4882a593Smuzhiyun 	} else {
411*4882a593Smuzhiyun 		c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
412*4882a593Smuzhiyun 	}
413*4882a593Smuzhiyun 
414*4882a593Smuzhiyun 	/* CNR */
415*4882a593Smuzhiyun 	if (dev->fe_status & FE_HAS_VITERBI) {
416*4882a593Smuzhiyun 		/* Es/No */
417*4882a593Smuzhiyun 		ret = regmap_bulk_read(dev->regmap, 0x3a, buf, 2);
418*4882a593Smuzhiyun 		if (ret)
419*4882a593Smuzhiyun 			goto error;
420*4882a593Smuzhiyun 
421*4882a593Smuzhiyun 		c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
422*4882a593Smuzhiyun 		c->cnr.stat[0].svalue = (buf[0] << 8 | buf[1] << 0) * 100;
423*4882a593Smuzhiyun 	} else {
424*4882a593Smuzhiyun 		c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
425*4882a593Smuzhiyun 	}
426*4882a593Smuzhiyun 
427*4882a593Smuzhiyun 	/* UCB/PER/BER */
428*4882a593Smuzhiyun 	if (dev->fe_status & FE_HAS_LOCK) {
429*4882a593Smuzhiyun 		/* TODO: report total bits/packets */
430*4882a593Smuzhiyun 		u8 delivery_system, reg, len;
431*4882a593Smuzhiyun 
432*4882a593Smuzhiyun 		switch (dev->delivery_system) {
433*4882a593Smuzhiyun 		case SYS_DVBS:
434*4882a593Smuzhiyun 			reg = 0x4c;
435*4882a593Smuzhiyun 			len = 8;
436*4882a593Smuzhiyun 			delivery_system = 1;
437*4882a593Smuzhiyun 			break;
438*4882a593Smuzhiyun 		case SYS_DVBS2:
439*4882a593Smuzhiyun 			reg = 0x4d;
440*4882a593Smuzhiyun 			len = 4;
441*4882a593Smuzhiyun 			delivery_system = 0;
442*4882a593Smuzhiyun 			break;
443*4882a593Smuzhiyun 		default:
444*4882a593Smuzhiyun 			ret = -EINVAL;
445*4882a593Smuzhiyun 			goto error;
446*4882a593Smuzhiyun 		}
447*4882a593Smuzhiyun 
448*4882a593Smuzhiyun 		ret = regmap_read(dev->regmap, reg, &uitmp);
449*4882a593Smuzhiyun 		if (ret)
450*4882a593Smuzhiyun 			goto error;
451*4882a593Smuzhiyun 
452*4882a593Smuzhiyun 		if (dev->meas_count == uitmp) {
453*4882a593Smuzhiyun 			dev_dbg(&client->dev, "meas not ready=%02x\n", uitmp);
454*4882a593Smuzhiyun 			ret = 0;
455*4882a593Smuzhiyun 			goto error;
456*4882a593Smuzhiyun 		} else {
457*4882a593Smuzhiyun 			dev->meas_count = uitmp;
458*4882a593Smuzhiyun 		}
459*4882a593Smuzhiyun 
460*4882a593Smuzhiyun 		cmd.args[0] = CMD_BER_UPDATE_COUNTERS;
461*4882a593Smuzhiyun 		cmd.args[1] = 0;
462*4882a593Smuzhiyun 		cmd.args[2] = delivery_system;
463*4882a593Smuzhiyun 		cmd.len = 3;
464*4882a593Smuzhiyun 		ret = tda10071_cmd_execute(dev, &cmd);
465*4882a593Smuzhiyun 		if (ret)
466*4882a593Smuzhiyun 			goto error;
467*4882a593Smuzhiyun 
468*4882a593Smuzhiyun 		ret = regmap_bulk_read(dev->regmap, cmd.len, buf, len);
469*4882a593Smuzhiyun 		if (ret)
470*4882a593Smuzhiyun 			goto error;
471*4882a593Smuzhiyun 
472*4882a593Smuzhiyun 		if (dev->delivery_system == SYS_DVBS) {
473*4882a593Smuzhiyun 			u32 bit_error = buf[0] << 24 | buf[1] << 16 |
474*4882a593Smuzhiyun 					buf[2] << 8 | buf[3] << 0;
475*4882a593Smuzhiyun 
476*4882a593Smuzhiyun 			dev->dvbv3_ber = bit_error;
477*4882a593Smuzhiyun 			dev->post_bit_error += bit_error;
478*4882a593Smuzhiyun 			c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER;
479*4882a593Smuzhiyun 			c->post_bit_error.stat[0].uvalue = dev->post_bit_error;
480*4882a593Smuzhiyun 			dev->block_error += buf[4] << 8 | buf[5] << 0;
481*4882a593Smuzhiyun 			c->block_error.stat[0].scale = FE_SCALE_COUNTER;
482*4882a593Smuzhiyun 			c->block_error.stat[0].uvalue = dev->block_error;
483*4882a593Smuzhiyun 		} else {
484*4882a593Smuzhiyun 			dev->dvbv3_ber = buf[0] << 8 | buf[1] << 0;
485*4882a593Smuzhiyun 			dev->post_bit_error += buf[0] << 8 | buf[1] << 0;
486*4882a593Smuzhiyun 			c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER;
487*4882a593Smuzhiyun 			c->post_bit_error.stat[0].uvalue = dev->post_bit_error;
488*4882a593Smuzhiyun 			c->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
489*4882a593Smuzhiyun 		}
490*4882a593Smuzhiyun 	} else {
491*4882a593Smuzhiyun 		c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
492*4882a593Smuzhiyun 		c->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
493*4882a593Smuzhiyun 	}
494*4882a593Smuzhiyun 
495*4882a593Smuzhiyun 	return ret;
496*4882a593Smuzhiyun error:
497*4882a593Smuzhiyun 	dev_dbg(&client->dev, "failed=%d\n", ret);
498*4882a593Smuzhiyun 	return ret;
499*4882a593Smuzhiyun }
500*4882a593Smuzhiyun 
tda10071_read_snr(struct dvb_frontend * fe,u16 * snr)501*4882a593Smuzhiyun static int tda10071_read_snr(struct dvb_frontend *fe, u16 *snr)
502*4882a593Smuzhiyun {
503*4882a593Smuzhiyun 	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
504*4882a593Smuzhiyun 
505*4882a593Smuzhiyun 	if (c->cnr.stat[0].scale == FE_SCALE_DECIBEL)
506*4882a593Smuzhiyun 		*snr = div_s64(c->cnr.stat[0].svalue, 100);
507*4882a593Smuzhiyun 	else
508*4882a593Smuzhiyun 		*snr = 0;
509*4882a593Smuzhiyun 	return 0;
510*4882a593Smuzhiyun }
511*4882a593Smuzhiyun 
tda10071_read_signal_strength(struct dvb_frontend * fe,u16 * strength)512*4882a593Smuzhiyun static int tda10071_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
513*4882a593Smuzhiyun {
514*4882a593Smuzhiyun 	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
515*4882a593Smuzhiyun 	unsigned int uitmp;
516*4882a593Smuzhiyun 
517*4882a593Smuzhiyun 	if (c->strength.stat[0].scale == FE_SCALE_DECIBEL) {
518*4882a593Smuzhiyun 		uitmp = div_s64(c->strength.stat[0].svalue, 1000) + 256;
519*4882a593Smuzhiyun 		uitmp = clamp(uitmp, 181U, 236U); /* -75dBm - -20dBm */
520*4882a593Smuzhiyun 		/* scale value to 0x0000-0xffff */
521*4882a593Smuzhiyun 		*strength = (uitmp-181) * 0xffff / (236-181);
522*4882a593Smuzhiyun 	} else {
523*4882a593Smuzhiyun 		*strength = 0;
524*4882a593Smuzhiyun 	}
525*4882a593Smuzhiyun 	return 0;
526*4882a593Smuzhiyun }
527*4882a593Smuzhiyun 
tda10071_read_ber(struct dvb_frontend * fe,u32 * ber)528*4882a593Smuzhiyun static int tda10071_read_ber(struct dvb_frontend *fe, u32 *ber)
529*4882a593Smuzhiyun {
530*4882a593Smuzhiyun 	struct tda10071_dev *dev = fe->demodulator_priv;
531*4882a593Smuzhiyun 
532*4882a593Smuzhiyun 	*ber = dev->dvbv3_ber;
533*4882a593Smuzhiyun 	return 0;
534*4882a593Smuzhiyun }
535*4882a593Smuzhiyun 
tda10071_read_ucblocks(struct dvb_frontend * fe,u32 * ucblocks)536*4882a593Smuzhiyun static int tda10071_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
537*4882a593Smuzhiyun {
538*4882a593Smuzhiyun 	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
539*4882a593Smuzhiyun 
540*4882a593Smuzhiyun 	if (c->block_error.stat[0].scale == FE_SCALE_COUNTER)
541*4882a593Smuzhiyun 		*ucblocks = c->block_error.stat[0].uvalue;
542*4882a593Smuzhiyun 	else
543*4882a593Smuzhiyun 		*ucblocks = 0;
544*4882a593Smuzhiyun 	return 0;
545*4882a593Smuzhiyun }
546*4882a593Smuzhiyun 
tda10071_set_frontend(struct dvb_frontend * fe)547*4882a593Smuzhiyun static int tda10071_set_frontend(struct dvb_frontend *fe)
548*4882a593Smuzhiyun {
549*4882a593Smuzhiyun 	struct tda10071_dev *dev = fe->demodulator_priv;
550*4882a593Smuzhiyun 	struct i2c_client *client = dev->client;
551*4882a593Smuzhiyun 	struct tda10071_cmd cmd;
552*4882a593Smuzhiyun 	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
553*4882a593Smuzhiyun 	int ret, i;
554*4882a593Smuzhiyun 	u8 mode, rolloff, pilot, inversion, div;
555*4882a593Smuzhiyun 	enum fe_modulation modulation;
556*4882a593Smuzhiyun 
557*4882a593Smuzhiyun 	dev_dbg(&client->dev,
558*4882a593Smuzhiyun 		"delivery_system=%d modulation=%d frequency=%u symbol_rate=%d inversion=%d pilot=%d rolloff=%d\n",
559*4882a593Smuzhiyun 		c->delivery_system, c->modulation, c->frequency, c->symbol_rate,
560*4882a593Smuzhiyun 		c->inversion, c->pilot, c->rolloff);
561*4882a593Smuzhiyun 
562*4882a593Smuzhiyun 	dev->delivery_system = SYS_UNDEFINED;
563*4882a593Smuzhiyun 
564*4882a593Smuzhiyun 	if (!dev->warm) {
565*4882a593Smuzhiyun 		ret = -EFAULT;
566*4882a593Smuzhiyun 		goto error;
567*4882a593Smuzhiyun 	}
568*4882a593Smuzhiyun 
569*4882a593Smuzhiyun 	switch (c->inversion) {
570*4882a593Smuzhiyun 	case INVERSION_OFF:
571*4882a593Smuzhiyun 		inversion = 1;
572*4882a593Smuzhiyun 		break;
573*4882a593Smuzhiyun 	case INVERSION_ON:
574*4882a593Smuzhiyun 		inversion = 0;
575*4882a593Smuzhiyun 		break;
576*4882a593Smuzhiyun 	case INVERSION_AUTO:
577*4882a593Smuzhiyun 		/* 2 = auto; try first on then off
578*4882a593Smuzhiyun 		 * 3 = auto; try first off then on */
579*4882a593Smuzhiyun 		inversion = 3;
580*4882a593Smuzhiyun 		break;
581*4882a593Smuzhiyun 	default:
582*4882a593Smuzhiyun 		dev_dbg(&client->dev, "invalid inversion\n");
583*4882a593Smuzhiyun 		ret = -EINVAL;
584*4882a593Smuzhiyun 		goto error;
585*4882a593Smuzhiyun 	}
586*4882a593Smuzhiyun 
587*4882a593Smuzhiyun 	switch (c->delivery_system) {
588*4882a593Smuzhiyun 	case SYS_DVBS:
589*4882a593Smuzhiyun 		modulation = QPSK;
590*4882a593Smuzhiyun 		rolloff = 0;
591*4882a593Smuzhiyun 		pilot = 2;
592*4882a593Smuzhiyun 		break;
593*4882a593Smuzhiyun 	case SYS_DVBS2:
594*4882a593Smuzhiyun 		modulation = c->modulation;
595*4882a593Smuzhiyun 
596*4882a593Smuzhiyun 		switch (c->rolloff) {
597*4882a593Smuzhiyun 		case ROLLOFF_20:
598*4882a593Smuzhiyun 			rolloff = 2;
599*4882a593Smuzhiyun 			break;
600*4882a593Smuzhiyun 		case ROLLOFF_25:
601*4882a593Smuzhiyun 			rolloff = 1;
602*4882a593Smuzhiyun 			break;
603*4882a593Smuzhiyun 		case ROLLOFF_35:
604*4882a593Smuzhiyun 			rolloff = 0;
605*4882a593Smuzhiyun 			break;
606*4882a593Smuzhiyun 		case ROLLOFF_AUTO:
607*4882a593Smuzhiyun 		default:
608*4882a593Smuzhiyun 			dev_dbg(&client->dev, "invalid rolloff\n");
609*4882a593Smuzhiyun 			ret = -EINVAL;
610*4882a593Smuzhiyun 			goto error;
611*4882a593Smuzhiyun 		}
612*4882a593Smuzhiyun 
613*4882a593Smuzhiyun 		switch (c->pilot) {
614*4882a593Smuzhiyun 		case PILOT_OFF:
615*4882a593Smuzhiyun 			pilot = 0;
616*4882a593Smuzhiyun 			break;
617*4882a593Smuzhiyun 		case PILOT_ON:
618*4882a593Smuzhiyun 			pilot = 1;
619*4882a593Smuzhiyun 			break;
620*4882a593Smuzhiyun 		case PILOT_AUTO:
621*4882a593Smuzhiyun 			pilot = 2;
622*4882a593Smuzhiyun 			break;
623*4882a593Smuzhiyun 		default:
624*4882a593Smuzhiyun 			dev_dbg(&client->dev, "invalid pilot\n");
625*4882a593Smuzhiyun 			ret = -EINVAL;
626*4882a593Smuzhiyun 			goto error;
627*4882a593Smuzhiyun 		}
628*4882a593Smuzhiyun 		break;
629*4882a593Smuzhiyun 	default:
630*4882a593Smuzhiyun 		dev_dbg(&client->dev, "invalid delivery_system\n");
631*4882a593Smuzhiyun 		ret = -EINVAL;
632*4882a593Smuzhiyun 		goto error;
633*4882a593Smuzhiyun 	}
634*4882a593Smuzhiyun 
635*4882a593Smuzhiyun 	for (i = 0, mode = 0xff; i < ARRAY_SIZE(TDA10071_MODCOD); i++) {
636*4882a593Smuzhiyun 		if (c->delivery_system == TDA10071_MODCOD[i].delivery_system &&
637*4882a593Smuzhiyun 			modulation == TDA10071_MODCOD[i].modulation &&
638*4882a593Smuzhiyun 			c->fec_inner == TDA10071_MODCOD[i].fec) {
639*4882a593Smuzhiyun 			mode = TDA10071_MODCOD[i].val;
640*4882a593Smuzhiyun 			dev_dbg(&client->dev, "mode found=%02x\n", mode);
641*4882a593Smuzhiyun 			break;
642*4882a593Smuzhiyun 		}
643*4882a593Smuzhiyun 	}
644*4882a593Smuzhiyun 
645*4882a593Smuzhiyun 	if (mode == 0xff) {
646*4882a593Smuzhiyun 		dev_dbg(&client->dev, "invalid parameter combination\n");
647*4882a593Smuzhiyun 		ret = -EINVAL;
648*4882a593Smuzhiyun 		goto error;
649*4882a593Smuzhiyun 	}
650*4882a593Smuzhiyun 
651*4882a593Smuzhiyun 	if (c->symbol_rate <= 5000000)
652*4882a593Smuzhiyun 		div = 14;
653*4882a593Smuzhiyun 	else
654*4882a593Smuzhiyun 		div = 4;
655*4882a593Smuzhiyun 
656*4882a593Smuzhiyun 	ret = regmap_write(dev->regmap, 0x81, div);
657*4882a593Smuzhiyun 	if (ret)
658*4882a593Smuzhiyun 		goto error;
659*4882a593Smuzhiyun 
660*4882a593Smuzhiyun 	ret = regmap_write(dev->regmap, 0xe3, div);
661*4882a593Smuzhiyun 	if (ret)
662*4882a593Smuzhiyun 		goto error;
663*4882a593Smuzhiyun 
664*4882a593Smuzhiyun 	cmd.args[0] = CMD_CHANGE_CHANNEL;
665*4882a593Smuzhiyun 	cmd.args[1] = 0;
666*4882a593Smuzhiyun 	cmd.args[2] = mode;
667*4882a593Smuzhiyun 	cmd.args[3] = (c->frequency >> 16) & 0xff;
668*4882a593Smuzhiyun 	cmd.args[4] = (c->frequency >>  8) & 0xff;
669*4882a593Smuzhiyun 	cmd.args[5] = (c->frequency >>  0) & 0xff;
670*4882a593Smuzhiyun 	cmd.args[6] = ((c->symbol_rate / 1000) >> 8) & 0xff;
671*4882a593Smuzhiyun 	cmd.args[7] = ((c->symbol_rate / 1000) >> 0) & 0xff;
672*4882a593Smuzhiyun 	cmd.args[8] = ((tda10071_ops.info.frequency_tolerance_hz / 1000) >> 8) & 0xff;
673*4882a593Smuzhiyun 	cmd.args[9] = ((tda10071_ops.info.frequency_tolerance_hz / 1000) >> 0) & 0xff;
674*4882a593Smuzhiyun 	cmd.args[10] = rolloff;
675*4882a593Smuzhiyun 	cmd.args[11] = inversion;
676*4882a593Smuzhiyun 	cmd.args[12] = pilot;
677*4882a593Smuzhiyun 	cmd.args[13] = 0x00;
678*4882a593Smuzhiyun 	cmd.args[14] = 0x00;
679*4882a593Smuzhiyun 	cmd.len = 15;
680*4882a593Smuzhiyun 	ret = tda10071_cmd_execute(dev, &cmd);
681*4882a593Smuzhiyun 	if (ret)
682*4882a593Smuzhiyun 		goto error;
683*4882a593Smuzhiyun 
684*4882a593Smuzhiyun 	dev->delivery_system = c->delivery_system;
685*4882a593Smuzhiyun 
686*4882a593Smuzhiyun 	return ret;
687*4882a593Smuzhiyun error:
688*4882a593Smuzhiyun 	dev_dbg(&client->dev, "failed=%d\n", ret);
689*4882a593Smuzhiyun 	return ret;
690*4882a593Smuzhiyun }
691*4882a593Smuzhiyun 
tda10071_get_frontend(struct dvb_frontend * fe,struct dtv_frontend_properties * c)692*4882a593Smuzhiyun static int tda10071_get_frontend(struct dvb_frontend *fe,
693*4882a593Smuzhiyun 				 struct dtv_frontend_properties *c)
694*4882a593Smuzhiyun {
695*4882a593Smuzhiyun 	struct tda10071_dev *dev = fe->demodulator_priv;
696*4882a593Smuzhiyun 	struct i2c_client *client = dev->client;
697*4882a593Smuzhiyun 	int ret, i;
698*4882a593Smuzhiyun 	u8 buf[5], tmp;
699*4882a593Smuzhiyun 
700*4882a593Smuzhiyun 	if (!dev->warm || !(dev->fe_status & FE_HAS_LOCK)) {
701*4882a593Smuzhiyun 		ret = 0;
702*4882a593Smuzhiyun 		goto error;
703*4882a593Smuzhiyun 	}
704*4882a593Smuzhiyun 
705*4882a593Smuzhiyun 	ret = regmap_bulk_read(dev->regmap, 0x30, buf, 5);
706*4882a593Smuzhiyun 	if (ret)
707*4882a593Smuzhiyun 		goto error;
708*4882a593Smuzhiyun 
709*4882a593Smuzhiyun 	tmp = buf[0] & 0x3f;
710*4882a593Smuzhiyun 	for (i = 0; i < ARRAY_SIZE(TDA10071_MODCOD); i++) {
711*4882a593Smuzhiyun 		if (tmp == TDA10071_MODCOD[i].val) {
712*4882a593Smuzhiyun 			c->modulation = TDA10071_MODCOD[i].modulation;
713*4882a593Smuzhiyun 			c->fec_inner = TDA10071_MODCOD[i].fec;
714*4882a593Smuzhiyun 			c->delivery_system = TDA10071_MODCOD[i].delivery_system;
715*4882a593Smuzhiyun 		}
716*4882a593Smuzhiyun 	}
717*4882a593Smuzhiyun 
718*4882a593Smuzhiyun 	switch ((buf[1] >> 0) & 0x01) {
719*4882a593Smuzhiyun 	case 0:
720*4882a593Smuzhiyun 		c->inversion = INVERSION_ON;
721*4882a593Smuzhiyun 		break;
722*4882a593Smuzhiyun 	case 1:
723*4882a593Smuzhiyun 		c->inversion = INVERSION_OFF;
724*4882a593Smuzhiyun 		break;
725*4882a593Smuzhiyun 	}
726*4882a593Smuzhiyun 
727*4882a593Smuzhiyun 	switch ((buf[1] >> 7) & 0x01) {
728*4882a593Smuzhiyun 	case 0:
729*4882a593Smuzhiyun 		c->pilot = PILOT_OFF;
730*4882a593Smuzhiyun 		break;
731*4882a593Smuzhiyun 	case 1:
732*4882a593Smuzhiyun 		c->pilot = PILOT_ON;
733*4882a593Smuzhiyun 		break;
734*4882a593Smuzhiyun 	}
735*4882a593Smuzhiyun 
736*4882a593Smuzhiyun 	c->frequency = (buf[2] << 16) | (buf[3] << 8) | (buf[4] << 0);
737*4882a593Smuzhiyun 
738*4882a593Smuzhiyun 	ret = regmap_bulk_read(dev->regmap, 0x52, buf, 3);
739*4882a593Smuzhiyun 	if (ret)
740*4882a593Smuzhiyun 		goto error;
741*4882a593Smuzhiyun 
742*4882a593Smuzhiyun 	c->symbol_rate = ((buf[0] << 16) | (buf[1] << 8) | (buf[2] << 0)) * 1000;
743*4882a593Smuzhiyun 
744*4882a593Smuzhiyun 	return ret;
745*4882a593Smuzhiyun error:
746*4882a593Smuzhiyun 	dev_dbg(&client->dev, "failed=%d\n", ret);
747*4882a593Smuzhiyun 	return ret;
748*4882a593Smuzhiyun }
749*4882a593Smuzhiyun 
tda10071_init(struct dvb_frontend * fe)750*4882a593Smuzhiyun static int tda10071_init(struct dvb_frontend *fe)
751*4882a593Smuzhiyun {
752*4882a593Smuzhiyun 	struct tda10071_dev *dev = fe->demodulator_priv;
753*4882a593Smuzhiyun 	struct i2c_client *client = dev->client;
754*4882a593Smuzhiyun 	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
755*4882a593Smuzhiyun 	struct tda10071_cmd cmd;
756*4882a593Smuzhiyun 	int ret, i, len, remaining, fw_size;
757*4882a593Smuzhiyun 	unsigned int uitmp;
758*4882a593Smuzhiyun 	const struct firmware *fw;
759*4882a593Smuzhiyun 	u8 *fw_file = TDA10071_FIRMWARE;
760*4882a593Smuzhiyun 	u8 tmp, buf[4];
761*4882a593Smuzhiyun 	struct tda10071_reg_val_mask tab[] = {
762*4882a593Smuzhiyun 		{ 0xcd, 0x00, 0x07 },
763*4882a593Smuzhiyun 		{ 0x80, 0x00, 0x02 },
764*4882a593Smuzhiyun 		{ 0xcd, 0x00, 0xc0 },
765*4882a593Smuzhiyun 		{ 0xce, 0x00, 0x1b },
766*4882a593Smuzhiyun 		{ 0x9d, 0x00, 0x01 },
767*4882a593Smuzhiyun 		{ 0x9d, 0x00, 0x02 },
768*4882a593Smuzhiyun 		{ 0x9e, 0x00, 0x01 },
769*4882a593Smuzhiyun 		{ 0x87, 0x00, 0x80 },
770*4882a593Smuzhiyun 		{ 0xce, 0x00, 0x08 },
771*4882a593Smuzhiyun 		{ 0xce, 0x00, 0x10 },
772*4882a593Smuzhiyun 	};
773*4882a593Smuzhiyun 	struct tda10071_reg_val_mask tab2[] = {
774*4882a593Smuzhiyun 		{ 0xf1, 0x70, 0xff },
775*4882a593Smuzhiyun 		{ 0x88, dev->pll_multiplier, 0x3f },
776*4882a593Smuzhiyun 		{ 0x89, 0x00, 0x10 },
777*4882a593Smuzhiyun 		{ 0x89, 0x10, 0x10 },
778*4882a593Smuzhiyun 		{ 0xc0, 0x01, 0x01 },
779*4882a593Smuzhiyun 		{ 0xc0, 0x00, 0x01 },
780*4882a593Smuzhiyun 		{ 0xe0, 0xff, 0xff },
781*4882a593Smuzhiyun 		{ 0xe0, 0x00, 0xff },
782*4882a593Smuzhiyun 		{ 0x96, 0x1e, 0x7e },
783*4882a593Smuzhiyun 		{ 0x8b, 0x08, 0x08 },
784*4882a593Smuzhiyun 		{ 0x8b, 0x00, 0x08 },
785*4882a593Smuzhiyun 		{ 0x8f, 0x1a, 0x7e },
786*4882a593Smuzhiyun 		{ 0x8c, 0x68, 0xff },
787*4882a593Smuzhiyun 		{ 0x8d, 0x08, 0xff },
788*4882a593Smuzhiyun 		{ 0x8e, 0x4c, 0xff },
789*4882a593Smuzhiyun 		{ 0x8f, 0x01, 0x01 },
790*4882a593Smuzhiyun 		{ 0x8b, 0x04, 0x04 },
791*4882a593Smuzhiyun 		{ 0x8b, 0x00, 0x04 },
792*4882a593Smuzhiyun 		{ 0x87, 0x05, 0x07 },
793*4882a593Smuzhiyun 		{ 0x80, 0x00, 0x20 },
794*4882a593Smuzhiyun 		{ 0xc8, 0x01, 0xff },
795*4882a593Smuzhiyun 		{ 0xb4, 0x47, 0xff },
796*4882a593Smuzhiyun 		{ 0xb5, 0x9c, 0xff },
797*4882a593Smuzhiyun 		{ 0xb6, 0x7d, 0xff },
798*4882a593Smuzhiyun 		{ 0xba, 0x00, 0x03 },
799*4882a593Smuzhiyun 		{ 0xb7, 0x47, 0xff },
800*4882a593Smuzhiyun 		{ 0xb8, 0x9c, 0xff },
801*4882a593Smuzhiyun 		{ 0xb9, 0x7d, 0xff },
802*4882a593Smuzhiyun 		{ 0xba, 0x00, 0x0c },
803*4882a593Smuzhiyun 		{ 0xc8, 0x00, 0xff },
804*4882a593Smuzhiyun 		{ 0xcd, 0x00, 0x04 },
805*4882a593Smuzhiyun 		{ 0xcd, 0x00, 0x20 },
806*4882a593Smuzhiyun 		{ 0xe8, 0x02, 0xff },
807*4882a593Smuzhiyun 		{ 0xcf, 0x20, 0xff },
808*4882a593Smuzhiyun 		{ 0x9b, 0xd7, 0xff },
809*4882a593Smuzhiyun 		{ 0x9a, 0x01, 0x03 },
810*4882a593Smuzhiyun 		{ 0xa8, 0x05, 0x0f },
811*4882a593Smuzhiyun 		{ 0xa8, 0x65, 0xf0 },
812*4882a593Smuzhiyun 		{ 0xa6, 0xa0, 0xf0 },
813*4882a593Smuzhiyun 		{ 0x9d, 0x50, 0xfc },
814*4882a593Smuzhiyun 		{ 0x9e, 0x20, 0xe0 },
815*4882a593Smuzhiyun 		{ 0xa3, 0x1c, 0x7c },
816*4882a593Smuzhiyun 		{ 0xd5, 0x03, 0x03 },
817*4882a593Smuzhiyun 	};
818*4882a593Smuzhiyun 
819*4882a593Smuzhiyun 	if (dev->warm) {
820*4882a593Smuzhiyun 		/* warm state - wake up device from sleep */
821*4882a593Smuzhiyun 
822*4882a593Smuzhiyun 		for (i = 0; i < ARRAY_SIZE(tab); i++) {
823*4882a593Smuzhiyun 			ret = tda10071_wr_reg_mask(dev, tab[i].reg,
824*4882a593Smuzhiyun 				tab[i].val, tab[i].mask);
825*4882a593Smuzhiyun 			if (ret)
826*4882a593Smuzhiyun 				goto error;
827*4882a593Smuzhiyun 		}
828*4882a593Smuzhiyun 
829*4882a593Smuzhiyun 		cmd.args[0] = CMD_SET_SLEEP_MODE;
830*4882a593Smuzhiyun 		cmd.args[1] = 0;
831*4882a593Smuzhiyun 		cmd.args[2] = 0;
832*4882a593Smuzhiyun 		cmd.len = 3;
833*4882a593Smuzhiyun 		ret = tda10071_cmd_execute(dev, &cmd);
834*4882a593Smuzhiyun 		if (ret)
835*4882a593Smuzhiyun 			goto error;
836*4882a593Smuzhiyun 	} else {
837*4882a593Smuzhiyun 		/* cold state - try to download firmware */
838*4882a593Smuzhiyun 
839*4882a593Smuzhiyun 		/* request the firmware, this will block and timeout */
840*4882a593Smuzhiyun 		ret = request_firmware(&fw, fw_file, &client->dev);
841*4882a593Smuzhiyun 		if (ret) {
842*4882a593Smuzhiyun 			dev_err(&client->dev,
843*4882a593Smuzhiyun 				"did not find the firmware file '%s' (status %d). You can use <kernel_dir>/scripts/get_dvb_firmware to get the firmware\n",
844*4882a593Smuzhiyun 				fw_file, ret);
845*4882a593Smuzhiyun 			goto error;
846*4882a593Smuzhiyun 		}
847*4882a593Smuzhiyun 
848*4882a593Smuzhiyun 		/* init */
849*4882a593Smuzhiyun 		for (i = 0; i < ARRAY_SIZE(tab2); i++) {
850*4882a593Smuzhiyun 			ret = tda10071_wr_reg_mask(dev, tab2[i].reg,
851*4882a593Smuzhiyun 				tab2[i].val, tab2[i].mask);
852*4882a593Smuzhiyun 			if (ret)
853*4882a593Smuzhiyun 				goto error_release_firmware;
854*4882a593Smuzhiyun 		}
855*4882a593Smuzhiyun 
856*4882a593Smuzhiyun 		/*  download firmware */
857*4882a593Smuzhiyun 		ret = regmap_write(dev->regmap, 0xe0, 0x7f);
858*4882a593Smuzhiyun 		if (ret)
859*4882a593Smuzhiyun 			goto error_release_firmware;
860*4882a593Smuzhiyun 
861*4882a593Smuzhiyun 		ret = regmap_write(dev->regmap, 0xf7, 0x81);
862*4882a593Smuzhiyun 		if (ret)
863*4882a593Smuzhiyun 			goto error_release_firmware;
864*4882a593Smuzhiyun 
865*4882a593Smuzhiyun 		ret = regmap_write(dev->regmap, 0xf8, 0x00);
866*4882a593Smuzhiyun 		if (ret)
867*4882a593Smuzhiyun 			goto error_release_firmware;
868*4882a593Smuzhiyun 
869*4882a593Smuzhiyun 		ret = regmap_write(dev->regmap, 0xf9, 0x00);
870*4882a593Smuzhiyun 		if (ret)
871*4882a593Smuzhiyun 			goto error_release_firmware;
872*4882a593Smuzhiyun 
873*4882a593Smuzhiyun 		dev_info(&client->dev,
874*4882a593Smuzhiyun 			 "found a '%s' in cold state, will try to load a firmware\n",
875*4882a593Smuzhiyun 			 tda10071_ops.info.name);
876*4882a593Smuzhiyun 		dev_info(&client->dev, "downloading firmware from file '%s'\n",
877*4882a593Smuzhiyun 			 fw_file);
878*4882a593Smuzhiyun 
879*4882a593Smuzhiyun 		/* do not download last byte */
880*4882a593Smuzhiyun 		fw_size = fw->size - 1;
881*4882a593Smuzhiyun 
882*4882a593Smuzhiyun 		for (remaining = fw_size; remaining > 0;
883*4882a593Smuzhiyun 			remaining -= (dev->i2c_wr_max - 1)) {
884*4882a593Smuzhiyun 			len = remaining;
885*4882a593Smuzhiyun 			if (len > (dev->i2c_wr_max - 1))
886*4882a593Smuzhiyun 				len = (dev->i2c_wr_max - 1);
887*4882a593Smuzhiyun 
888*4882a593Smuzhiyun 			ret = regmap_bulk_write(dev->regmap, 0xfa,
889*4882a593Smuzhiyun 				(u8 *) &fw->data[fw_size - remaining], len);
890*4882a593Smuzhiyun 			if (ret) {
891*4882a593Smuzhiyun 				dev_err(&client->dev,
892*4882a593Smuzhiyun 					"firmware download failed=%d\n", ret);
893*4882a593Smuzhiyun 				goto error_release_firmware;
894*4882a593Smuzhiyun 			}
895*4882a593Smuzhiyun 		}
896*4882a593Smuzhiyun 		release_firmware(fw);
897*4882a593Smuzhiyun 
898*4882a593Smuzhiyun 		ret = regmap_write(dev->regmap, 0xf7, 0x0c);
899*4882a593Smuzhiyun 		if (ret)
900*4882a593Smuzhiyun 			goto error;
901*4882a593Smuzhiyun 
902*4882a593Smuzhiyun 		ret = regmap_write(dev->regmap, 0xe0, 0x00);
903*4882a593Smuzhiyun 		if (ret)
904*4882a593Smuzhiyun 			goto error;
905*4882a593Smuzhiyun 
906*4882a593Smuzhiyun 		/* wait firmware start */
907*4882a593Smuzhiyun 		msleep(250);
908*4882a593Smuzhiyun 
909*4882a593Smuzhiyun 		/* firmware status */
910*4882a593Smuzhiyun 		ret = regmap_read(dev->regmap, 0x51, &uitmp);
911*4882a593Smuzhiyun 		if (ret)
912*4882a593Smuzhiyun 			goto error;
913*4882a593Smuzhiyun 
914*4882a593Smuzhiyun 		if (uitmp) {
915*4882a593Smuzhiyun 			dev_info(&client->dev, "firmware did not run\n");
916*4882a593Smuzhiyun 			ret = -EFAULT;
917*4882a593Smuzhiyun 			goto error;
918*4882a593Smuzhiyun 		} else {
919*4882a593Smuzhiyun 			dev->warm = true;
920*4882a593Smuzhiyun 		}
921*4882a593Smuzhiyun 
922*4882a593Smuzhiyun 		cmd.args[0] = CMD_GET_FW_VERSION;
923*4882a593Smuzhiyun 		cmd.len = 1;
924*4882a593Smuzhiyun 		ret = tda10071_cmd_execute(dev, &cmd);
925*4882a593Smuzhiyun 		if (ret)
926*4882a593Smuzhiyun 			goto error;
927*4882a593Smuzhiyun 
928*4882a593Smuzhiyun 		ret = regmap_bulk_read(dev->regmap, cmd.len, buf, 4);
929*4882a593Smuzhiyun 		if (ret)
930*4882a593Smuzhiyun 			goto error;
931*4882a593Smuzhiyun 
932*4882a593Smuzhiyun 		dev_info(&client->dev, "firmware version %d.%d.%d.%d\n",
933*4882a593Smuzhiyun 			 buf[0], buf[1], buf[2], buf[3]);
934*4882a593Smuzhiyun 		dev_info(&client->dev, "found a '%s' in warm state\n",
935*4882a593Smuzhiyun 			 tda10071_ops.info.name);
936*4882a593Smuzhiyun 
937*4882a593Smuzhiyun 		ret = regmap_bulk_read(dev->regmap, 0x81, buf, 2);
938*4882a593Smuzhiyun 		if (ret)
939*4882a593Smuzhiyun 			goto error;
940*4882a593Smuzhiyun 
941*4882a593Smuzhiyun 		cmd.args[0] = CMD_DEMOD_INIT;
942*4882a593Smuzhiyun 		cmd.args[1] = ((dev->clk / 1000) >> 8) & 0xff;
943*4882a593Smuzhiyun 		cmd.args[2] = ((dev->clk / 1000) >> 0) & 0xff;
944*4882a593Smuzhiyun 		cmd.args[3] = buf[0];
945*4882a593Smuzhiyun 		cmd.args[4] = buf[1];
946*4882a593Smuzhiyun 		cmd.args[5] = dev->pll_multiplier;
947*4882a593Smuzhiyun 		cmd.args[6] = dev->spec_inv;
948*4882a593Smuzhiyun 		cmd.args[7] = 0x00;
949*4882a593Smuzhiyun 		cmd.len = 8;
950*4882a593Smuzhiyun 		ret = tda10071_cmd_execute(dev, &cmd);
951*4882a593Smuzhiyun 		if (ret)
952*4882a593Smuzhiyun 			goto error;
953*4882a593Smuzhiyun 
954*4882a593Smuzhiyun 		if (dev->tuner_i2c_addr)
955*4882a593Smuzhiyun 			tmp = dev->tuner_i2c_addr;
956*4882a593Smuzhiyun 		else
957*4882a593Smuzhiyun 			tmp = 0x14;
958*4882a593Smuzhiyun 
959*4882a593Smuzhiyun 		cmd.args[0] = CMD_TUNER_INIT;
960*4882a593Smuzhiyun 		cmd.args[1] = 0x00;
961*4882a593Smuzhiyun 		cmd.args[2] = 0x00;
962*4882a593Smuzhiyun 		cmd.args[3] = 0x00;
963*4882a593Smuzhiyun 		cmd.args[4] = 0x00;
964*4882a593Smuzhiyun 		cmd.args[5] = tmp;
965*4882a593Smuzhiyun 		cmd.args[6] = 0x00;
966*4882a593Smuzhiyun 		cmd.args[7] = 0x03;
967*4882a593Smuzhiyun 		cmd.args[8] = 0x02;
968*4882a593Smuzhiyun 		cmd.args[9] = 0x02;
969*4882a593Smuzhiyun 		cmd.args[10] = 0x00;
970*4882a593Smuzhiyun 		cmd.args[11] = 0x00;
971*4882a593Smuzhiyun 		cmd.args[12] = 0x00;
972*4882a593Smuzhiyun 		cmd.args[13] = 0x00;
973*4882a593Smuzhiyun 		cmd.args[14] = 0x00;
974*4882a593Smuzhiyun 		cmd.len = 15;
975*4882a593Smuzhiyun 		ret = tda10071_cmd_execute(dev, &cmd);
976*4882a593Smuzhiyun 		if (ret)
977*4882a593Smuzhiyun 			goto error;
978*4882a593Smuzhiyun 
979*4882a593Smuzhiyun 		cmd.args[0] = CMD_MPEG_CONFIG;
980*4882a593Smuzhiyun 		cmd.args[1] = 0;
981*4882a593Smuzhiyun 		cmd.args[2] = dev->ts_mode;
982*4882a593Smuzhiyun 		cmd.args[3] = 0x00;
983*4882a593Smuzhiyun 		cmd.args[4] = 0x04;
984*4882a593Smuzhiyun 		cmd.args[5] = 0x00;
985*4882a593Smuzhiyun 		cmd.len = 6;
986*4882a593Smuzhiyun 		ret = tda10071_cmd_execute(dev, &cmd);
987*4882a593Smuzhiyun 		if (ret)
988*4882a593Smuzhiyun 			goto error;
989*4882a593Smuzhiyun 
990*4882a593Smuzhiyun 		ret = regmap_update_bits(dev->regmap, 0xf0, 0x01, 0x01);
991*4882a593Smuzhiyun 		if (ret)
992*4882a593Smuzhiyun 			goto error;
993*4882a593Smuzhiyun 
994*4882a593Smuzhiyun 		cmd.args[0] = CMD_LNB_CONFIG;
995*4882a593Smuzhiyun 		cmd.args[1] = 0;
996*4882a593Smuzhiyun 		cmd.args[2] = 150;
997*4882a593Smuzhiyun 		cmd.args[3] = 3;
998*4882a593Smuzhiyun 		cmd.args[4] = 22;
999*4882a593Smuzhiyun 		cmd.args[5] = 1;
1000*4882a593Smuzhiyun 		cmd.args[6] = 1;
1001*4882a593Smuzhiyun 		cmd.args[7] = 30;
1002*4882a593Smuzhiyun 		cmd.args[8] = 30;
1003*4882a593Smuzhiyun 		cmd.args[9] = 30;
1004*4882a593Smuzhiyun 		cmd.args[10] = 30;
1005*4882a593Smuzhiyun 		cmd.len = 11;
1006*4882a593Smuzhiyun 		ret = tda10071_cmd_execute(dev, &cmd);
1007*4882a593Smuzhiyun 		if (ret)
1008*4882a593Smuzhiyun 			goto error;
1009*4882a593Smuzhiyun 
1010*4882a593Smuzhiyun 		cmd.args[0] = CMD_BER_CONTROL;
1011*4882a593Smuzhiyun 		cmd.args[1] = 0;
1012*4882a593Smuzhiyun 		cmd.args[2] = 14;
1013*4882a593Smuzhiyun 		cmd.args[3] = 14;
1014*4882a593Smuzhiyun 		cmd.len = 4;
1015*4882a593Smuzhiyun 		ret = tda10071_cmd_execute(dev, &cmd);
1016*4882a593Smuzhiyun 		if (ret)
1017*4882a593Smuzhiyun 			goto error;
1018*4882a593Smuzhiyun 	}
1019*4882a593Smuzhiyun 
1020*4882a593Smuzhiyun 	/* init stats here in order signal app which stats are supported */
1021*4882a593Smuzhiyun 	c->strength.len = 1;
1022*4882a593Smuzhiyun 	c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
1023*4882a593Smuzhiyun 	c->cnr.len = 1;
1024*4882a593Smuzhiyun 	c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
1025*4882a593Smuzhiyun 	c->post_bit_error.len = 1;
1026*4882a593Smuzhiyun 	c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
1027*4882a593Smuzhiyun 	c->block_error.len = 1;
1028*4882a593Smuzhiyun 	c->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
1029*4882a593Smuzhiyun 
1030*4882a593Smuzhiyun 	return ret;
1031*4882a593Smuzhiyun error_release_firmware:
1032*4882a593Smuzhiyun 	release_firmware(fw);
1033*4882a593Smuzhiyun error:
1034*4882a593Smuzhiyun 	dev_dbg(&client->dev, "failed=%d\n", ret);
1035*4882a593Smuzhiyun 	return ret;
1036*4882a593Smuzhiyun }
1037*4882a593Smuzhiyun 
tda10071_sleep(struct dvb_frontend * fe)1038*4882a593Smuzhiyun static int tda10071_sleep(struct dvb_frontend *fe)
1039*4882a593Smuzhiyun {
1040*4882a593Smuzhiyun 	struct tda10071_dev *dev = fe->demodulator_priv;
1041*4882a593Smuzhiyun 	struct i2c_client *client = dev->client;
1042*4882a593Smuzhiyun 	struct tda10071_cmd cmd;
1043*4882a593Smuzhiyun 	int ret, i;
1044*4882a593Smuzhiyun 	struct tda10071_reg_val_mask tab[] = {
1045*4882a593Smuzhiyun 		{ 0xcd, 0x07, 0x07 },
1046*4882a593Smuzhiyun 		{ 0x80, 0x02, 0x02 },
1047*4882a593Smuzhiyun 		{ 0xcd, 0xc0, 0xc0 },
1048*4882a593Smuzhiyun 		{ 0xce, 0x1b, 0x1b },
1049*4882a593Smuzhiyun 		{ 0x9d, 0x01, 0x01 },
1050*4882a593Smuzhiyun 		{ 0x9d, 0x02, 0x02 },
1051*4882a593Smuzhiyun 		{ 0x9e, 0x01, 0x01 },
1052*4882a593Smuzhiyun 		{ 0x87, 0x80, 0x80 },
1053*4882a593Smuzhiyun 		{ 0xce, 0x08, 0x08 },
1054*4882a593Smuzhiyun 		{ 0xce, 0x10, 0x10 },
1055*4882a593Smuzhiyun 	};
1056*4882a593Smuzhiyun 
1057*4882a593Smuzhiyun 	if (!dev->warm) {
1058*4882a593Smuzhiyun 		ret = -EFAULT;
1059*4882a593Smuzhiyun 		goto error;
1060*4882a593Smuzhiyun 	}
1061*4882a593Smuzhiyun 
1062*4882a593Smuzhiyun 	cmd.args[0] = CMD_SET_SLEEP_MODE;
1063*4882a593Smuzhiyun 	cmd.args[1] = 0;
1064*4882a593Smuzhiyun 	cmd.args[2] = 1;
1065*4882a593Smuzhiyun 	cmd.len = 3;
1066*4882a593Smuzhiyun 	ret = tda10071_cmd_execute(dev, &cmd);
1067*4882a593Smuzhiyun 	if (ret)
1068*4882a593Smuzhiyun 		goto error;
1069*4882a593Smuzhiyun 
1070*4882a593Smuzhiyun 	for (i = 0; i < ARRAY_SIZE(tab); i++) {
1071*4882a593Smuzhiyun 		ret = tda10071_wr_reg_mask(dev, tab[i].reg, tab[i].val,
1072*4882a593Smuzhiyun 			tab[i].mask);
1073*4882a593Smuzhiyun 		if (ret)
1074*4882a593Smuzhiyun 			goto error;
1075*4882a593Smuzhiyun 	}
1076*4882a593Smuzhiyun 
1077*4882a593Smuzhiyun 	return ret;
1078*4882a593Smuzhiyun error:
1079*4882a593Smuzhiyun 	dev_dbg(&client->dev, "failed=%d\n", ret);
1080*4882a593Smuzhiyun 	return ret;
1081*4882a593Smuzhiyun }
1082*4882a593Smuzhiyun 
tda10071_get_tune_settings(struct dvb_frontend * fe,struct dvb_frontend_tune_settings * s)1083*4882a593Smuzhiyun static int tda10071_get_tune_settings(struct dvb_frontend *fe,
1084*4882a593Smuzhiyun 	struct dvb_frontend_tune_settings *s)
1085*4882a593Smuzhiyun {
1086*4882a593Smuzhiyun 	s->min_delay_ms = 8000;
1087*4882a593Smuzhiyun 	s->step_size = 0;
1088*4882a593Smuzhiyun 	s->max_drift = 0;
1089*4882a593Smuzhiyun 
1090*4882a593Smuzhiyun 	return 0;
1091*4882a593Smuzhiyun }
1092*4882a593Smuzhiyun 
1093*4882a593Smuzhiyun static const struct dvb_frontend_ops tda10071_ops = {
1094*4882a593Smuzhiyun 	.delsys = { SYS_DVBS, SYS_DVBS2 },
1095*4882a593Smuzhiyun 	.info = {
1096*4882a593Smuzhiyun 		.name = "NXP TDA10071",
1097*4882a593Smuzhiyun 		.frequency_min_hz    =  950 * MHz,
1098*4882a593Smuzhiyun 		.frequency_max_hz    = 2150 * MHz,
1099*4882a593Smuzhiyun 		.frequency_tolerance_hz = 5 * MHz,
1100*4882a593Smuzhiyun 		.symbol_rate_min = 1000000,
1101*4882a593Smuzhiyun 		.symbol_rate_max = 45000000,
1102*4882a593Smuzhiyun 		.caps = FE_CAN_INVERSION_AUTO |
1103*4882a593Smuzhiyun 			FE_CAN_FEC_1_2 |
1104*4882a593Smuzhiyun 			FE_CAN_FEC_2_3 |
1105*4882a593Smuzhiyun 			FE_CAN_FEC_3_4 |
1106*4882a593Smuzhiyun 			FE_CAN_FEC_4_5 |
1107*4882a593Smuzhiyun 			FE_CAN_FEC_5_6 |
1108*4882a593Smuzhiyun 			FE_CAN_FEC_6_7 |
1109*4882a593Smuzhiyun 			FE_CAN_FEC_7_8 |
1110*4882a593Smuzhiyun 			FE_CAN_FEC_8_9 |
1111*4882a593Smuzhiyun 			FE_CAN_FEC_AUTO |
1112*4882a593Smuzhiyun 			FE_CAN_QPSK |
1113*4882a593Smuzhiyun 			FE_CAN_RECOVER |
1114*4882a593Smuzhiyun 			FE_CAN_2G_MODULATION
1115*4882a593Smuzhiyun 	},
1116*4882a593Smuzhiyun 
1117*4882a593Smuzhiyun 	.get_tune_settings = tda10071_get_tune_settings,
1118*4882a593Smuzhiyun 
1119*4882a593Smuzhiyun 	.init = tda10071_init,
1120*4882a593Smuzhiyun 	.sleep = tda10071_sleep,
1121*4882a593Smuzhiyun 
1122*4882a593Smuzhiyun 	.set_frontend = tda10071_set_frontend,
1123*4882a593Smuzhiyun 	.get_frontend = tda10071_get_frontend,
1124*4882a593Smuzhiyun 
1125*4882a593Smuzhiyun 	.read_status = tda10071_read_status,
1126*4882a593Smuzhiyun 	.read_snr = tda10071_read_snr,
1127*4882a593Smuzhiyun 	.read_signal_strength = tda10071_read_signal_strength,
1128*4882a593Smuzhiyun 	.read_ber = tda10071_read_ber,
1129*4882a593Smuzhiyun 	.read_ucblocks = tda10071_read_ucblocks,
1130*4882a593Smuzhiyun 
1131*4882a593Smuzhiyun 	.diseqc_send_master_cmd = tda10071_diseqc_send_master_cmd,
1132*4882a593Smuzhiyun 	.diseqc_recv_slave_reply = tda10071_diseqc_recv_slave_reply,
1133*4882a593Smuzhiyun 	.diseqc_send_burst = tda10071_diseqc_send_burst,
1134*4882a593Smuzhiyun 
1135*4882a593Smuzhiyun 	.set_tone = tda10071_set_tone,
1136*4882a593Smuzhiyun 	.set_voltage = tda10071_set_voltage,
1137*4882a593Smuzhiyun };
1138*4882a593Smuzhiyun 
tda10071_get_dvb_frontend(struct i2c_client * client)1139*4882a593Smuzhiyun static struct dvb_frontend *tda10071_get_dvb_frontend(struct i2c_client *client)
1140*4882a593Smuzhiyun {
1141*4882a593Smuzhiyun 	struct tda10071_dev *dev = i2c_get_clientdata(client);
1142*4882a593Smuzhiyun 
1143*4882a593Smuzhiyun 	dev_dbg(&client->dev, "\n");
1144*4882a593Smuzhiyun 
1145*4882a593Smuzhiyun 	return &dev->fe;
1146*4882a593Smuzhiyun }
1147*4882a593Smuzhiyun 
tda10071_probe(struct i2c_client * client,const struct i2c_device_id * id)1148*4882a593Smuzhiyun static int tda10071_probe(struct i2c_client *client,
1149*4882a593Smuzhiyun 			const struct i2c_device_id *id)
1150*4882a593Smuzhiyun {
1151*4882a593Smuzhiyun 	struct tda10071_dev *dev;
1152*4882a593Smuzhiyun 	struct tda10071_platform_data *pdata = client->dev.platform_data;
1153*4882a593Smuzhiyun 	int ret;
1154*4882a593Smuzhiyun 	unsigned int uitmp;
1155*4882a593Smuzhiyun 	static const struct regmap_config regmap_config = {
1156*4882a593Smuzhiyun 		.reg_bits = 8,
1157*4882a593Smuzhiyun 		.val_bits = 8,
1158*4882a593Smuzhiyun 	};
1159*4882a593Smuzhiyun 
1160*4882a593Smuzhiyun 	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
1161*4882a593Smuzhiyun 	if (!dev) {
1162*4882a593Smuzhiyun 		ret = -ENOMEM;
1163*4882a593Smuzhiyun 		goto err;
1164*4882a593Smuzhiyun 	}
1165*4882a593Smuzhiyun 
1166*4882a593Smuzhiyun 	dev->client = client;
1167*4882a593Smuzhiyun 	mutex_init(&dev->cmd_execute_mutex);
1168*4882a593Smuzhiyun 	dev->clk = pdata->clk;
1169*4882a593Smuzhiyun 	dev->i2c_wr_max = pdata->i2c_wr_max;
1170*4882a593Smuzhiyun 	dev->ts_mode = pdata->ts_mode;
1171*4882a593Smuzhiyun 	dev->spec_inv = pdata->spec_inv;
1172*4882a593Smuzhiyun 	dev->pll_multiplier = pdata->pll_multiplier;
1173*4882a593Smuzhiyun 	dev->tuner_i2c_addr = pdata->tuner_i2c_addr;
1174*4882a593Smuzhiyun 	dev->regmap = devm_regmap_init_i2c(client, &regmap_config);
1175*4882a593Smuzhiyun 	if (IS_ERR(dev->regmap)) {
1176*4882a593Smuzhiyun 		ret = PTR_ERR(dev->regmap);
1177*4882a593Smuzhiyun 		goto err_kfree;
1178*4882a593Smuzhiyun 	}
1179*4882a593Smuzhiyun 
1180*4882a593Smuzhiyun 	/* chip ID */
1181*4882a593Smuzhiyun 	ret = regmap_read(dev->regmap, 0xff, &uitmp);
1182*4882a593Smuzhiyun 	if (ret)
1183*4882a593Smuzhiyun 		goto err_kfree;
1184*4882a593Smuzhiyun 	if (uitmp != 0x0f) {
1185*4882a593Smuzhiyun 		ret = -ENODEV;
1186*4882a593Smuzhiyun 		goto err_kfree;
1187*4882a593Smuzhiyun 	}
1188*4882a593Smuzhiyun 
1189*4882a593Smuzhiyun 	/* chip type */
1190*4882a593Smuzhiyun 	ret = regmap_read(dev->regmap, 0xdd, &uitmp);
1191*4882a593Smuzhiyun 	if (ret)
1192*4882a593Smuzhiyun 		goto err_kfree;
1193*4882a593Smuzhiyun 	if (uitmp != 0x00) {
1194*4882a593Smuzhiyun 		ret = -ENODEV;
1195*4882a593Smuzhiyun 		goto err_kfree;
1196*4882a593Smuzhiyun 	}
1197*4882a593Smuzhiyun 
1198*4882a593Smuzhiyun 	/* chip version */
1199*4882a593Smuzhiyun 	ret = regmap_read(dev->regmap, 0xfe, &uitmp);
1200*4882a593Smuzhiyun 	if (ret)
1201*4882a593Smuzhiyun 		goto err_kfree;
1202*4882a593Smuzhiyun 	if (uitmp != 0x01) {
1203*4882a593Smuzhiyun 		ret = -ENODEV;
1204*4882a593Smuzhiyun 		goto err_kfree;
1205*4882a593Smuzhiyun 	}
1206*4882a593Smuzhiyun 
1207*4882a593Smuzhiyun 	/* create dvb_frontend */
1208*4882a593Smuzhiyun 	memcpy(&dev->fe.ops, &tda10071_ops, sizeof(struct dvb_frontend_ops));
1209*4882a593Smuzhiyun 	dev->fe.demodulator_priv = dev;
1210*4882a593Smuzhiyun 	i2c_set_clientdata(client, dev);
1211*4882a593Smuzhiyun 
1212*4882a593Smuzhiyun 	/* setup callbacks */
1213*4882a593Smuzhiyun 	pdata->get_dvb_frontend = tda10071_get_dvb_frontend;
1214*4882a593Smuzhiyun 
1215*4882a593Smuzhiyun 	dev_info(&client->dev, "NXP TDA10071 successfully identified\n");
1216*4882a593Smuzhiyun 	return 0;
1217*4882a593Smuzhiyun err_kfree:
1218*4882a593Smuzhiyun 	kfree(dev);
1219*4882a593Smuzhiyun err:
1220*4882a593Smuzhiyun 	dev_dbg(&client->dev, "failed=%d\n", ret);
1221*4882a593Smuzhiyun 	return ret;
1222*4882a593Smuzhiyun }
1223*4882a593Smuzhiyun 
tda10071_remove(struct i2c_client * client)1224*4882a593Smuzhiyun static int tda10071_remove(struct i2c_client *client)
1225*4882a593Smuzhiyun {
1226*4882a593Smuzhiyun 	struct tda10071_dev *dev = i2c_get_clientdata(client);
1227*4882a593Smuzhiyun 
1228*4882a593Smuzhiyun 	dev_dbg(&client->dev, "\n");
1229*4882a593Smuzhiyun 
1230*4882a593Smuzhiyun 	kfree(dev);
1231*4882a593Smuzhiyun 	return 0;
1232*4882a593Smuzhiyun }
1233*4882a593Smuzhiyun 
1234*4882a593Smuzhiyun static const struct i2c_device_id tda10071_id_table[] = {
1235*4882a593Smuzhiyun 	{"tda10071_cx24118", 0},
1236*4882a593Smuzhiyun 	{}
1237*4882a593Smuzhiyun };
1238*4882a593Smuzhiyun MODULE_DEVICE_TABLE(i2c, tda10071_id_table);
1239*4882a593Smuzhiyun 
1240*4882a593Smuzhiyun static struct i2c_driver tda10071_driver = {
1241*4882a593Smuzhiyun 	.driver = {
1242*4882a593Smuzhiyun 		.name	= "tda10071",
1243*4882a593Smuzhiyun 		.suppress_bind_attrs = true,
1244*4882a593Smuzhiyun 	},
1245*4882a593Smuzhiyun 	.probe		= tda10071_probe,
1246*4882a593Smuzhiyun 	.remove		= tda10071_remove,
1247*4882a593Smuzhiyun 	.id_table	= tda10071_id_table,
1248*4882a593Smuzhiyun };
1249*4882a593Smuzhiyun 
1250*4882a593Smuzhiyun module_i2c_driver(tda10071_driver);
1251*4882a593Smuzhiyun 
1252*4882a593Smuzhiyun MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
1253*4882a593Smuzhiyun MODULE_DESCRIPTION("NXP TDA10071 DVB-S/S2 demodulator driver");
1254*4882a593Smuzhiyun MODULE_LICENSE("GPL");
1255*4882a593Smuzhiyun MODULE_FIRMWARE(TDA10071_FIRMWARE);
1256