[PATCH] dvb: tda10046: support for different firmware versions

added support for different tda10046 firmware versions. tested with v20, v21
and v25. (Andreas Oberritter)

Signed-off-by: Johannes Stezenbach <js@linuxtv.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

authored by

Johannes Stezenbach and committed by
Linus Torvalds
71e34201 1dfb800f

+36 -4
+2 -2
Documentation/dvb/get_dvb_firmware
··· 107 107 sub tda10046 { 108 108 my $sourcefile = "tt_budget_217g.zip"; 109 109 my $url = "http://www.technotrend.de/new/217g/$sourcefile"; 110 - my $hash = "a25b579e37109af60f4a36c37893957c"; 110 + my $hash = "6a7e1e2f2644b162ff0502367553c72d"; 111 111 my $outfile = "dvb-fe-tda10046.fw"; 112 112 my $tmpdir = tempdir(DIR => "/tmp", CLEANUP => 1); 113 113 ··· 115 115 116 116 wgetfile($sourcefile, $url); 117 117 unzip($sourcefile, $tmpdir); 118 - extract("$tmpdir/software/OEM/PCI/App/ttlcdacc.dll", 0x3f731, 24479, "$tmpdir/fwtmp"); 118 + extract("$tmpdir/software/OEM/PCI/App/ttlcdacc.dll", 0x3f731, 24478, "$tmpdir/fwtmp"); 119 119 verify("$tmpdir/fwtmp", $hash); 120 120 copy("$tmpdir/fwtmp", $outfile); 121 121
+34 -2
drivers/media/dvb/frontends/tda1004x.c
··· 49 49 /* private demod data */ 50 50 u8 initialised; 51 51 enum tda1004x_demod demod_type; 52 + u8 fw_version; 52 53 }; 53 54 54 55 ··· 381 380 return tda1004x_check_upload_ok(state, 0x2c); 382 381 } 383 382 383 + static int tda10046_get_fw_version(struct tda1004x_state *state, 384 + const struct firmware *fw) 385 + { 386 + const unsigned char pattern[] = { 0x67, 0x00, 0x50, 0x62, 0x5e, 0x18, 0x67 }; 387 + unsigned int i; 388 + 389 + /* area guessed from firmware v20, v21 and v25 */ 390 + for (i = 0x660; i < 0x700; i++) { 391 + if (!memcmp(&fw->data[i], pattern, sizeof(pattern))) { 392 + state->fw_version = fw->data[i + sizeof(pattern)]; 393 + printk(KERN_INFO "tda1004x: using firmware v%02x\n", 394 + state->fw_version); 395 + return 0; 396 + } 397 + } 398 + 399 + return -EINVAL; 400 + } 401 + 384 402 static int tda10046_fwupload(struct dvb_frontend* fe) 385 403 { 386 404 struct tda1004x_state* state = fe->demodulator_priv; ··· 413 393 msleep(100); 414 394 415 395 /* don't re-upload unless necessary */ 416 - if (tda1004x_check_upload_ok(state, 0x20) == 0) 396 + if (tda1004x_check_upload_ok(state, state->fw_version) == 0) 417 397 return 0; 418 398 419 399 /* request the firmware, this will block until someone uploads it */ ··· 421 401 ret = state->config->request_firmware(fe, &fw, TDA10046_DEFAULT_FIRMWARE); 422 402 if (ret) { 423 403 printk("tda1004x: no firmware upload (timeout or file not found?)\n"); 404 + return ret; 405 + } 406 + 407 + if (fw->size < 24478) { /* size of firmware v20, which is the smallest of v20, v21 and v25 */ 408 + printk("tda1004x: firmware file seems to be too small (%d bytes)\n", fw->size); 409 + return -EINVAL; 410 + } 411 + 412 + ret = tda10046_get_fw_version(state, fw); 413 + if (ret < 0) { 414 + printk("tda1004x: unable to find firmware version\n"); 424 415 return ret; 425 416 } 426 417 ··· 458 427 msleep(1); 459 428 } 460 429 461 - return tda1004x_check_upload_ok(state, 0x20); 430 + return tda1004x_check_upload_ok(state, state->fw_version); 462 431 } 463 432 464 433 static int tda1004x_encode_fec(int fec) ··· 1216 1185 memcpy(&state->ops, &tda10046_ops, sizeof(struct dvb_frontend_ops)); 1217 1186 state->initialised = 0; 1218 1187 state->demod_type = TDA1004X_DEMOD_TDA10046; 1188 + state->fw_version = 0x20; /* dummy default value */ 1219 1189 1220 1190 /* check if the demod is there */ 1221 1191 if (tda1004x_read_byte(state, TDA1004X_CHIPID) != 0x46) {