Mailing List archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[linux-dvb] [patch] kernel i2c - at76c651



Hi,

seeing how easy it was to convert the frontends to kernel i2c layer, I did 
another one this morning. I belive it should work ok, but I have no way of 
testing. Please, can someone with this frontend test this patch.

Kenneth
Index: linux/drivers/media/dvb/frontends/at76c651.c
===================================================================
RCS file: /cvs/linuxtv/dvb-kernel/linux/drivers/media/dvb/frontends/at76c651.c,v
retrieving revision 1.15
diff -u -r1.15 at76c651.c
--- linux/drivers/media/dvb/frontends/at76c651.c	11 Mar 2004 18:40:44 -0000	1.15
+++ linux/drivers/media/dvb/frontends/at76c651.c	22 Jun 2004 09:36:12 -0000
@@ -38,11 +38,12 @@
 #include "dvb_functions.h"
 
 static int debug = 0;
-static u8 at76c651_qam;
-static u8 at76c651_revision;
 
 #define dprintk	if (debug) printk
 
+//FIXME: Move to i2c-id.h
+#define I2C_DRIVERID_DVBFE_AT76C651 I2C_DRIVERID_EXP0
+
 /*
  * DAT7021
  * -------
@@ -74,6 +75,13 @@
 	    FE_CAN_MUTE_TS | FE_CAN_QAM_256 | FE_CAN_RECOVER
 };
 
+struct at76c651_state {
+	u8 revision;
+	u8 qam;
+	struct i2c_adapter *i2c;
+	struct dvb_adapter *dvb;
+};
+
 #if ! defined(__powerpc__)
 static __inline__ int __ilog2(unsigned long x)
 {
@@ -89,14 +97,13 @@
 }
 #endif
 
-static int at76c651_writereg(struct dvb_i2c_bus *i2c, u8 reg, u8 data)
+static int at76c651_writereg(struct i2c_adapter *i2c, u8 reg, u8 data)
 {
-
 	int ret;
 	u8 buf[] = { reg, data };
 	struct i2c_msg msg = { .addr = 0x1a >> 1, .flags = 0, .buf = buf, .len = 2 };
 
-	ret = i2c->xfer(i2c, &msg, 1);
+	ret = i2c_transfer(i2c, &msg, 1);
 
 	if (ret != 1)
 		dprintk("%s: writereg error "
@@ -106,43 +113,37 @@
 	dvb_delay(10);
 
 	return (ret != 1) ? -EREMOTEIO : 0;
-
 }
 
-static u8 at76c651_readreg(struct dvb_i2c_bus *i2c, u8 reg)
+static u8 at76c651_readreg(struct i2c_adapter *i2c, u8 reg)
 {
-
 	int ret;
 	u8 b0[] = { reg };
 	u8 b1[] = { 0 };
 	struct i2c_msg msg[] = { {.addr =  0x1a >> 1, .flags =  0, .buf =  b0, .len = 1},
 			  {.addr =  0x1a >> 1, .flags =  I2C_M_RD, .buf =  b1, .len = 1} };
 
-	ret = i2c->xfer(i2c, msg, 2);
+	ret = i2c_transfer(i2c, msg, 2);
 
 	if (ret != 2)
 		dprintk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret);
 
 	return b1[0];
-
 }
 
-static int at76c651_reset(struct dvb_i2c_bus *i2c)
+static int at76c651_reset(struct i2c_adapter *i2c)
 {
-
 	return at76c651_writereg(i2c, 0x07, 0x01);
-
 }
 
-static int at76c651_disable_interrupts(struct dvb_i2c_bus *i2c)
+static int at76c651_disable_interrupts(struct i2c_adapter *i2c)
 {
-
 	return at76c651_writereg(i2c, 0x0b, 0x00);
-
 }
 
-static int at76c651_set_auto_config(struct dvb_i2c_bus *i2c)
+static int at76c651_set_auto_config(struct at76c651_state *state)
 {
+	struct i2c_adapter *i2c = state->i2c;
 
 	/*
 	 * Autoconfig
@@ -155,19 +156,19 @@
 	 */
 
 	at76c651_writereg(i2c, 0x10, 0x06);
