writeback: show writeback reason with __print_symbolic
[pandora-kernel.git] / drivers / media / common / tuners / tda18218.c
1 /*
2  * NXP TDA18218HN silicon tuner driver
3  *
4  * Copyright (C) 2010 Antti Palosaari <crope@iki.fi>
5  *
6  *    This program is free software; you can redistribute it and/or modify
7  *    it under the terms of the GNU General Public License as published by
8  *    the Free Software Foundation; either version 2 of the License, or
9  *    (at your option) any later version.
10  *
11  *    This program is distributed in the hope that it will be useful,
12  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *    GNU General Public License for more details.
15  *
16  *    You should have received a copy of the GNU General Public License
17  *    along with this program; if not, write to the Free Software
18  *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  */
20
21 #include "tda18218.h"
22 #include "tda18218_priv.h"
23
24 static int debug;
25 module_param(debug, int, 0644);
26 MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
27
28 /* write multiple registers */
29 static int tda18218_wr_regs(struct tda18218_priv *priv, u8 reg, u8 *val, u8 len)
30 {
31         int ret = 0;
32         u8 buf[1+len], quotient, remainder, i, msg_len, msg_len_max;
33         struct i2c_msg msg[1] = {
34                 {
35                         .addr = priv->cfg->i2c_address,
36                         .flags = 0,
37                         .buf = buf,
38                 }
39         };
40
41         msg_len_max = priv->cfg->i2c_wr_max - 1;
42         quotient = len / msg_len_max;
43         remainder = len % msg_len_max;
44         msg_len = msg_len_max;
45         for (i = 0; (i <= quotient && remainder); i++) {
46                 if (i == quotient)  /* set len of the last msg */
47                         msg_len = remainder;
48
49                 msg[0].len = msg_len + 1;
50                 buf[0] = reg + i * msg_len_max;
51                 memcpy(&buf[1], &val[i * msg_len_max], msg_len);
52
53                 ret = i2c_transfer(priv->i2c, msg, 1);
54                 if (ret != 1)
55                         break;
56         }
57
58         if (ret == 1) {
59                 ret = 0;
60         } else {
61                 warn("i2c wr failed ret:%d reg:%02x len:%d", ret, reg, len);
62                 ret = -EREMOTEIO;
63         }
64
65         return ret;
66 }
67
68 /* read multiple registers */
69 static int tda18218_rd_regs(struct tda18218_priv *priv, u8 reg, u8 *val, u8 len)
70 {
71         int ret;
72         u8 buf[reg+len]; /* we must start read always from reg 0x00 */
73         struct i2c_msg msg[2] = {
74                 {
75                         .addr = priv->cfg->i2c_address,
76                         .flags = 0,
77                         .len = 1,
78                         .buf = "\x00",
79                 }, {
80                         .addr = priv->cfg->i2c_address,
81                         .flags = I2C_M_RD,
82                         .len = sizeof(buf),
83                         .buf = buf,
84                 }
85         };
86
87         ret = i2c_transfer(priv->i2c, msg, 2);
88         if (ret == 2) {
89                 memcpy(val, &buf[reg], len);
90                 ret = 0;
91         } else {
92                 warn("i2c rd failed ret:%d reg:%02x len:%d", ret, reg, len);
93                 ret = -EREMOTEIO;
94         }
95
96         return ret;
97 }
98
99 /* write single register */
100 static int tda18218_wr_reg(struct tda18218_priv *priv, u8 reg, u8 val)
101 {
102         return tda18218_wr_regs(priv, reg, &val, 1);
103 }
104
105 /* read single register */
106
107 static int tda18218_rd_reg(struct tda18218_priv *priv, u8 reg, u8 *val)
108 {
109         return tda18218_rd_regs(priv, reg, val, 1);
110 }
111
112 static int tda18218_set_params(struct dvb_frontend *fe,
113         struct dvb_frontend_parameters *params)
114 {
115         struct tda18218_priv *priv = fe->tuner_priv;
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 */
141         switch (params->u.ofdm.bandwidth) {
142         case BANDWIDTH_6_MHZ:
143                 LP_Fc = 0;
144                 LO_Frac = params->frequency + 4000000;
145                 break;
146         case BANDWIDTH_7_MHZ:
147                 LP_Fc = 1;
148                 LO_Frac = params->frequency + 3500000;
149                 break;
150         case BANDWIDTH_8_MHZ:
151         default:
152                 LP_Fc = 2;
153                 LO_Frac = params->frequency + 4000000;
154                 break;
155         }
156
157         /* band-pass filter */
158         if (LO_Frac < 188000000)
159                 BP_Filter = 3;
160         else if (LO_Frac < 253000000)
161                 BP_Filter = 4;
162         else if (LO_Frac < 343000000)
163                 BP_Filter = 5;
164         else
165                 BP_Filter = 6;
166
167         buf[0] = (priv->regs[R1A_IF1] & ~7) | BP_Filter; /* BP_Filter */
168         buf[1] = (priv->regs[R1B_IF2] & ~3) | LP_Fc; /* LP_Fc */
169         buf[2] = priv->regs[R1C_AGC2B];
170         ret = tda18218_wr_regs(priv, R1A_IF1, buf, 3);
171         if (ret)
172                 goto error;
173
174         buf[0] = (LO_Frac / 1000) >> 12; /* LO_Frac_0 */
175         buf[1] = (LO_Frac / 1000) >> 4; /* LO_Frac_1 */
176         buf[2] = (LO_Frac / 1000) << 4 |
177                 (priv->regs[R0C_MD5] & 0x0f); /* LO_Frac_2 */
178         ret = tda18218_wr_regs(priv, R0A_MD3, buf, 3);
179         if (ret)
180                 goto error;
181
182         buf[0] = priv->regs[R0F_MD8] | (1 << 6); /* Freq_prog_Start */
183         ret = tda18218_wr_regs(priv, R0F_MD8, buf, 1);
184         if (ret)
185                 goto error;
186
187         buf[0] = priv->regs[R0F_MD8] & ~(1 << 6); /* Freq_prog_Start */
188         ret = tda18218_wr_regs(priv, R0F_MD8, buf, 1);
189         if (ret)
190                 goto error;
191
192         /* trigger AGC */
193         for (i = 0; i < ARRAY_SIZE(agc); i++) {
194                 ret = tda18218_wr_reg(priv, agc[i][0], agc[i][1]);
195                 if (ret)
196                         goto error;
197         }
198
199 error:
200         if (fe->ops.i2c_gate_ctrl)
201                 fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
202
203         if (ret)
204                 dbg("%s: failed ret:%d", __func__, ret);
205
206         return ret;
207 }
208
209 static int tda18218_sleep(struct dvb_frontend *fe)
210 {
211         struct tda18218_priv *priv = fe->tuner_priv;
212         int ret;
213
214         if (fe->ops.i2c_gate_ctrl)
215                 fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */
216
217         /* standby */
218         ret = tda18218_wr_reg(priv, R17_PD1, priv->regs[R17_PD1] | (1 << 0));
219
220         if (fe->ops.i2c_gate_ctrl)
221                 fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
222
223         if (ret)
224                 dbg("%s: failed ret:%d", __func__, ret);
225
226         return ret;
227 }
228
229 static int tda18218_init(struct dvb_frontend *fe)
230 {
231         struct tda18218_priv *priv = fe->tuner_priv;
232         int ret;
233
234         /* TODO: calibrations */
235
236         if (fe->ops.i2c_gate_ctrl)
237                 fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */
238
239         ret = tda18218_wr_regs(priv, R00_ID, priv->regs, TDA18218_NUM_REGS);
240
241         if (fe->ops.i2c_gate_ctrl)
242                 fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
243
244         if (ret)
245                 dbg("%s: failed ret:%d", __func__, ret);
246
247         return ret;
248 }
249
250 static int tda18218_release(struct dvb_frontend *fe)
251 {
252         kfree(fe->tuner_priv);
253         fe->tuner_priv = NULL;
254         return 0;
255 }
256
257 static const struct dvb_tuner_ops tda18218_tuner_ops = {
258         .info = {
259                 .name           = "NXP TDA18218",
260
261                 .frequency_min  = 174000000,
262                 .frequency_max  = 864000000,
263                 .frequency_step =      1000,
264         },
265
266         .release       = tda18218_release,
267         .init          = tda18218_init,
268         .sleep         = tda18218_sleep,
269
270         .set_params    = tda18218_set_params,
271 };
272
273 struct dvb_frontend *tda18218_attach(struct dvb_frontend *fe,
274         struct i2c_adapter *i2c, struct tda18218_config *cfg)
275 {
276         struct tda18218_priv *priv = NULL;
277         u8 val;
278         int ret;
279         /* chip default registers values */
280         static u8 def_regs[] = {
281                 0xc0, 0x88, 0x00, 0x8e, 0x03, 0x00, 0x00, 0xd0, 0x00, 0x40,
282                 0x00, 0x00, 0x07, 0xff, 0x84, 0x09, 0x00, 0x13, 0x00, 0x00,
283                 0x01, 0x84, 0x09, 0xf0, 0x19, 0x0a, 0x8e, 0x69, 0x98, 0x01,
284                 0x00, 0x58, 0x10, 0x40, 0x8c, 0x00, 0x0c, 0x48, 0x85, 0xc9,
285                 0xa7, 0x00, 0x00, 0x00, 0x30, 0x81, 0x80, 0x00, 0x39, 0x00,
286                 0x8a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, 0xf6
287         };
288
289         priv = kzalloc(sizeof(struct tda18218_priv), GFP_KERNEL);
290         if (priv == NULL)
291                 return NULL;
292
293         priv->cfg = cfg;
294         priv->i2c = i2c;
295         fe->tuner_priv = priv;
296
297         if (fe->ops.i2c_gate_ctrl)
298                 fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */
299
300         /* check if the tuner is there */
301         ret = tda18218_rd_reg(priv, R00_ID, &val);
302         dbg("%s: ret:%d chip ID:%02x", __func__, ret, val);
303         if (ret || val != def_regs[R00_ID]) {
304                 kfree(priv);
305                 return NULL;
306         }
307
308         info("NXP TDA18218HN successfully identified.");
309
310         memcpy(&fe->ops.tuner_ops, &tda18218_tuner_ops,
311                 sizeof(struct dvb_tuner_ops));
312         memcpy(priv->regs, def_regs, sizeof(def_regs));
313
314         /* loop-through enabled chip default register values */
315         if (priv->cfg->loop_through) {
316                 priv->regs[R17_PD1] = 0xb0;
317                 priv->regs[R18_PD2] = 0x59;
318         }
319
320         /* standby */
321         ret = tda18218_wr_reg(priv, R17_PD1, priv->regs[R17_PD1] | (1 << 0));
322         if (ret)
323                 dbg("%s: failed ret:%d", __func__, ret);
324
325         if (fe->ops.i2c_gate_ctrl)
326                 fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
327
328         return fe;
329 }
330 EXPORT_SYMBOL(tda18218_attach);
331
332 MODULE_DESCRIPTION("NXP TDA18218HN silicon tuner driver");
333 MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
334 MODULE_LICENSE("GPL");