aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/media/dvb/frontends/tda1004x.c36
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
384static 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
383static int tda10046_fwupload(struct dvb_frontend* fe) 403static 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
433static int tda1004x_encode_fec(int fec) 464static 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) {