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

Commit 7400516a authored by Jean Delvare's avatar Jean Delvare
Browse files

go7007: Convert to the new i2c device binding model



Move the go7007 driver away from the legacy i2c binding model, which
is going away really soon now.

The I2C addresses of the audio and video chips in s2250-board didn't
look quite right, apparently they were left-aligned values when Linux
wants right-aligned values, so I fixed them too.

Signed-off-by: default avatarJean Delvare <khali@linux-fr.org>
Cc: Greg Kroah-Hartman <gregkh@suse.de>
parent a939b96c
Loading
Loading
Loading
Loading
+9 −2
Original line number Diff line number Diff line
@@ -191,8 +191,10 @@ int go7007_reset_encoder(struct go7007 *go)
/*
 * Attempt to instantiate an I2C client by ID, probably loading a module.
 */
static int init_i2c_module(struct i2c_adapter *adapter, int id, int addr)
static int init_i2c_module(struct i2c_adapter *adapter, const char *type,
			   int id, int addr)
{
	struct i2c_board_info info;
	char *modname;

	switch (id) {
@@ -226,7 +228,11 @@ static int init_i2c_module(struct i2c_adapter *adapter, int id, int addr)
	}
	if (modname != NULL)
		request_module(modname);
	if (wis_i2c_probe_device(adapter, id, addr) == 1)

	memset(&info, 0, sizeof(struct i2c_board_info));
	info.addr = addr;
	strlcpy(info.type, type, I2C_NAME_SIZE);
	if (!i2c_new_device(adapter, &info))
		return 0;
	if (modname != NULL)
		printk(KERN_INFO
@@ -266,6 +272,7 @@ int go7007_register_encoder(struct go7007 *go)
	if (go->i2c_adapter_online) {
		for (i = 0; i < go->board_info->num_i2c_devs; ++i)
			init_i2c_module(&go->i2c_adapter,
					go->board_info->i2c_devs[i].type,
					go->board_info->i2c_devs[i].id,
					go->board_info->i2c_devs[i].addr);
		if (go->board_id == GO7007_BOARDID_ADLINK_MPG24)
+0 −83
Original line number Diff line number Diff line
@@ -31,87 +31,6 @@
#include "go7007-priv.h"
#include "wis-i2c.h"

/************** Registration interface for I2C client drivers **************/

/* Since there's no way to auto-probe the I2C devices connected to the I2C
 * bus on the go7007, we have this silly little registration system that
 * client drivers can use to register their I2C driver ID and their
 * detect_client function (the one that's normally passed to i2c_probe).
 *
 * When a new go7007 device is connected, we can look up in a board info
 * table by the USB or PCI vendor/product/revision ID to determine
 * which I2C client module to load.  The client driver module will register
 * itself here, and then we can call the registered detect_client function
 * to force-load a new client at the address listed in the board info table.
 *
 * Really the I2C subsystem should have a way to force-load I2C client
 * drivers when we have a priori knowledge of what's on the bus, especially
 * since the existing I2C auto-probe mechanism is so hokey, but we'll use
 * our own mechanism for the time being. */

struct wis_i2c_client_driver {
	unsigned int id;
	found_proc found_proc;
	struct list_head list;
};

static LIST_HEAD(i2c_client_drivers);
static DECLARE_MUTEX(i2c_client_driver_list_lock);

/* Client drivers register here by their I2C driver ID */
int wis_i2c_add_driver(unsigned int id, found_proc found_proc)
{
	struct wis_i2c_client_driver *driver;

	driver = kmalloc(sizeof(struct wis_i2c_client_driver), GFP_KERNEL);
	if (driver == NULL)
		return -ENOMEM;
	driver->id = id;
	driver->found_proc = found_proc;

	down(&i2c_client_driver_list_lock);
	list_add_tail(&driver->list, &i2c_client_drivers);
	up(&i2c_client_driver_list_lock);

	return 0;
}
EXPORT_SYMBOL(wis_i2c_add_driver);

void wis_i2c_del_driver(found_proc found_proc)
{
	struct wis_i2c_client_driver *driver, *next;

	down(&i2c_client_driver_list_lock);
	list_for_each_entry_safe(driver, next, &i2c_client_drivers, list)
		if (driver->found_proc == found_proc) {
			list_del(&driver->list);
			kfree(driver);
		}
	up(&i2c_client_driver_list_lock);
}
EXPORT_SYMBOL(wis_i2c_del_driver);

/* The main go7007 driver calls this to instantiate a client by driver
 * ID and bus address, which are both stored in the board info table */
int wis_i2c_probe_device(struct i2c_adapter *adapter,
				unsigned int id, int addr)
{
	struct wis_i2c_client_driver *driver;
	int found = 0;

	if (addr < 0 || addr > 0x7f)
		return -1;
	down(&i2c_client_driver_list_lock);
	list_for_each_entry(driver, &i2c_client_drivers, list)
		if (driver->id == id) {
			if (driver->found_proc(adapter, addr, 0) == 0)
				found = 1;
			break;
		}
	up(&i2c_client_driver_list_lock);
	return found;
}

/********************* Driver for on-board I2C adapter *********************/

/* #define GO7007_I2C_DEBUG */
@@ -287,9 +206,7 @@ static struct i2c_algorithm go7007_algo = {

static struct i2c_adapter go7007_adap_templ = {
	.owner			= THIS_MODULE,
	.class			= I2C_CLASS_TV_ANALOG,
	.name			= "WIS GO7007SB",
	.id			= I2C_ALGO_GO7007,
	.algo			= &go7007_algo,
};

+1 −0
Original line number Diff line number Diff line
@@ -87,6 +87,7 @@ struct go7007_board_info {
	int audio_main_div;
	int num_i2c_devs;
	struct {
		const char *type;
		int id;
		int addr;
	} i2c_devs[4];
+11 −3
Original line number Diff line number Diff line
@@ -91,6 +91,7 @@ static struct go7007_usb_board board_matrix_ii = {
		.num_i2c_devs	 = 1,
		.i2c_devs	 = {
			{
				.type	= "wis_saa7115",
				.id	= I2C_DRIVERID_WIS_SAA7115,
				.addr	= 0x20,
			},
@@ -127,6 +128,7 @@ static struct go7007_usb_board board_matrix_reload = {
		.num_i2c_devs	 = 1,
		.i2c_devs	 = {
			{
				.type	= "wis_saa7113",
				.id	= I2C_DRIVERID_WIS_SAA7113,
				.addr	= 0x25,
			},
@@ -164,6 +166,7 @@ static struct go7007_usb_board board_star_trek = {
		.num_i2c_devs	 = 1,
		.i2c_devs	 = {
			{
				.type	= "wis_saa7115",
				.id	= I2C_DRIVERID_WIS_SAA7115,
				.addr	= 0x20,
			},
@@ -209,14 +212,17 @@ static struct go7007_usb_board board_px_tv402u = {
		.num_i2c_devs	 = 3,
		.i2c_devs	 = {
			{
				.type	= "wis_saa7115",
				.id	= I2C_DRIVERID_WIS_SAA7115,
				.addr	= 0x20,
			},
			{
				.type	= "wis_uda1342",
				.id	= I2C_DRIVERID_WIS_UDA1342,
				.addr	= 0x1a,
			},
			{
				.type	= "wis_sony_tuner",
				.id	= I2C_DRIVERID_WIS_SONY_TUNER,
				.addr	= 0x60,
			},
@@ -264,6 +270,7 @@ static struct go7007_usb_board board_xmen = {
		.num_i2c_devs	  = 1,
		.i2c_devs	  = {
			{
				.type	= "wis_ov7640",
				.id	= I2C_DRIVERID_WIS_OV7640,
				.addr	= 0x21,
			},
@@ -296,6 +303,7 @@ static struct go7007_usb_board board_matrix_revolution = {
		.num_i2c_devs	 = 1,
		.i2c_devs	 = {
			{
				.type	= "wis_tw9903",
				.id	= I2C_DRIVERID_WIS_TW9903,
				.addr	= 0x44,
			},
@@ -385,6 +393,7 @@ static struct go7007_usb_board board_adlink_mpg24 = {
		.num_i2c_devs	 = 1,
		.i2c_devs	 = {
			{
				.type	= "wis_twTW2804",
				.id	= I2C_DRIVERID_WIS_TW2804,
				.addr	= 0x00, /* yes, really */
			},
@@ -415,8 +424,9 @@ static struct go7007_usb_board board_sensoray_2250 = {
		.num_i2c_devs	 = 1,
		.i2c_devs	 = {
			{
				.type	= "s2250_board",
				.id	= I2C_DRIVERID_S2250,
				.addr	= 0x34,
				.addr	= 0x43,
			},
		},
		.num_inputs	 = 2,
@@ -943,9 +953,7 @@ static struct i2c_algorithm go7007_usb_algo = {

static struct i2c_adapter go7007_usb_adap_templ = {
	.owner			= THIS_MODULE,
	.class			= I2C_CLASS_TV_ANALOG,
	.name			= "WIS GO7007SB EZ-USB",
	.id			= I2C_ALGO_GO7007_USB,
	.algo			= &go7007_usb_algo,
};

+30 −41
Original line number Diff line number Diff line
@@ -28,7 +28,6 @@ extern int s2250loader_init(void);
extern void s2250loader_cleanup(void);

#define TLV320_ADDRESS      0x34
#define S2250_VIDDEC        0x86
#define VPX322_ADDR_ANALOGCONTROL1	0x02
#define VPX322_ADDR_BRIGHTNESS0		0x0127
#define VPX322_ADDR_BRIGHTNESS1		0x0131
@@ -123,6 +122,7 @@ struct s2250 {
	int hue;
	int reg12b_val;
	int audio_input;
	struct i2c_client *audio;
};

/* from go7007-usb.c which is Copyright (C) 2005-2006 Micronas USA Inc.*/
@@ -452,16 +452,15 @@ static int s2250_command(struct i2c_client *client,
	{
		struct v4l2_audio *audio = arg;

		client->addr = TLV320_ADDRESS;
		switch (audio->index) {
		case 0:
			write_reg(client, 0x08, 0x02); /* Line In */
			write_reg(dec->audio, 0x08, 0x02); /* Line In */
			break;
		case 1:
			write_reg(client, 0x08, 0x04); /* Mic */
			write_reg(dec->audio, 0x08, 0x04); /* Mic */
			break;
		case 2:
			write_reg(client, 0x08, 0x05); /* Mic Boost */
			write_reg(dec->audio, 0x08, 0x05); /* Mic Boost */
			break;
		default:
			return -EINVAL;
@@ -477,31 +476,23 @@ static int s2250_command(struct i2c_client *client,
	return 0;
}

static struct i2c_driver s2250_driver;

static struct i2c_client s2250_client_templ = {
	.name		= "Sensoray 2250",
	.driver		= &s2250_driver,
};

static int s2250_detect(struct i2c_adapter *adapter, int addr, int kind)
static int s2250_probe(struct i2c_client *client,
		       const struct i2c_device_id *id)
{
	struct i2c_client *client;
	struct i2c_client *audio;
	struct i2c_adapter *adapter = client->adapter;
	struct s2250 *dec;
	u8 *data;
	struct go7007 *go = i2c_get_adapdata(adapter);
	struct go7007_usb *usb = go->hpi_context;

	client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
	if (client == NULL)
	audio = i2c_new_dummy(adapter, TLV320_ADDRESS >> 1);
	if (audio == NULL)
		return -ENOMEM;
	memcpy(client, &s2250_client_templ,
	       sizeof(s2250_client_templ));
	client->adapter = adapter;

	dec = kmalloc(sizeof(struct s2250), GFP_KERNEL);
	if (dec == NULL) {
		kfree(client);
		i2c_unregister_device(audio);
		return -ENOMEM;
	}

@@ -510,7 +501,7 @@ static int s2250_detect(struct i2c_adapter *adapter, int addr, int kind)
	dec->contrast = 50;
	dec->saturation = 50;
	dec->hue = 0;
	client->addr = TLV320_ADDRESS;
	dec->audio = audio;
	i2c_set_clientdata(client, dec);

	printk(KERN_DEBUG
@@ -518,28 +509,25 @@ static int s2250_detect(struct i2c_adapter *adapter, int addr, int kind)
	       adapter->name);

	/* initialize the audio */
	client->addr = TLV320_ADDRESS;
	if (write_regs(client, aud_regs) < 0) {
	if (write_regs(audio, aud_regs) < 0) {
		printk(KERN_ERR
		       "s2250: error initializing audio\n");
		kfree(client);
		i2c_unregister_device(audio);
		kfree(dec);
		return 0;
	}
	client->addr = S2250_VIDDEC;
	i2c_set_clientdata(client, dec);

	if (write_regs(client, vid_regs) < 0) {
		printk(KERN_ERR
		       "s2250: error initializing decoder\n");
		kfree(client);
		i2c_unregister_device(audio);
		kfree(dec);
		return 0;
	}
	if (write_regs_fp(client, vid_regs_fp) < 0) {
		printk(KERN_ERR
		       "s2250: error initializing decoder\n");
		kfree(client);
		i2c_unregister_device(audio);
		kfree(dec);
		return 0;
	}
@@ -575,32 +563,33 @@ static int s2250_detect(struct i2c_adapter *adapter, int addr, int kind)
		up(&usb->i2c_lock);
	}

	i2c_attach_client(client);
	printk("s2250: initialized successfully\n");
	return 0;
}

static int s2250_detach(struct i2c_client *client)
static int s2250_remove(struct i2c_client *client)
{
	struct s2250 *dec = i2c_get_clientdata(client);
	int r;

	r = i2c_detach_client(client);
	if (r < 0)
		return r;

	kfree(client);
	i2c_set_clientdata(client, NULL);
	i2c_unregister_device(dec->audio);
	kfree(dec);
	return 0;
}

static struct i2c_device_id s2250_id[] = {
	{ "s2250_board", 0 },
	{ }
};

static struct i2c_driver s2250_driver = {
	.driver = {
		.name	= "Sensoray 2250 board driver",
	},
	.id		= I2C_DRIVERID_S2250,
	.detach_client	= s2250_detach,
	.probe		= s2250_probe,
	.remove		= s2250_remove,
	.command	= s2250_command,
	.id_table	= s2250_id,
};

static int __init s2250_init(void)
@@ -613,13 +602,13 @@ static int __init s2250_init(void)

	r = i2c_add_driver(&s2250_driver);
	if (r < 0)
		s2250loader_cleanup();

	return r;
	return wis_i2c_add_driver(s2250_driver.id, s2250_detect);
}

static void __exit s2250_cleanup(void)
{
	wis_i2c_del_driver(s2250_detect);
	i2c_del_driver(&s2250_driver);

	s2250loader_cleanup();
Loading