Skip to content

Commit 1c35ba3

Browse files
committed
media: si2157: use a different namespace for firmware
Each chip at the si21xx TER family seems to have a different firmware, with seems to actually be a patch against the ROM code. Rework the code in order to use different firmware files depending on the chip ID and rom ID. Signed-off-by: Mauro Carvalho Chehab <[email protected]>
1 parent 7c2d8ee commit 1c35ba3

File tree

2 files changed

+132
-79
lines changed

2 files changed

+132
-79
lines changed

drivers/media/tuners/si2157.c

Lines changed: 101 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,19 @@ static int si2157_cmd_execute(struct i2c_client *client, struct si2157_cmd *cmd)
7676
return ret;
7777
}
7878

79+
static const struct si2157_tuner_info si2157_tuners[] = {
80+
{ SI2141, false, 0x60, SI2141_60_FIRMWARE, SI2141_A10_FIRMWARE },
81+
{ SI2141, false, 0x61, SI2141_61_FIRMWARE, SI2141_A10_FIRMWARE },
82+
{ SI2146, false, 0x11, SI2146_11_FIRMWARE, NULL },
83+
{ SI2147, false, 0x50, SI2147_50_FIRMWARE, NULL },
84+
{ SI2148, true, 0x32, SI2148_32_FIRMWARE, SI2158_A20_FIRMWARE },
85+
{ SI2148, true, 0x33, SI2148_33_FIRMWARE, SI2158_A20_FIRMWARE },
86+
{ SI2157, false, 0x50, SI2157_50_FIRMWARE, SI2157_A30_FIRMWARE },
87+
{ SI2158, false, 0x50, SI2158_50_FIRMWARE, SI2158_A20_FIRMWARE },
88+
{ SI2158, false, 0x51, SI2158_51_FIRMWARE, SI2158_A20_FIRMWARE },
89+
{ SI2177, false, 0x50, SI2177_50_FIRMWARE, SI2157_A30_FIRMWARE },
90+
};
91+
7992
static int si2157_load_firmware(struct dvb_frontend *fe,
8093
const char *fw_name)
8194
{
@@ -85,7 +98,7 @@ static int si2157_load_firmware(struct dvb_frontend *fe,
8598
struct si2157_cmd cmd;
8699

87100
/* request the firmware, this will block and timeout */
88-
ret = request_firmware(&fw, fw_name, &client->dev);
101+
ret = firmware_request_nowarn(&fw, fw_name, &client->dev);
89102
if (ret)
90103
return ret;
91104

@@ -124,16 +137,86 @@ static int si2157_load_firmware(struct dvb_frontend *fe,
124137
return ret;
125138
}
126139

140+
static int si2157_find_and_load_firmware(struct dvb_frontend *fe)
141+
{
142+
struct i2c_client *client = fe->tuner_priv;
143+
struct si2157_dev *dev = i2c_get_clientdata(client);
144+
const char *fw_alt_name = NULL;
145+
unsigned char part_id, rom_id;
146+
const char *fw_name = NULL;
147+
struct si2157_cmd cmd;
148+
bool required = true;
149+
int ret, i;
150+
151+
if (dev->dont_load_firmware) {
152+
dev_info(&client->dev,
153+
"device is buggy, skipping firmware download\n");
154+
return 0;
155+
}
156+
157+
/* query chip revision */
158+
memcpy(cmd.args, "\x02", 1);
159+
cmd.wlen = 1;
160+
cmd.rlen = 13;
161+
ret = si2157_cmd_execute(client, &cmd);
162+
if (ret)
163+
return ret;
164+
165+
part_id = cmd.args[2];
166+
rom_id = cmd.args[12];
167+
168+
for (i = 0; i < ARRAY_SIZE(si2157_tuners); i++) {
169+
if (si2157_tuners[i].part_id != part_id)
170+
continue;
171+
required = si2157_tuners[i].required;
172+
fw_alt_name = si2157_tuners[i].fw_alt_name;
173+
174+
/* Both part and rom ID match */
175+
if (si2157_tuners[i].rom_id == rom_id) {
176+
fw_name = si2157_tuners[i].fw_name;
177+
break;
178+
}
179+
}
180+
181+
if (!fw_name && !fw_alt_name) {
182+
dev_err(&client->dev,
183+
"unknown chip version Si21%d-%c%c%c ROM 0x%02x\n",
184+
part_id, cmd.args[1], cmd.args[3], cmd.args[4], rom_id);
185+
return -EINVAL;
186+
}
187+
188+
dev_info(&client->dev,
189+
"found a 'Silicon Labs Si21%d-%c%c%c ROM 0x%02x'\n",
190+
part_id, cmd.args[1], cmd.args[3], cmd.args[4], rom_id);
191+
192+
if (fw_name)
193+
ret = si2157_load_firmware(fe, fw_name);
194+
else
195+
ret = -ENOENT;
196+
197+
/* Try alternate name, if any */
198+
if (ret == -ENOENT && fw_alt_name)
199+
ret = si2157_load_firmware(fe, fw_alt_name);
200+
201+
if (ret == -ENOENT) {
202+
if (!required) {
203+
dev_info(&client->dev, "Using ROM firmware.\n");
204+
return 0;
205+
}
206+
dev_err(&client->dev, "Can't continue without a firmware.\n");
207+
} else if (ret < 0) {
208+
dev_err(&client->dev, "error %d when loading firmware\n", ret);
209+
}
210+
return ret;
211+
}
212+
127213
static int si2157_init(struct dvb_frontend *fe)
128214
{
129215
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
130216
struct i2c_client *client = fe->tuner_priv;
131217
struct si2157_dev *dev = i2c_get_clientdata(client);
132-
bool warn_firmware_not_loaded = false;
133-
unsigned int chip_id, xtal_trim;
134-
bool fw_required = true;
218+
unsigned int xtal_trim;
135219
struct si2157_cmd cmd;
136-
const char *fw_name;
137220
int ret;
138221

139222
dev_dbg(&client->dev, "\n");
@@ -176,72 +259,11 @@ static int si2157_init(struct dvb_frontend *fe)
176259
goto err;
177260
}
178261

179-
if (dev->dont_load_firmware) {
180-
dev_info(&client->dev, "device is buggy, skipping firmware download\n");
181-
goto skip_fw_download;
182-
}
183-
184-
/* query chip revision */
185-
memcpy(cmd.args, "\x02", 1);
186-
cmd.wlen = 1;
187-
cmd.rlen = 13;
188-
ret = si2157_cmd_execute(client, &cmd);
189-
if (ret)
262+
/* Try to load the firmware */
263+
ret = si2157_find_and_load_firmware(fe);
264+
if (ret < 0)
190265
goto err;
191266

192-
chip_id = cmd.args[1] << 24 | cmd.args[2] << 16 | cmd.args[3] << 8 |
193-
cmd.args[4] << 0;
194-
195-
#define SI2177_A30 ('A' << 24 | 77 << 16 | '3' << 8 | '0' << 0)
196-
#define SI2158_A20 ('A' << 24 | 58 << 16 | '2' << 8 | '0' << 0)
197-
#define SI2148_A20 ('A' << 24 | 48 << 16 | '2' << 8 | '0' << 0)
198-
#define SI2157_A30 ('A' << 24 | 57 << 16 | '3' << 8 | '0' << 0)
199-
#define SI2147_A30 ('A' << 24 | 47 << 16 | '3' << 8 | '0' << 0)
200-
#define SI2146_A10 ('A' << 24 | 46 << 16 | '1' << 8 | '0' << 0)
201-
#define SI2141_A10 ('A' << 24 | 41 << 16 | '1' << 8 | '0' << 0)
202-
203-
switch (chip_id) {
204-
case SI2158_A20:
205-
case SI2148_A20:
206-
fw_name = SI2158_A20_FIRMWARE;
207-
break;
208-
case SI2141_A10:
209-
fw_name = SI2141_A10_FIRMWARE;
210-
break;
211-
case SI2157_A30:
212-
fw_required = false;
213-
fallthrough;
214-
case SI2177_A30:
215-
fw_name = SI2157_A30_FIRMWARE;
216-
break;
217-
case SI2147_A30:
218-
case SI2146_A10:
219-
fw_name = NULL;
220-
break;
221-
default:
222-
dev_err(&client->dev, "unknown chip version Si21%d-%c%c%c\n",
223-
cmd.args[2], cmd.args[1],
224-
cmd.args[3], cmd.args[4]);
225-
ret = -EINVAL;
226-
goto err;
227-
}
228-
229-
dev_info(&client->dev, "found a 'Silicon Labs Si21%d-%c%c%c'\n",
230-
cmd.args[2], cmd.args[1], cmd.args[3], cmd.args[4]);
231-
232-
if (fw_name == NULL)
233-
goto skip_fw_download;
234-
235-
ret = si2157_load_firmware(fe, fw_name);
236-
if (fw_required && ret == -ENOENT)
237-
warn_firmware_not_loaded = true;
238-
else if (ret < 0) {
239-
dev_err(&client->dev, "error %d when loading firmware file '%s'\n",
240-
ret, fw_name);
241-
goto err;
242-
}
243-
244-
skip_fw_download:
245267
/* reboot the tuner with new firmware? */
246268
memcpy(cmd.args, "\x01\x01", 2);
247269
cmd.wlen = 2;
@@ -258,11 +280,6 @@ static int si2157_init(struct dvb_frontend *fe)
258280
if (ret)
259281
goto err;
260282

261-
if (warn_firmware_not_loaded) {
262-
dev_warn(&client->dev, "firmware file '%s' not found. Using firmware from eeprom.\n",
263-
fw_name);
264-
warn_firmware_not_loaded = false;
265-
}
266283
dev_info(&client->dev, "firmware version: %c.%c.%d\n",
267284
cmd.args[6], cmd.args[7], cmd.args[8]);
268285

@@ -298,11 +315,6 @@ static int si2157_init(struct dvb_frontend *fe)
298315
return 0;
299316

300317
err:
301-
if (warn_firmware_not_loaded)
302-
dev_err(&client->dev,
303-
"firmware file '%s' not found. Can't continue without a firmware.\n",
304-
fw_name);
305-
306318
dev_dbg(&client->dev, "failed=%d\n", ret);
307319
return ret;
308320
}
@@ -968,3 +980,13 @@ MODULE_LICENSE("GPL");
968980
MODULE_FIRMWARE(SI2158_A20_FIRMWARE);
969981
MODULE_FIRMWARE(SI2141_A10_FIRMWARE);
970982
MODULE_FIRMWARE(SI2157_A30_FIRMWARE);
983+
MODULE_FIRMWARE(SI2141_60_FIRMWARE);
984+
MODULE_FIRMWARE(SI2141_61_FIRMWARE);
985+
MODULE_FIRMWARE(SI2146_11_FIRMWARE);
986+
MODULE_FIRMWARE(SI2147_50_FIRMWARE);
987+
MODULE_FIRMWARE(SI2148_32_FIRMWARE);
988+
MODULE_FIRMWARE(SI2148_33_FIRMWARE);
989+
MODULE_FIRMWARE(SI2157_50_FIRMWARE);
990+
MODULE_FIRMWARE(SI2158_50_FIRMWARE);
991+
MODULE_FIRMWARE(SI2158_51_FIRMWARE);
992+
MODULE_FIRMWARE(SI2177_50_FIRMWARE);

drivers/media/tuners/si2157_priv.h

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,23 @@ struct si2157_dev {
4141

4242
};
4343

44+
enum si2157_part_id {
45+
SI2141 = 41,
46+
SI2146 = 46,
47+
SI2147 = 47,
48+
SI2148 = 48,
49+
SI2157 = 57,
50+
SI2158 = 58,
51+
SI2177 = 77,
52+
};
53+
54+
struct si2157_tuner_info {
55+
enum si2157_part_id part_id;
56+
unsigned char rom_id;
57+
bool required;
58+
const char *fw_name, *fw_alt_name;
59+
};
60+
4461
#define SI2157_CHIPTYPE_SI2157 0
4562
#define SI2157_CHIPTYPE_SI2146 1
4663
#define SI2157_CHIPTYPE_SI2141 2
@@ -54,7 +71,21 @@ struct si2157_cmd {
5471
unsigned rlen;
5572
};
5673

74+
/* Old firmware namespace */
5775
#define SI2158_A20_FIRMWARE "dvb-tuner-si2158-a20-01.fw"
5876
#define SI2141_A10_FIRMWARE "dvb-tuner-si2141-a10-01.fw"
5977
#define SI2157_A30_FIRMWARE "dvb-tuner-si2157-a30-01.fw"
78+
79+
/* New firmware namespace */
80+
#define SI2141_60_FIRMWARE "dvb_driver_si2141_rom60.fw"
81+
#define SI2141_61_FIRMWARE "dvb_driver_si2141_rom61.fw"
82+
#define SI2146_11_FIRMWARE "dvb_driver_si2146_rom11.fw"
83+
#define SI2147_50_FIRMWARE "dvb_driver_si2147_rom50.fw"
84+
#define SI2148_32_FIRMWARE "dvb_driver_si2148_rom32.fw"
85+
#define SI2148_33_FIRMWARE "dvb_driver_si2148_rom33.fw"
86+
#define SI2157_50_FIRMWARE "dvb_driver_si2157_rom50.fw"
87+
#define SI2158_50_FIRMWARE "dvb_driver_si2178_rom50.fw"
88+
#define SI2158_51_FIRMWARE "dvb_driver_si2158_rom51.fw"
89+
#define SI2177_50_FIRMWARE "dvb_driver_si2177_rom50.fw"
90+
6091
#endif

0 commit comments

Comments
 (0)