diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/media/video/tuner-xc2028.c | 46 |
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 | ||
409 | found: | 438 | found: |
410 | *id = priv->firm[i].id; | 439 | *id = priv->firm[i].id; |
411 | 440 | ||
412 | ret: | 441 | ret: |
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; |