aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/tuner-xc2028.c
diff options
context:
space:
mode:
authorChris Pascoe <c.pascoe@itee.uq.edu.au>2007-11-19 08:04:06 -0500
committerMauro Carvalho Chehab <mchehab@infradead.org>2008-01-25 16:02:28 -0500
commitb1535293dc816f01b0934718c370f9533c7d635e (patch)
treedba0a95be2648e66402c805ce470efd755d2051e /drivers/media/video/tuner-xc2028.c
parent0a196b6fa9b42a2bb49733b37565aaaa97ffb07f (diff)
V4L/DVB (6643): xc2028: use best match instead of first partial match during firmware selection
Rather than picking the first video standard firmware that supports any of the standards that the user has requested, try to select one that supports as many of them as possible. This improves the likelihood that the firmware we select will support the user's desired TV standard. Signed-off-by: Chris Pascoe <c.pascoe@itee.uq.edu.au> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/video/tuner-xc2028.c')
-rw-r--r--drivers/media/video/tuner-xc2028.c46
1 files changed, 38 insertions, 8 deletions
diff --git a/drivers/media/video/tuner-xc2028.c b/drivers/media/video/tuner-xc2028.c
index e19449603d73..3edf5be47197 100644
--- a/drivers/media/video/tuner-xc2028.c
+++ b/drivers/media/video/tuner-xc2028.c
@@ -377,9 +377,13 @@ static int seek_firmware(struct dvb_frontend *fe, unsigned int type,
377 v4l2_std_id *id) 377 v4l2_std_id *id)
378{ 378{
379 struct xc2028_data *priv = fe->tuner_priv; 379 struct xc2028_data *priv = fe->tuner_priv;
380 int i; 380 int i, best_i = -1, best_nr_matches = 0;
381 381
382 tuner_dbg("%s called\n", __FUNCTION__); 382 tuner_dbg("%s called, want type=", __FUNCTION__);
383 if (debug) {
384 dump_firm_type(type);
385 printk("(%x), id %016llx.\n", type, (unsigned long long)*id);
386 }
383 387
384 if (!priv->firm) { 388 if (!priv->firm) {
385 tuner_err("Error! firmware not loaded\n"); 389 tuner_err("Error! firmware not loaded\n");
@@ -397,20 +401,45 @@ static int seek_firmware(struct dvb_frontend *fe, unsigned int type,
397 401
398 /* Seek for generic video standard match */ 402 /* Seek for generic video standard match */
399 for (i = 0; i < priv->firm_size; i++) { 403 for (i = 0; i < priv->firm_size; i++) {
400 if ((type == priv->firm[i].type) && (*id & priv->firm[i].id)) 404 v4l2_std_id match_mask;
401 goto found; 405 int nr_matches;
406
407 if (type != priv->firm[i].type)
408 continue;
409
410 match_mask = *id & priv->firm[i].id;
411 if (!match_mask)
412 continue;
413
414 if ((*id & match_mask) == *id)
415 goto found; /* Supports all the requested standards */
416
417 nr_matches = hweight64(match_mask);
418 if (nr_matches > best_nr_matches) {
419 best_nr_matches = nr_matches;
420 best_i = i;
421 }
422 }
423
424 if (best_nr_matches > 0) {
425 tuner_dbg("Selecting best matching firmware (%d bits) for "
426 "type=", best_nr_matches);
427 dump_firm_type(type);
428 printk("(%x), id %016llx:\n", type, (unsigned long long)*id);
429 i = best_i;
430 goto found;
402 } 431 }
403 432
404 /*FIXME: Would make sense to seek for type "hint" match ? */ 433 /*FIXME: Would make sense to seek for type "hint" match ? */
405 434
406 i = -EINVAL; 435 i = -ENOENT;
407 goto ret; 436 goto ret;
408 437
409found: 438found:
410 *id = priv->firm[i].id; 439 *id = priv->firm[i].id;
411 440
412ret: 441ret:
413 tuner_dbg("%s firmware for type=", (i < 0)? "Can't find": "Found"); 442 tuner_dbg("%s firmware for type=", (i < 0) ? "Can't find" : "Found");
414 if (debug) { 443 if (debug) {
415 dump_firm_type(type); 444 dump_firm_type(type);
416 printk("(%x), id %016llx.\n", type, (unsigned long long)*id); 445 printk("(%x), id %016llx.\n", type, (unsigned long long)*id);
@@ -432,8 +461,9 @@ static int load_firmware(struct dvb_frontend *fe, unsigned int type,
432 return pos; 461 return pos;
433 462
434 tuner_info("Loading firmware for type="); 463 tuner_info("Loading firmware for type=");
435 dump_firm_type(type); 464 dump_firm_type(priv->firm[pos].type);
436 printk("(%x), id %016llx.\n", type, (unsigned long long)*id); 465 printk("(%x), id %016llx.\n", priv->firm[pos].type,
466 (unsigned long long)*id);
437 467
438 p = priv->firm[pos].ptr; 468 p = priv->firm[pos].ptr;
439 endp = p + priv->firm[pos].size; 469 endp = p + priv->firm[pos].size;