-	at76c651_writereg(i2c, 0x11, ((at76c651_qam == 5) || (at76c651_qam == 7)) ? 0x12 : 0x10);
+	at76c651_writereg(i2c, 0x11, ((state->qam == 5) || (state->qam == 7)) ? 0x12 : 0x10);
 	at76c651_writereg(i2c, 0x15, 0x28);
 	at76c651_writereg(i2c, 0x20, 0x09);
-	at76c651_writereg(i2c, 0x24, ((at76c651_qam == 5) || (at76c651_qam == 7)) ? 0xC0 : 0x90);
+	at76c651_writereg(i2c, 0x24, ((state->qam == 5) || (state->qam == 7)) ? 0xC0 : 0x90);
 	at76c651_writereg(i2c, 0x30, 0x90);
-	if (at76c651_qam == 5)
+	if (state->qam == 5)
 		at76c651_writereg(i2c, 0x35, 0x2A);
 
 	/*
 	 * Initialize A/D-converter
 	 */
 
-	if (at76c651_revision == 0x11) {
+	if (state->revision == 0x11) {
 		at76c651_writereg(i2c, 0x2E, 0x38);
 		at76c651_writereg(i2c, 0x2F, 0x13);
 	}
@@ -181,32 +182,25 @@
 	at76c651_reset(i2c);
 
 	return 0;
-
 }
 
-static int at76c651_set_bbfreq(struct dvb_i2c_bus *i2c)
+static int at76c651_set_bbfreq(struct i2c_adapter *i2c)
 {
-
 	at76c651_writereg(i2c, 0x04, 0x3f);
 	at76c651_writereg(i2c, 0x05, 0xee);
-
 	return 0;
-
 }
 
-static int at76c651_switch_tuner_i2c(struct dvb_i2c_bus *i2c, u8 enable)
+static int at76c651_switch_tuner_i2c(struct i2c_adapter *i2c, u8 enable)
 {
-
 	if (enable)
 		return at76c651_writereg(i2c, 0x0c, 0xc2 | 0x01);
 	else
 		return at76c651_writereg(i2c, 0x0c, 0xc2);
-
 }
 
-static int dat7021_write(struct dvb_i2c_bus *i2c, u32 tw)
+static int dat7021_write(struct i2c_adapter *i2c, u32 tw)
 {
-
 	int ret;
 	struct i2c_msg msg =
 	    { .addr = 0xc2 >> 1, .flags = 0, .buf = (u8 *) & tw, .len = sizeof (tw) };
@@ -217,7 +211,7 @@
 
 	at76c651_switch_tuner_i2c(i2c, 1);
 
-	ret = i2c->xfer(i2c, &msg, 1);
+	ret = i2c_transfer(i2c, &msg, 1);
 
 	at76c651_switch_tuner_i2c(i2c, 0);
 
@@ -227,12 +221,10 @@
 	at76c651_reset(i2c);
 
 	return 0;
-
 }
 
-static int dat7021_set_tv_freq(struct dvb_i2c_bus *i2c, u32 freq)
+static int dat7021_set_tv_freq(struct i2c_adapter *i2c, u32 freq)
 {
-
 	u32 dw;
 
 	freq /= 1000;
@@ -255,12 +247,10 @@
 		dw += 0x4E28E06;
 
 	return dat7021_write(i2c, dw);
-
 }
 
-static int at76c651_set_symbolrate(struct dvb_i2c_bus *i2c, u32 symbolrate)
+static int at76c651_set_symbolrate(struct i2c_adapter *i2c, u32 symbolrate)
 {
-
 	u8 exponent;
 	u32 mantissa;
 
@@ -281,37 +271,35 @@
 	at76c651_writereg(i2c, 0x02, (mantissa << 3) | exponent);
 
 	return 0;
-
 }
 
