Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 159ffe77 authored by Hans Verkuil's avatar Hans Verkuil Committed by Mauro Carvalho Chehab
Browse files

V4L/DVB (6553): tuner: replace default_mode_mask



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: default avatarHans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@infradead.org>
parent a818e1c8
Loading
Loading
Loading
Loading
+54 −11
Original line number Diff line number Diff line
@@ -585,8 +585,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.
@@ -595,6 +625,8 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind)
{
	struct i2c_client *client;
	struct tuner *t;
	struct tuner *radio;
	struct tuner *tv;

	client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
	if (NULL == client)
@@ -638,7 +670,9 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind)
				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;
			}
@@ -665,7 +699,9 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind)
				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;
			}
@@ -673,13 +709,21 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind)
		}
	}

	/* 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 */
@@ -729,8 +773,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;

	if (adap->class & I2C_CLASS_TV_ANALOG)
		return i2c_probe(adap, &addr_data, tuner_attach);
	return 0;
@@ -752,6 +794,7 @@ static int tuner_detach(struct i2c_client *client)
	if (ops && ops->release)
		ops->release(&t->fe);

	list_del(&t->list);
	kfree(t);
	kfree(client);
	return 0;
+1 −0
Original line number Diff line number Diff line
@@ -46,6 +46,7 @@ struct analog_tuner_ops {
struct tuner {
	/* device */
	struct i2c_client *i2c;
	struct list_head list;  /* list of tuners */

	unsigned int type;	/* chip type */