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

Commit 4e1a04d9 authored by Hans Verkuil's avatar Hans Verkuil Committed by Mauro Carvalho Chehab
Browse files

V4L/DVB (9205): saa7111: convert i2c driver for new i2c API



- Convert to use v4l2-i2c-drv-legacy.h to be able to handle the new i2c API
- Cleanups
- Use v4l_dbg/v4l_info to have uniform kernel messages

Signed-off-by: default avatarHans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 85ede69f
Loading
Loading
Loading
Loading
+58 −166
Original line number Diff line number Diff line
@@ -28,43 +28,24 @@
 */

#include <linux/module.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/slab.h>
#include <linux/mm.h>
#include <linux/signal.h>
#include <linux/types.h>
#include <linux/i2c.h>
#include <asm/io.h>
#include <asm/pgtable.h>
#include <asm/page.h>
#include <linux/ioctl.h>
#include <asm/uaccess.h>

#include <linux/i2c.h>
#include <linux/i2c-id.h>
#include <linux/videodev.h>
#include <linux/video_decoder.h>
#include <media/v4l2-common.h>
#include <media/v4l2-i2c-drv-legacy.h>

MODULE_DESCRIPTION("Philips SAA7111 video decoder driver");
MODULE_AUTHOR("Dave Perks");
MODULE_LICENSE("GPL");


#define I2C_NAME(s) (s)->name


static int debug;
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "Debug level (0-1)");

