]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/media/tuners/tda18212.c
Merge remote-tracking branch 'v9fs/for-next'
[karo-tx-linux.git] / drivers / media / 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 #include "tda18212.h"
22 #include <linux/regmap.h>
23
24 struct tda18212_dev {
25         struct tda18212_config cfg;
26         struct i2c_client *client;
27         struct regmap *regmap;
28
29         u32 if_frequency;
30 };
31
32 static int tda18212_set_params(struct dvb_frontend *fe)
33 {
34         struct tda18212_dev *dev = fe->tuner_priv;
35         struct dtv_frontend_properties *c = &fe->dtv_property_cache;
36         int ret, i;
37         u32 if_khz;
38         u8 buf[9];
39         #define DVBT_6   0
40         #define DVBT_7   1
41         #define DVBT_8   2
42         #define DVBT2_6  3
43         #define DVBT2_7  4
44         #define DVBT2_8  5
45         #define DVBC_6   6
46         #define DVBC_8   7
47         #define ATSC_VSB 8
48         #define ATSC_QAM 9
49         static const u8 bw_params[][3] = {
50                      /* reg:   0f    13    23 */
51                 [DVBT_6]  = { 0xb3, 0x20, 0x03 },
52                 [DVBT_7]  = { 0xb3, 0x31, 0x01 },
53                 [DVBT_8]  = { 0xb3, 0x22, 0x01 },
54                 [DVBT2_6] = { 0xbc, 0x20, 0x03 },
55                 [DVBT2_7] = { 0xbc, 0x72, 0x03 },
56                 [DVBT2_8] = { 0xbc, 0x22, 0x01 },
57                 [DVBC_6]  = { 0x92, 0x50, 0x03 },
58                 [DVBC_8]  = { 0x92, 0x53, 0x03 },
59                 [ATSC_VSB] = { 0x7d, 0x20, 0x63 },
60                 [ATSC_QAM] = { 0x7d, 0x20, 0x63 },
61         };
62
63         dev_dbg(&dev->client->dev,
64                         "delivery_system=%d frequency=%d bandwidth_hz=%d\n",
65                         c->delivery_system, c->frequency,
66                         c->bandwidth_hz);
67
68         if (fe->ops.i2c_gate_ctrl)
69                 fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */
70
71         switch (c->delivery_system) {
72         case SYS_ATSC:
73                 if_khz = dev->cfg.if_atsc_vsb;
74                 i = ATSC_VSB;
75                 break;
76         case SYS_DVBC_ANNEX_B:
77                 if_khz = dev->cfg.if_atsc_qam;
78                 i = ATSC_QAM;
79                 break;
80         case SYS_DVBT:
81                 switch (c->bandwidth_hz) {
82                 case 6000000:
83                         if_khz = dev->cfg.if_dvbt_6;
84                         i = DVBT_6;
85                         break;
86                 case 7000000:
87                         if_khz = dev->cfg.if_dvbt_7;
88                         i = DVBT_7;
89                         break;
90                 case 8000000:
91                         if_khz = dev->cfg.if_dvbt_8;
92                         i = DVBT_8;
93                         break;
94                 default:
95                         ret = -EINVAL;
96                         goto error;
97                 }
98                 break;
99         case SYS_DVBT2:
100                 switch (c->bandwidth_hz) {
101                 case 6000000:
102                         if_khz = dev->cfg.if_dvbt2_6;
103                         i = DVBT2_6;
104                         break;
105                 case 7000000:
106                         if_khz = dev->cfg.if_dvbt2_7;
107                         i = DVBT2_7;
108                         break;
109                 case 8000000:
110                         if_khz = dev->cfg.if_dvbt2_8;
111                         i = DVBT2_8;
112                         break;
113                 default:
114                         ret = -EINVAL;
115                         goto error;
116                 }
117                 break;
118         case SYS_DVBC_ANNEX_A:
119         case SYS_DVBC_ANNEX_C:
120                 if_khz = dev->cfg.if_dvbc;
121                 i = DVBC_8;
122                 break;
123         default:
124                 ret = -EINVAL;
125                 goto error;
126         }
127
128         ret = regmap_write(dev->regmap, 0x23, bw_params[i][2]);
129         if (ret)
130                 goto error;
131
132         ret = regmap_write(dev->regmap, 0x06, 0x00);
133         if (ret)
134                 goto error;
135
136         ret = regmap_write(dev->regmap, 0x0f, bw_params[i][0]);
137         if (ret)
138                 goto error;
139
140         buf[0] = 0x02;
141         buf[1] = bw_params[i][1];
142         buf[2] = 0x03; /* default value */
143         buf[3] = DIV_ROUND_CLOSEST(if_khz, 50);
144         buf[4] = ((c->frequency / 1000) >> 16) & 0xff;
145         buf[5] = ((c->frequency / 1000) >>  8) & 0xff;
146         buf[6] = ((c->frequency / 1000) >>  0) & 0xff;
147         buf[7] = 0xc1;
148         buf[8] = 0x01;
149         ret = regmap_bulk_write(dev->regmap, 0x12, buf, sizeof(buf));
150         if (ret)
151                 goto error;
152
153         /* actual IF rounded as it is on register */
154         dev->if_frequency = buf[3] * 50 * 1000;
155
156 exit:
157         if (fe->ops.i2c_gate_ctrl)
158                 fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
159
160         return ret;
161
162 error:
163         dev_dbg(&dev->client->dev, "failed=%d\n", ret);
164         goto exit;
165 }
166
167 static int tda18212_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
168 {
169         struct tda18212_dev *dev = fe->tuner_priv;
170
171         *frequency = dev->if_frequency;
172
173         return 0;
174 }
175
176 static const struct dvb_tuner_ops tda18212_tuner_ops = {
177         .info = {
178                 .name           = "NXP TDA18212",
179
180                 .frequency_min  =  48000000,
181                 .frequency_max  = 864000000,
182                 .frequency_step =      1000,
183         },
184
185         .set_params    = tda18212_set_params,
186         .get_if_frequency = tda18212_get_if_frequency,
187 };
188
189 static int tda18212_probe(struct i2c_client *client,
190                 const struct i2c_device_id *id)
191 {
192         struct tda18212_config *cfg = client->dev.platform_data;
193         struct dvb_frontend *fe = cfg->fe;
194         struct tda18212_dev *dev;
195         int ret;
196         unsigned int chip_id;
197         char *version;
198         static const struct regmap_config regmap_config = {
199                 .reg_bits = 8,
200                 .val_bits = 8,
201         };
202
203         dev = kzalloc(sizeof(*dev), GFP_KERNEL);
204         if (dev == NULL) {
205                 ret = -ENOMEM;
206                 dev_err(&client->dev, "kzalloc() failed\n");
207                 goto err;
208         }
209
210         memcpy(&dev->cfg, cfg, sizeof(struct tda18212_config));
211         dev->client = client;
212         dev->regmap = devm_regmap_init_i2c(client, &regmap_config);
213         if (IS_ERR(dev->regmap)) {
214                 ret = PTR_ERR(dev->regmap);
215                 goto err;
216         }
217
218         /* check if the tuner is there */
219         if (fe->ops.i2c_gate_ctrl)
220                 fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */
221
222         ret = regmap_read(dev->regmap, 0x00, &chip_id);
223         dev_dbg(&dev->client->dev, "chip_id=%02x\n", chip_id);
224
225         if (fe->ops.i2c_gate_ctrl)
226                 fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
227
228         if (ret)
229                 goto err;
230
231         switch (chip_id) {
232         case 0xc7:
233                 version = "M"; /* master */
234                 break;
235         case 0x47:
236                 version = "S"; /* slave */
237                 break;
238         default:
239                 ret = -ENODEV;
240                 goto err;
241         }
242
243         dev_info(&dev->client->dev,
244                         "NXP TDA18212HN/%s successfully identified\n", version);
245
246         fe->tuner_priv = dev;
247         memcpy(&fe->ops.tuner_ops, &tda18212_tuner_ops,
248                         sizeof(struct dvb_tuner_ops));
249         i2c_set_clientdata(client, dev);
250
251         return 0;
252 err:
253         dev_dbg(&client->dev, "failed=%d\n", ret);
254         kfree(dev);
255         return ret;
256 }
257
258 static int tda18212_remove(struct i2c_client *client)
259 {
260         struct tda18212_dev *dev = i2c_get_clientdata(client);
261         struct dvb_frontend *fe = dev->cfg.fe;
262
263         dev_dbg(&client->dev, "\n");
264
265         memset(&fe->ops.tuner_ops, 0, sizeof(struct dvb_tuner_ops));
266         fe->tuner_priv = NULL;
267         kfree(dev);
268
269         return 0;
270 }
271
272 static const struct i2c_device_id tda18212_id[] = {
273         {"tda18212", 0},
274         {}
275 };
276 MODULE_DEVICE_TABLE(i2c, tda18212_id);
277
278 static struct i2c_driver tda18212_driver = {
279         .driver = {
280                 .name   = "tda18212",
281         },
282         .probe          = tda18212_probe,
283         .remove         = tda18212_remove,
284         .id_table       = tda18212_id,
285 };
286
287 module_i2c_driver(tda18212_driver);
288
289 MODULE_DESCRIPTION("NXP TDA18212HN silicon tuner driver");
290 MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
291 MODULE_LICENSE("GPL");