aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@infradead.org>2007-11-15 06:43:53 -0500
committerMauro Carvalho Chehab <mchehab@infradead.org>2008-01-25 16:02:10 -0500
commitf380e1d2c9a1ff82a89ec68850ce53094359000e (patch)
tree00813ee13c2420a84bd8d2b98c1934cbaefb0858 /drivers/media
parent43efe70253dd13b2d22ee51bb474ece25b3b41b1 (diff)
V4L/DVB (6593): Fix scode table loading
Xceive 2028/3028 has a concept of scode/dcode. Scode is a table of 16 values (each with 12 bytes i2c sequence). Dcode is the entry of Scode table that should be used, given a certain frequency. The idea is that, depending on what frequency is selected, and according with a country-based (or standard-based?) table, the Xceive should be "hacked" to fine-tune that specific frequency. By default, Scode=0 is used, for undefined frequencies. Also, Scode=0 seems to be the most used value. This patch adds the capability of selecting a scode. However, extra work will be needed to allow auto-selecting the proper scode, for a given set of frequencies. I'm not sure what would be the proper way for implementing the dcode selection. Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media')
-rw-r--r--drivers/media/video/tuner-xc2028.c98
1 files changed, 77 insertions, 21 deletions
diff --git a/drivers/media/video/tuner-xc2028.c b/drivers/media/video/tuner-xc2028.c
index ac0c9c3cde98..e046c21be0b9 100644
--- a/drivers/media/video/tuner-xc2028.c
+++ b/drivers/media/video/tuner-xc2028.c
@@ -116,6 +116,8 @@ void dump_firm_type(unsigned int type)
116{ 116{
117 if (type & BASE) 117 if (type & BASE)
118 printk("BASE "); 118 printk("BASE ");
119 if (type & INIT1)
120 printk("INIT1 ");
119 if (type & F8MHZ) 121 if (type & F8MHZ)
120 printk("F8MHZ "); 122 printk("F8MHZ ");
121 if (type & MTS) 123 if (type & MTS)
@@ -201,7 +203,7 @@ static int load_all_firmwares(struct dvb_frontend *fe)
201 203
202 tuner_info("%s called\n", __FUNCTION__); 204 tuner_info("%s called\n", __FUNCTION__);
203 205
204 tuner_info("Loading firmware %s\n", priv->ctrl.fname); 206 tuner_info("Reading firmware %s\n", priv->ctrl.fname);
205 rc = request_firmware(&fw, priv->ctrl.fname, priv->dev); 207 rc = request_firmware(&fw, priv->ctrl.fname, priv->dev);
206 if (rc < 0) { 208 if (rc < 0) {
207 if (rc == -ENOENT) 209 if (rc == -ENOENT)
@@ -325,12 +327,11 @@ done:
325 return rc; 327 return rc;
326} 328}
327 329
328static int load_firmware(struct dvb_frontend *fe, unsigned int type, 330static int seek_firmware(struct dvb_frontend *fe, unsigned int type,
329 v4l2_std_id * id) 331 v4l2_std_id *id)
330{ 332{
331 struct xc2028_data *priv = fe->tuner_priv; 333 struct xc2028_data *priv = fe->tuner_priv;
332 int i, rc; 334 int i;
333 unsigned char *p, *endp, buf[priv->max_len];
334 335
335 tuner_info("%s called\n", __FUNCTION__); 336 tuner_info("%s called\n", __FUNCTION__);
336 337
@@ -339,7 +340,7 @@ static int load_firmware(struct dvb_frontend *fe, unsigned int type,
339 return -EINVAL; 340 return -EINVAL;
340 } 341 }
341 342
342 if ((type == 0) && (*id == 0)) 343 if (((type & ~SCODE) == 0) && (*id == 0))
343 *id = V4L2_STD_PAL; 344 *id = V4L2_STD_PAL;
344 345
345 /* Seek for exact match */ 346 /* Seek for exact match */
@@ -356,21 +357,40 @@ static int load_firmware(struct dvb_frontend *fe, unsigned int type,
356 357
357 /*FIXME: Would make sense to seek for type "hint" match ? */ 358 /*FIXME: Would make sense to seek for type "hint" match ? */
358 359
359 tuner_info("Can't find firmware for type=%x, id=%lx\n", type, 360 i = -EINVAL;
360 (long int)*id); 361 goto ret;
361 return -EINVAL;
362 362
363found: 363found:
364 *id = priv->firm[i].id; 364 *id = priv->firm[i].id;
365 tuner_info("Found firmware for type=%x, id=%lx\n", type, (long int)*id);
366 365
367 p = priv->firm[i].ptr; 366ret:
367 tuner_info("%s firmware for type=", (i < 0)? "Can't find": "Found");
368 dump_firm_type(type);
369 printk("(%x), id %08lx.\n", type, (unsigned long)*id);
370
371 return i;
372}
373
374static int load_firmware(struct dvb_frontend *fe, unsigned int type,
375 v4l2_std_id *id)
376{
377 struct xc2028_data *priv = fe->tuner_priv;
378 int pos, rc;
379 unsigned char *p, *endp, buf[priv->max_len];
380
381 tuner_info("%s called\n", __FUNCTION__);
382
383 pos = seek_firmware(fe, type, id);
384 if (pos < 0)
385 return pos;
386
387 p = priv->firm[pos].ptr;
368 388
369 if (!p) { 389 if (!p) {
370 printk(KERN_ERR PREFIX "Firmware pointer were freed!"); 390 printk(KERN_ERR PREFIX "Firmware pointer were freed!");
371 return -EINVAL; 391 return -EINVAL;
372 } 392 }
373 endp = p + priv->firm[i].size; 393 endp = p + priv->firm[pos].size;
374 394
375 while (p < endp) { 395 while (p < endp) {
376 __u16 size; 396 __u16 size;
@@ -435,6 +455,42 @@ found:
435 return 0; 455 return 0;
436} 456}
437 457
458static int load_scode(struct dvb_frontend *fe, unsigned int type,
459 v4l2_std_id *id, int scode)
460{
461 struct xc2028_data *priv = fe->tuner_priv;
462 int pos, rc;
463 unsigned char *p;
464
465 tuner_info("%s called\n", __FUNCTION__);
466
467 pos = seek_firmware(fe, type, id);
468 if (pos < 0)
469 return pos;
470
471 p = priv->firm[pos].ptr;
472
473 if (!p) {
474 printk(KERN_ERR PREFIX "Firmware pointer were freed!");
475 return -EINVAL;
476 }
477
478 if ((priv->firm[pos].size != 12 * 16) || (scode >= 16))
479 return -EINVAL;
480
481 if (priv->version < 0x0202) {
482 send_seq(priv, {0x20, 0x00, 0x00, 0x00});
483 } else {
484 send_seq(priv, {0xa0, 0x00, 0x00, 0x00});
485 }
486
487 i2c_send(rc, priv, p + 12 * scode, 12);
488
489 send_seq(priv, {0x00, 0x8c});
490
491 return 0;
492}
493
438static int check_firmware(struct dvb_frontend *fe, enum tuner_mode new_mode, 494static int check_firmware(struct dvb_frontend *fe, enum tuner_mode new_mode,
439 v4l2_std_id std, fe_bandwidth_t bandwidth) 495 v4l2_std_id std, fe_bandwidth_t bandwidth)
440{ 496{
@@ -527,8 +583,8 @@ static int check_firmware(struct dvb_frontend *fe, enum tuner_mode new_mode,
527 } 583 }
528 584
529 /* Load INIT1, if needed */ 585 /* Load INIT1, if needed */
530 tuner_info("Trying to load init1 firmware\n"); 586 tuner_info("Load init1 firmware, if exists\n");
531 type0 = BASE | INIT1 | priv->ctrl.type; 587 type0 = BASE | INIT1;
532 if (priv->ctrl.type == XC2028_FIRM_MTS) 588 if (priv->ctrl.type == XC2028_FIRM_MTS)
533 type0 |= MTS; 589 type0 |= MTS;
534 590
@@ -541,9 +597,9 @@ static int check_firmware(struct dvb_frontend *fe, enum tuner_mode new_mode,
541 if (priv->ctrl.type == XC2028_FIRM_MTS) 597 if (priv->ctrl.type == XC2028_FIRM_MTS)
542 type |= MTS; 598 type |= MTS;
543 599
544 tuner_info("firmware standard to load: %08lx\n", (unsigned long)std); 600 tuner_info("Firmware standard to load: %08lx\n", (unsigned long)std);
545 if (priv->firm_type & std) { 601 if (priv->firm_type & std) {
546 tuner_info("no need to load a std-specific firmware.\n"); 602 tuner_info("Std-specific firmware already loaded.\n");
547 return 0; 603 return 0;
548 } 604 }
549 605
@@ -551,11 +607,11 @@ static int check_firmware(struct dvb_frontend *fe, enum tuner_mode new_mode,
551 if (rc < 0) 607 if (rc < 0)
552 return rc; 608 return rc;
553 609
554 /* Load SCODE firmware, if needed */ 610 /* Load SCODE firmware, if exists */
555 tuner_info("Trying to load scode firmware\n"); 611 tuner_info("Trying to load scode 0\n");
556 type0 = SCODE | priv->ctrl.type; 612 type |= SCODE;
557 if (priv->ctrl.type == XC2028_FIRM_MTS) 613
558 type0 |= MTS; 614 rc = load_scode(fe, type, &std, 0);
559 615
560 version = xc2028_get_reg(priv, 0x0004); 616 version = xc2028_get_reg(priv, 0x0004);
561 hwmodel = xc2028_get_reg(priv, 0x0008); 617 hwmodel = xc2028_get_reg(priv, 0x0008);