#define dprintk(num, format, args...) \
	do { \
		if (debug >= num) \
			printk(format, ##args); \
	} while (0)

/* ----------------------------------------------------------------------- */

#define SAA7111_NR_REG		0x18
@@ -77,14 +58,9 @@ struct saa7111 {
	int enable;
};

#define   I2C_SAA7111        0x48

/* ----------------------------------------------------------------------- */

static inline int
saa7111_write (struct i2c_client *client,
	       u8                 reg,
	       u8                 value)
static inline int saa7111_write(struct i2c_client *client, u8 reg, u8 value)
{
	struct saa7111 *decoder = i2c_get_clientdata(client);

@@ -92,8 +68,7 @@ saa7111_write (struct i2c_client *client,
	return i2c_smbus_write_byte_data(client, reg, value);
}

static inline void
saa7111_write_if_changed(struct i2c_client *client, u8 reg, u8 value)
static inline void saa7111_write_if_changed(struct i2c_client *client, u8 reg, u8 value)
{
	struct saa7111 *decoder = i2c_get_clientdata(client);

@@ -103,10 +78,7 @@ saa7111_write_if_changed(struct i2c_client *client, u8 reg, u8 value)
	}
}

static int
saa7111_write_block (struct i2c_client *client,
		     const u8          *data,
		     unsigned int       len)
static int saa7111_write_block(struct i2c_client *client, const u8 *data, unsigned int len)
{
	int ret = -1;
	u8 reg;
@@ -127,18 +99,17 @@ saa7111_write_block (struct i2c_client *client,
				    decoder->reg[reg++] = data[1];
				len -= 2;
				data += 2;
			} while (len >= 2 && data[0] == reg &&
				 block_len < 32);
			if ((ret = i2c_master_send(client, block_data,
						   block_len)) < 0)
			} while (len >= 2 && data[0] == reg && block_len < 32);
			ret = i2c_master_send(client, block_data, block_len);
			if (ret < 0)
				break;
		}
	} else {
		/* do some slow I2C emulation kind of thing */
		while (len >= 2) {
			reg = *data++;
			if ((ret = saa7111_write(client, reg,
						 *data++)) < 0)
			ret = saa7111_write(client, reg, *data++);
			if (ret < 0)
				break;
			len -= 2;
		}
@@ -147,16 +118,13 @@ saa7111_write_block (struct i2c_client *client,
	return ret;
}

static int
saa7111_init_decoder (struct i2c_client *client,
static int saa7111_init_decoder(struct i2c_client *client,
		struct video_decoder_init *init)
{
	return saa7111_write_block(client, init->data, init->len);
}

static inline int
saa7111_read (struct i2c_client *client,
	      u8                 reg)
static inline int saa7111_read(struct i2c_client *client, u8 reg)
{
	return i2c_smbus_read_byte_data(client, reg);
}
@@ -203,29 +171,24 @@ static const unsigned char saa7111_i2c_init[] = {
	0x17, 0x00,		/* 17 - VBI */
};

static int
saa7111_command (struct i2c_client *client,
		 unsigned int       cmd,
		 void              *arg)
static int saa7111_command(struct i2c_client *client, unsigned cmd, void *arg)
{
	struct saa7111 *decoder = i2c_get_clientdata(client);

	switch (cmd) {

	case 0:
		break;
	case DECODER_INIT:
	{
		struct video_decoder_init *init = arg;
		struct video_decoder_init vdi;

		if (NULL != init)
			return saa7111_init_decoder(client, init);
		else {
			struct video_decoder_init vdi;
		vdi.data = saa7111_i2c_init;
		vdi.len = sizeof(saa7111_i2c_init);
		return saa7111_init_decoder(client, &vdi);
	}
	}

	case DECODER_DUMP:
	{
@@ -234,15 +197,15 @@ saa7111_command (struct i2c_client *client,
		for (i = 0; i < SAA7111_NR_REG; i += 16) {
			int j;

			printk(KERN_DEBUG "%s: %03x", I2C_NAME(client), i);
			v4l_info(client, "%03x", i);
			for (j = 0; j < 16 && i + j < SAA7111_NR_REG; ++j) {
				printk(" %02x",
				printk(KERN_CONT " %02x",
				       saa7111_read(client, i + j));
			}
			printk("\n");
		}
			printk(KERN_CONT "\n");
		}
		break;
	}

	case DECODER_GET_CAPABILITIES:
	{
@@ -255,8 +218,8 @@ saa7111_command (struct i2c_client *client,
			     VIDEO_DECODER_CCIR;
		cap->inputs = 8;
		cap->outputs = 1;
	}
		break;
	}

	case DECODER_GET_STATUS:
	{
@@ -265,8 +228,7 @@ saa7111_command (struct i2c_client *client,
		int res;

		status = saa7111_read(client, 0x1f);
		dprintk(1, KERN_DEBUG "%s status: 0x%02x\n", I2C_NAME(client),
			status);
		v4l_dbg(1, debug, client, "status: 0x%02x\n", status);
		res = 0;
		if ((status & (1 << 6)) == 0) {
			res |= DECODER_STATUS_GOOD;
@@ -294,8 +256,8 @@ saa7111_command (struct i2c_client *client,
			res |= DECODER_STATUS_COLOR;
		}
		*iarg = res;
	}
		break;
	}

	case DECODER_SET_GPIO:
	{
@@ -362,8 +324,8 @@ saa7111_command (struct i2c_client *client,

		}
		decoder->norm = *iarg;
	}
		break;
	}

	case DECODER_SET_INPUT:
	{
@@ -387,8 +349,8 @@ saa7111_command (struct i2c_client *client,
							     3) ? 0x80 :
							    0));
		}
	}
		break;
	}

	case DECODER_SET_OUTPUT:
	{
@@ -398,8 +360,8 @@ saa7111_command (struct i2c_client *client,
		if (*iarg != 0) {
			return -EINVAL;
		}
	}
		break;
	}

	case DECODER_ENABLE_OUTPUT:
	{
@@ -439,8 +401,8 @@ saa7111_command (struct i2c_client *client,
					      (decoder->reg[0x11] & 0xf3));
			}
		}
	}
		break;
	}

	case DECODER_SET_PICTURE:
	{
@@ -454,8 +416,8 @@ saa7111_command (struct i2c_client *client,
		saa7111_write(client, 0x0c, pic->colour >> 9);
		/* We want -128 to 127 we get 0-65535 */
		saa7111_write(client, 0x0d, (pic->hue - 32768) >> 8);
	}
		break;
	}

	default:
		return -EINVAL;