-static int at76c651_set_qam(struct dvb_i2c_bus *i2c, fe_modulation_t qam)
+static int at76c651_set_qam(struct at76c651_state *state, fe_modulation_t qam)
 {
-
 	switch (qam) {
 	case QPSK:
-		at76c651_qam = 0x02;
+		state->qam = 0x02;
 		break;
 	case QAM_16:
-		at76c651_qam = 0x04;
+		state->qam = 0x04;
 		break;
 	case QAM_32:
-		at76c651_qam = 0x05;
+		state->qam = 0x05;
 		break;
 	case QAM_64:
-		at76c651_qam = 0x06;
+		state->qam = 0x06;
 		break;
 	case QAM_128:
-		at76c651_qam = 0x07;
+		state->qam = 0x07;
 		break;
 	case QAM_256:
-		at76c651_qam = 0x08;
+		state->qam = 0x08;
 		break;
 #if 0
 	case QAM_512:
-		at76c651_qam = 0x09;
+		state->qam = 0x09;
 		break;
 	case QAM_1024:
-		at76c651_qam = 0x0A;
+		state->qam = 0x0A;
 		break;
 #endif
 	default:
@@ -319,14 +307,12 @@
 
 	}
 
-	return at76c651_writereg(i2c, 0x03, at76c651_qam);
-
+	return at76c651_writereg(state->i2c, 0x03, state->qam);
 }
 
-static int at76c651_set_inversion(struct dvb_i2c_bus *i2c,
-		       fe_spectral_inversion_t inversion)
+static int at76c651_set_inversion(struct i2c_adapter *i2c,
+				  fe_spectral_inversion_t inversion)
 {
-
 	u8 feciqinv = at76c651_readreg(i2c, 0x60);
 
 	switch (inversion) {
@@ -348,36 +334,38 @@
 	}
 
 	return at76c651_writereg(i2c, 0x60, feciqinv);
-
 }
 
-static int at76c651_set_parameters(struct dvb_i2c_bus *i2c,
-			struct dvb_frontend_parameters *p)
+static int at76c651_set_parameters(struct at76c651_state *state,
+				   struct dvb_frontend_parameters *p)
 {
+	struct i2c_adapter *i2c = state->i2c;
+
 	dat7021_set_tv_freq(i2c, p->frequency);
 	at76c651_set_symbolrate(i2c, p->u.qam.symbol_rate);
 	at76c651_set_inversion(i2c, p->inversion);
-	at76c651_set_auto_config(i2c);
+	at76c651_set_auto_config(state);
         at76c651_reset(i2c);
     
 	return 0;
-
 }
 
