summaryrefslogtreecommitdiff
path: root/linux
diff options
context:
space:
mode:
authorChris Pascoe <c.pascoe@itee.uq.edu.au>2007-11-19 23:04:06 +1000
committerChris Pascoe <c.pascoe@itee.uq.edu.au>2007-11-19 23:04:06 +1000
commitecfc8a73b44e35d80a7d1061010ad502c0985080 (patch)
treecb09b9093a5f09b8370ef79bdeb6211b9de0f865 /linux
parent9f4f9e69cfa1eb86ebac72b9d472ed4dafcba7c9 (diff)
downloadmediapointer-dvb-s2-ecfc8a73b44e35d80a7d1061010ad502c0985080.tar.gz
mediapointer-dvb-s2-ecfc8a73b44e35d80a7d1061010ad502c0985080.tar.bz2
xc2028: use best match instead of first partial match during firmware selection
From: Chris Pascoe <c.pascoe@itee.uq.edu.au> 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 'linux')
-rw-r--r--linux/drivers/media/video/tuner-xc2028.c46
1 files changed, 38 insertions, 8 deletions
diff --git a/linux/drivers/media/video/tuner-xc2028.c b/linux/drivers/media/video/tuner-xc2028.c
index 1017b1d10..131687ea4 100644
--- a/linux/drivers/media/video/tuner-xc2028.c
+++ b/linux/drivers/media/video/tuner-xc2028.c
@@ -392,9 +392,13 @@ static int seek_firmware(struct dvb_frontend *fe, unsigned int type,
v4l2_std_id *id)
{
struct xc2028_data *priv = fe->tuner_priv;
- int i;
+ int i, best_i = -1, best_nr_matches = 0;
- tuner_dbg("%s called\n", __FUNCTION__);
+ tuner_dbg("%s called, want type=", __FUNCTION__);
+ if (debug) {
+ dump_firm_type(type);
+ printk("(%x), id %016llx.\n", type, (unsigned long long)*id);
+ }
if (!priv->firm) {
tuner_err("Error! firmware not loaded\n");
@@ -412,20 +416,45 @@ static int seek_firmware(struct dvb_frontend *fe, unsigned int type,
/* Seek for generic video standard match */
for (i = 0; i < priv->firm_size; i++) {
- if ((type == priv->firm[i].type) && (*id & priv->firm[i].id))
- goto found;
+ v4l2_std_id match_mask;
+ int nr_matches;
+
+ if (type != priv->firm[i].type)
+ continue;
+
+ match_mask = *id & priv->firm[i].id;
+ if (!match_mask)
+ continue;
+
+ if ((*id & match_mask) == *id)
+ goto found; /* Supports all the requested standards */
+
+ nr_matches = hweight64(match_mask);
+ if (nr_matches > best_nr_matches) {
+ best_nr_matches = nr_matches;
+ best_i = i;
+ }
+ }
+
+ if (best_nr_matches > 0) {
+ tuner_dbg("Selecting best matching firmware (%d bits) for "
+ "type=", best_nr_matches);
+ dump_firm_type(type);
+ printk("(%x), id %016llx:\n", type, (unsigned long long)*id);
+ i = best_i;
+ goto found;
}
/*FIXME: Would make sense to seek for type "hint" match ? */
- i = -EINVAL;
+ i = -ENOENT;
goto ret;
found:
*id = priv->firm[i].id;
ret:
- tuner_dbg("%s firmware for type=", (i < 0)? "Can't find": "Found");
+ tuner_dbg("%s firmware for type=", (i < 0) ? "Can't find" : "Found");
if (debug) {
dump_firm_type(type);
printk("(%x), id %016llx.\n", type, (unsigned long long)*id);
@@ -447,8 +476,9 @@ static int load_firmware(struct dvb_frontend *fe, unsigned int type,
return pos;
tuner_info("Loading firmware for type=");
- dump_firm_type(type);
- printk("(%x), id %016llx.\n", type, (unsigned long long)*id);
+ dump_firm_type(priv->firm[pos].type);
+ printk("(%x), id %016llx.\n", priv->firm[pos].type,
+ (unsigned long long)*id);
p = priv->firm[pos].ptr;
endp = p + priv->firm[pos].size;