media: dvb: symbol fixup for dvb_attach()
[linux-block.git] / drivers / media / tuners / tda18218.c
CommitLineData
c942fddf 1// SPDX-License-Identifier: GPL-2.0-or-later
51ff2e2c
AP
2/*
3 * NXP TDA18218HN silicon tuner driver
4 *
5 * Copyright (C) 2010 Antti Palosaari <crope@iki.fi>
51ff2e2c
AP
6 */
7
51ff2e2c
AP
8#include "tda18218_priv.h"
9
f1baab87
MCC
10/* Max transfer size done by I2C transfer functions */
11#define MAX_XFER_SIZE 64
12
51ff2e2c
AP
13/* write multiple registers */
14static int tda18218_wr_regs(struct tda18218_priv *priv, u8 reg, u8 *val, u8 len)
15{
af3a07ac 16 int ret = 0, len2, remaining;
f1baab87 17 u8 buf[MAX_XFER_SIZE];
51ff2e2c
AP
18 struct i2c_msg msg[1] = {
19 {
20 .addr = priv->cfg->i2c_address,
21 .flags = 0,
22 .buf = buf,
23 }
24 };
25
f1baab87
MCC
26 if (1 + len > sizeof(buf)) {
27 dev_warn(&priv->i2c->dev,
28 "%s: i2c wr reg=%04x: len=%d is too big!\n",
29 KBUILD_MODNAME, reg, len);
30 return -EINVAL;
31 }
32
af3a07ac
AP
33 for (remaining = len; remaining > 0;
34 remaining -= (priv->cfg->i2c_wr_max - 1)) {
35 len2 = remaining;
36 if (len2 > (priv->cfg->i2c_wr_max - 1))
37 len2 = (priv->cfg->i2c_wr_max - 1);
51ff2e2c 38
af3a07ac
AP
39 msg[0].len = 1 + len2;
40 buf[0] = reg + len - remaining;
41 memcpy(&buf[1], &val[len - remaining], len2);
51ff2e2c
AP
42
43 ret = i2c_transfer(priv->i2c, msg, 1);
44 if (ret != 1)
45 break;
46 }
47
48 if (ret == 1) {
49 ret = 0;
50 } else {
9edd6987
AP
51 dev_warn(&priv->i2c->dev, "%s: i2c wr failed=%d reg=%02x " \
52 "len=%d\n", KBUILD_MODNAME, ret, reg, len);
51ff2e2c
AP
53 ret = -EREMOTEIO;
54 }
55
56 return ret;
57}
58
59/* read multiple registers */
60static int tda18218_rd_regs(struct tda18218_priv *priv, u8 reg, u8 *val, u8 len)
61{
62 int ret;
f1baab87 63 u8 buf[MAX_XFER_SIZE]; /* we must start read always from reg 0x00 */
51ff2e2c
AP
64 struct i2c_msg msg[2] = {
65 {
66 .addr = priv->cfg->i2c_address,
67 .flags = 0,
68 .len = 1,
69 .buf = "\x00",
70 }, {
71 .addr = priv->cfg->i2c_address,
72 .flags = I2C_M_RD,
f1baab87 73 .len = reg + len,
51ff2e2c
AP
74 .buf = buf,
75 }
76 };
77
f1baab87
MCC
78 if (reg + len > sizeof(buf)) {
79 dev_warn(&priv->i2c->dev,
80 "%s: i2c wr reg=%04x: len=%d is too big!\n",
81 KBUILD_MODNAME, reg, len);
82 return -EINVAL;
83 }
84
51ff2e2c
AP
85 ret = i2c_transfer(priv->i2c, msg, 2);
86 if (ret == 2) {
87 memcpy(val, &buf[reg], len);
88 ret = 0;
89 } else {
9edd6987
AP
90 dev_warn(&priv->i2c->dev, "%s: i2c rd failed=%d reg=%02x " \
91 "len=%d\n", KBUILD_MODNAME, ret, reg, len);
51ff2e2c
AP
92 ret = -EREMOTEIO;
93 }
94
95 return ret;
96}
97
98/* write single register */
99static int tda18218_wr_reg(struct tda18218_priv *priv, u8 reg, u8 val)
100{
101 return tda18218_wr_regs(priv, reg, &val, 1);
102}
103
104/* read single register */
105
106static int tda18218_rd_reg(struct tda18218_priv *priv, u8 reg, u8 *val)
107{
108 return tda18218_rd_regs(priv, reg, val, 1);
109}
110
14d24d14 111static int tda18218_set_params(struct dvb_frontend *fe)
51ff2e2c
AP
112{
113 struct tda18218_priv *priv = fe->tuner_priv;
67ccfe3b
MCC
114 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
115 u32 bw = c->bandwidth_hz;
51ff2e2c
AP
116 int ret;
117 u8 buf[3], i, BP_Filter, LP_Fc;
118 u32 LO_Frac;
119 /* TODO: find out correct AGC algorithm */
120 u8 agc[][2] = {
121 { R20_AGC11, 0x60 },
122 { R23_AGC21, 0x02 },
123 { R20_AGC11, 0xa0 },
124 { R23_AGC21, 0x09 },
125 { R20_AGC11, 0xe0 },
126 { R23_AGC21, 0x0c },
127 { R20_AGC11, 0x40 },
128 { R23_AGC21, 0x01 },
129 { R20_AGC11, 0x80 },
130 { R23_AGC21, 0x08 },
131 { R20_AGC11, 0xc0 },
132 { R23_AGC21, 0x0b },
133 { R24_AGC22, 0x1c },
134 { R24_AGC22, 0x0c },
135 };
136
137 if (fe->ops.i2c_gate_ctrl)
138 fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */
139
140 /* low-pass filter cut-off frequency */
67ccfe3b 141 if (bw <= 6000000) {
51ff2e2c 142 LP_Fc = 0;
b4d48c94 143 priv->if_frequency = 3000000;
67ccfe3b 144 } else if (bw <= 7000000) {
51ff2e2c 145 LP_Fc = 1;
522fdf73 146 priv->if_frequency = 3500000;
67ccfe3b 147 } else {
51ff2e2c 148 LP_Fc = 2;
522fdf73 149 priv->if_frequency = 4000000;
51ff2e2c
AP
150 }
151
67ccfe3b 152 LO_Frac = c->frequency + priv->if_frequency;
522fdf73 153
51ff2e2c
AP
154 /* band-pass filter */
155 if (LO_Frac < 188000000)
156 BP_Filter = 3;
157 else if (LO_Frac < 253000000)
158 BP_Filter = 4;
159 else if (LO_Frac < 343000000)
160 BP_Filter = 5;
161 else
162 BP_Filter = 6;
163
164 buf[0] = (priv->regs[R1A_IF1] & ~7) | BP_Filter; /* BP_Filter */
165 buf[1] = (priv->regs[R1B_IF2] & ~3) | LP_Fc; /* LP_Fc */
166 buf[2] = priv->regs[R1C_AGC2B];
167 ret = tda18218_wr_regs(priv, R1A_IF1, buf, 3);
168 if (ret)
169 goto error;
170
171 buf[0] = (LO_Frac / 1000) >> 12; /* LO_Frac_0 */
172 buf[1] = (LO_Frac / 1000) >> 4; /* LO_Frac_1 */
173 buf[2] = (LO_Frac / 1000) << 4 |
174 (priv->regs[R0C_MD5] & 0x0f); /* LO_Frac_2 */
175 ret = tda18218_wr_regs(priv, R0A_MD3, buf, 3);
176 if (ret)
177 goto error;
178
179 buf[0] = priv->regs[R0F_MD8] | (1 << 6); /* Freq_prog_Start */
180 ret = tda18218_wr_regs(priv, R0F_MD8, buf, 1);
181 if (ret)
182 goto error;
183
184 buf[0] = priv->regs[R0F_MD8] & ~(1 << 6); /* Freq_prog_Start */
185 ret = tda18218_wr_regs(priv, R0F_MD8, buf, 1);
186 if (ret)
187 goto error;
188
189 /* trigger AGC */
190 for (i = 0; i < ARRAY_SIZE(agc); i++) {
191 ret = tda18218_wr_reg(priv, agc[i][0], agc[i][1]);
192 if (ret)
193 goto error;
194 }
195
196error:
197 if (fe->ops.i2c_gate_ctrl)
198 fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
199
200 if (ret)
9edd6987 201 dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
51ff2e2c
AP
202
203 return ret;
204}
205
522fdf73
AP
206static int tda18218_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
207{
208 struct tda18218_priv *priv = fe->tuner_priv;
209 *frequency = priv->if_frequency;
9edd6987 210 dev_dbg(&priv->i2c->dev, "%s: if_frequency=%d\n", __func__, *frequency);
522fdf73
AP
211 return 0;
212}
213
51ff2e2c
AP
214static int tda18218_sleep(struct dvb_frontend *fe)
215{
216 struct tda18218_priv *priv = fe->tuner_priv;
217 int ret;
218
219 if (fe->ops.i2c_gate_ctrl)
220 fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */
221
222 /* standby */
223 ret = tda18218_wr_reg(priv, R17_PD1, priv->regs[R17_PD1] | (1 << 0));
224
225 if (fe->ops.i2c_gate_ctrl)
226 fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
227
228 if (ret)
9edd6987 229 dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
51ff2e2c
AP
230
231 return ret;
232}
233
234static int tda18218_init(struct dvb_frontend *fe)
235{
236 struct tda18218_priv *priv = fe->tuner_priv;
237 int ret;
238
239 /* TODO: calibrations */
240
241 if (fe->ops.i2c_gate_ctrl)
242 fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */
243
244 ret = tda18218_wr_regs(priv, R00_ID, priv->regs, TDA18218_NUM_REGS);
245
246 if (fe->ops.i2c_gate_ctrl)
247 fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
248
249 if (ret)
9edd6987 250 dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
51ff2e2c
AP
251
252 return ret;
253}
254
f2709c20
MCC
255static void tda18218_release(struct dvb_frontend *fe)
256{
257 kfree(fe->tuner_priv);
258 fe->tuner_priv = NULL;
259}
260
51ff2e2c
AP
261static const struct dvb_tuner_ops tda18218_tuner_ops = {
262 .info = {
a3f90c75 263 .name = "NXP TDA18218",
51ff2e2c 264
a3f90c75
MCC
265 .frequency_min_hz = 174 * MHz,
266 .frequency_max_hz = 864 * MHz,
267 .frequency_step_hz = 1 * kHz,
51ff2e2c
AP
268 },
269
f2709c20 270 .release = tda18218_release,
51ff2e2c
AP
271 .init = tda18218_init,
272 .sleep = tda18218_sleep,
273
274 .set_params = tda18218_set_params,
522fdf73
AP
275
276 .get_if_frequency = tda18218_get_if_frequency,
51ff2e2c
AP
277};
278
279struct dvb_frontend *tda18218_attach(struct dvb_frontend *fe,
280 struct i2c_adapter *i2c, struct tda18218_config *cfg)
281{
282 struct tda18218_priv *priv = NULL;
ed2e3301 283 u8 val;
51ff2e2c
AP
284 int ret;
285 /* chip default registers values */
286 static u8 def_regs[] = {
287 0xc0, 0x88, 0x00, 0x8e, 0x03, 0x00, 0x00, 0xd0, 0x00, 0x40,
288 0x00, 0x00, 0x07, 0xff, 0x84, 0x09, 0x00, 0x13, 0x00, 0x00,
289 0x01, 0x84, 0x09, 0xf0, 0x19, 0x0a, 0x8e, 0x69, 0x98, 0x01,
290 0x00, 0x58, 0x10, 0x40, 0x8c, 0x00, 0x0c, 0x48, 0x85, 0xc9,
291 0xa7, 0x00, 0x00, 0x00, 0x30, 0x81, 0x80, 0x00, 0x39, 0x00,
292 0x8a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, 0xf6
293 };
294
295 priv = kzalloc(sizeof(struct tda18218_priv), GFP_KERNEL);
296 if (priv == NULL)
297 return NULL;
298
299 priv->cfg = cfg;
300 priv->i2c = i2c;
301 fe->tuner_priv = priv;
302
303 if (fe->ops.i2c_gate_ctrl)
304 fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */
305
306 /* check if the tuner is there */
307 ret = tda18218_rd_reg(priv, R00_ID, &val);
ed2e3301
PB
308 if (!ret)
309 dev_dbg(&priv->i2c->dev, "%s: chip id=%02x\n", __func__, val);
51ff2e2c
AP
310 if (ret || val != def_regs[R00_ID]) {
311 kfree(priv);
312 return NULL;
313 }
314
9edd6987
AP
315 dev_info(&priv->i2c->dev,
316 "%s: NXP TDA18218HN successfully identified\n",
317 KBUILD_MODNAME);
51ff2e2c
AP
318
319 memcpy(&fe->ops.tuner_ops, &tda18218_tuner_ops,
320 sizeof(struct dvb_tuner_ops));
321 memcpy(priv->regs, def_regs, sizeof(def_regs));
322
323 /* loop-through enabled chip default register values */
324 if (priv->cfg->loop_through) {
325 priv->regs[R17_PD1] = 0xb0;
326 priv->regs[R18_PD2] = 0x59;
327 }
328
329 /* standby */
330 ret = tda18218_wr_reg(priv, R17_PD1, priv->regs[R17_PD1] | (1 << 0));
331 if (ret)
9edd6987 332 dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
51ff2e2c
AP
333
334 if (fe->ops.i2c_gate_ctrl)
335 fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
336
337 return fe;
338}
86495af1 339EXPORT_SYMBOL_GPL(tda18218_attach);
51ff2e2c
AP
340
341MODULE_DESCRIPTION("NXP TDA18218HN silicon tuner driver");
342MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
343MODULE_LICENSE("GPL");