Merge tag 'for-linus-5.11-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux-2.6-microblaze.git] / drivers / media / tuners / si2157.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Silicon Labs Si2146/2147/2148/2157/2158 silicon tuner driver
4  *
5  * Copyright (C) 2014 Antti Palosaari <crope@iki.fi>
6  */
7
8 #include "si2157_priv.h"
9
10 static const struct dvb_tuner_ops si2157_ops;
11
12 static int tuner_lock_debug;
13 module_param(tuner_lock_debug, int, 0644);
14 MODULE_PARM_DESC(tuner_lock_debug, "if set, signal lock is briefly waited on after setting params");
15
16 /* execute firmware command */
17 static int si2157_cmd_execute(struct i2c_client *client, struct si2157_cmd *cmd)
18 {
19         struct si2157_dev *dev = i2c_get_clientdata(client);
20         int ret;
21         unsigned long timeout;
22
23         mutex_lock(&dev->i2c_mutex);
24
25         if (cmd->wlen) {
26                 /* write cmd and args for firmware */
27                 ret = i2c_master_send(client, cmd->args, cmd->wlen);
28                 if (ret < 0) {
29                         goto err_mutex_unlock;
30                 } else if (ret != cmd->wlen) {
31                         ret = -EREMOTEIO;
32                         goto err_mutex_unlock;
33                 }
34         }
35
36         if (cmd->rlen) {
37                 /* wait cmd execution terminate */
38                 #define TIMEOUT 80
39                 timeout = jiffies + msecs_to_jiffies(TIMEOUT);
40                 while (!time_after(jiffies, timeout)) {
41                         ret = i2c_master_recv(client, cmd->args, cmd->rlen);
42                         if (ret < 0) {
43                                 goto err_mutex_unlock;
44                         } else if (ret != cmd->rlen) {
45                                 ret = -EREMOTEIO;
46                                 goto err_mutex_unlock;
47                         }
48
49                         /* firmware ready? */
50                         if ((cmd->args[0] >> 7) & 0x01)
51                                 break;
52                 }
53
54                 dev_dbg(&client->dev, "cmd execution took %d ms, status=%x\n",
55                         jiffies_to_msecs(jiffies) -
56                         (jiffies_to_msecs(timeout) - TIMEOUT),
57                         cmd->args[0]);
58
59                 if (!((cmd->args[0] >> 7) & 0x01)) {
60                         ret = -ETIMEDOUT;
61                         goto err_mutex_unlock;
62                 }
63                 /* check error status bit */
64                 if (cmd->args[0] & 0x40) {
65                         ret = -EAGAIN;
66                         goto err_mutex_unlock;
67                 }
68         }
69
70         mutex_unlock(&dev->i2c_mutex);
71         return 0;
72
73 err_mutex_unlock:
74         mutex_unlock(&dev->i2c_mutex);
75         dev_dbg(&client->dev, "failed=%d\n", ret);
76         return ret;
77 }
78
79 static int si2157_init(struct dvb_frontend *fe)
80 {
81         struct i2c_client *client = fe->tuner_priv;
82         struct si2157_dev *dev = i2c_get_clientdata(client);
83         struct dtv_frontend_properties *c = &fe->dtv_property_cache;
84         int ret, len, remaining;
85         struct si2157_cmd cmd;
86         const struct firmware *fw;
87         const char *fw_name;
88         unsigned int chip_id, xtal_trim;
89
90         dev_dbg(&client->dev, "\n");
91
92         /* Try to get Xtal trim property, to verify tuner still running */
93         memcpy(cmd.args, "\x15\x00\x04\x02", 4);
94         cmd.wlen = 4;
95         cmd.rlen = 4;
96         ret = si2157_cmd_execute(client, &cmd);
97
98         xtal_trim = cmd.args[2] | (cmd.args[3] << 8);
99
100         if (ret == 0 && xtal_trim < 16)
101                 goto warm;
102
103         dev->if_frequency = 0; /* we no longer know current tuner state */
104
105         /* power up */
106         if (dev->chiptype == SI2157_CHIPTYPE_SI2146) {
107                 memcpy(cmd.args, "\xc0\x05\x01\x00\x00\x0b\x00\x00\x01", 9);
108                 cmd.wlen = 9;
109         } else if (dev->chiptype == SI2157_CHIPTYPE_SI2141) {
110                 memcpy(cmd.args, "\xc0\x00\x0d\x0e\x00\x01\x01\x01\x01\x03", 10);
111                 cmd.wlen = 10;
112         } else {
113                 memcpy(cmd.args, "\xc0\x00\x0c\x00\x00\x01\x01\x01\x01\x01\x01\x02\x00\x00\x01", 15);
114                 cmd.wlen = 15;
115         }
116         cmd.rlen = 1;
117         ret = si2157_cmd_execute(client, &cmd);
118         if (ret && (dev->chiptype != SI2157_CHIPTYPE_SI2141 || ret != -EAGAIN))
119                 goto err;
120
121         /* Si2141 needs a second command before it answers the revision query */
122         if (dev->chiptype == SI2157_CHIPTYPE_SI2141) {
123                 memcpy(cmd.args, "\xc0\x08\x01\x02\x00\x00\x01", 7);
124                 cmd.wlen = 7;
125                 ret = si2157_cmd_execute(client, &cmd);
126                 if (ret)
127                         goto err;
128         }
129
130         if (dev->dont_load_firmware) {
131                 dev_info(&client->dev, "device is buggy, skipping firmware download\n");
132                 goto skip_fw_download;
133         }
134
135         /* query chip revision */
136         memcpy(cmd.args, "\x02", 1);
137         cmd.wlen = 1;
138         cmd.rlen = 13;
139         ret = si2157_cmd_execute(client, &cmd);
140         if (ret)
141                 goto err;
142
143         chip_id = cmd.args[1] << 24 | cmd.args[2] << 16 | cmd.args[3] << 8 |
144                         cmd.args[4] << 0;
145
146         #define SI2177_A30 ('A' << 24 | 77 << 16 | '3' << 8 | '0' << 0)
147         #define SI2158_A20 ('A' << 24 | 58 << 16 | '2' << 8 | '0' << 0)
148         #define SI2148_A20 ('A' << 24 | 48 << 16 | '2' << 8 | '0' << 0)
149         #define SI2157_A30 ('A' << 24 | 57 << 16 | '3' << 8 | '0' << 0)
150         #define SI2147_A30 ('A' << 24 | 47 << 16 | '3' << 8 | '0' << 0)
151         #define SI2146_A10 ('A' << 24 | 46 << 16 | '1' << 8 | '0' << 0)
152         #define SI2141_A10 ('A' << 24 | 41 << 16 | '1' << 8 | '0' << 0)
153
154         switch (chip_id) {
155         case SI2158_A20:
156         case SI2148_A20:
157                 fw_name = SI2158_A20_FIRMWARE;
158                 break;
159         case SI2141_A10:
160                 fw_name = SI2141_A10_FIRMWARE;
161                 break;
162         case SI2177_A30:
163                 fw_name = SI2157_A30_FIRMWARE;
164                 break;
165         case SI2157_A30:
166         case SI2147_A30:
167         case SI2146_A10:
168                 fw_name = NULL;
169                 break;
170         default:
171                 dev_err(&client->dev, "unknown chip version Si21%d-%c%c%c\n",
172                                 cmd.args[2], cmd.args[1],
173                                 cmd.args[3], cmd.args[4]);
174                 ret = -EINVAL;
175                 goto err;
176         }
177
178         dev_info(&client->dev, "found a 'Silicon Labs Si21%d-%c%c%c'\n",
179                         cmd.args[2], cmd.args[1], cmd.args[3], cmd.args[4]);
180
181         if (fw_name == NULL)
182                 goto skip_fw_download;
183
184         /* request the firmware, this will block and timeout */
185         ret = request_firmware(&fw, fw_name, &client->dev);
186         if (ret) {
187                 dev_err(&client->dev, "firmware file '%s' not found\n",
188                                 fw_name);
189                 goto err;
190         }
191
192         /* firmware should be n chunks of 17 bytes */
193         if (fw->size % 17 != 0) {
194                 dev_err(&client->dev, "firmware file '%s' is invalid\n",
195                                 fw_name);
196                 ret = -EINVAL;
197                 goto err_release_firmware;
198         }
199
200         dev_info(&client->dev, "downloading firmware from file '%s'\n",
201                         fw_name);
202
203         for (remaining = fw->size; remaining > 0; remaining -= 17) {
204                 len = fw->data[fw->size - remaining];
205                 if (len > SI2157_ARGLEN) {
206                         dev_err(&client->dev, "Bad firmware length\n");
207                         ret = -EINVAL;
208                         goto err_release_firmware;
209                 }
210                 memcpy(cmd.args, &fw->data[(fw->size - remaining) + 1], len);
211                 cmd.wlen = len;
212                 cmd.rlen = 1;
213                 ret = si2157_cmd_execute(client, &cmd);
214                 if (ret) {
215                         dev_err(&client->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(client, &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(client, &cmd);
237         if (ret)
238                 goto err;
239
240         dev_info(&client->dev, "firmware version: %c.%c.%d\n",
241                         cmd.args[6], cmd.args[7], cmd.args[8]);
242
243         /* enable tuner status flags */
244         memcpy(cmd.args, "\x14\x00\x01\x05\x01\x00", 6);
245         cmd.wlen = 6;
246         cmd.rlen = 1;
247         ret = si2157_cmd_execute(client, &cmd);
248         if (ret)
249                 goto err;
250
251         memcpy(cmd.args, "\x14\x00\x01\x06\x01\x00", 6);
252         cmd.wlen = 6;
253         cmd.rlen = 1;
254         ret = si2157_cmd_execute(client, &cmd);
255         if (ret)
256                 goto err;
257
258         memcpy(cmd.args, "\x14\x00\x01\x07\x01\x00", 6);
259         cmd.wlen = 6;
260         cmd.rlen = 1;
261         ret = si2157_cmd_execute(client, &cmd);
262         if (ret)
263                 goto err;
264 warm:
265         /* init statistics in order signal app which are supported */
266         c->strength.len = 1;
267         c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
268         /* start statistics polling */
269         schedule_delayed_work(&dev->stat_work, msecs_to_jiffies(1000));
270
271         dev->active = true;
272         return 0;
273 err_release_firmware:
274         release_firmware(fw);
275 err:
276         dev_dbg(&client->dev, "failed=%d\n", ret);
277         return ret;
278 }
279
280 static int si2157_sleep(struct dvb_frontend *fe)
281 {
282         struct i2c_client *client = fe->tuner_priv;
283         struct si2157_dev *dev = i2c_get_clientdata(client);
284         int ret;
285         struct si2157_cmd cmd;
286
287         dev_dbg(&client->dev, "\n");
288
289         dev->active = false;
290
291         /* stop statistics polling */
292         cancel_delayed_work_sync(&dev->stat_work);
293
294         /* standby */
295         memcpy(cmd.args, "\x16\x00", 2);
296         cmd.wlen = 2;
297         cmd.rlen = 1;
298         ret = si2157_cmd_execute(client, &cmd);
299         if (ret)
300                 goto err;
301
302         return 0;
303 err:
304         dev_dbg(&client->dev, "failed=%d\n", ret);
305         return ret;
306 }
307
308 static int si2157_tune_wait(struct i2c_client *client, u8 is_digital)
309 {
310 #define TUN_TIMEOUT 40
311 #define DIG_TIMEOUT 30
312 #define ANALOG_TIMEOUT 150
313         struct si2157_dev *dev = i2c_get_clientdata(client);
314         int ret;
315         unsigned long timeout;
316         unsigned long start_time;
317         u8 wait_status;
318         u8  tune_lock_mask;
319
320         if (is_digital)
321                 tune_lock_mask = 0x04;
322         else
323                 tune_lock_mask = 0x02;
324
325         mutex_lock(&dev->i2c_mutex);
326
327         /* wait tuner command complete */
328         start_time = jiffies;
329         timeout = start_time + msecs_to_jiffies(TUN_TIMEOUT);
330         while (1) {
331                 ret = i2c_master_recv(client, &wait_status,
332                                       sizeof(wait_status));
333                 if (ret < 0) {
334                         goto err_mutex_unlock;
335                 } else if (ret != sizeof(wait_status)) {
336                         ret = -EREMOTEIO;
337                         goto err_mutex_unlock;
338                 }
339
340                 if (time_after(jiffies, timeout))
341                         break;
342
343                 /* tuner done? */
344                 if ((wait_status & 0x81) == 0x81)
345                         break;
346                 usleep_range(5000, 10000);
347         }
348
349         dev_dbg(&client->dev, "tuning took %d ms, status=0x%x\n",
350                 jiffies_to_msecs(jiffies) - jiffies_to_msecs(start_time),
351                 wait_status);
352
353         /* if we tuned ok, wait a bit for tuner lock */
354         if (tuner_lock_debug && (wait_status & 0x81) == 0x81) {
355                 if (is_digital)
356                         timeout = jiffies + msecs_to_jiffies(DIG_TIMEOUT);
357                 else
358                         timeout = jiffies + msecs_to_jiffies(ANALOG_TIMEOUT);
359
360                 while (!time_after(jiffies, timeout)) {
361                         ret = i2c_master_recv(client, &wait_status,
362                                               sizeof(wait_status));
363                         if (ret < 0) {
364                                 goto err_mutex_unlock;
365                         } else if (ret != sizeof(wait_status)) {
366                                 ret = -EREMOTEIO;
367                                 goto err_mutex_unlock;
368                         }
369
370                         /* tuner locked? */
371                         if (wait_status & tune_lock_mask)
372                                 break;
373                         usleep_range(5000, 10000);
374                 }
375
376                 dev_dbg(&client->dev, "tuning+lock took %d ms, status=0x%x\n",
377                         jiffies_to_msecs(jiffies) - jiffies_to_msecs(start_time),
378                         wait_status);
379         }
380
381         if ((wait_status & 0xc0) != 0x80) {
382                 ret = -ETIMEDOUT;
383                 goto err_mutex_unlock;
384         }
385
386         mutex_unlock(&dev->i2c_mutex);
387         return 0;
388
389 err_mutex_unlock:
390         mutex_unlock(&dev->i2c_mutex);
391         dev_err(&client->dev, "failed=%d\n", ret);
392         return ret;
393 }
394
395 static int si2157_set_params(struct dvb_frontend *fe)
396 {
397         struct i2c_client *client = fe->tuner_priv;
398         struct si2157_dev *dev = i2c_get_clientdata(client);
399         struct dtv_frontend_properties *c = &fe->dtv_property_cache;
400         int ret;
401         struct si2157_cmd cmd;
402         u8 bandwidth, delivery_system;
403         u32 if_frequency = 5000000;
404
405         dev_dbg(&client->dev,
406                         "delivery_system=%d frequency=%u bandwidth_hz=%u\n",
407                         c->delivery_system, c->frequency, c->bandwidth_hz);
408
409         if (!dev->active) {
410                 ret = -EAGAIN;
411                 goto err;
412         }
413
414         if (c->bandwidth_hz <= 6000000)
415                 bandwidth = 0x06;
416         else if (c->bandwidth_hz <= 7000000)
417                 bandwidth = 0x07;
418         else if (c->bandwidth_hz <= 8000000)
419                 bandwidth = 0x08;
420         else
421                 bandwidth = 0x0f;
422
423         switch (c->delivery_system) {
424         case SYS_ATSC:
425                         delivery_system = 0x00;
426                         if_frequency = 3250000;
427                         break;
428         case SYS_DVBC_ANNEX_B:
429                         delivery_system = 0x10;
430                         if_frequency = 4000000;
431                         break;
432         case SYS_DVBT:
433         case SYS_DVBT2: /* it seems DVB-T and DVB-T2 both are 0x20 here */
434                         delivery_system = 0x20;
435                         break;
436         case SYS_DVBC_ANNEX_A:
437                         delivery_system = 0x30;
438                         break;
439         default:
440                         ret = -EINVAL;
441                         goto err;
442         }
443
444         memcpy(cmd.args, "\x14\x00\x03\x07\x00\x00", 6);
445         cmd.args[4] = delivery_system | bandwidth;
446         if (dev->inversion)
447                 cmd.args[5] = 0x01;
448         cmd.wlen = 6;
449         cmd.rlen = 4;
450         ret = si2157_cmd_execute(client, &cmd);
451         if (ret)
452                 goto err;
453
454         if (dev->chiptype == SI2157_CHIPTYPE_SI2146)
455                 memcpy(cmd.args, "\x14\x00\x02\x07\x00\x01", 6);
456         else
457                 memcpy(cmd.args, "\x14\x00\x02\x07\x00\x00", 6);
458         cmd.args[4] = dev->if_port;
459         cmd.wlen = 6;
460         cmd.rlen = 4;
461         ret = si2157_cmd_execute(client, &cmd);
462         if (ret)
463                 goto err;
464
465         /* set digital if frequency if needed */
466         if (if_frequency != dev->if_frequency) {
467                 memcpy(cmd.args, "\x14\x00\x06\x07", 4);
468                 cmd.args[4] = (if_frequency / 1000) & 0xff;
469                 cmd.args[5] = ((if_frequency / 1000) >> 8) & 0xff;
470                 cmd.wlen = 6;
471                 cmd.rlen = 4;
472                 ret = si2157_cmd_execute(client, &cmd);
473                 if (ret)
474                         goto err;
475
476                 dev->if_frequency = if_frequency;
477         }
478
479         /* set digital frequency */
480         memcpy(cmd.args, "\x41\x00\x00\x00\x00\x00\x00\x00", 8);
481         cmd.args[4] = (c->frequency >>  0) & 0xff;
482         cmd.args[5] = (c->frequency >>  8) & 0xff;
483         cmd.args[6] = (c->frequency >> 16) & 0xff;
484         cmd.args[7] = (c->frequency >> 24) & 0xff;
485         cmd.wlen = 8;
486         cmd.rlen = 1;
487         ret = si2157_cmd_execute(client, &cmd);
488         if (ret)
489                 goto err;
490
491         dev->bandwidth = bandwidth;
492         dev->frequency = c->frequency;
493
494         si2157_tune_wait(client, 1); /* wait to complete, ignore any errors */
495
496         return 0;
497 err:
498         dev->bandwidth = 0;
499         dev->frequency = 0;
500         dev->if_frequency = 0;
501         dev_dbg(&client->dev, "failed=%d\n", ret);
502         return ret;
503 }
504
505 static int si2157_set_analog_params(struct dvb_frontend *fe,
506                                     struct analog_parameters *params)
507 {
508         struct i2c_client *client = fe->tuner_priv;
509         struct si2157_dev *dev = i2c_get_clientdata(client);
510         char *std; /* for debugging */
511         int ret;
512         struct si2157_cmd cmd;
513         u32 bandwidth = 0;
514         u32 if_frequency = 0;
515         u32 freq = 0;
516         u64 tmp_lval = 0;
517         u8 system = 0;
518         u8 color = 0;    /* 0=NTSC/PAL, 0x10=SECAM */
519         u8 invert_analog = 1; /* analog tuner spectrum; 0=normal, 1=inverted */
520
521         if (dev->chiptype != SI2157_CHIPTYPE_SI2157) {
522                 dev_info(&client->dev, "Analog tuning not supported for chiptype=%u\n",
523                          dev->chiptype);
524                 ret = -EINVAL;
525                 goto err;
526         }
527
528         if (!dev->active)
529                 si2157_init(fe);
530
531         if (!dev->active) {
532                 ret = -EAGAIN;
533                 goto err;
534         }
535         if (params->mode == V4L2_TUNER_RADIO) {
536         /*
537          * std = "fm";
538          * bandwidth = 1700000; //best can do for FM, AGC will be a mess though
539          * if_frequency = 1250000;  //HVR-225x(saa7164), HVR-12xx(cx23885)
540          * if_frequency = 6600000;  //HVR-9xx(cx231xx)
541          * if_frequency = 5500000;  //HVR-19xx(pvrusb2)
542          */
543                 dev_err(&client->dev, "si2157 does not currently support FM radio\n");
544                 ret = -EINVAL;
545                 goto err;
546         }
547         tmp_lval = params->frequency * 625LL;
548         do_div(tmp_lval, 10); /* convert to HZ */
549         freq = (u32)tmp_lval;
550
551         if (freq < 1000000) /* is freq in KHz */
552                 freq = freq * 1000;
553         dev->frequency = freq;
554
555         /* if_frequency values based on tda187271C2 */
556         if (params->std & (V4L2_STD_B | V4L2_STD_GH)) {
557                 if (freq >= 470000000) {
558                         std = "palGH";
559                         bandwidth = 8000000;
560                         if_frequency = 6000000;
561                         system = 1;
562                         if (params->std &
563                             (V4L2_STD_SECAM_G | V4L2_STD_SECAM_H)) {
564                                 std = "secamGH";
565                                 color = 0x10;
566                         }
567                 } else {
568                         std = "palB";
569                         bandwidth = 7000000;
570                         if_frequency = 6000000;
571                         system = 0;
572                         if (params->std & V4L2_STD_SECAM_B) {
573                                 std = "secamB";
574                                 color = 0x10;
575                         }
576                 }
577         } else if (params->std & V4L2_STD_MN) {
578                 std = "MN";
579                 bandwidth = 6000000;
580                 if_frequency = 5400000;
581                 system = 2;
582         } else if (params->std & V4L2_STD_PAL_I) {
583                 std = "palI";
584                 bandwidth = 8000000;
585                 if_frequency = 7250000; /* TODO: does not work yet */
586                 system = 4;
587         } else if (params->std & V4L2_STD_DK) {
588                 std = "palDK";
589                 bandwidth = 8000000;
590                 if_frequency = 6900000; /* TODO: does not work yet */
591                 system = 5;
592                 if (params->std & V4L2_STD_SECAM_DK) {
593                         std = "secamDK";
594                         color = 0x10;
595                 }
596         } else if (params->std & V4L2_STD_SECAM_L) {
597                 std = "secamL";
598                 bandwidth = 8000000;
599                 if_frequency = 6750000; /* TODO: untested */
600                 system = 6;
601                 color = 0x10;
602         } else if (params->std & V4L2_STD_SECAM_LC) {
603                 std = "secamL'";
604                 bandwidth = 7000000;
605                 if_frequency = 1250000; /* TODO: untested */
606                 system = 7;
607                 color = 0x10;
608         } else {
609                 std = "unknown";
610         }
611         /* calc channel center freq */
612         freq = freq - 1250000 + (bandwidth / 2);
613
614         dev_dbg(&client->dev,
615                 "mode=%d system=%u std='%s' params->frequency=%u center freq=%u if=%u bandwidth=%u\n",
616                 params->mode, system, std, params->frequency,
617                 freq, if_frequency, bandwidth);
618
619         /* set analog IF port */
620         memcpy(cmd.args, "\x14\x00\x03\x06\x08\x02", 6);
621         /* in using dev->if_port, we assume analog and digital IF's */
622         /*   are always on different ports */
623         /* assumes if_port definition is 0 or 1 for digital out */
624         cmd.args[4] = (dev->if_port == 1) ? 8 : 10;
625         /* Analog AGC assumed external */
626         cmd.args[5] = (dev->if_port == 1) ? 2 : 1;
627         cmd.wlen = 6;
628         cmd.rlen = 4;
629         ret = si2157_cmd_execute(client, &cmd);
630         if (ret)
631                 goto err;
632
633         /* set analog IF output config */
634         memcpy(cmd.args, "\x14\x00\x0d\x06\x94\x64", 6);
635         cmd.wlen = 6;
636         cmd.rlen = 4;
637         ret = si2157_cmd_execute(client, &cmd);
638         if (ret)
639                 goto err;
640
641         /* make this distinct from a digital IF */
642         dev->if_frequency = if_frequency | 1;
643
644         /* calc and set tuner analog if center frequency */
645         if_frequency = if_frequency + 1250000 - (bandwidth / 2);
646         dev_dbg(&client->dev, "IF Ctr freq=%d\n", if_frequency);
647
648         memcpy(cmd.args, "\x14\x00\x0C\x06", 4);
649         cmd.args[4] = (if_frequency / 1000) & 0xff;
650         cmd.args[5] = ((if_frequency / 1000) >> 8) & 0xff;
651         cmd.wlen = 6;
652         cmd.rlen = 4;
653         ret = si2157_cmd_execute(client, &cmd);
654         if (ret)
655                 goto err;
656
657         /* set analog AGC config */
658         memcpy(cmd.args, "\x14\x00\x07\x06\x32\xc8", 6);
659         cmd.wlen = 6;
660         cmd.rlen = 4;
661         ret = si2157_cmd_execute(client, &cmd);
662         if (ret)
663                 goto err;
664
665         /* set analog video mode */
666         memcpy(cmd.args, "\x14\x00\x04\x06\x00\x00", 6);
667         cmd.args[4] = system | color;
668         /* can use dev->inversion if assumed applies to both digital/analog */
669         if (invert_analog)
670                 cmd.args[5] |= 0x02;
671         cmd.wlen = 6;
672         cmd.rlen = 1;
673         ret = si2157_cmd_execute(client, &cmd);
674         if (ret)
675                 goto err;
676
677         /* set analog frequency */
678         memcpy(cmd.args, "\x41\x01\x00\x00\x00\x00\x00\x00", 8);
679         cmd.args[4] = (freq >>  0) & 0xff;
680         cmd.args[5] = (freq >>  8) & 0xff;
681         cmd.args[6] = (freq >> 16) & 0xff;
682         cmd.args[7] = (freq >> 24) & 0xff;
683         cmd.wlen = 8;
684         cmd.rlen = 1;
685         ret = si2157_cmd_execute(client, &cmd);
686         if (ret)
687                 goto err;
688
689         dev->bandwidth = bandwidth;
690
691         si2157_tune_wait(client, 0); /* wait to complete, ignore any errors */
692
693         return 0;
694 err:
695         dev->bandwidth = 0;
696         dev->frequency = 0;
697         dev->if_frequency = 0;
698         dev_dbg(&client->dev, "failed=%d\n", ret);
699         return ret;
700 }
701
702 static int si2157_get_frequency(struct dvb_frontend *fe, u32 *frequency)
703 {
704         struct i2c_client *client = fe->tuner_priv;
705         struct si2157_dev *dev = i2c_get_clientdata(client);
706
707         *frequency = dev->frequency;
708         dev_dbg(&client->dev, "freq=%u\n", dev->frequency);
709         return 0;
710 }
711
712 static int si2157_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
713 {
714         struct i2c_client *client = fe->tuner_priv;
715         struct si2157_dev *dev = i2c_get_clientdata(client);
716
717         *bandwidth = dev->bandwidth;
718         dev_dbg(&client->dev, "bandwidth=%u\n", dev->bandwidth);
719         return 0;
720 }
721
722 static int si2157_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
723 {
724         struct i2c_client *client = fe->tuner_priv;
725         struct si2157_dev *dev = i2c_get_clientdata(client);
726
727         *frequency = dev->if_frequency & ~1; /* strip analog IF indicator bit */
728         dev_dbg(&client->dev, "if_frequency=%u\n", *frequency);
729         return 0;
730 }
731
732 static int si2157_get_rf_strength(struct dvb_frontend *fe, u16 *rssi)
733 {
734         struct i2c_client *client = fe->tuner_priv;
735         struct dtv_frontend_properties *c = &fe->dtv_property_cache;
736         struct si2157_cmd cmd;
737         int ret;
738         int strength;
739
740         dev_dbg(&client->dev, "\n");
741
742         memcpy(cmd.args, "\x42\x00", 2);
743         cmd.wlen = 2;
744         cmd.rlen = 12;
745         ret = si2157_cmd_execute(client, &cmd);
746         if (ret)
747                 goto err;
748
749         c->strength.stat[0].scale = FE_SCALE_DECIBEL;
750         c->strength.stat[0].svalue = (s8)cmd.args[3] * 1000;
751
752         /* normalize values based on Silicon Labs reference
753          * add 100, then anything > 80 is 100% signal
754          */
755         strength = (s8)cmd.args[3] + 100;
756         strength = clamp_val(strength, 0, 80);
757         *rssi = (u16)(strength * 0xffff / 80);
758
759         dev_dbg(&client->dev, "strength=%d rssi=%u\n",
760                 (s8)cmd.args[3], *rssi);
761
762         return 0;
763 err:
764         dev_dbg(&client->dev, "failed=%d\n", ret);
765         return ret;
766 }
767
768 static const struct dvb_tuner_ops si2157_ops = {
769         .info = {
770                 .name             = "Silicon Labs Si2141/Si2146/2147/2148/2157/2158",
771                 .frequency_min_hz =  42 * MHz,
772                 .frequency_max_hz = 870 * MHz,
773         },
774
775         .init = si2157_init,
776         .sleep = si2157_sleep,
777         .set_params = si2157_set_params,
778         .set_analog_params = si2157_set_analog_params,
779         .get_frequency     = si2157_get_frequency,
780         .get_bandwidth     = si2157_get_bandwidth,
781         .get_if_frequency  = si2157_get_if_frequency,
782
783         .get_rf_strength   = si2157_get_rf_strength,
784 };
785
786 static void si2157_stat_work(struct work_struct *work)
787 {
788         struct si2157_dev *dev = container_of(work, struct si2157_dev, stat_work.work);
789         struct dvb_frontend *fe = dev->fe;
790         struct i2c_client *client = fe->tuner_priv;
791         struct dtv_frontend_properties *c = &fe->dtv_property_cache;
792         struct si2157_cmd cmd;
793         int ret;
794
795         dev_dbg(&client->dev, "\n");
796
797         memcpy(cmd.args, "\x42\x00", 2);
798         cmd.wlen = 2;
799         cmd.rlen = 12;
800         ret = si2157_cmd_execute(client, &cmd);
801         if (ret)
802                 goto err;
803
804         c->strength.stat[0].scale = FE_SCALE_DECIBEL;
805         c->strength.stat[0].svalue = (s8) cmd.args[3] * 1000;
806
807         schedule_delayed_work(&dev->stat_work, msecs_to_jiffies(2000));
808         return;
809 err:
810         c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
811         dev_dbg(&client->dev, "failed=%d\n", ret);
812 }
813
814 static int si2157_probe(struct i2c_client *client,
815                         const struct i2c_device_id *id)
816 {
817         struct si2157_config *cfg = client->dev.platform_data;
818         struct dvb_frontend *fe = cfg->fe;
819         struct si2157_dev *dev;
820         struct si2157_cmd cmd;
821         int ret;
822
823         dev = kzalloc(sizeof(*dev), GFP_KERNEL);
824         if (!dev) {
825                 ret = -ENOMEM;
826                 dev_err(&client->dev, "kzalloc() failed\n");
827                 goto err;
828         }
829
830         i2c_set_clientdata(client, dev);
831         dev->fe = cfg->fe;
832         dev->inversion = cfg->inversion;
833         dev->dont_load_firmware = cfg->dont_load_firmware;
834         dev->if_port = cfg->if_port;
835         dev->chiptype = (u8)id->driver_data;
836         dev->if_frequency = 5000000; /* default value of property 0x0706 */
837         mutex_init(&dev->i2c_mutex);
838         INIT_DELAYED_WORK(&dev->stat_work, si2157_stat_work);
839
840         /* check if the tuner is there */
841         cmd.wlen = 0;
842         cmd.rlen = 1;
843         ret = si2157_cmd_execute(client, &cmd);
844         if (ret && ret != -EAGAIN)
845                 goto err_kfree;
846
847         memcpy(&fe->ops.tuner_ops, &si2157_ops, sizeof(struct dvb_tuner_ops));
848         fe->tuner_priv = client;
849
850 #ifdef CONFIG_MEDIA_CONTROLLER
851         if (cfg->mdev) {
852                 dev->mdev = cfg->mdev;
853
854                 dev->ent.name = KBUILD_MODNAME;
855                 dev->ent.function = MEDIA_ENT_F_TUNER;
856
857                 dev->pad[SI2157_PAD_RF_INPUT].flags = MEDIA_PAD_FL_SINK;
858                 dev->pad[SI2157_PAD_RF_INPUT].sig_type = PAD_SIGNAL_ANALOG;
859                 dev->pad[SI2157_PAD_VID_OUT].flags = MEDIA_PAD_FL_SOURCE;
860                 dev->pad[SI2157_PAD_VID_OUT].sig_type = PAD_SIGNAL_ANALOG;
861                 dev->pad[SI2157_PAD_AUD_OUT].flags = MEDIA_PAD_FL_SOURCE;
862                 dev->pad[SI2157_PAD_AUD_OUT].sig_type = PAD_SIGNAL_AUDIO;
863
864                 ret = media_entity_pads_init(&dev->ent, SI2157_NUM_PADS,
865                                              &dev->pad[0]);
866
867                 if (ret)
868                         goto err_kfree;
869
870                 ret = media_device_register_entity(cfg->mdev, &dev->ent);
871                 if (ret) {
872                         media_entity_cleanup(&dev->ent);
873                         goto err_kfree;
874                 }
875         }
876 #endif
877
878         dev_info(&client->dev, "Silicon Labs %s successfully attached\n",
879                         dev->chiptype == SI2157_CHIPTYPE_SI2141 ?  "Si2141" :
880                         dev->chiptype == SI2157_CHIPTYPE_SI2146 ?
881                         "Si2146" : "Si2147/2148/2157/2158");
882
883         return 0;
884
885 err_kfree:
886         kfree(dev);
887 err:
888         dev_dbg(&client->dev, "failed=%d\n", ret);
889         return ret;
890 }
891
892 static int si2157_remove(struct i2c_client *client)
893 {
894         struct si2157_dev *dev = i2c_get_clientdata(client);
895         struct dvb_frontend *fe = dev->fe;
896
897         dev_dbg(&client->dev, "\n");
898
899         /* stop statistics polling */
900         cancel_delayed_work_sync(&dev->stat_work);
901
902 #ifdef CONFIG_MEDIA_CONTROLLER_DVB
903         if (dev->mdev)
904                 media_device_unregister_entity(&dev->ent);
905 #endif
906
907         memset(&fe->ops.tuner_ops, 0, sizeof(struct dvb_tuner_ops));
908         fe->tuner_priv = NULL;
909         kfree(dev);
910
911         return 0;
912 }
913
914 static const struct i2c_device_id si2157_id_table[] = {
915         {"si2157", SI2157_CHIPTYPE_SI2157},
916         {"si2146", SI2157_CHIPTYPE_SI2146},
917         {"si2141", SI2157_CHIPTYPE_SI2141},
918         {"si2177", SI2157_CHIPTYPE_SI2177},
919         {}
920 };
921 MODULE_DEVICE_TABLE(i2c, si2157_id_table);
922
923 static struct i2c_driver si2157_driver = {
924         .driver = {
925                 .name                = "si2157",
926                 .suppress_bind_attrs = true,
927         },
928         .probe          = si2157_probe,
929         .remove         = si2157_remove,
930         .id_table       = si2157_id_table,
931 };
932
933 module_i2c_driver(si2157_driver);
934
935 MODULE_DESCRIPTION("Silicon Labs Si2141/Si2146/2147/2148/2157/2158 silicon tuner driver");
936 MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
937 MODULE_LICENSE("GPL");
938 MODULE_FIRMWARE(SI2158_A20_FIRMWARE);
939 MODULE_FIRMWARE(SI2141_A10_FIRMWARE);
940 MODULE_FIRMWARE(SI2157_A30_FIRMWARE);