Merge branch 'work.regset' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
[linux/fpc-iii.git] / drivers / media / tuners / si2157.c
blobfefb2625f6558e340488586395607781f2becf2c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Silicon Labs Si2146/2147/2148/2157/2158 silicon tuner driver
5 * Copyright (C) 2014 Antti Palosaari <crope@iki.fi>
6 */
8 #include "si2157_priv.h"
10 static const struct dvb_tuner_ops si2157_ops;
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");
16 /* execute firmware command */
17 static int si2157_cmd_execute(struct i2c_client *client, struct si2157_cmd *cmd)
19 struct si2157_dev *dev = i2c_get_clientdata(client);
20 int ret;
21 unsigned long timeout;
23 mutex_lock(&dev->i2c_mutex);
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;
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;
49 /* firmware ready? */
50 if ((cmd->args[0] >> 7) & 0x01)
51 break;
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]);
59 if (!((cmd->args[0] >> 7) & 0x01)) {
60 ret = -ETIMEDOUT;
61 goto err_mutex_unlock;
63 /* check error status bit */
64 if (cmd->args[0] & 0x40) {
65 ret = -EAGAIN;
66 goto err_mutex_unlock;
70 mutex_unlock(&dev->i2c_mutex);
71 return 0;
73 err_mutex_unlock:
74 mutex_unlock(&dev->i2c_mutex);
75 dev_dbg(&client->dev, "failed=%d\n", ret);
76 return ret;
79 static int si2157_init(struct dvb_frontend *fe)
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;
90 dev_dbg(&client->dev, "\n");
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);
98 xtal_trim = cmd.args[2] | (cmd.args[3] << 8);
100 if (ret == 0 && xtal_trim < 16)
101 goto warm;
103 dev->if_frequency = 0; /* we no longer know current tuner state */
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;
116 cmd.rlen = 1;
117 ret = si2157_cmd_execute(client, &cmd);
118 if (ret && (dev->chiptype != SI2157_CHIPTYPE_SI2141 || ret != -EAGAIN))
119 goto err;
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;
130 if (dev->dont_load_firmware) {
131 dev_info(&client->dev, "device is buggy, skipping firmware download\n");
132 goto skip_fw_download;
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;
143 chip_id = cmd.args[1] << 24 | cmd.args[2] << 16 | cmd.args[3] << 8 |
144 cmd.args[4] << 0;
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)
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;
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]);
181 if (fw_name == NULL)
182 goto skip_fw_download;
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;
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;
200 dev_info(&client->dev, "downloading firmware from file '%s'\n",
201 fw_name);
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;
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;
221 release_firmware(fw);
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;
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;
240 dev_info(&client->dev, "firmware version: %c.%c.%d\n",
241 cmd.args[6], cmd.args[7], cmd.args[8]);
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;
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;
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));
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;
280 static int si2157_sleep(struct dvb_frontend *fe)
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;
287 dev_dbg(&client->dev, "\n");
289 dev->active = false;
291 /* stop statistics polling */
292 cancel_delayed_work_sync(&dev->stat_work);
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;
302 return 0;
303 err:
304 dev_dbg(&client->dev, "failed=%d\n", ret);
305 return ret;
308 static int si2157_tune_wait(struct i2c_client *client, u8 is_digital)
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;
320 if (is_digital)
321 tune_lock_mask = 0x04;
322 else
323 tune_lock_mask = 0x02;
325 mutex_lock(&dev->i2c_mutex);
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;
340 if (time_after(jiffies, timeout))
341 break;
343 /* tuner done? */
344 if ((wait_status & 0x81) == 0x81)
345 break;
346 usleep_range(5000, 10000);
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);
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);
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;
370 /* tuner locked? */
371 if (wait_status & tune_lock_mask)
372 break;
373 usleep_range(5000, 10000);
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);
381 if ((wait_status & 0xc0) != 0x80) {
382 ret = -ETIMEDOUT;
383 goto err_mutex_unlock;
386 mutex_unlock(&dev->i2c_mutex);
387 return 0;
389 err_mutex_unlock:
390 mutex_unlock(&dev->i2c_mutex);
391 dev_err(&client->dev, "failed=%d\n", ret);
392 return ret;
395 static int si2157_set_params(struct dvb_frontend *fe)
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;
405 dev_dbg(&client->dev,
406 "delivery_system=%d frequency=%u bandwidth_hz=%u\n",
407 c->delivery_system, c->frequency, c->bandwidth_hz);
409 if (!dev->active) {
410 ret = -EAGAIN;
411 goto err;
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;
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;
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;
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;
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;
476 dev->if_frequency = if_frequency;
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;
491 dev->bandwidth = bandwidth;
492 dev->frequency = c->frequency;
494 si2157_tune_wait(client, 1); /* wait to complete, ignore any errors */
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;
505 static int si2157_set_analog_params(struct dvb_frontend *fe,
506 struct analog_parameters *params)
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 */
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;
528 if (!dev->active)
529 si2157_init(fe);
531 if (!dev->active) {
532 ret = -EAGAIN;
533 goto err;
535 if (params->mode == V4L2_TUNER_RADIO) {
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)
543 dev_err(&client->dev, "si2157 does not currently support FM radio\n");
544 ret = -EINVAL;
545 goto err;
547 tmp_lval = params->frequency * 625LL;
548 do_div(tmp_lval, 10); /* convert to HZ */
549 freq = (u32)tmp_lval;
551 if (freq < 1000000) /* is freq in KHz */
552 freq = freq * 1000;
553 dev->frequency = freq;
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;
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;
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;
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";
611 /* calc channel center freq */
612 freq = freq - 1250000 + (bandwidth / 2);
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);
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;
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;
641 /* make this distinct from a digital IF */
642 dev->if_frequency = if_frequency | 1;
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);
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;
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;
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;
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;
689 dev->bandwidth = bandwidth;
691 si2157_tune_wait(client, 0); /* wait to complete, ignore any errors */
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;
702 static int si2157_get_frequency(struct dvb_frontend *fe, u32 *frequency)
704 struct i2c_client *client = fe->tuner_priv;
705 struct si2157_dev *dev = i2c_get_clientdata(client);
707 *frequency = dev->frequency;
708 dev_dbg(&client->dev, "freq=%u\n", dev->frequency);
709 return 0;
712 static int si2157_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
714 struct i2c_client *client = fe->tuner_priv;
715 struct si2157_dev *dev = i2c_get_clientdata(client);
717 *bandwidth = dev->bandwidth;
718 dev_dbg(&client->dev, "bandwidth=%u\n", dev->bandwidth);
719 return 0;
722 static int si2157_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
724 struct i2c_client *client = fe->tuner_priv;
725 struct si2157_dev *dev = i2c_get_clientdata(client);
727 *frequency = dev->if_frequency & ~1; /* strip analog IF indicator bit */
728 dev_dbg(&client->dev, "if_frequency=%u\n", *frequency);
729 return 0;
732 static int si2157_get_rf_strength(struct dvb_frontend *fe, u16 *rssi)
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;
740 dev_dbg(&client->dev, "\n");
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;
749 c->strength.stat[0].scale = FE_SCALE_DECIBEL;
750 c->strength.stat[0].svalue = (s8)cmd.args[3] * 1000;
752 /* normalize values based on Silicon Labs reference
753 * add 100, then anything > 80 is 100% signal
755 strength = (s8)cmd.args[3] + 100;
756 strength = clamp_val(strength, 0, 80);
757 *rssi = (u16)(strength * 0xffff / 80);
759 dev_dbg(&client->dev, "strength=%d rssi=%u\n",
760 (s8)cmd.args[3], *rssi);
762 return 0;
763 err:
764 dev_dbg(&client->dev, "failed=%d\n", ret);
765 return ret;
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,
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,
783 .get_rf_strength = si2157_get_rf_strength,
786 static void si2157_stat_work(struct work_struct *work)
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;
795 dev_dbg(&client->dev, "\n");
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;
804 c->strength.stat[0].scale = FE_SCALE_DECIBEL;
805 c->strength.stat[0].svalue = (s8) cmd.args[3] * 1000;
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);
814 static int si2157_probe(struct i2c_client *client,
815 const struct i2c_device_id *id)
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;
823 dev = kzalloc(sizeof(*dev), GFP_KERNEL);
824 if (!dev) {
825 ret = -ENOMEM;
826 dev_err(&client->dev, "kzalloc() failed\n");
827 goto err;
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);
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;
847 memcpy(&fe->ops.tuner_ops, &si2157_ops, sizeof(struct dvb_tuner_ops));
848 fe->tuner_priv = client;
850 #ifdef CONFIG_MEDIA_CONTROLLER
851 if (cfg->mdev) {
852 dev->mdev = cfg->mdev;
854 dev->ent.name = KBUILD_MODNAME;
855 dev->ent.function = MEDIA_ENT_F_TUNER;
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;
864 ret = media_entity_pads_init(&dev->ent, SI2157_NUM_PADS,
865 &dev->pad[0]);
867 if (ret)
868 goto err_kfree;
870 ret = media_device_register_entity(cfg->mdev, &dev->ent);
871 if (ret) {
872 media_entity_cleanup(&dev->ent);
873 goto err_kfree;
876 #endif
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");
883 return 0;
885 err_kfree:
886 kfree(dev);
887 err:
888 dev_dbg(&client->dev, "failed=%d\n", ret);
889 return ret;
892 static int si2157_remove(struct i2c_client *client)
894 struct si2157_dev *dev = i2c_get_clientdata(client);
895 struct dvb_frontend *fe = dev->fe;
897 dev_dbg(&client->dev, "\n");
899 /* stop statistics polling */
900 cancel_delayed_work_sync(&dev->stat_work);
902 #ifdef CONFIG_MEDIA_CONTROLLER_DVB
903 if (dev->mdev)
904 media_device_unregister_entity(&dev->ent);
905 #endif
907 memset(&fe->ops.tuner_ops, 0, sizeof(struct dvb_tuner_ops));
908 fe->tuner_priv = NULL;
909 kfree(dev);
911 return 0;
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},
921 MODULE_DEVICE_TABLE(i2c, si2157_id_table);
923 static struct i2c_driver si2157_driver = {
924 .driver = {
925 .name = "si2157",
926 .suppress_bind_attrs = true,
928 .probe = si2157_probe,
929 .remove = si2157_remove,
930 .id_table = si2157_id_table,
933 module_i2c_driver(si2157_driver);
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);