[media] tda18212: Use standard logging, remove tda18212_priv.h
[pandora-kernel.git] / drivers / media / common / tuners / tda18212.c
1 /*
2  * NXP TDA18212HN silicon tuner driver
3  *
4  * Copyright (C) 2011 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 along
17  *    with this program; if not, write to the Free Software Foundation, Inc.,
18  *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19  */
20
21 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
22
23 #include "tda18212.h"
24
25 struct tda18212_priv {
26         struct tda18212_config *cfg;
27         struct i2c_adapter *i2c;
28 };
29
30 #define dbg(fmt, arg...)                                        \
31 do {                                                            \
32         if (debug)                                              \
33                 pr_info("%s: " fmt, __func__, ##arg);           \
34 } while (0)
35
36 static int debug;
37 module_param(debug, int, 0644);
38 MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
39
40 /* write multiple registers */
41 static int tda18212_wr_regs(struct tda18212_priv *priv, u8 reg, u8 *val,
42         int len)
43 {
44         int ret;
45         u8 buf[len+1];
46         struct i2c_msg msg[1] = {
47                 {
48                         .addr = priv->cfg->i2c_address,
49                         .flags = 0,
50                         .len = sizeof(buf),
51                         .buf = buf,
52                 }
53         };
54
55         buf[0] = reg;
56         memcpy(&buf[1], val, len);
57
58         ret = i2c_transfer(priv->i2c, msg, 1);
59         if (ret == 1) {
60                 ret = 0;
61         } else {
62                 pr_warn("i2c wr failed ret:%d reg:%02x len:%d\n",
63                         ret, reg, len);
64                 ret = -EREMOTEIO;
65         }
66         return ret;
67 }
68
69 /* read multiple registers */
70 static int tda18212_rd_regs(struct tda18212_priv *priv, u8 reg, u8 *val,
71         int len)
72 {
73         int ret;
74         u8 buf[len];
75         struct i2c_msg msg[2] = {
76                 {
77                         .addr = priv->cfg->i2c_address,
78                         .flags = 0,
79                         .len = 1,
80                         .buf = &reg,
81                 }, {
82                         .addr = priv->cfg->i2c_address,
83                         .flags = I2C_M_RD,
84                         .len = sizeof(buf),
85                         .buf = buf,
86                 }
87         };
88
89         ret = i2c_transfer(priv->i2c, msg, 2);
90         if (ret == 2) {
91                 memcpy(val, buf, len);
92                 ret = 0;
93         } else {
94                 pr_warn("i2c rd failed ret:%d reg:%02x len:%d\n",
95                         ret, reg, len);
96                 ret = -EREMOTEIO;
97         }
98
99         return ret;
100 }
101
102 /* write single register */
103 static int tda18212_wr_reg(struct tda18212_priv *priv, u8 reg, u8 val)
104 {
105         return tda18212_wr_regs(priv, reg, &val, 1);
106 }
107
108 /* read single register */
109 static int tda18212_rd_reg(struct tda18212_priv *priv, u8 reg, u8 *val)
110 {
111         return tda18212_rd_regs(priv, reg, val, 1);
112 }
113
114 #if 0 /* keep, useful when developing driver */
115 static void tda18212_dump_regs(struct tda18212_priv *priv)
116 {
117         int i;
118         u8 buf[256];
119
120         #define TDA18212_RD_LEN 32
121         for (i = 0; i < sizeof(buf); i += TDA18212_RD_LEN)
122                 tda18212_rd_regs(priv, i, &buf[i], TDA18212_RD_LEN);
123
124         print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 32, 1, buf,
125                 sizeof(buf), true);
126
127         return;
128 }
129 #endif
130
131 static int tda18212_set_params(struct dvb_frontend *fe,
132         struct dvb_frontend_parameters *p)
133 {
134         struct tda18212_priv *priv = fe->tuner_priv;
135         struct dtv_frontend_properties *c = &fe->dtv_property_cache;
136         int ret, i;
137         u32 if_khz;
138         u8 buf[9];
139         static const u8 bw_params[][3] = {
140                 /*  0f    13    23 */
141                 { 0xb3, 0x20, 0x03 }, /* DVB-T 6 MHz */
142                 { 0xb3, 0x31, 0x01 }, /* DVB-T 7 MHz */
143                 { 0xb3, 0x22, 0x01 }, /* DVB-T 8 MHz */
144                 { 0x92, 0x53, 0x03 }, /* DVB-C */
145         };
146
147         dbg("delsys=%d RF=%d BW=%d\n",
148             c->delivery_system, c->frequency, c->bandwidth_hz);
149
150         if (fe->ops.i2c_gate_ctrl)
151                 fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */
152
153         switch (c->delivery_system) {
154         case SYS_DVBT:
155                 switch (c->bandwidth_hz) {
156                 case 6000000:
157                         if_khz = priv->cfg->if_dvbt_6;
158                         i = 0;
159                         break;
160                 case 7000000:
161                         if_khz = priv->cfg->if_dvbt_7;
162                         i = 1;
163                         break;
164                 case 8000000:
165                         if_khz = priv->cfg->if_dvbt_8;
166                         i = 2;
167                         break;
168                 default:
169                         ret = -EINVAL;
170                         goto error;
171                 }
172                 break;
173         case SYS_DVBC_ANNEX_AC:
174                 if_khz = priv->cfg->if_dvbc;
175                 i = 3;
176                 break;
177         default:
178                 ret = -EINVAL;
179                 goto error;
180         }
181
182         ret = tda18212_wr_reg(priv, 0x23, bw_params[i][2]);
183         if (ret)
184                 goto error;
185
186         ret = tda18212_wr_reg(priv, 0x06, 0x00);
187         if (ret)
188                 goto error;
189
190         ret = tda18212_wr_reg(priv, 0x0f, bw_params[i][0]);
191         if (ret)
192                 goto error;
193
194         buf[0] = 0x02;
195         buf[1] = bw_params[i][1];
196         buf[2] = 0x03; /* default value */
197         buf[3] = if_khz / 50;
198         buf[4] = ((c->frequency / 1000) >> 16) & 0xff;
199         buf[5] = ((c->frequency / 1000) >>  8) & 0xff;
200         buf[6] = ((c->frequency / 1000) >>  0) & 0xff;
201         buf[7] = 0xc1;
202         buf[8] = 0x01;
203         ret = tda18212_wr_regs(priv, 0x12, buf, sizeof(buf));
204         if (ret)
205                 goto error;
206
207 exit:
208         if (fe->ops.i2c_gate_ctrl)
209                 fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
210
211         return ret;
212
213 error:
214         dbg("failed:%d\n", ret);
215         goto exit;
216 }
217
218 static int tda18212_release(struct dvb_frontend *fe)
219 {
220         kfree(fe->tuner_priv);
221         fe->tuner_priv = NULL;
222         return 0;
223 }
224
225 static const struct dvb_tuner_ops tda18212_tuner_ops = {
226         .info = {
227                 .name           = "NXP TDA18212",
228
229                 .frequency_min  =  48000000,
230                 .frequency_max  = 864000000,
231                 .frequency_step =      1000,
232         },
233
234         .release       = tda18212_release,
235
236         .set_params    = tda18212_set_params,
237 };
238
239 struct dvb_frontend *tda18212_attach(struct dvb_frontend *fe,
240         struct i2c_adapter *i2c, struct tda18212_config *cfg)
241 {
242         struct tda18212_priv *priv = NULL;
243         int ret;
244         u8 val;
245
246         priv = kzalloc(sizeof(struct tda18212_priv), GFP_KERNEL);
247         if (priv == NULL)
248                 return NULL;
249
250         priv->cfg = cfg;
251         priv->i2c = i2c;
252         fe->tuner_priv = priv;
253
254         if (fe->ops.i2c_gate_ctrl)
255                 fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */
256
257         /* check if the tuner is there */
258         ret = tda18212_rd_reg(priv, 0x00, &val);
259
260         if (fe->ops.i2c_gate_ctrl)
261                 fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
262
263         dbg("ret:%d chip ID:%02x\n", ret, val);
264         if (ret || val != 0xc7) {
265                 kfree(priv);
266                 return NULL;
267         }
268
269         pr_info("NXP TDA18212HN successfully identified\n");
270
271         memcpy(&fe->ops.tuner_ops, &tda18212_tuner_ops,
272                 sizeof(struct dvb_tuner_ops));
273
274         return fe;
275 }
276 EXPORT_SYMBOL(tda18212_attach);
277
278 MODULE_DESCRIPTION("NXP TDA18212HN silicon tuner driver");
279 MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
280 MODULE_LICENSE("GPL");