diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/media/dvb/frontends/tda1004x.c | 36 |
1 files changed, 34 insertions, 2 deletions
diff --git a/drivers/media/dvb/frontends/tda1004x.c b/drivers/media/dvb/frontends/tda1004x.c index ecfa8c7a9784..0beb370792ae 100644 --- a/drivers/media/dvb/frontends/tda1004x.c +++ b/drivers/media/dvb/frontends/tda1004x.c | |||
@@ -49,6 +49,7 @@ struct tda1004x_state { | |||
49 | /* private demod data */ | 49 | /* private demod data */ |
50 | u8 initialised; | 50 | u8 initialised; |
51 | enum tda1004x_demod demod_type; | 51 | enum tda1004x_demod demod_type; |
52 | u8 fw_version; | ||
52 | }; | 53 | }; |
53 | 54 | ||
54 | 55 | ||
@@ -380,6 +381,25 @@ static int tda10045_fwupload(struct dvb_frontend* fe) | |||
380 | return tda1004x_check_upload_ok(state, 0x2c); | 381 | return tda1004x_check_upload_ok(state, 0x2c); |
381 | } | 382 | } |
382 | 383 | ||
384 | static int tda10046_get_fw_version(struct tda1004x_state *state, | ||
385 | const struct firmware *fw) | ||
386 | { | ||
387 | const unsigned char pattern[] = { 0x67, 0x00, 0x50, 0x62, 0x5e, 0x18, 0x67 }; | ||
388 | unsigned int i; | ||
389 | |||
390 | /* area guessed from firmware v20, v21 and v25 */ | ||
391 | for (i = 0x660; i < 0x700; i++) { | ||
392 | if (!memcmp(&fw->data[i], pattern, sizeof(pattern))) { | ||
393 | state->fw_version = fw->data[i + sizeof(pattern)]; | ||
394 | printk(KERN_INFO "tda1004x: using firmware v%02x\n", | ||
395 | state->fw_version); | ||
396 | return 0; | ||
397 | } | ||
398 | } | ||
399 | |||
400 | return -EINVAL; | ||
401 | } | ||
402 | |||
383 | static int tda10046_fwupload(struct dvb_frontend* fe) | 403 | static int tda10046_fwupload(struct dvb_frontend* fe) |
384 | { | 404 | { |
385 | struct tda1004x_state* state = fe->demodulator_priv; | 405 | struct tda1004x_state* state = fe->demodulator_priv; |
@@ -393,7 +413,7 @@ static int tda10046_fwupload(struct dvb_frontend* fe) | |||
393 | msleep(100); | 413 | msleep(100); |
394 | 414 | ||
395 | /* don't re-upload unless necessary */ | 415 | /* don't re-upload unless necessary */ |
396 | if (tda1004x_check_upload_ok(state, 0x20) == 0) | 416 | if (tda1004x_check_upload_ok(state, state->fw_version) == 0) |
397 | return 0; | 417 | return 0; |
398 | 418 | ||
399 | /* request the firmware, this will block until someone uploads it */ | 419 | /* request the firmware, this will block until someone uploads it */ |
@@ -404,6 +424,17 @@ static int tda10046_fwupload(struct dvb_frontend* fe) | |||
404 | return ret; | 424 | return ret; |
405 | } | 425 | } |
406 | 426 | ||
427 | if (fw->size < 24478) { /* size of firmware v20, which is the smallest of v20, v21 and v25 */ | ||
428 | printk("tda1004x: firmware file seems to be too small (%d bytes)\n", fw->size); | ||
429 | return -EINVAL; | ||
430 | } | ||
431 | |||
432 | ret = tda10046_get_fw_version(state, fw); | ||
433 | if (ret < 0) { | ||
434 | printk("tda1004x: unable to find firmware version\n"); | ||
435 | return ret; | ||
436 | } | ||
437 | |||
407 | /* set parameters */ | 438 | /* set parameters */ |
408 | tda1004x_write_byteI(state, TDA10046H_CONFPLL2, 10); | 439 | tda1004x_write_byteI(state, TDA10046H_CONFPLL2, 10); |
409 | tda1004x_write_byteI(state, TDA10046H_CONFPLL3, state->config->n_i2c); | 440 | tda1004x_write_byteI(state, TDA10046H_CONFPLL3, state->config->n_i2c); |
@@ -427,7 +458,7 @@ static int tda10046_fwupload(struct dvb_frontend* fe) | |||
427 | msleep(1); | 458 | msleep(1); |
428 | } | 459 | } |
429 | 460 | ||
430 | return tda1004x_check_upload_ok(state, 0x20); | 461 | return tda1004x_check_upload_ok(state, state->fw_version); |
431 | } | 462 | } |
432 | 463 | ||
433 | static int tda1004x_encode_fec(int fec) | 464 | static int tda1004x_encode_fec(int fec) |
@@ -1185,6 +1216,7 @@ struct dvb_frontend* tda10046_attach(const struct tda1004x_config* config, | |||
1185 | memcpy(&state->ops, &tda10046_ops, sizeof(struct dvb_frontend_ops)); | 1216 | memcpy(&state->ops, &tda10046_ops, sizeof(struct dvb_frontend_ops)); |
1186 | state->initialised = 0; | 1217 | state->initialised = 0; |
1187 | state->demod_type = TDA1004X_DEMOD_TDA10046; | 1218 | state->demod_type = TDA1004X_DEMOD_TDA10046; |
1219 | state->fw_version = 0x20; /* dummy default value */ | ||
1188 | 1220 | ||
1189 | /* check if the demod is there */ | 1221 | /* check if the demod is there */ |
1190 | if (tda1004x_read_byte(state, TDA1004X_CHIPID) != 0x46) { | 1222 | if (tda1004x_read_byte(state, TDA1004X_CHIPID) != 0x46) { |