@@ -466,48 +428,23 @@ saa7111_command (struct i2c_client *client,

/* ----------------------------------------------------------------------- */

/*
 * Generic i2c probe
 * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
 */
static unsigned short normal_i2c[] = { I2C_SAA7111 >> 1, I2C_CLIENT_END };
static unsigned short normal_i2c[] = { 0x48 >> 1, I2C_CLIENT_END };

static unsigned short ignore = I2C_CLIENT_END;
I2C_CLIENT_INSMOD;

static struct i2c_client_address_data addr_data = {
	.normal_i2c		= normal_i2c,
	.probe			= &ignore,
	.ignore			= &ignore,
};

static struct i2c_driver i2c_driver_saa7111;

static int
saa7111_detect_client (struct i2c_adapter *adapter,
		       int                 address,
		       int                 kind)
static int saa7111_probe(struct i2c_client *client,
			const struct i2c_device_id *id)
{
	int i;
	struct i2c_client *client;
	struct saa7111 *decoder;
	struct video_decoder_init vdi;

	dprintk(1,
		KERN_INFO
		"saa7111.c: detecting saa7111 client on address 0x%x\n",
		address << 1);

	/* Check if the adapter supports the needed features */
	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
		return 0;
	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
		return -ENODEV;

	client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
	if (!client)
		return -ENOMEM;
	client->addr = address;
	client->adapter = adapter;
	client->driver = &i2c_driver_saa7111;
	strlcpy(I2C_NAME(client), "saa7111", sizeof(I2C_NAME(client)));
	v4l_info(client, "chip found @ 0x%x (%s)\n",
			client->addr << 1, client->adapter->name);

	decoder = kzalloc(sizeof(struct saa7111), GFP_KERNEL);
	if (decoder == NULL) {
@@ -519,82 +456,37 @@ saa7111_detect_client (struct i2c_adapter *adapter,
	decoder->enable = 1;
	i2c_set_clientdata(client, decoder);

	i = i2c_attach_client(client);
	if (i) {
		kfree(client);
		kfree(decoder);
		return i;
	}

	vdi.data = saa7111_i2c_init;
	vdi.len = sizeof(saa7111_i2c_init);
	i = saa7111_init_decoder(client, &vdi);
	if (i < 0) {
		dprintk(1, KERN_ERR "%s_attach error: init status %d\n",
			I2C_NAME(client), i);
		v4l_dbg(1, debug, client, "init status %d\n", i);
	} else {
		dprintk(1,
			KERN_INFO
			"%s_attach: chip version %x at address 0x%x\n",
			I2C_NAME(client), saa7111_read(client, 0x00) >> 4,
			client->addr << 1);
		v4l_dbg(1, debug, client, "revision %x\n",
			saa7111_read(client, 0x00) >> 4);
	}

	return 0;
}

static int
saa7111_attach_adapter (struct i2c_adapter *adapter)
static int saa7111_remove(struct i2c_client *client)
{
	dprintk(1,
		KERN_INFO
		"saa7111.c: starting probe for adapter %s (0x%x)\n",
		I2C_NAME(adapter), adapter->id);
	return i2c_probe(adapter, &addr_data, &saa7111_detect_client);
}

static int
saa7111_detach_client (struct i2c_client *client)
{
	struct saa7111 *decoder = i2c_get_clientdata(client);
	int err;

	err = i2c_detach_client(client);
	if (err) {
		return err;
	}

	kfree(decoder);
	kfree(client);

	kfree(i2c_get_clientdata(client));
	return 0;
}

/* ----------------------------------------------------------------------- */

static struct i2c_driver i2c_driver_saa7111 = {
	.driver = {
		.name = "saa7111",
	},

	.id = I2C_DRIVERID_SAA7111A,
static const struct i2c_device_id saa7111_id[] = {
	{ "saa7111_old", 0 },	/* "saa7111" maps to the saa7115 driver */
	{ }
};
MODULE_DEVICE_TABLE(i2c, saa7111_id);

	.attach_adapter = saa7111_attach_adapter,
	.detach_client = saa7111_detach_client,
static struct v4l2_i2c_driver_data v4l2_i2c_data = {
	.name = "saa7111",
	.driverid = I2C_DRIVERID_SAA7111A,
	.command = saa7111_command,
	.probe = saa7111_probe,
	.remove = saa7111_remove,
	.id_table = saa7111_id,
};

static int __init
saa7111_init (void)
{
	return i2c_add_driver(&i2c_driver_saa7111);
}

static void __exit
saa7111_exit (void)
{
	i2c_del_driver(&i2c_driver_saa7111);
}

module_init(saa7111_init);
module_exit(saa7111_exit);