hc
2024-05-13 9d77db3c730780c8ef5ccd4b66403ff5675cfe4e
kernel/drivers/media/tuners/si2157.c
....@@ -1,22 +1,17 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * Silicon Labs Si2146/2147/2148/2157/2158 silicon tuner driver
34 *
45 * 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.
156 */
167
178 #include "si2157_priv.h"
189
1910 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");
2015
2116 /* execute firmware command */
2217 static int si2157_cmd_execute(struct i2c_client *client, struct si2157_cmd *cmd)
....@@ -56,12 +51,18 @@
5651 break;
5752 }
5853
59
- dev_dbg(&client->dev, "cmd execution took %d ms\n",
60
- jiffies_to_msecs(jiffies) -
61
- (jiffies_to_msecs(timeout) - TIMEOUT));
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]);
6258
6359 if (!((cmd->args[0] >> 7) & 0x01)) {
6460 ret = -ETIMEDOUT;
61
+ goto err_mutex_unlock;
62
+ }
63
+ /* check error status bit */
64
+ if (cmd->args[0] & 0x40) {
65
+ ret = -EAGAIN;
6566 goto err_mutex_unlock;
6667 }
6768 }
....@@ -114,7 +115,7 @@
114115 }
115116 cmd.rlen = 1;
116117 ret = si2157_cmd_execute(client, &cmd);
117
- if (ret)
118
+ if (ret && (dev->chiptype != SI2157_CHIPTYPE_SI2141 || ret != -EAGAIN))
118119 goto err;
119120
120121 /* Si2141 needs a second command before it answers the revision query */
....@@ -124,6 +125,11 @@
124125 ret = si2157_cmd_execute(client, &cmd);
125126 if (ret)
126127 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;
127133 }
128134
129135 /* query chip revision */
....@@ -137,6 +143,7 @@
137143 chip_id = cmd.args[1] << 24 | cmd.args[2] << 16 | cmd.args[3] << 8 |
138144 cmd.args[4] << 0;
139145
146
+ #define SI2177_A30 ('A' << 24 | 77 << 16 | '3' << 8 | '0' << 0)
140147 #define SI2158_A20 ('A' << 24 | 58 << 16 | '2' << 8 | '0' << 0)
141148 #define SI2148_A20 ('A' << 24 | 48 << 16 | '2' << 8 | '0' << 0)
142149 #define SI2157_A30 ('A' << 24 | 57 << 16 | '3' << 8 | '0' << 0)
....@@ -151,6 +158,9 @@
151158 break;
152159 case SI2141_A10:
153160 fw_name = SI2141_A10_FIRMWARE;
161
+ break;
162
+ case SI2177_A30:
163
+ fw_name = SI2157_A30_FIRMWARE;
154164 break;
155165 case SI2157_A30:
156166 case SI2147_A30:
....@@ -229,6 +239,28 @@
229239
230240 dev_info(&client->dev, "firmware version: %c.%c.%d\n",
231241 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;
232264 warm:
233265 /* init statistics in order signal app which are supported */
234266 c->strength.len = 1;
....@@ -270,6 +302,93 @@
270302 return 0;
271303 err:
272304 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);
273392 return ret;
274393 }
275394
....@@ -343,7 +462,7 @@
343462 if (ret)
344463 goto err;
345464
346
- /* set if frequency if needed */
465
+ /* set digital if frequency if needed */
347466 if (if_frequency != dev->if_frequency) {
348467 memcpy(cmd.args, "\x14\x00\x06\x07", 4);
349468 cmd.args[4] = (if_frequency / 1000) & 0xff;
....@@ -357,7 +476,7 @@
357476 dev->if_frequency = if_frequency;
358477 }
359478
360
- /* set frequency */
479
+ /* set digital frequency */
361480 memcpy(cmd.args, "\x41\x00\x00\x00\x00\x00\x00\x00", 8);
362481 cmd.args[4] = (c->frequency >> 0) & 0xff;
363482 cmd.args[5] = (c->frequency >> 8) & 0xff;
....@@ -369,10 +488,235 @@
369488 if (ret)
370489 goto err;
371490
491
+ dev->bandwidth = bandwidth;
492
+ dev->frequency = c->frequency;
493
+
494
+ si2157_tune_wait(client, 1); /* wait to complete, ignore any errors */
495
+
372496 return 0;
373497 err:
498
+ dev->bandwidth = 0;
499
+ dev->frequency = 0;
500
+ dev->if_frequency = 0;
374501 dev_dbg(&client->dev, "failed=%d\n", ret);
375502 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;
376720 }
377721
378722 static int si2157_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
....@@ -380,8 +724,45 @@
380724 struct i2c_client *client = fe->tuner_priv;
381725 struct si2157_dev *dev = i2c_get_clientdata(client);
382726
383
- *frequency = dev->if_frequency;
727
+ *frequency = dev->if_frequency & ~1; /* strip analog IF indicator bit */
728
+ dev_dbg(&client->dev, "if_frequency=%u\n", *frequency);
384729 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;
385766 }
386767
387768 static const struct dvb_tuner_ops si2157_ops = {
....@@ -394,7 +775,12 @@
394775 .init = si2157_init,
395776 .sleep = si2157_sleep,
396777 .set_params = si2157_set_params,
397
- .get_if_frequency = si2157_get_if_frequency,
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,
398784 };
399785
400786 static void si2157_stat_work(struct work_struct *work)
....@@ -444,6 +830,7 @@
444830 i2c_set_clientdata(client, dev);
445831 dev->fe = cfg->fe;
446832 dev->inversion = cfg->inversion;
833
+ dev->dont_load_firmware = cfg->dont_load_firmware;
447834 dev->if_port = cfg->if_port;
448835 dev->chiptype = (u8)id->driver_data;
449836 dev->if_frequency = 5000000; /* default value of property 0x0706 */
....@@ -454,7 +841,7 @@
454841 cmd.wlen = 0;
455842 cmd.rlen = 1;
456843 ret = si2157_cmd_execute(client, &cmd);
457
- if (ret)
844
+ if (ret && ret != -EAGAIN)
458845 goto err_kfree;
459846
460847 memcpy(&fe->ops.tuner_ops, &si2157_ops, sizeof(struct dvb_tuner_ops));
....@@ -467,11 +854,14 @@
467854 dev->ent.name = KBUILD_MODNAME;
468855 dev->ent.function = MEDIA_ENT_F_TUNER;
469856
470
- dev->pad[TUNER_PAD_RF_INPUT].flags = MEDIA_PAD_FL_SINK;
471
- dev->pad[TUNER_PAD_OUTPUT].flags = MEDIA_PAD_FL_SOURCE;
472
- dev->pad[TUNER_PAD_AUD_OUT].flags = MEDIA_PAD_FL_SOURCE;
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;
473863
474
- ret = media_entity_pads_init(&dev->ent, TUNER_NUM_PADS,
864
+ ret = media_entity_pads_init(&dev->ent, SI2157_NUM_PADS,
475865 &dev->pad[0]);
476866
477867 if (ret)
....@@ -525,6 +915,7 @@
525915 {"si2157", SI2157_CHIPTYPE_SI2157},
526916 {"si2146", SI2157_CHIPTYPE_SI2146},
527917 {"si2141", SI2157_CHIPTYPE_SI2141},
918
+ {"si2177", SI2157_CHIPTYPE_SI2177},
528919 {}
529920 };
530921 MODULE_DEVICE_TABLE(i2c, si2157_id_table);
....@@ -546,3 +937,4 @@
546937 MODULE_LICENSE("GPL");
547938 MODULE_FIRMWARE(SI2158_A20_FIRMWARE);
548939 MODULE_FIRMWARE(SI2141_A10_FIRMWARE);
940
+MODULE_FIRMWARE(SI2157_A30_FIRMWARE);