si2157.c (7c2d8ee486b9ebd462dcd0aea1969758522f4c3a) | si2157.c (1c35ba3bf97213538b82067acc0f23f18e652226) |
---|---|
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" --- 62 unchanged lines hidden (view full) --- 71 return 0; 72 73err_mutex_unlock: 74 mutex_unlock(&dev->i2c_mutex); 75 dev_dbg(&client->dev, "failed=%d\n", ret); 76 return ret; 77} 78 | 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" --- 62 unchanged lines hidden (view full) --- 71 return 0; 72 73err_mutex_unlock: 74 mutex_unlock(&dev->i2c_mutex); 75 dev_dbg(&client->dev, "failed=%d\n", ret); 76 return ret; 77} 78 |
79static 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 |
|
79static int si2157_load_firmware(struct dvb_frontend *fe, 80 const char *fw_name) 81{ 82 struct i2c_client *client = fe->tuner_priv; 83 const struct firmware *fw; 84 int ret, len, remaining; 85 struct si2157_cmd cmd; 86 87 /* request the firmware, this will block and timeout */ | 92static int si2157_load_firmware(struct dvb_frontend *fe, 93 const char *fw_name) 94{ 95 struct i2c_client *client = fe->tuner_priv; 96 const struct firmware *fw; 97 int ret, len, remaining; 98 struct si2157_cmd cmd; 99 100 /* 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); |
89 if (ret) 90 return ret; 91 92 /* firmware should be n chunks of 17 bytes */ 93 if (fw->size % 17 != 0) { 94 dev_err(&client->dev, "firmware file '%s' is invalid\n", 95 fw_name); 96 ret = -EINVAL; --- 22 unchanged lines hidden (view full) --- 119 } 120 121err_release_firmware: 122 release_firmware(fw); 123 124 return ret; 125} 126 | 102 if (ret) 103 return ret; 104 105 /* firmware should be n chunks of 17 bytes */ 106 if (fw->size % 17 != 0) { 107 dev_err(&client->dev, "firmware file '%s' is invalid\n", 108 fw_name); 109 ret = -EINVAL; --- 22 unchanged lines hidden (view full) --- 132 } 133 134err_release_firmware: 135 release_firmware(fw); 136 137 return ret; 138} 139 |
140static 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 |
|
127static int si2157_init(struct dvb_frontend *fe) 128{ 129 struct dtv_frontend_properties *c = &fe->dtv_property_cache; 130 struct i2c_client *client = fe->tuner_priv; 131 struct si2157_dev *dev = i2c_get_clientdata(client); | 213static int si2157_init(struct dvb_frontend *fe) 214{ 215 struct dtv_frontend_properties *c = &fe->dtv_property_cache; 216 struct i2c_client *client = fe->tuner_priv; 217 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; |
135 struct si2157_cmd cmd; | 219 struct si2157_cmd cmd; |
136 const char *fw_name; | |
137 int ret; 138 139 dev_dbg(&client->dev, "\n"); 140 141 /* Try to get Xtal trim property, to verify tuner still running */ 142 memcpy(cmd.args, "\x15\x00\x02\x04", 4); 143 cmd.wlen = 4; 144 cmd.rlen = 4; --- 26 unchanged lines hidden (view full) --- 171 if (dev->chiptype == SI2157_CHIPTYPE_SI2141) { 172 memcpy(cmd.args, "\xc0\x08\x01\x02\x00\x00\x01", 7); 173 cmd.wlen = 7; 174 ret = si2157_cmd_execute(client, &cmd); 175 if (ret) 176 goto err; 177 } 178 | 220 int ret; 221 222 dev_dbg(&client->dev, "\n"); 223 224 /* Try to get Xtal trim property, to verify tuner still running */ 225 memcpy(cmd.args, "\x15\x00\x02\x04", 4); 226 cmd.wlen = 4; 227 cmd.rlen = 4; --- 26 unchanged lines hidden (view full) --- 254 if (dev->chiptype == SI2157_CHIPTYPE_SI2141) { 255 memcpy(cmd.args, "\xc0\x08\x01\x02\x00\x00\x01", 7); 256 cmd.wlen = 7; 257 ret = si2157_cmd_execute(client, &cmd); 258 if (ret) 259 goto err; 260 } 261 |
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) |
190 goto err; 191 | 265 goto err; 266 |
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 244skip_fw_download: | |
245 /* reboot the tuner with new firmware? */ 246 memcpy(cmd.args, "\x01\x01", 2); 247 cmd.wlen = 2; 248 cmd.rlen = 1; 249 ret = si2157_cmd_execute(client, &cmd); 250 if (ret) 251 goto err; 252 253 /* query firmware version */ 254 memcpy(cmd.args, "\x11", 1); 255 cmd.wlen = 1; 256 cmd.rlen = 10; 257 ret = si2157_cmd_execute(client, &cmd); 258 if (ret) 259 goto err; 260 | 267 /* reboot the tuner with new firmware? */ 268 memcpy(cmd.args, "\x01\x01", 2); 269 cmd.wlen = 2; 270 cmd.rlen = 1; 271 ret = si2157_cmd_execute(client, &cmd); 272 if (ret) 273 goto err; 274 275 /* query firmware version */ 276 memcpy(cmd.args, "\x11", 1); 277 cmd.wlen = 1; 278 cmd.rlen = 10; 279 ret = si2157_cmd_execute(client, &cmd); 280 if (ret) 281 goto err; 282 |
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 } | |
266 dev_info(&client->dev, "firmware version: %c.%c.%d\n", 267 cmd.args[6], cmd.args[7], cmd.args[8]); 268 269 /* enable tuner status flags */ 270 memcpy(cmd.args, "\x14\x00\x01\x05\x01\x00", 6); 271 cmd.wlen = 6; 272 cmd.rlen = 1; 273 ret = si2157_cmd_execute(client, &cmd); --- 19 unchanged lines hidden (view full) --- 293 c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 294 /* start statistics polling */ 295 schedule_delayed_work(&dev->stat_work, msecs_to_jiffies(1000)); 296 297 dev->active = true; 298 return 0; 299 300err: | 283 dev_info(&client->dev, "firmware version: %c.%c.%d\n", 284 cmd.args[6], cmd.args[7], cmd.args[8]); 285 286 /* enable tuner status flags */ 287 memcpy(cmd.args, "\x14\x00\x01\x05\x01\x00", 6); 288 cmd.wlen = 6; 289 cmd.rlen = 1; 290 ret = si2157_cmd_execute(client, &cmd); --- 19 unchanged lines hidden (view full) --- 310 c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 311 /* start statistics polling */ 312 schedule_delayed_work(&dev->stat_work, msecs_to_jiffies(1000)); 313 314 dev->active = true; 315 return 0; 316 317err: |
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 | |
306 dev_dbg(&client->dev, "failed=%d\n", ret); 307 return ret; 308} 309 310static int si2157_sleep(struct dvb_frontend *fe) 311{ 312 struct i2c_client *client = fe->tuner_priv; 313 struct si2157_dev *dev = i2c_get_clientdata(client); --- 649 unchanged lines hidden (view full) --- 963module_i2c_driver(si2157_driver); 964 965MODULE_DESCRIPTION("Silicon Labs Si2141/Si2146/2147/2148/2157/2158 silicon tuner driver"); 966MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); 967MODULE_LICENSE("GPL"); 968MODULE_FIRMWARE(SI2158_A20_FIRMWARE); 969MODULE_FIRMWARE(SI2141_A10_FIRMWARE); 970MODULE_FIRMWARE(SI2157_A30_FIRMWARE); | 318 dev_dbg(&client->dev, "failed=%d\n", ret); 319 return ret; 320} 321 322static int si2157_sleep(struct dvb_frontend *fe) 323{ 324 struct i2c_client *client = fe->tuner_priv; 325 struct si2157_dev *dev = i2c_get_clientdata(client); --- 649 unchanged lines hidden (view full) --- 975module_i2c_driver(si2157_driver); 976 977MODULE_DESCRIPTION("Silicon Labs Si2141/Si2146/2147/2148/2157/2158 silicon tuner driver"); 978MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); 979MODULE_LICENSE("GPL"); 980MODULE_FIRMWARE(SI2158_A20_FIRMWARE); 981MODULE_FIRMWARE(SI2141_A10_FIRMWARE); 982MODULE_FIRMWARE(SI2157_A30_FIRMWARE); |
983MODULE_FIRMWARE(SI2141_60_FIRMWARE); 984MODULE_FIRMWARE(SI2141_61_FIRMWARE); 985MODULE_FIRMWARE(SI2146_11_FIRMWARE); 986MODULE_FIRMWARE(SI2147_50_FIRMWARE); 987MODULE_FIRMWARE(SI2148_32_FIRMWARE); 988MODULE_FIRMWARE(SI2148_33_FIRMWARE); 989MODULE_FIRMWARE(SI2157_50_FIRMWARE); 990MODULE_FIRMWARE(SI2158_50_FIRMWARE); 991MODULE_FIRMWARE(SI2158_51_FIRMWARE); 992MODULE_FIRMWARE(SI2177_50_FIRMWARE); |
|