diff options
author | Hans Verkuil <hverkuil@xs4all.nl> | 2007-11-04 14:42:42 +0100 |
---|---|---|
committer | Hans Verkuil <hverkuil@xs4all.nl> | 2007-11-04 14:42:42 +0100 |
commit | 745ed6ed26c97d4b99fc125df175a018753b12ca (patch) | |
tree | 45b4d8c74fdb5618c5deacb95b7d0b67f7bbbd6f /linux/drivers/media/video/tuner-core.c | |
parent | 971898bb2fef994eccedc53e385ec8fec1b01244 (diff) | |
download | mediapointer-dvb-s2-745ed6ed26c97d4b99fc125df175a018753b12ca.tar.gz mediapointer-dvb-s2-745ed6ed26c97d4b99fc125df175a018753b12ca.tar.bz2 |
tuner: replace default_mode_mask
From: Hans Verkuil <hverkuil@xs4all.nl>
The default_mode_mask global is replaced by a list of tuner structs. The
tuner driver now walks that list to see which radio and/or tv tuner
devices are registered to a given i2c adapter.
The default_mode_mask global had to go since this is no longer supported
with the new bus-based I2C API.
Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
Diffstat (limited to 'linux/drivers/media/video/tuner-core.c')
-rw-r--r-- | linux/drivers/media/video/tuner-core.c | 65 |
1 files changed, 54 insertions, 11 deletions
diff --git a/linux/drivers/media/video/tuner-core.c b/linux/drivers/media/video/tuner-core.c index 1285c44ab..f7c657964 100644 --- a/linux/drivers/media/video/tuner-core.c +++ b/linux/drivers/media/video/tuner-core.c @@ -619,8 +619,38 @@ static void tuner_status(struct dvb_frontend *fe) /* ---------------------------------------------------------------------- */ -/* static vars: used only in tuner_attach and tuner_probe */ -static unsigned default_mode_mask; +LIST_HEAD(tuner_list); + +/* Search for existing radio and/or TV tuners on the given I2C adapter. + Note that when this function is called from tuner_attach you can be + certain no other devices will be added/deleted at the same time, I2C + core protects against that. */ +static void tuner_lookup(struct i2c_adapter *adap, + struct tuner **radio, struct tuner **tv) +{ + struct tuner *pos; + + *radio = NULL; + *tv = NULL; + + list_for_each_entry(pos, &tuner_list, list) { + int mode_mask; + + if (pos->i2c->adapter != adap || + pos->i2c->driver->id != I2C_DRIVERID_TUNER) + continue; + + mode_mask = pos->mode_mask & ~T_STANDBY; + if (*radio == NULL && mode_mask == T_RADIO) + *radio = pos; + /* Note: currently TDA9887 is the only demod-only + device. If other devices appear then we need to + make this test more general. */ + else if (*tv == NULL && pos->type != TUNER_TDA9887 && + (pos->mode_mask & (T_ANALOG_TV | T_DIGITAL_TV))) + *tv = pos; + } +} /* During client attach, set_type is called by adapter's attach_inform callback. set_type must then be completed by tuner_attach. @@ -634,6 +664,8 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, { struct i2c_client *client; struct tuner *t; + struct tuner *radio; + struct tuner *tv; client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL); if (NULL == client) @@ -677,7 +709,9 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, t->mode_mask = T_RADIO; t->mode = T_STANDBY; t->radio_freq = 87.5 * 16000; /* Sets freq to FM range */ - default_mode_mask &= ~T_RADIO; + tuner_lookup(t->i2c->adapter, &radio, &tv); + if (tv) + tv->mode_mask &= ~T_RADIO; goto register_client; } @@ -704,7 +738,9 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, t->mode_mask = T_RADIO; t->mode = T_STANDBY; t->radio_freq = 87.5 * 16000; /* Sets freq to FM range */ - default_mode_mask &= ~T_RADIO; + tuner_lookup(t->i2c->adapter, &radio, &tv); + if (tv) + tv->mode_mask &= ~T_RADIO; goto register_client; } @@ -712,13 +748,21 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, } } - /* Initializes only the first adapter found */ - if (default_mode_mask != T_UNINITIALIZED) { - tuner_dbg ("Setting mode_mask to 0x%02x\n", default_mode_mask); - t->mode_mask = default_mode_mask; + /* Initializes only the first TV tuner on this adapter. Why only the + first? Because there are some devices (notably the ones with TI + tuners) that have more than one i2c address for the *same* device. + Experience shows that, except for just one case, the first + address is the right one. The exception is a Russian tuner + (ACORP_Y878F). So, the desired behavior is just to enable the + first found TV tuner. */ + tuner_lookup(t->i2c->adapter, &radio, &tv); + if (tv == NULL) { + t->mode_mask = T_ANALOG_TV | T_DIGITAL_TV; + if (radio == NULL) + t->mode_mask |= T_RADIO; + tuner_dbg("Setting mode_mask to 0x%02x\n", t->mode_mask); t->tv_freq = 400 * 16; /* Sets freq to VHF High */ t->radio_freq = 87.5 * 16000; /* Sets freq to FM range */ - default_mode_mask = T_UNINITIALIZED; } /* Should be just before return */ @@ -771,8 +815,6 @@ static int tuner_probe(struct i2c_adapter *adap) "in i2c probe ignore list!\n"); } - default_mode_mask = T_RADIO | T_ANALOG_TV | T_DIGITAL_TV; - #ifdef I2C_CLASS_TV_ANALOG if (adap->class & I2C_CLASS_TV_ANALOG) return i2c_probe(adap, &addr_data, tuner_attach); @@ -802,6 +844,7 @@ MOD_DEC_USE_COUNT; if (ops && ops->release) ops->release(&t->fe); + list_del(&t->list); kfree(t); kfree(client); return 0; |