1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * ITE IT913X silicon tuner driver
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright (C) 2011 Malcolm Priestley (tvboxspy@gmail.com)
6*4882a593Smuzhiyun * IT9137 Copyright (C) ITE Tech Inc.
7*4882a593Smuzhiyun */
8*4882a593Smuzhiyun
9*4882a593Smuzhiyun #include "it913x.h"
10*4882a593Smuzhiyun #include <linux/platform_device.h>
11*4882a593Smuzhiyun #include <linux/regmap.h>
12*4882a593Smuzhiyun
13*4882a593Smuzhiyun struct it913x_dev {
14*4882a593Smuzhiyun struct platform_device *pdev;
15*4882a593Smuzhiyun struct regmap *regmap;
16*4882a593Smuzhiyun struct dvb_frontend *fe;
17*4882a593Smuzhiyun u8 chip_ver:2;
18*4882a593Smuzhiyun u8 role:2;
19*4882a593Smuzhiyun u16 xtal;
20*4882a593Smuzhiyun u8 fdiv;
21*4882a593Smuzhiyun u8 clk_mode;
22*4882a593Smuzhiyun u32 fn_min;
23*4882a593Smuzhiyun bool active;
24*4882a593Smuzhiyun };
25*4882a593Smuzhiyun
it913x_init(struct dvb_frontend * fe)26*4882a593Smuzhiyun static int it913x_init(struct dvb_frontend *fe)
27*4882a593Smuzhiyun {
28*4882a593Smuzhiyun struct it913x_dev *dev = fe->tuner_priv;
29*4882a593Smuzhiyun struct platform_device *pdev = dev->pdev;
30*4882a593Smuzhiyun int ret;
31*4882a593Smuzhiyun unsigned int utmp;
32*4882a593Smuzhiyun u8 iqik_m_cal, nv_val, buf[2];
33*4882a593Smuzhiyun static const u8 nv[] = {48, 32, 24, 16, 12, 8, 6, 4, 2};
34*4882a593Smuzhiyun unsigned long timeout;
35*4882a593Smuzhiyun
36*4882a593Smuzhiyun dev_dbg(&pdev->dev, "role %u\n", dev->role);
37*4882a593Smuzhiyun
38*4882a593Smuzhiyun ret = regmap_write(dev->regmap, 0x80ec4c, 0x68);
39*4882a593Smuzhiyun if (ret)
40*4882a593Smuzhiyun goto err;
41*4882a593Smuzhiyun
42*4882a593Smuzhiyun usleep_range(10000, 100000);
43*4882a593Smuzhiyun
44*4882a593Smuzhiyun ret = regmap_read(dev->regmap, 0x80ec86, &utmp);
45*4882a593Smuzhiyun if (ret)
46*4882a593Smuzhiyun goto err;
47*4882a593Smuzhiyun
48*4882a593Smuzhiyun switch (utmp) {
49*4882a593Smuzhiyun case 0:
50*4882a593Smuzhiyun /* 12.000 MHz */
51*4882a593Smuzhiyun dev->clk_mode = utmp;
52*4882a593Smuzhiyun dev->xtal = 2000;
53*4882a593Smuzhiyun dev->fdiv = 3;
54*4882a593Smuzhiyun iqik_m_cal = 16;
55*4882a593Smuzhiyun break;
56*4882a593Smuzhiyun case 1:
57*4882a593Smuzhiyun /* 20.480 MHz */
58*4882a593Smuzhiyun dev->clk_mode = utmp;
59*4882a593Smuzhiyun dev->xtal = 640;
60*4882a593Smuzhiyun dev->fdiv = 1;
61*4882a593Smuzhiyun iqik_m_cal = 6;
62*4882a593Smuzhiyun break;
63*4882a593Smuzhiyun default:
64*4882a593Smuzhiyun dev_err(&pdev->dev, "unknown clock identifier %d\n", utmp);
65*4882a593Smuzhiyun goto err;
66*4882a593Smuzhiyun }
67*4882a593Smuzhiyun
68*4882a593Smuzhiyun ret = regmap_read(dev->regmap, 0x80ed03, &utmp);
69*4882a593Smuzhiyun if (ret)
70*4882a593Smuzhiyun goto err;
71*4882a593Smuzhiyun
72*4882a593Smuzhiyun else if (utmp < ARRAY_SIZE(nv))
73*4882a593Smuzhiyun nv_val = nv[utmp];
74*4882a593Smuzhiyun else
75*4882a593Smuzhiyun nv_val = 2;
76*4882a593Smuzhiyun
77*4882a593Smuzhiyun #define TIMEOUT 50
78*4882a593Smuzhiyun timeout = jiffies + msecs_to_jiffies(TIMEOUT);
79*4882a593Smuzhiyun while (!time_after(jiffies, timeout)) {
80*4882a593Smuzhiyun ret = regmap_bulk_read(dev->regmap, 0x80ed23, buf, 2);
81*4882a593Smuzhiyun if (ret)
82*4882a593Smuzhiyun goto err;
83*4882a593Smuzhiyun
84*4882a593Smuzhiyun utmp = (buf[1] << 8) | (buf[0] << 0);
85*4882a593Smuzhiyun if (utmp)
86*4882a593Smuzhiyun break;
87*4882a593Smuzhiyun }
88*4882a593Smuzhiyun
89*4882a593Smuzhiyun dev_dbg(&pdev->dev, "r_fbc_m_bdry took %u ms, val %u\n",
90*4882a593Smuzhiyun jiffies_to_msecs(jiffies) -
91*4882a593Smuzhiyun (jiffies_to_msecs(timeout) - TIMEOUT), utmp);
92*4882a593Smuzhiyun
93*4882a593Smuzhiyun dev->fn_min = dev->xtal * utmp;
94*4882a593Smuzhiyun dev->fn_min /= (dev->fdiv * nv_val);
95*4882a593Smuzhiyun dev->fn_min *= 1000;
96*4882a593Smuzhiyun dev_dbg(&pdev->dev, "fn_min %u\n", dev->fn_min);
97*4882a593Smuzhiyun
98*4882a593Smuzhiyun /*
99*4882a593Smuzhiyun * Chip version BX never sets that flag so we just wait 50ms in that
100*4882a593Smuzhiyun * case. It is possible poll BX similarly than AX and then timeout in
101*4882a593Smuzhiyun * order to get 50ms delay, but that causes about 120 extra I2C
102*4882a593Smuzhiyun * messages. As for now, we just wait and reduce IO.
103*4882a593Smuzhiyun */
104*4882a593Smuzhiyun if (dev->chip_ver == 1) {
105*4882a593Smuzhiyun #define TIMEOUT 50
106*4882a593Smuzhiyun timeout = jiffies + msecs_to_jiffies(TIMEOUT);
107*4882a593Smuzhiyun while (!time_after(jiffies, timeout)) {
108*4882a593Smuzhiyun ret = regmap_read(dev->regmap, 0x80ec82, &utmp);
109*4882a593Smuzhiyun if (ret)
110*4882a593Smuzhiyun goto err;
111*4882a593Smuzhiyun
112*4882a593Smuzhiyun if (utmp)
113*4882a593Smuzhiyun break;
114*4882a593Smuzhiyun }
115*4882a593Smuzhiyun
116*4882a593Smuzhiyun dev_dbg(&pdev->dev, "p_tsm_init_mode took %u ms, val %u\n",
117*4882a593Smuzhiyun jiffies_to_msecs(jiffies) -
118*4882a593Smuzhiyun (jiffies_to_msecs(timeout) - TIMEOUT), utmp);
119*4882a593Smuzhiyun } else {
120*4882a593Smuzhiyun msleep(50);
121*4882a593Smuzhiyun }
122*4882a593Smuzhiyun
123*4882a593Smuzhiyun ret = regmap_write(dev->regmap, 0x80ed81, iqik_m_cal);
124*4882a593Smuzhiyun if (ret)
125*4882a593Smuzhiyun goto err;
126*4882a593Smuzhiyun
127*4882a593Smuzhiyun ret = regmap_write(dev->regmap, 0x80ec57, 0x00);
128*4882a593Smuzhiyun if (ret)
129*4882a593Smuzhiyun goto err;
130*4882a593Smuzhiyun
131*4882a593Smuzhiyun ret = regmap_write(dev->regmap, 0x80ec58, 0x00);
132*4882a593Smuzhiyun if (ret)
133*4882a593Smuzhiyun goto err;
134*4882a593Smuzhiyun
135*4882a593Smuzhiyun ret = regmap_write(dev->regmap, 0x80ec40, 0x01);
136*4882a593Smuzhiyun if (ret)
137*4882a593Smuzhiyun goto err;
138*4882a593Smuzhiyun
139*4882a593Smuzhiyun dev->active = true;
140*4882a593Smuzhiyun
141*4882a593Smuzhiyun return 0;
142*4882a593Smuzhiyun err:
143*4882a593Smuzhiyun dev_dbg(&pdev->dev, "failed %d\n", ret);
144*4882a593Smuzhiyun return ret;
145*4882a593Smuzhiyun }
146*4882a593Smuzhiyun
it913x_sleep(struct dvb_frontend * fe)147*4882a593Smuzhiyun static int it913x_sleep(struct dvb_frontend *fe)
148*4882a593Smuzhiyun {
149*4882a593Smuzhiyun struct it913x_dev *dev = fe->tuner_priv;
150*4882a593Smuzhiyun struct platform_device *pdev = dev->pdev;
151*4882a593Smuzhiyun int ret, len;
152*4882a593Smuzhiyun
153*4882a593Smuzhiyun dev_dbg(&pdev->dev, "role %u\n", dev->role);
154*4882a593Smuzhiyun
155*4882a593Smuzhiyun dev->active = false;
156*4882a593Smuzhiyun
157*4882a593Smuzhiyun ret = regmap_bulk_write(dev->regmap, 0x80ec40, "\x00", 1);
158*4882a593Smuzhiyun if (ret)
159*4882a593Smuzhiyun goto err;
160*4882a593Smuzhiyun
161*4882a593Smuzhiyun /*
162*4882a593Smuzhiyun * Writing '0x00' to master tuner register '0x80ec08' causes slave tuner
163*4882a593Smuzhiyun * communication lost. Due to that, we cannot put master full sleep.
164*4882a593Smuzhiyun */
165*4882a593Smuzhiyun if (dev->role == IT913X_ROLE_DUAL_MASTER)
166*4882a593Smuzhiyun len = 4;
167*4882a593Smuzhiyun else
168*4882a593Smuzhiyun len = 15;
169*4882a593Smuzhiyun
170*4882a593Smuzhiyun dev_dbg(&pdev->dev, "role %u, len %d\n", dev->role, len);
171*4882a593Smuzhiyun
172*4882a593Smuzhiyun ret = regmap_bulk_write(dev->regmap, 0x80ec02,
173*4882a593Smuzhiyun "\x3f\x1f\x3f\x3e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
174*4882a593Smuzhiyun len);
175*4882a593Smuzhiyun if (ret)
176*4882a593Smuzhiyun goto err;
177*4882a593Smuzhiyun
178*4882a593Smuzhiyun ret = regmap_bulk_write(dev->regmap, 0x80ec12, "\x00\x00\x00\x00", 4);
179*4882a593Smuzhiyun if (ret)
180*4882a593Smuzhiyun goto err;
181*4882a593Smuzhiyun
182*4882a593Smuzhiyun ret = regmap_bulk_write(dev->regmap, 0x80ec17,
183*4882a593Smuzhiyun "\x00\x00\x00\x00\x00\x00\x00\x00\x00", 9);
184*4882a593Smuzhiyun if (ret)
185*4882a593Smuzhiyun goto err;
186*4882a593Smuzhiyun
187*4882a593Smuzhiyun ret = regmap_bulk_write(dev->regmap, 0x80ec22,
188*4882a593Smuzhiyun "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 10);
189*4882a593Smuzhiyun if (ret)
190*4882a593Smuzhiyun goto err;
191*4882a593Smuzhiyun
192*4882a593Smuzhiyun ret = regmap_bulk_write(dev->regmap, 0x80ec20, "\x00", 1);
193*4882a593Smuzhiyun if (ret)
194*4882a593Smuzhiyun goto err;
195*4882a593Smuzhiyun
196*4882a593Smuzhiyun ret = regmap_bulk_write(dev->regmap, 0x80ec3f, "\x01", 1);
197*4882a593Smuzhiyun if (ret)
198*4882a593Smuzhiyun goto err;
199*4882a593Smuzhiyun
200*4882a593Smuzhiyun return 0;
201*4882a593Smuzhiyun err:
202*4882a593Smuzhiyun dev_dbg(&pdev->dev, "failed %d\n", ret);
203*4882a593Smuzhiyun return ret;
204*4882a593Smuzhiyun }
205*4882a593Smuzhiyun
it913x_set_params(struct dvb_frontend * fe)206*4882a593Smuzhiyun static int it913x_set_params(struct dvb_frontend *fe)
207*4882a593Smuzhiyun {
208*4882a593Smuzhiyun struct it913x_dev *dev = fe->tuner_priv;
209*4882a593Smuzhiyun struct platform_device *pdev = dev->pdev;
210*4882a593Smuzhiyun struct dtv_frontend_properties *c = &fe->dtv_property_cache;
211*4882a593Smuzhiyun int ret;
212*4882a593Smuzhiyun unsigned int utmp;
213*4882a593Smuzhiyun u32 pre_lo_freq, t_cal_freq;
214*4882a593Smuzhiyun u16 iqik_m_cal, n_div;
215*4882a593Smuzhiyun u8 u8tmp, n, l_band, lna_band;
216*4882a593Smuzhiyun
217*4882a593Smuzhiyun dev_dbg(&pdev->dev, "role=%u, frequency %u, bandwidth_hz %u\n",
218*4882a593Smuzhiyun dev->role, c->frequency, c->bandwidth_hz);
219*4882a593Smuzhiyun
220*4882a593Smuzhiyun if (!dev->active) {
221*4882a593Smuzhiyun ret = -EINVAL;
222*4882a593Smuzhiyun goto err;
223*4882a593Smuzhiyun }
224*4882a593Smuzhiyun
225*4882a593Smuzhiyun if (c->frequency <= 74000000) {
226*4882a593Smuzhiyun n_div = 48;
227*4882a593Smuzhiyun n = 0;
228*4882a593Smuzhiyun } else if (c->frequency <= 111000000) {
229*4882a593Smuzhiyun n_div = 32;
230*4882a593Smuzhiyun n = 1;
231*4882a593Smuzhiyun } else if (c->frequency <= 148000000) {
232*4882a593Smuzhiyun n_div = 24;
233*4882a593Smuzhiyun n = 2;
234*4882a593Smuzhiyun } else if (c->frequency <= 222000000) {
235*4882a593Smuzhiyun n_div = 16;
236*4882a593Smuzhiyun n = 3;
237*4882a593Smuzhiyun } else if (c->frequency <= 296000000) {
238*4882a593Smuzhiyun n_div = 12;
239*4882a593Smuzhiyun n = 4;
240*4882a593Smuzhiyun } else if (c->frequency <= 445000000) {
241*4882a593Smuzhiyun n_div = 8;
242*4882a593Smuzhiyun n = 5;
243*4882a593Smuzhiyun } else if (c->frequency <= dev->fn_min) {
244*4882a593Smuzhiyun n_div = 6;
245*4882a593Smuzhiyun n = 6;
246*4882a593Smuzhiyun } else if (c->frequency <= 950000000) {
247*4882a593Smuzhiyun n_div = 4;
248*4882a593Smuzhiyun n = 7;
249*4882a593Smuzhiyun } else {
250*4882a593Smuzhiyun n_div = 2;
251*4882a593Smuzhiyun n = 0;
252*4882a593Smuzhiyun }
253*4882a593Smuzhiyun
254*4882a593Smuzhiyun ret = regmap_read(dev->regmap, 0x80ed81, &utmp);
255*4882a593Smuzhiyun if (ret)
256*4882a593Smuzhiyun goto err;
257*4882a593Smuzhiyun
258*4882a593Smuzhiyun iqik_m_cal = utmp * n_div;
259*4882a593Smuzhiyun
260*4882a593Smuzhiyun if (utmp < 0x20) {
261*4882a593Smuzhiyun if (dev->clk_mode == 0)
262*4882a593Smuzhiyun iqik_m_cal = (iqik_m_cal * 9) >> 5;
263*4882a593Smuzhiyun else
264*4882a593Smuzhiyun iqik_m_cal >>= 1;
265*4882a593Smuzhiyun } else {
266*4882a593Smuzhiyun iqik_m_cal = 0x40 - iqik_m_cal;
267*4882a593Smuzhiyun if (dev->clk_mode == 0)
268*4882a593Smuzhiyun iqik_m_cal = ~((iqik_m_cal * 9) >> 5);
269*4882a593Smuzhiyun else
270*4882a593Smuzhiyun iqik_m_cal = ~(iqik_m_cal >> 1);
271*4882a593Smuzhiyun }
272*4882a593Smuzhiyun
273*4882a593Smuzhiyun t_cal_freq = (c->frequency / 1000) * n_div * dev->fdiv;
274*4882a593Smuzhiyun pre_lo_freq = t_cal_freq / dev->xtal;
275*4882a593Smuzhiyun utmp = pre_lo_freq * dev->xtal;
276*4882a593Smuzhiyun
277*4882a593Smuzhiyun if ((t_cal_freq - utmp) >= (dev->xtal >> 1))
278*4882a593Smuzhiyun pre_lo_freq++;
279*4882a593Smuzhiyun
280*4882a593Smuzhiyun pre_lo_freq += (u32) n << 13;
281*4882a593Smuzhiyun /* Frequency OMEGA_IQIK_M_CAL_MID*/
282*4882a593Smuzhiyun t_cal_freq = pre_lo_freq + (u32)iqik_m_cal;
283*4882a593Smuzhiyun dev_dbg(&pdev->dev, "t_cal_freq %u, pre_lo_freq %u\n",
284*4882a593Smuzhiyun t_cal_freq, pre_lo_freq);
285*4882a593Smuzhiyun
286*4882a593Smuzhiyun if (c->frequency <= 440000000) {
287*4882a593Smuzhiyun l_band = 0;
288*4882a593Smuzhiyun lna_band = 0;
289*4882a593Smuzhiyun } else if (c->frequency <= 484000000) {
290*4882a593Smuzhiyun l_band = 1;
291*4882a593Smuzhiyun lna_band = 1;
292*4882a593Smuzhiyun } else if (c->frequency <= 533000000) {
293*4882a593Smuzhiyun l_band = 1;
294*4882a593Smuzhiyun lna_band = 2;
295*4882a593Smuzhiyun } else if (c->frequency <= 587000000) {
296*4882a593Smuzhiyun l_band = 1;
297*4882a593Smuzhiyun lna_band = 3;
298*4882a593Smuzhiyun } else if (c->frequency <= 645000000) {
299*4882a593Smuzhiyun l_band = 1;
300*4882a593Smuzhiyun lna_band = 4;
301*4882a593Smuzhiyun } else if (c->frequency <= 710000000) {
302*4882a593Smuzhiyun l_band = 1;
303*4882a593Smuzhiyun lna_band = 5;
304*4882a593Smuzhiyun } else if (c->frequency <= 782000000) {
305*4882a593Smuzhiyun l_band = 1;
306*4882a593Smuzhiyun lna_band = 6;
307*4882a593Smuzhiyun } else if (c->frequency <= 860000000) {
308*4882a593Smuzhiyun l_band = 1;
309*4882a593Smuzhiyun lna_band = 7;
310*4882a593Smuzhiyun } else if (c->frequency <= 1492000000) {
311*4882a593Smuzhiyun l_band = 1;
312*4882a593Smuzhiyun lna_band = 0;
313*4882a593Smuzhiyun } else if (c->frequency <= 1685000000) {
314*4882a593Smuzhiyun l_band = 1;
315*4882a593Smuzhiyun lna_band = 1;
316*4882a593Smuzhiyun } else {
317*4882a593Smuzhiyun ret = -EINVAL;
318*4882a593Smuzhiyun goto err;
319*4882a593Smuzhiyun }
320*4882a593Smuzhiyun
321*4882a593Smuzhiyun /* XXX: latest windows driver does not set that at all */
322*4882a593Smuzhiyun ret = regmap_write(dev->regmap, 0x80ee06, lna_band);
323*4882a593Smuzhiyun if (ret)
324*4882a593Smuzhiyun goto err;
325*4882a593Smuzhiyun
326*4882a593Smuzhiyun if (c->bandwidth_hz <= 5000000)
327*4882a593Smuzhiyun u8tmp = 0;
328*4882a593Smuzhiyun else if (c->bandwidth_hz <= 6000000)
329*4882a593Smuzhiyun u8tmp = 2;
330*4882a593Smuzhiyun else if (c->bandwidth_hz <= 7000000)
331*4882a593Smuzhiyun u8tmp = 4;
332*4882a593Smuzhiyun else
333*4882a593Smuzhiyun u8tmp = 6; /* 8000000 */
334*4882a593Smuzhiyun
335*4882a593Smuzhiyun ret = regmap_write(dev->regmap, 0x80ec56, u8tmp);
336*4882a593Smuzhiyun if (ret)
337*4882a593Smuzhiyun goto err;
338*4882a593Smuzhiyun
339*4882a593Smuzhiyun /* XXX: latest windows driver sets different value (a8 != 68) */
340*4882a593Smuzhiyun ret = regmap_write(dev->regmap, 0x80ec4c, 0xa0 | (l_band << 3));
341*4882a593Smuzhiyun if (ret)
342*4882a593Smuzhiyun goto err;
343*4882a593Smuzhiyun
344*4882a593Smuzhiyun ret = regmap_write(dev->regmap, 0x80ec4d, (t_cal_freq >> 0) & 0xff);
345*4882a593Smuzhiyun if (ret)
346*4882a593Smuzhiyun goto err;
347*4882a593Smuzhiyun
348*4882a593Smuzhiyun ret = regmap_write(dev->regmap, 0x80ec4e, (t_cal_freq >> 8) & 0xff);
349*4882a593Smuzhiyun if (ret)
350*4882a593Smuzhiyun goto err;
351*4882a593Smuzhiyun
352*4882a593Smuzhiyun ret = regmap_write(dev->regmap, 0x80011e, (pre_lo_freq >> 0) & 0xff);
353*4882a593Smuzhiyun if (ret)
354*4882a593Smuzhiyun goto err;
355*4882a593Smuzhiyun
356*4882a593Smuzhiyun ret = regmap_write(dev->regmap, 0x80011f, (pre_lo_freq >> 8) & 0xff);
357*4882a593Smuzhiyun if (ret)
358*4882a593Smuzhiyun goto err;
359*4882a593Smuzhiyun
360*4882a593Smuzhiyun return 0;
361*4882a593Smuzhiyun err:
362*4882a593Smuzhiyun dev_dbg(&pdev->dev, "failed %d\n", ret);
363*4882a593Smuzhiyun return ret;
364*4882a593Smuzhiyun }
365*4882a593Smuzhiyun
366*4882a593Smuzhiyun static const struct dvb_tuner_ops it913x_tuner_ops = {
367*4882a593Smuzhiyun .info = {
368*4882a593Smuzhiyun .name = "ITE IT913X",
369*4882a593Smuzhiyun .frequency_min_hz = 174 * MHz,
370*4882a593Smuzhiyun .frequency_max_hz = 862 * MHz,
371*4882a593Smuzhiyun },
372*4882a593Smuzhiyun
373*4882a593Smuzhiyun .init = it913x_init,
374*4882a593Smuzhiyun .sleep = it913x_sleep,
375*4882a593Smuzhiyun .set_params = it913x_set_params,
376*4882a593Smuzhiyun };
377*4882a593Smuzhiyun
it913x_probe(struct platform_device * pdev)378*4882a593Smuzhiyun static int it913x_probe(struct platform_device *pdev)
379*4882a593Smuzhiyun {
380*4882a593Smuzhiyun struct it913x_platform_data *pdata = pdev->dev.platform_data;
381*4882a593Smuzhiyun struct dvb_frontend *fe = pdata->fe;
382*4882a593Smuzhiyun struct it913x_dev *dev;
383*4882a593Smuzhiyun const struct platform_device_id *id = platform_get_device_id(pdev);
384*4882a593Smuzhiyun int ret;
385*4882a593Smuzhiyun char *chip_ver_str;
386*4882a593Smuzhiyun
387*4882a593Smuzhiyun dev = kzalloc(sizeof(struct it913x_dev), GFP_KERNEL);
388*4882a593Smuzhiyun if (dev == NULL) {
389*4882a593Smuzhiyun ret = -ENOMEM;
390*4882a593Smuzhiyun dev_err(&pdev->dev, "kzalloc() failed\n");
391*4882a593Smuzhiyun goto err;
392*4882a593Smuzhiyun }
393*4882a593Smuzhiyun
394*4882a593Smuzhiyun dev->pdev = pdev;
395*4882a593Smuzhiyun dev->regmap = pdata->regmap;
396*4882a593Smuzhiyun dev->fe = pdata->fe;
397*4882a593Smuzhiyun dev->chip_ver = id->driver_data;
398*4882a593Smuzhiyun dev->role = pdata->role;
399*4882a593Smuzhiyun
400*4882a593Smuzhiyun fe->tuner_priv = dev;
401*4882a593Smuzhiyun memcpy(&fe->ops.tuner_ops, &it913x_tuner_ops,
402*4882a593Smuzhiyun sizeof(struct dvb_tuner_ops));
403*4882a593Smuzhiyun platform_set_drvdata(pdev, dev);
404*4882a593Smuzhiyun
405*4882a593Smuzhiyun if (dev->chip_ver == 1)
406*4882a593Smuzhiyun chip_ver_str = "AX";
407*4882a593Smuzhiyun else if (dev->chip_ver == 2)
408*4882a593Smuzhiyun chip_ver_str = "BX";
409*4882a593Smuzhiyun else
410*4882a593Smuzhiyun chip_ver_str = "??";
411*4882a593Smuzhiyun
412*4882a593Smuzhiyun dev_info(&pdev->dev, "ITE IT913X %s successfully attached\n",
413*4882a593Smuzhiyun chip_ver_str);
414*4882a593Smuzhiyun dev_dbg(&pdev->dev, "chip_ver %u, role %u\n", dev->chip_ver, dev->role);
415*4882a593Smuzhiyun return 0;
416*4882a593Smuzhiyun err:
417*4882a593Smuzhiyun dev_dbg(&pdev->dev, "failed %d\n", ret);
418*4882a593Smuzhiyun return ret;
419*4882a593Smuzhiyun }
420*4882a593Smuzhiyun
it913x_remove(struct platform_device * pdev)421*4882a593Smuzhiyun static int it913x_remove(struct platform_device *pdev)
422*4882a593Smuzhiyun {
423*4882a593Smuzhiyun struct it913x_dev *dev = platform_get_drvdata(pdev);
424*4882a593Smuzhiyun struct dvb_frontend *fe = dev->fe;
425*4882a593Smuzhiyun
426*4882a593Smuzhiyun dev_dbg(&pdev->dev, "\n");
427*4882a593Smuzhiyun
428*4882a593Smuzhiyun memset(&fe->ops.tuner_ops, 0, sizeof(struct dvb_tuner_ops));
429*4882a593Smuzhiyun fe->tuner_priv = NULL;
430*4882a593Smuzhiyun kfree(dev);
431*4882a593Smuzhiyun
432*4882a593Smuzhiyun return 0;
433*4882a593Smuzhiyun }
434*4882a593Smuzhiyun
435*4882a593Smuzhiyun static const struct platform_device_id it913x_id_table[] = {
436*4882a593Smuzhiyun {"it9133ax-tuner", 1},
437*4882a593Smuzhiyun {"it9133bx-tuner", 2},
438*4882a593Smuzhiyun {},
439*4882a593Smuzhiyun };
440*4882a593Smuzhiyun MODULE_DEVICE_TABLE(platform, it913x_id_table);
441*4882a593Smuzhiyun
442*4882a593Smuzhiyun static struct platform_driver it913x_driver = {
443*4882a593Smuzhiyun .driver = {
444*4882a593Smuzhiyun .name = "it913x",
445*4882a593Smuzhiyun .suppress_bind_attrs = true,
446*4882a593Smuzhiyun },
447*4882a593Smuzhiyun .probe = it913x_probe,
448*4882a593Smuzhiyun .remove = it913x_remove,
449*4882a593Smuzhiyun .id_table = it913x_id_table,
450*4882a593Smuzhiyun };
451*4882a593Smuzhiyun
452*4882a593Smuzhiyun module_platform_driver(it913x_driver);
453*4882a593Smuzhiyun
454*4882a593Smuzhiyun MODULE_DESCRIPTION("ITE IT913X silicon tuner driver");
455*4882a593Smuzhiyun MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
456*4882a593Smuzhiyun MODULE_LICENSE("GPL");
457