-static int at76c651_set_defaults(struct dvb_i2c_bus *i2c)
+static int at76c651_set_defaults(struct at76c651_state *state)
 {
+	struct i2c_adapter *i2c = state->i2c;
 
 	at76c651_set_symbolrate(i2c, 6900000);
-	at76c651_set_qam(i2c, QAM_64);
+	at76c651_set_qam(state, QAM_64);
 	at76c651_set_bbfreq(i2c);
-	at76c651_set_auto_config(i2c);
+	at76c651_set_auto_config(state);
 
 	return 0;
-
 }
 
 static int at76c651_ioctl(struct dvb_frontend *fe, unsigned int cmd, void *arg)
 {
+	struct at76c651_state *state = fe->data;
+	struct i2c_adapter *i2c = state->i2c;
 
 	switch (cmd) {
 	case FE_GET_INFO:
@@ -393,7 +381,7 @@
 			/*
 			 * Bits: FEC, CAR, EQU, TIM, AGC2, AGC1, ADC, PLL (PLL=0) 
 			 */
-			sync = at76c651_readreg(fe->i2c, 0x80);
+			sync = at76c651_readreg(i2c, 0x80);
 
 			*status = 0;
 
@@ -420,9 +408,9 @@
 		{
 			u32 *ber = (u32 *) arg;
 
-			*ber = (at76c651_readreg(fe->i2c, 0x81) & 0x0F) << 16;
-			*ber |= at76c651_readreg(fe->i2c, 0x82) << 8;
-			*ber |= at76c651_readreg(fe->i2c, 0x83);
+			*ber = (at76c651_readreg(i2c, 0x81) & 0x0F) << 16;
+			*ber |= at76c651_readreg(i2c, 0x82) << 8;
+			*ber |= at76c651_readreg(i2c, 0x83);
 			*ber *= 10;
 
 			break;
@@ -430,7 +418,7 @@
 
 	case FE_READ_SIGNAL_STRENGTH:
 		{
-			u8 gain = ~at76c651_readreg(fe->i2c, 0x91);
+			u8 gain = ~at76c651_readreg(i2c, 0x91);
 
 			*(u16 *) arg = (gain << 8) | gain;
 			break;
@@ -439,16 +427,16 @@
 	case FE_READ_SNR:
 		*(u16 *) arg =
 		    0xFFFF -
-		    ((at76c651_readreg(fe->i2c, 0x8F) << 8) |
-		     at76c651_readreg(fe->i2c, 0x90));
+		    ((at76c651_readreg(i2c, 0x8F) << 8) |
+		     at76c651_readreg(i2c, 0x90));
 		break;
 
 	case FE_READ_UNCORRECTED_BLOCKS:
-		*(u32 *) arg = at76c651_readreg(fe->i2c, 0x82);
+		*(u32 *) arg = at76c651_readreg(i2c, 0x82);
 		break;
 
 	case FE_SET_FRONTEND:
-		return at76c651_set_parameters(fe->i2c, arg);
+		return at76c651_set_parameters(state, arg);
 
 	case FE_GET_FRONTEND:
 		break;
@@ -457,11 +445,13 @@
 		break;
 
 	case FE_INIT:
-		return at76c651_set_defaults(fe->i2c);
+		return at76c651_set_defaults(state);
 
 	case FE_GET_TUNE_SETTINGS:
 	{
-	        struct dvb_frontend_tune_settings* fesettings = (struct dvb_frontend_tune_settings*) arg;
+	        struct dvb_frontend_tune_settings* fesettings =
+			(struct dvb_frontend_tune_settings*) arg;
+
 	        fesettings->min_delay_ms = 50;
 	        fesettings->step_size = 0;
 	        fesettings->max_drift = 0;
@@ -473,55 +463,126 @@
 	}
 
 	return 0;
-
 }
 
-static int at76c651_attach(struct dvb_i2c_bus *i2c, void **data)
+static struct i2c_client client_template;
+
+static int attach_adapter(struct i2c_adapter *adapter)
 {
-	if ( (at76c651_readreg(i2c, 0x0E) != 0x65) ||
-	     ( ( (at76c651_revision = at76c651_readreg(i2c, 0x0F)) & 0xFE) != 0x10) )
-	{
+	struct at76c651_state *state;
+	struct i2c_client *client;
+	int ret;
+
+	if (NULL == (state = kmalloc(sizeof(struct at76c651_state), GFP_KERNEL)))
+		return -ENOMEM;
+
+	state->i2c = adapter;
+	state->revision = at76c651_readreg(adapter, 0x0F) & 0xFE;
+
+	if (state->revision == 0x10) {
+		dprintk("AT76C651A found\n");
+		strcpy(at76c651_info.name, "Atmel AT76C651A with DAT7021");
+	} else {
+		dprintk("AT76C651B found\n");
+		strcpy(at76c651_info.name, "Atmel AT76C651B with DAT7021");
+	}
+
+	if (at76c651_readreg(adapter, 0x0E) != 0x65 ||
+	    state->revision != 0x10) {
 		dprintk("no AT76C651(B) found\n");
+		kfree(state);
 		return -ENODEV;
 	}
 
-	if (at76c651_revision == 0x10)
-	{
-		dprintk("AT76C651A found\n");
-		strcpy(at76c651_info.name,"Atmel AT76C651A with DAT7021");
+	if (NULL == (client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL))) {
+		kfree(state);
+		return -ENOMEM;
 	}
-	else
-	{
-		strcpy(at76c651_info.name,"Atmel AT76C651B with DAT7021");
-		dprintk("AT76C651B found\n");
+
+	memcpy(client, &client_template, sizeof(struct i2c_client));
+	client->adapter = adapter;
+	client->addr = 0x1a >> 1;
+	i2c_set_clientdata(client, state);
+
+	ret = i2c_attach_client(client);
+	if (ret) {
+		kfree(state);
+		kfree(client);
+		return ret;
 	}
 
-	at76c651_set_defaults(i2c);
+	BUG_ON(!state->dvb);
 
-	return dvb_register_frontend(at76c651_ioctl, i2c, NULL, &at76c651_info);
+	ret = dvb_register_frontend_new(at76c651_ioctl, state->dvb, state, &at76c651_info);
+	if (ret) {
+		i2c_detach_client(client);
+		kfree(client);
+		kfree(state);
+		return ret;
+	}
 
+	return 0;
 }
 
-static void at76c651_detach(struct dvb_i2c_bus *i2c, void *data)
+static int detach_client(struct i2c_client *client)
 {
+	struct at76c651_state *state = (struct at76c651_state*)i2c_get_clientdata(client);
 
-	dvb_unregister_frontend(at76c651_ioctl, i2c);
+	dprintk ("%s\n", __FUNCTION__);
 
+	dvb_unregister_frontend_new(at76c651_ioctl, state->dvb);
+	i2c_detach_client(client);
+	BUG_ON(state->dvb);
+	kfree(client);
+	kfree(state);
+	return 0;
 }
 
-static int __init at76c651_init(void)
+static int command (struct i2c_client *client, unsigned int cmd, void *arg)
 {
+	struct at76c651_state *state = (struct at76c651_state*)i2c_get_clientdata(client);
 
-	return dvb_register_i2c_device(THIS_MODULE, at76c651_attach,
-				       at76c651_detach);
+	dprintk ("%s\n", __FUNCTION__);
 
+	switch (cmd) {
+	case FE_REGISTER:
+		state->dvb = (struct dvb_adapter*)arg;
+		break;
+	case FE_UNREGISTER:
+		state->dvb = NULL;
+		break;
+	default:
+		return -EOPNOTSUPP;
+	}
+	return 0;
 }
 
-static void __exit at76c651_exit(void)
-{
 
-	dvb_unregister_i2c_device(at76c651_attach);
+static struct i2c_driver driver = {
+	.owner		= THIS_MODULE,
+	.name		= "dvb_at76c651",
+	.id		= I2C_DRIVERID_DVBFE_AT76C651,
+	.flags		= I2C_DF_NOTIFY,
+	.attach_adapter	= attach_adapter,
+	.detach_client	= detach_client,
+	.command	= command,
+};
 
+static struct i2c_client client_template = {
+	I2C_DEVNAME("dvb_at76c651"),
+	.flags		= I2C_CLIENT_ALLOW_USE,
+	.driver		= &driver,
+};
+
+static int __init at76c651_init(void)
+{
+	return i2c_add_driver(&driver);
+}
+
+static void __exit at76c651_exit(void)
+{
+	if (i2c_del_driver(&driver))
+		printk(KERN_ERR "at76c651: driver deregistration failed.\n");
 }
 
 module_init(at76c651_init);

Home | Main Index | Thread Index