usbtuner: add Hauppauge 955Q USB tuner support
[linux-3.10.git] / drivers / media / tuners / si2157.c
1 /*
2  * Silicon Labs Si2146/2147/2148/2157/2158 silicon tuner driver
3  *
4  * Copyright (C) 2014 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
17 #include "si2157_priv.h"
18
19 static const struct dvb_tuner_ops si2157_ops;
20
21 /* si2157_i2c_master_send - issue a single I2C message in master transmit mode */
22 static int si2157_i2c_master_send(struct i2c_adapter *adap, u8 i2c_addr,
23                                   const char *buf, int count)
24 {
25         int ret;
26         struct i2c_msg msg;
27
28         msg.addr = i2c_addr;
29         msg.flags = 0;
30         msg.len = count;
31         msg.buf = (char *)buf;
32
33         ret = i2c_transfer(adap, &msg, 1);
34
35         /*
36          * If everything went ok (i.e. 1 msg transmitted), return #bytes
37          * transmitted, else error code.
38          */
39         return (ret == 1) ? count : ret;
40 }
41
42 /* si2157_i2c_master_recv - issue a single I2C message in master receive mode */
43 static int si2157_i2c_master_recv(struct i2c_adapter *adap, u8 i2c_addr,
44                                   char *buf, int count)
45 {
46         struct i2c_msg msg;
47         int ret;
48
49         msg.addr = i2c_addr;
50         msg.flags = I2C_M_RD;
51         msg.len = count;
52         msg.buf = buf;
53
54         ret = i2c_transfer(adap, &msg, 1);
55
56         /*
57          * If everything went ok (i.e. 1 msg received), return #bytes received,
58          * else error code.
59          */
60         return (ret == 1) ? count : ret;
61 }
62
63 /* execute firmware command */
64 static int si2157_cmd_execute(struct si2157_dev *dev, struct si2157_cmd *cmd)
65 {
66         int ret;
67         unsigned long timeout;
68
69         mutex_lock(&dev->i2c_mutex);
70
71         if (cmd->wlen) {
72                 /* write cmd and args for firmware */
73                 ret = si2157_i2c_master_send(dev->i2c_adap, dev->i2c_addr,
74                                                                          cmd->args, cmd->wlen);
75                 if (ret < 0) {
76                         goto err_mutex_unlock;
77                 } else if (ret != cmd->wlen) {
78                         ret = -EREMOTEIO;
79                         goto err_mutex_unlock;
80                 }
81         }
82
83         if (cmd->rlen) {
84                 /* wait cmd execution terminate */
85                 #define TIMEOUT 80
86                 timeout = jiffies + msecs_to_jiffies(TIMEOUT);
87                 while (!time_after(jiffies, timeout)) {
88                         ret = si2157_i2c_master_recv(dev->i2c_adap, dev->i2c_addr,
89                                                                                  cmd->args, cmd->rlen);
90                         if (ret < 0) {
91                                 goto err_mutex_unlock;
92                         } else if (ret != cmd->rlen) {
93                                 ret = -EREMOTEIO;
94                                 goto err_mutex_unlock;
95                         }
96
97                         /* firmware ready? */
98                         if ((cmd->args[0] >> 7) & 0x01)
99                                 break;
100                 }
101
102                 dev_dbg(&dev->i2c_adap->dev, "cmd execution took %d ms\n",
103                                 jiffies_to_msecs(jiffies) -
104                                 (jiffies_to_msecs(timeout) - TIMEOUT));
105
106                 if (!((cmd->args[0] >> 7) & 0x01)) {
107                         ret = -ETIMEDOUT;
108                         goto err_mutex_unlock;
109                 }
110         }
111
112         mutex_unlock(&dev->i2c_mutex);
113         return 0;
114
115 err_mutex_unlock:
116         mutex_unlock(&dev->i2c_mutex);
117         dev_dbg(&dev->i2c_adap->dev, "failed=%d\n", ret);
118         return ret;
119 }
120
121 static int si2157_init(struct dvb_frontend *fe)
122 {
123         struct si2157_dev *dev = fe->tuner_priv;
124         int ret, len, remaining;
125         struct si2157_cmd cmd;
126         const struct firmware *fw;
127         const char *fw_name;
128         unsigned int chip_id;
129
130         dev_dbg(&dev->i2c_adap->dev, "\n");
131
132         if (dev->fw_loaded)
133                 goto warm;
134
135         /* power up */
136         if (dev->chiptype == SI2157_CHIPTYPE_SI2146) {
137                 memcpy(cmd.args, "\xc0\x05\x01\x00\x00\x0b\x00\x00\x01", 9);
138                 cmd.wlen = 9;
139         } else {
140                 memcpy(cmd.args, "\xc0\x00\x0c\x00\x00\x01\x01\x01\x01\x01\x01\x02\x00\x00\x01", 15);
141                 cmd.wlen = 15;
142         }
143         cmd.rlen = 1;
144         ret = si2157_cmd_execute(dev, &cmd);
145         if (ret)
146                 goto err;
147
148         /* query chip revision */
149         memcpy(cmd.args, "\x02", 1);
150         cmd.wlen = 1;
151         cmd.rlen = 13;
152         ret = si2157_cmd_execute(dev, &cmd);
153         if (ret)
154                 goto err;
155
156         chip_id = cmd.args[1] << 24 | cmd.args[2] << 16 | cmd.args[3] << 8 |
157                         cmd.args[4] << 0;
158
159         #define SI2158_A20 ('A' << 24 | 58 << 16 | '2' << 8 | '0' << 0)
160         #define SI2148_A20 ('A' << 24 | 48 << 16 | '2' << 8 | '0' << 0)
161         #define SI2157_A30 ('A' << 24 | 57 << 16 | '3' << 8 | '0' << 0)
162         #define SI2147_A30 ('A' << 24 | 47 << 16 | '3' << 8 | '0' << 0)
163         #define SI2146_A10 ('A' << 24 | 46 << 16 | '1' << 8 | '0' << 0)
164
165         switch (chip_id) {
166         case SI2158_A20:
167         case SI2148_A20:
168                 fw_name = SI2158_A20_FIRMWARE;
169                 break;
170         case SI2157_A30:
171         case SI2147_A30:
172         case SI2146_A10:
173                 fw_name = NULL;
174                 break;
175         default:
176                 dev_err(&dev->i2c_adap->dev,
177                         "unknown chip version Si21%d-%c%c%c\n", cmd.args[2],
178                         cmd.args[1], cmd.args[3], cmd.args[4]);
179                 ret = -EINVAL;
180                 goto err;
181         }
182
183         dev_info(&dev->i2c_adap->dev, "found a 'Silicon Labs Si21%d-%c%c%c'\n",
184                         cmd.args[2], cmd.args[1], cmd.args[3], cmd.args[4]);
185
186         if (fw_name == NULL)
187                 goto skip_fw_download;
188
189         /* request the firmware, this will block and timeout */
190         ret = request_firmware(&fw, fw_name, &dev->i2c_adap->dev);
191         if (ret) {
192                 dev_err(&dev->i2c_adap->dev, "firmware file '%s' not found\n",
193                                 fw_name);
194                 goto err;
195         }
196
197         /* firmware should be n chunks of 17 bytes */
198         if (fw->size % 17 != 0) {
199                 dev_err(&dev->i2c_adap->dev, "firmware file '%s' is invalid\n",
200                                 fw_name);
201                 ret = -EINVAL;
202                 goto err_release_firmware;
203         }
204
205         dev_info(&dev->i2c_adap->dev, "downloading firmware from file '%s'\n",
206                         fw_name);
207
208         for (remaining = fw->size; remaining > 0; remaining -= 17) {
209                 len = fw->data[fw->size - remaining];
210                 memcpy(cmd.args, &fw->data[(fw->size - remaining) + 1], len);
211                 cmd.wlen = len;
212                 cmd.rlen = 1;
213                 ret = si2157_cmd_execute(dev, &cmd);
214                 if (ret) {
215                         dev_err(&dev->i2c_adap->dev, "firmware download failed %d\n",
216                                         ret);
217                         goto err_release_firmware;
218                 }
219         }
220
221         release_firmware(fw);
222
223 skip_fw_download:
224         /* reboot the tuner with new firmware? */
225         memcpy(cmd.args, "\x01\x01", 2);
226         cmd.wlen = 2;
227         cmd.rlen = 1;
228         ret = si2157_cmd_execute(dev, &cmd);
229         if (ret)
230                 goto err;
231
232         /* query firmware version */
233         memcpy(cmd.args, "\x11", 1);
234         cmd.wlen = 1;
235         cmd.rlen = 10;
236         ret = si2157_cmd_execute(dev, &cmd);
237         if (ret)
238                 goto err;
239
240         dev_info(&dev->i2c_adap->dev, "firmware version: %c.%c.%d\n",
241                         cmd.args[6], cmd.args[7], cmd.args[8]);
242
243         dev->fw_loaded = true;
244
245 warm:
246         dev->active = true;
247         return 0;
248
249 err_release_firmware:
250         release_firmware(fw);
251 err:
252         dev_dbg(&dev->i2c_adap->dev, "failed=%d\n", ret);
253         return ret;
254 }
255
256 static int si2157_sleep(struct dvb_frontend *fe)
257 {
258         struct si2157_dev *dev = fe->tuner_priv;
259         int ret;
260         struct si2157_cmd cmd;
261
262         dev_dbg(&dev->i2c_adap->dev, "\n");
263
264         dev->active = false;
265
266         /* standby */
267         memcpy(cmd.args, "\x16\x00", 2);
268         cmd.wlen = 2;
269         cmd.rlen = 1;
270         ret = si2157_cmd_execute(dev, &cmd);
271         if (ret)
272                 goto err;
273
274         return 0;
275 err:
276         dev_dbg(&dev->i2c_adap->dev, "failed=%d\n", ret);
277         return ret;
278 }
279
280 static int si2157_set_params(struct dvb_frontend *fe)
281 {
282         struct si2157_dev *dev = fe->tuner_priv;
283         struct dtv_frontend_properties *c = &fe->dtv_property_cache;
284         int ret;
285         struct si2157_cmd cmd;
286         u8 bandwidth, delivery_system;
287         u32 if_frequency = 5000000;
288
289         dev_dbg(&dev->i2c_adap->dev,
290                         "delivery_system=%d frequency=%u bandwidth_hz=%u\n",
291                         c->delivery_system, c->frequency, c->bandwidth_hz);
292
293         if (!dev->active) {
294                 ret = -EAGAIN;
295                 goto err;
296         }
297
298         if (c->bandwidth_hz <= 6000000)
299                 bandwidth = 0x06;
300         else if (c->bandwidth_hz <= 7000000)
301                 bandwidth = 0x07;
302         else if (c->bandwidth_hz <= 8000000)
303                 bandwidth = 0x08;
304         else
305                 bandwidth = 0x0f;
306
307         switch (c->delivery_system) {
308         case SYS_ATSC:
309                         delivery_system = 0x00;
310                         if_frequency = 3250000;
311                         break;
312         case SYS_DVBC_ANNEX_B:
313                         delivery_system = 0x10;
314                         if_frequency = 4000000;
315                         break;
316         case SYS_DVBT:
317         case SYS_DVBT2: /* it seems DVB-T and DVB-T2 both are 0x20 here */
318                         delivery_system = 0x20;
319                         break;
320         case SYS_DVBC_ANNEX_A:
321                         delivery_system = 0x30;
322                         break;
323         default:
324                         ret = -EINVAL;
325                         goto err;
326         }
327
328         memcpy(cmd.args, "\x14\x00\x03\x07\x00\x00", 6);
329         cmd.args[4] = delivery_system | bandwidth;
330         if (dev->inversion)
331                 cmd.args[5] = 0x01;
332         cmd.wlen = 6;
333         cmd.rlen = 4;
334         ret = si2157_cmd_execute(dev, &cmd);
335         if (ret)
336                 goto err;
337
338         if (dev->chiptype == SI2157_CHIPTYPE_SI2146)
339                 memcpy(cmd.args, "\x14\x00\x02\x07\x00\x01", 6);
340         else
341                 memcpy(cmd.args, "\x14\x00\x02\x07\x01\x00", 6);
342         cmd.wlen = 6;
343         cmd.rlen = 4;
344         ret = si2157_cmd_execute(dev, &cmd);
345         if (ret)
346                 goto err;
347
348         /* set if frequency if needed */
349         if (if_frequency != dev->if_frequency) {
350                 memcpy(cmd.args, "\x14\x00\x06\x07", 4);
351                 cmd.args[4] = (if_frequency / 1000) & 0xff;
352                 cmd.args[5] = ((if_frequency / 1000) >> 8) & 0xff;
353                 cmd.wlen = 6;
354                 cmd.rlen = 4;
355                 ret = si2157_cmd_execute(dev, &cmd);
356                 if (ret)
357                         goto err;
358
359                 dev->if_frequency = if_frequency;
360         }
361
362         /* set frequency */
363         memcpy(cmd.args, "\x41\x00\x00\x00\x00\x00\x00\x00", 8);
364         cmd.args[4] = (c->frequency >>  0) & 0xff;
365         cmd.args[5] = (c->frequency >>  8) & 0xff;
366         cmd.args[6] = (c->frequency >> 16) & 0xff;
367         cmd.args[7] = (c->frequency >> 24) & 0xff;
368         cmd.wlen = 8;
369         cmd.rlen = 1;
370         ret = si2157_cmd_execute(dev, &cmd);
371         if (ret)
372                 goto err;
373
374         return 0;
375 err:
376         dev_dbg(&dev->i2c_adap->dev, "failed=%d\n", ret);
377         return ret;
378 }
379
380 static int si2157_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
381 {
382         struct si2157_dev *dev = fe->tuner_priv;
383
384         *frequency = dev->if_frequency;
385         return 0;
386 }
387
388 static int si2157_release(struct dvb_frontend *fe)
389 {
390         struct si2157_dev *dev = fe->tuner_priv;
391
392         dev_dbg(&dev->i2c_adap->dev, "%s:\n", __func__);
393
394         kfree(fe->tuner_priv);
395
396         return 0;
397 }
398
399 static const struct dvb_tuner_ops si2157_ops = {
400         .info = {
401                 .name           = "Silicon Labs Si2146/2147/2148/2157/2158",
402                 .frequency_min  = 55000000,
403                 .frequency_max  = 862000000,
404         },
405
406         .release = si2157_release,
407         .init = si2157_init,
408         .sleep = si2157_sleep,
409         .set_params = si2157_set_params,
410         .get_if_frequency = si2157_get_if_frequency,
411 };
412
413 struct dvb_frontend *si2157_attach(struct dvb_frontend *fe,
414                 struct i2c_adapter *i2c, const struct si2157_config *cfg)
415 {
416         struct si2157_dev *dev;
417         struct si2157_cmd cmd;
418         int ret;
419
420         if (!cfg) {
421                 dev_err(&i2c->dev, "no configuration submitted\n");
422                 goto err;
423         }
424
425         dev = kzalloc(sizeof(*dev), GFP_KERNEL);
426         if (!dev) {
427                 ret = -ENOMEM;
428                 dev_err(&i2c->dev, "%s: kzalloc() failed\n", KBUILD_MODNAME);
429                 goto err;
430         }
431
432         dev->i2c_adap = i2c;
433         dev->i2c_addr = cfg->i2c_addr;
434         dev->inversion = cfg->inversion;
435         dev->fw_loaded = false;
436         dev->chiptype = SI2157_CHIPTYPE_SI2157; /* (u8)id->driver_data; */
437         dev->if_frequency = 5000000; /* default value of property 0x0706 */
438         mutex_init(&dev->i2c_mutex);
439
440         /* check if the tuner is there */
441         cmd.wlen = 0;
442         cmd.rlen = 1;
443         ret = si2157_cmd_execute(dev, &cmd);
444         if (ret)
445                 goto err_kfree;
446
447         memcpy(&fe->ops.tuner_ops, &si2157_ops, sizeof(struct dvb_tuner_ops));
448         fe->tuner_priv = dev;
449
450         dev_info(&i2c->dev, "%s: Silicon Labs %s successfully attached\n",
451                         KBUILD_MODNAME, dev->chiptype == SI2157_CHIPTYPE_SI2146 ?
452                         "Si2146" : "Si2147/2148/2157/2158");
453
454         return fe;
455
456 err_kfree:
457         kfree(dev);
458 err:
459         dev_dbg(&i2c->dev, "failed=%d\n", ret);
460         return NULL;
461 }
462 EXPORT_SYMBOL(si2157_attach);
463
464 MODULE_DESCRIPTION("Silicon Labs Si2146/2147/2148/2157/2158 silicon tuner driver");
465 MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
466 MODULE_LICENSE("GPL");
467 MODULE_FIRMWARE(SI2158_A20_FIRMWARE);