rendered paste bodydiff -r 19981e560c9f linux/drivers/media/video/cx88/cx88-alsa.c--- a/linux/drivers/media/video/cx88/cx88-alsa.c Thu Aug 24 14:08:31 2006 -0700+++ b/linux/drivers/media/video/cx88/cx88-alsa.c Thu Aug 24 15:04:06 2006 -0700@@ -174,7 +174,7 @@ static int _cx88_start_audio_dma(snd_cx8 dprintk(1,"Enabling IRQ, setting mask from 0x%x to 0x%x\n",chip->core->pci_irqmask,(chip->core->pci_irqmask | 0x02)); /* enable irqs */- cx_set(MO_PCI_INTMSK, chip->core->pci_irqmask | 0x02);+ cx_set(MO_PCI_INTMSK, chip->core->pci_irqmask | MO_INT_AUDINT); /* Enables corresponding bits at AUD_INT_STAT */@@ -207,7 +207,7 @@ static int _cx88_stop_audio_dma(snd_cx88 cx_clear(MO_AUD_DMACNTRL, 0x11); /* disable irqs */- cx_clear(MO_PCI_INTMSK, 0x02);+ cx_clear(MO_PCI_INTMSK, MO_INT_AUDINT); cx_clear(MO_AUD_INTMSK, (1<<16)| (1<<12)|@@ -295,7 +295,7 @@ static irqreturn_t cx8801_irq(int irq, v int loop, handled = 0; for (loop = 0; loop < MAX_IRQ_LOOP; loop++) {- status = cx_read(MO_PCI_INTSTAT) & (core->pci_irqmask | 0x02);+ status = cx_read(MO_PCI_INTSTAT) & (core->pci_irqmask | MO_INT_AUDINT); if (0 == status) goto out; dprintk( 3, "cx8801_irq\n" );@@ -304,8 +304,9 @@ static irqreturn_t cx8801_irq(int irq, v handled = 1; cx_write(MO_PCI_INTSTAT, status); - if (status & 0x02)- {+ if (status & core->pci_irqmask)+ cx88_core_irq(core, status);+ if (status & MO_INT_AUDINT) { dprintk( 2, " ALSA IRQ handling\n" ); cx8801_aud_irq(chip); }@@ -822,6 +823,8 @@ static int __devinit snd_cx88_create(str chip->irq = pci->irq; synchronize_irq(chip->irq); + /* I2C Initialization */+ cx88_devs_init(core, pci); snd_card_set_dev(card, &pci->dev); *rchip = chip;diff -r 19981e560c9f linux/drivers/media/video/cx88/cx88-core.c--- a/linux/drivers/media/video/cx88/cx88-core.c Thu Aug 24 14:08:31 2006 -0700+++ b/linux/drivers/media/video/cx88/cx88-core.c Thu Aug 24 15:04:06 2006 -0700@@ -548,6 +548,11 @@ int cx88_core_irq(struct cx88_core *core cx88_ir_irq(core); handled++; }+ if (status & (MO_INT_I2CDONE | MO_INT_I2CRACK)) {+ core->int_status = status & (MO_INT_I2CRACK | MO_INT_I2CDONE);+ wake_up(&core->i2c_wq);+ handled++;+ } if (!handled) cx88_print_irqbits(core->name, "irq pci", cx88_pci_irqs, status,@@ -1110,6 +1115,7 @@ struct cx88_core* cx88_core_get(struct p core->pci_bus = pci->bus->number; core->pci_slot = PCI_SLOT(pci->devfn); core->pci_irqmask = 0x00fc00;+ core->pci_irqmask = 0x00fc00 | MO_INT_I2CDONE | MO_INT_I2CRACK; mutex_init(&core->lock); core->nr = cx88_devcount++;@@ -1168,12 +1174,7 @@ struct cx88_core* cx88_core_get(struct p core->tda9887_conf = cx88_boards[core->board].tda9887_conf; /* init hardware */- cx88_reset(core);- cx88_i2c_init(core,pci);- cx88_call_i2c_clients (core, TUNER_SET_STANDBY, NULL);- cx88_card_setup(core);- cx88_ir_init(core,pci);-+ /* moved alongwith i2c init */ mutex_unlock(&devlist); return core; @@ -1203,6 +1204,21 @@ void cx88_core_put(struct cx88_core *cor kfree(core); } +void cx88_devs_init(struct cx88_core *core, struct pci_dev *pci)+{+ /* init */+ if (!core->initialized) {+ init_waitqueue_head(&core->i2c_wq);+ cx88_reset(core);+ cx88_i2c_init(core, pci);+ cx88_call_i2c_clients (core, TUNER_SET_STANDBY, NULL);+ cx88_card_setup(core);+ cx88_ir_init(core, pci);+ core->initialized = 1;+ }+}+EXPORT_SYMBOL(cx88_devs_init);+ /* ------------------------------------------------------------------ */ EXPORT_SYMBOL(cx88_print_irqbits);diff -r 19981e560c9f linux/drivers/media/video/cx88/cx88-i2c.c--- a/linux/drivers/media/video/cx88/cx88-i2c.c Thu Aug 24 14:08:31 2006 -0700+++ b/linux/drivers/media/video/cx88/cx88-i2c.c Thu Aug 24 15:04:06 2006 -0700@@ -6,6 +6,7 @@ & Marcus Metzler (mocm@thp.uni-koeln.de) (c) 2002 Yurij Sysoev <yurij@naturesoft.net> (c) 1999-2003 Gerd Knorr <kraxel@bytesex.org>+ (C) 2006 Manu Abraham <abraham.manu@gmail.com> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by@@ -46,6 +47,139 @@ MODULE_PARM_DESC(i2c_scan,"scan i2c bus #define dprintk(level,fmt, arg...) if (i2c_debug >= level) \ printk(KERN_DEBUG "%s: " fmt, core->name , ## arg)++/* ---------------------------------------------------------------------------- */+/* CX88 I2C Routines */++#define CX88_HW_I2C (MO_I2C_MODE | \+ MO_I2C_SYNC | \+ MO_I2C_SCL | \+ MO_I2C_SDA)++static int cx88_ack_wait(struct cx88_core *core)+{+ int ret = 0;++ if (wait_event_interruptible_timeout(core->i2c_wq,+ core->int_status,+ msecs_to_jiffies(50)) == -ERESTARTSYS) {++ dprintk(1, "I/O Error\n");+ ret = -EREMOTEIO;+ }+ if (core->int_status & MO_INT_I2CRACK) {+ dprintk(1, "I2CRACK\n");+ core->int_status &= ~MO_INT_I2CRACK;+ } else {+ dprintk(1, "ACK fail\n");+ return -EREMOTEIO;+ }+ if (core->int_status & MO_INT_I2CDONE) {+ dprintk(1, "I2CDONE\n");+ ret = 1;+ }+ core->int_status &= ~MO_INT_I2CDONE;++ return ret;+}++/* Hardware I2C Enable */+static void cx88_i2c_enable(struct cx88_core *core)+{+ cx_set(MO_PCI_INTMSK, MO_INT_I2CDONE | MO_INT_I2CRACK);+}++static int cx88_i2c_write(struct cx88_core *core, const struct i2c_msg *msg, int last)+{+ u32 txd;+ int i;++ if (0 == msg->len)+ return -EINVAL;++ txd = (msg->addr << 25) | (msg->buf[0] << 16)+ | CX88_HW_I2C;++ if (msg->len > 1 || !last)+ txd |= MO_I2C_NOSTOP;+ cx_write(MO_I2C, txd);+ msleep_interruptible(1);+ if (cx88_ack_wait(core) < 0)+ return -EREMOTEIO;++ for (i = 1; i < msg->len; i++) {+ txd = (msg->buf[i] << 24) | CX88_HW_I2C+ | MO_I2C_NOS1B;++ if (i < msg->len - 1 || !last)+ txd |= MO_I2C_NOSTOP;+ cx_write(MO_I2C, txd);+ if (cx88_ack_wait(core) < 0)+ return -EREMOTEIO;+ }+ return msg->len;+}++static int cx88_i2c_read(struct cx88_core *core, const struct i2c_msg *msg, int last)+{+ u32 txd, i;++ for (i = 0; i < msg->len; i++) {+ txd = (msg->addr << 25) | (1 << 24)+ | CX88_HW_I2C;++ if (i < msg->len - 1)+ txd |= MO_I2C_W3BRA;+ if (i < msg->len - 1 || !last)+ txd |= MO_I2C_NOSTOP;+ if (i)+ txd |= MO_I2C_NOS1B;++ cx_write(MO_I2C, txd);+ msleep_interruptible(1);+ if (cx88_ack_wait(core) < 0)+ return -EREMOTEIO;++ msg->buf[i] = ((u32) cx_read(MO_I2C) >> 8) & 0xff;+ }+ return msg->len;+}++static int cx88_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num)+{+ struct cx88_core *core = i2c_get_adapdata(adapter);+ int ret = 0;+ int i;++ for (i = 0 ; i < num; i++) {+ if (msgs[i].flags & I2C_M_RD)+ ret = cx88_i2c_read(core, &msgs[i], i + 1 == num);+ else+ ret = cx88_i2c_write(core, &msgs[i], i + 1 == num);+ if (ret < 0)+ return ret;+ }+ return num;+}++static u32 cx88_i2c_func(struct i2c_adapter *adapter)+{+ return I2C_FUNC_SMBUS_EMUL;+}++#define I2C_HW_B_CX88 0x1c++static struct i2c_algorithm cx88_i2c_algo = {+ .master_xfer = cx88_i2c_xfer,+ .functionality = cx88_i2c_func,+};++static struct i2c_adapter cx88_i2c_adapter = {+ .owner = THIS_MODULE,+ .name = "CX88 I2C",+ .id = I2C_HW_B_CX88,+ .algo = &cx88_i2c_algo,+}; /* ----------------------------------------------------------------------- */ @@ -92,7 +226,6 @@ static int cx8800_bit_getsda(void *data) } /* ----------------------------------------------------------------------- */- static int attach_inform(struct i2c_client *client) { struct tuner_setup tun_setup;@@ -159,6 +292,7 @@ void cx88_call_i2c_clients(struct cx88_c #endif i2c_clients_command(&core->i2c_adap, cmd, arg); }+EXPORT_SYMBOL(cx88_call_i2c_clients); static struct i2c_algo_bit_data cx8800_i2c_algo_template = { .setsda = cx8800_bit_setsda,@@ -212,16 +346,43 @@ static void do_i2c_scan(char *name, stru /* init + register i2c algo-bit adapter */ int cx88_i2c_init(struct cx88_core *core, struct pci_dev *pci) {- memcpy(&core->i2c_adap, &cx8800_i2c_adap_template,- sizeof(core->i2c_adap));- memcpy(&core->i2c_algo, &cx8800_i2c_algo_template,- sizeof(core->i2c_algo));- memcpy(&core->i2c_client, &cx8800_i2c_client_template,- sizeof(core->i2c_client));-+ core->i2c_hw = 1; // Temporary testing+ if (core->i2c_hw) {+ dprintk(1, "I2C intializing\n");+ core->int_status = 0;+ memcpy(&core->i2c_adap, &cx88_i2c_adapter,+ sizeof (struct i2c_adapter));++ memcpy(&core->i2c_client, &cx8800_i2c_client_template,+ sizeof (core->i2c_client));++ i2c_set_adapdata(&core->i2c_adap, core);+ core->i2c_algo.data = core;+ core->i2c_client.adapter = &core->i2c_adap;+ core->i2c_rc = i2c_add_adapter(&core->i2c_adap);+ cx88_i2c_enable(core);+ } else {+ dprintk(1, "Bitbanging initializing\n");+ memcpy(&core->i2c_adap, &cx8800_i2c_adap_template,+ sizeof(core->i2c_adap));++ memcpy(&core->i2c_algo, &cx8800_i2c_algo_template,+ sizeof(core->i2c_algo));+ memcpy(&core->i2c_client, &cx8800_i2c_client_template,+ sizeof(core->i2c_client));++ i2c_set_adapdata(&core->i2c_adap,core);+ core->i2c_adap.algo_data = &core->i2c_algo;+ core->i2c_client.adapter = &core->i2c_adap;++ cx8800_bit_setscl(core,1);+ cx8800_bit_setsda(core,1);+ core->i2c_rc = i2c_bit_add_bus(&core->i2c_adap);++ } #ifdef I2C_CLASS_TV_ANALOG if (core->tuner_type != TUNER_ABSENT)- core->i2c_adap.class |= I2C_CLASS_TV_ANALOG;+ core->i2c_adap.class |= I2C_CLASS_TV_ANALOG; #endif #ifdef I2C_CLASS_TV_DIGITAL if (cx88_boards[core->board].dvb)@@ -233,14 +394,7 @@ int cx88_i2c_init(struct cx88_core *core #endif strlcpy(core->i2c_adap.name,core->name,sizeof(core->i2c_adap.name)); core->i2c_algo.data = core;- i2c_set_adapdata(&core->i2c_adap,core);- core->i2c_adap.algo_data = &core->i2c_algo;- core->i2c_client.adapter = &core->i2c_adap;-- cx8800_bit_setscl(core,1);- cx8800_bit_setsda(core,1);-- core->i2c_rc = i2c_bit_add_bus(&core->i2c_adap);+ if (0 == core->i2c_rc) { dprintk(1, "i2c register ok\n"); if (i2c_scan)@@ -249,13 +403,10 @@ int cx88_i2c_init(struct cx88_core *core printk("%s: i2c register FAILED\n", core->name); return core->i2c_rc; }-+EXPORT_SYMBOL(cx88_i2c_init); /* ----------------------------------------------------------------------- */--EXPORT_SYMBOL(cx88_call_i2c_clients);- /*- * Local variables:- * c-basic-offset: 8- * End:- */+* Local variables:+* c-basic-offset: 8+* End:+*/diff -r 19981e560c9f linux/drivers/media/video/cx88/cx88-mpeg.c--- a/linux/drivers/media/video/cx88/cx88-mpeg.c Thu Aug 24 14:08:31 2006 -0700+++ b/linux/drivers/media/video/cx88/cx88-mpeg.c Thu Aug 24 15:04:06 2006 -0700@@ -127,7 +127,7 @@ static int cx8802_start_dma(struct cx880 /* enable irqs */ dprintk( 1, "setting the interrupt mask\n" );- cx_set(MO_PCI_INTMSK, core->pci_irqmask | 0x04);+ cx_set(MO_PCI_INTMSK, core->pci_irqmask | MO_INT_TSINT); cx_set(MO_TS_INTMSK, 0x1f0011); #if 0 cx_write(MO_TS_INTMSK, 0x0f0011);@@ -400,7 +400,8 @@ static irqreturn_t cx8802_irq(int irq, v int loop, handled = 0; for (loop = 0; loop < MAX_IRQ_LOOP; loop++) {- status = cx_read(MO_PCI_INTSTAT) & (core->pci_irqmask | 0x04);+ status = cx_read(MO_PCI_INTSTAT) & (core->pci_irqmask | MO_INT_TSINT);+ if (0 == status) goto out; dprintk( 1, "cx8802_irq\n" );@@ -410,10 +411,10 @@ static irqreturn_t cx8802_irq(int irq, v cx_write(MO_PCI_INTSTAT, status); if (status & core->pci_irqmask)- cx88_core_irq(core,status);- if (status & 0x04)+ cx88_core_irq(core, status);+ if (status & MO_INT_TSINT) cx8802_mpeg_irq(dev);- };+ } if (MAX_IRQ_LOOP == loop) { dprintk( 0, "clearing mask\n" ); printk(KERN_WARNING "%s/0: irq loop -- clearing mask\n",@@ -475,8 +476,11 @@ int cx8802_init_common(struct cx8802_dev } cx_set(MO_PCI_INTMSK, core->pci_irqmask); + /* init */+ cx88_devs_init(core, dev->pci); /* everything worked */ pci_set_drvdata(dev->pci,dev);+ return 0; } diff -r 19981e560c9f linux/drivers/media/video/cx88/cx88-reg.h--- a/linux/drivers/media/video/cx88/cx88-reg.h Thu Aug 24 14:08:31 2006 -0700+++ b/linux/drivers/media/video/cx88/cx88-reg.h Thu Aug 24 15:04:06 2006 -0700@@ -6,6 +6,7 @@ 2001 Michael Eskin 2002 Yurij Sysoev <yurij@naturesoft.net> 2003 Gerd Knorr <kraxel@bytesex.org>+ Copyright (C) 2006 Manu Abraham <abraham.manu@gmail.com> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by@@ -76,8 +77,20 @@ #define MO_PDMA_DCNTRL 0x20001C // Destination control #define MO_LD_SSID 0x200030 // Load subsystem ID #define MO_DEV_CNTRL2 0x200034 // Device control+ #define MO_PCI_INTMSK 0x200040 // PCI interrupt mask #define MO_PCI_INTSTAT 0x200044 // PCI interrupt status+#define MO_INT_I2CRACK (1 << 17)+#define MO_INT_I2CDONE (1 << 16)+#define MO_INT_DSTDMAINT (1 << 7)+#define MO_INT_SRCDMAINT (1 << 6)+#define MO_INT_TM1INT (1 << 5)+#define MO_INT_HSTINT (1 << 4)+#define MO_INT_VIPINT (1 << 3)+#define MO_INT_TSINT (1 << 2)+#define MO_INT_AUDINT (1 << 1)+#define MO_INT_VIDINT (1 << 0)+ #define MO_PCI_INTMSTAT 0x200048 // PCI interrupt masked status #define MO_VID_INTMSK 0x200050 // Video interrupt mask #define MO_VID_INTSTAT 0x200054 // Video interrupt status@@ -514,12 +527,22 @@ /* i2c bus registers */ #define MO_I2C 0x368000 // I2C data/control-#define MO_I2C_DIV (0xf<<4)+#define MO_I2C_DB0 (0xff<<24)+#define MO_I2C_DB1 (0xff<<16)+#define MO_I2C_DB2 (0xff<<8)+#define MO_I2C_MODE (1<<7)+#define MO_I2C_RATE (1<<6)+#define MO_I2C_NOSTOP (1<<5)+#define MO_I2C_NOS1B (1<<4) #define MO_I2C_SYNC (1<<3)-#define MO_I2C_W3B (1<<2)+#define MO_I2C_W3BRA (1<<2) #define MO_I2C_SCL (1<<1) #define MO_I2C_SDA (1<<0) +enum cx88_i2crate {+ CX88_I2CRATE_LOW,+ CX88_I2CRATE_HIGH,+}; /* ---------------------------------------------------------------------- */ /* general purpose host registers */@@ -576,7 +599,7 @@ #define RISC_CNT_INC 0x00010000 #define RISC_CNT_RSVR 0x00020000 #define RISC_CNT_RESET 0x00030000-#define RISC_JMP_SRP 0x01+#define RISC_JMP_SRP 0x01 /* ---------------------------------------------------------------------- */diff -r 19981e560c9f linux/drivers/media/video/cx88/cx88-video.c--- a/linux/drivers/media/video/cx88/cx88-video.c Thu Aug 24 14:08:31 2006 -0700+++ b/linux/drivers/media/video/cx88/cx88-video.c Thu Aug 24 15:04:06 2006 -0700@@ -2039,17 +2039,18 @@ static irqreturn_t cx8800_irq(int irq, v int loop, handled = 0; for (loop = 0; loop < 10; loop++) {- status = cx_read(MO_PCI_INTSTAT) & (core->pci_irqmask | 0x01);+ status = cx_read(MO_PCI_INTSTAT) & (core->pci_irqmask | MO_INT_VIDINT);+ if (0 == status) goto out; cx_write(MO_PCI_INTSTAT, status); handled = 1; if (status & core->pci_irqmask)- cx88_core_irq(core,status);- if (status & 0x01)+ cx88_core_irq(core, status);+ if (status & MO_INT_VIDINT) cx8800_vid_irq(dev);- };+ } if (10 == loop) { printk(KERN_WARNING "%s/0: irq loop -- clearing mask\n", core->name);@@ -2219,6 +2220,8 @@ static int __devinit cx8800_initdev(stru } cx_set(MO_PCI_INTMSK, core->pci_irqmask); + /* I2C Initialization */+ cx88_devs_init(core, pci_dev); /* load and configure helper modules */ if (TUNER_ABSENT != core->tuner_type) request_module("tuner");@@ -2310,6 +2313,7 @@ static void __devexit cx8800_finidev(str pci_disable_device(pci_dev); /* unregister stuff */+ i2c_del_adapter(&core->i2c_adap); free_irq(pci_dev->irq, dev); cx8800_unregister_video(dev);diff -r 19981e560c9f linux/drivers/media/video/cx88/cx88.h--- a/linux/drivers/media/video/cx88/cx88.h Thu Aug 24 14:08:31 2006 -0700+++ b/linux/drivers/media/video/cx88/cx88.h Thu Aug 24 15:04:06 2006 -0700@@ -239,6 +239,8 @@ struct cx88_board { struct cx88_input radio; unsigned int blackbird:1; unsigned int dvb:1;+ unsigned int hw_i2c;+ enum cx88_i2crate i2c_rate; }; struct cx88_subid {@@ -319,7 +321,7 @@ struct cx88_core { #ifdef HAVE_VIDEO_BUF_DVB struct dvb_pll_desc *pll_desc; unsigned int pll_addr;- int (*prev_set_voltage)(struct dvb_frontend* fe, fe_sec_voltage_t voltage);+ int (*prev_set_voltage)(struct dvb_frontend* fe, fe_sec_voltage_t voltage); #endif /* state info */@@ -345,6 +347,12 @@ struct cx88_core { /* cx88-video needs to access cx8802 for hybrid tuner pll access. */ struct cx8802_dev *dvbdev;++ u32 int_status;+ wait_queue_head_t i2c_wq;+ enum cx88_i2crate tx_rate;+ u32 i2c_hw;+ int initialized; }; struct cx8800_dev;@@ -638,6 +646,7 @@ extern int cx88_do_ioctl(struct inode *i void *arg, v4l2_kioctl driver_ioctl); extern const u32 cx88_user_ctrls[]; extern int cx8800_ctrl_query(struct v4l2_queryctrl *qctrl);+extern void cx88_devs_init(struct cx88_core *core, struct pci_dev *pci); /* * Local variables: