@ -22,6 +22,8 @@
* Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
# include "cx88.h"
# include <linux/module.h>
# include <linux/slab.h>
# include <linux/init.h>
@ -30,8 +32,6 @@
# include <linux/interrupt.h>
# include <asm/delay.h>
# include "cx88.h"
/* ------------------------------------------------------------------ */
MODULE_DESCRIPTION ( " mpeg driver for cx2388x based TV cards " ) ;
@ -45,15 +45,11 @@ static unsigned int debug;
module_param ( debug , int , 0644 ) ;
MODULE_PARM_DESC ( debug , " enable debug messages [mpeg] " ) ;
# define dprintk(level, fmt, arg...) do { \
if ( debug + 1 > level ) \
printk ( KERN_DEBUG " %s/2-mpeg: " fmt , dev - > core - > name , # # arg ) ; \
} while ( 0 )
# define mpeg_dbg(level, fmt, arg...) do { \
if ( debug + 1 > level ) \
printk ( KERN_DEBUG " %s/2-mpeg: " fmt , core - > name , # # arg ) ; \
} while ( 0 )
# define dprintk(level, fmt, arg...) do { \
if ( debug + 1 > level ) \
printk ( KERN_DEBUG pr_fmt ( " %s: mpeg: " fmt ) , \
__func__ , # # arg ) ; \
} while ( 0 )
# if defined(CONFIG_MODULES) && defined(MODULE)
static void request_module_async ( struct work_struct * work )
@ -92,7 +88,7 @@ int cx8802_start_dma(struct cx8802_dev *dev,
{
struct cx88_core * core = dev - > core ;
dprintk ( 1 , " cx8802_start_dma w: %d, h: %d, f: %d\n " ,
dprintk ( 1 , " w: %d, h: %d, f: %d \n " ,
core - > width , core - > height , core - > field ) ;
/* setup fifo + format */
@ -105,12 +101,12 @@ int cx8802_start_dma(struct cx8802_dev *dev,
/* FIXME: this needs a review.
* also : move to cx88 - blackbird + cx88 - dvb source files ? */
dprintk ( 1 , " core->active_type_id = 0x%08x \n " , core - > active_type_id ) ;
dprintk ( 1 , " core->active_type_id = 0x%08x \n " , core - > active_type_id ) ;
if ( ( core - > active_type_id = = CX88_MPEG_DVB ) & &
( core - > board . mpeg & CX88_MPEG_DVB ) ) {
dprintk ( 1 , " cx8802_start_dma doing .dvb \n " ) ;
dprintk ( 1 , " cx8802_start_dma doing .dvb \n " ) ;
/* negedge driven & software reset */
cx_write ( TS_GEN_CNTRL , 0x0040 | dev - > ts_gen_cntrl ) ;
udelay ( 100 ) ;
@ -154,7 +150,7 @@ int cx8802_start_dma(struct cx8802_dev *dev,
udelay ( 100 ) ;
} else if ( ( core - > active_type_id = = CX88_MPEG_BLACKBIRD ) & &
( core - > board . mpeg & CX88_MPEG_BLACKBIRD ) ) {
dprintk ( 1 , " cx8802_start_dma doing .blackbird \n " ) ;
dprintk ( 1 , " cx8802_start_dma doing .blackbird \n " ) ;
cx_write ( MO_PINMUX_IO , 0x88 ) ; /* enable MPEG parallel IO */
cx_write ( TS_GEN_CNTRL , 0x46 ) ; /* punctured clock TS & posedge driven & software reset */
@ -166,8 +162,8 @@ int cx8802_start_dma(struct cx8802_dev *dev,
cx_write ( TS_GEN_CNTRL , 0x06 ) ; /* punctured clock TS & posedge driven */
udelay ( 100 ) ;
} else {
printk ( " %s() Failed. Unsupported value in .mpeg (0x%08x) \n " , __func__ ,
core - > board . mpeg ) ;
pr_err ( " %s() Failed. Unsupported value in .mpeg (0x%08x) \n " ,
__func__ , core - > board . mpeg ) ;
return - EINVAL ;
}
@ -176,7 +172,7 @@ int cx8802_start_dma(struct cx8802_dev *dev,
q - > count = 0 ;
/* enable irqs */
dprintk ( 1 , " setting the interrupt mask \n " ) ;
dprintk ( 1 , " setting the interrupt mask \n " ) ;
cx_set ( MO_PCI_INTMSK , core - > pci_irqmask | PCI_INT_TSINT ) ;
cx_set ( MO_TS_INTMSK , 0x1f0011 ) ;
@ -189,7 +185,7 @@ int cx8802_start_dma(struct cx8802_dev *dev,
static int cx8802_stop_dma ( struct cx8802_dev * dev )
{
struct cx88_core * core = dev - > core ;
dprintk ( 1 , " cx8802_stop_dma \n " ) ;
dprintk ( 1 , " \n " ) ;
/* stop dma */
cx_clear ( MO_TS_DMACNTRL , 0x11 ) ;
@ -208,7 +204,7 @@ static int cx8802_restart_queue(struct cx8802_dev *dev,
{
struct cx88_buffer * buf ;
dprintk ( 1 , " cx8802_restart_queue \n " ) ;
dprintk ( 1 , " \n " ) ;
if ( list_empty ( & q - > active ) )
return 0 ;
@ -249,25 +245,25 @@ void cx8802_buf_queue(struct cx8802_dev *dev, struct cx88_buffer *buf)
struct cx88_buffer * prev ;
struct cx88_dmaqueue * cx88q = & dev - > mpegq ;
dprintk ( 1 , " cx8802_buf_queue \n " ) ;
dprintk ( 1 , " \n " ) ;
/* add jump to start */
buf - > risc . cpu [ 1 ] = cpu_to_le32 ( buf - > risc . dma + 8 ) ;
buf - > risc . jmp [ 0 ] = cpu_to_le32 ( RISC_JUMP | RISC_CNT_INC ) ;
buf - > risc . jmp [ 1 ] = cpu_to_le32 ( buf - > risc . dma + 8 ) ;
if ( list_empty ( & cx88q - > active ) ) {
dprintk ( 1 , " queue is empty - first active \n " ) ;
dprintk ( 1 , " queue is empty - first active \n " ) ;
list_add_tail ( & buf - > list , & cx88q - > active ) ;
dprintk ( 1 , " [%p/%d] %s - first active \n " ,
buf , buf - > vb . vb2_buf . index , __func__ ) ;
} else {
buf - > risc . cpu [ 0 ] | = cpu_to_le32 ( RISC_IRQ1 ) ;
dprintk ( 1 , " queue is not empty - append to active \n " ) ;
dprintk ( 1 , " queue is not empty - append to active \n " ) ;
prev = list_entry ( cx88q - > active . prev , struct cx88_buffer , list ) ;
list_add_tail ( & buf - > list , & cx88q - > active ) ;
prev - > risc . jmp [ 1 ] = cpu_to_le32 ( buf - > risc . dma ) ;
dprintk ( 1 , " [%p/%d] %s - append to active \n " ,
dprintk ( 1 , " [%p/%d] %s - append to active \n " ,
buf , buf - > vb . vb2_buf . index , __func__ ) ;
}
}
@ -291,7 +287,7 @@ static void do_cancel_buffers(struct cx8802_dev *dev)
void cx8802_cancel_buffers ( struct cx8802_dev * dev )
{
dprintk ( 1 , " cx8802_cancel_buffers " ) ;
dprintk ( 1 , " \n " ) ;
cx8802_stop_dma ( dev ) ;
do_cancel_buffers ( dev ) ;
}
@ -310,7 +306,7 @@ static void cx8802_mpeg_irq(struct cx8802_dev *dev)
struct cx88_core * core = dev - > core ;
u32 status , mask , count ;
dprintk ( 1 , " cx8802_mpeg_irq \n " ) ;
dprintk ( 1 , " \n " ) ;
status = cx_read ( MO_TS_INTSTAT ) ;
mask = cx_read ( MO_TS_INTMSK ) ;
if ( 0 = = ( status & mask ) )
@ -319,20 +315,20 @@ static void cx8802_mpeg_irq(struct cx8802_dev *dev)
cx_write ( MO_TS_INTSTAT , status ) ;
if ( debug | | ( status & mask & ~ 0xff ) )
cx88_print_irqbits ( core - > name , " irq mpeg " ,
cx88_print_irqbits ( " irq mpeg " ,
cx88_mpeg_irqs , ARRAY_SIZE ( cx88_mpeg_irqs ) ,
status , mask ) ;
/* risc op code error */
if ( status & ( 1 < < 16 ) ) {
printk ( KERN_WARNING " %s: mpeg risc op code error\n " , core - > name ) ;
pr_warn ( " mpeg risc op code error \n " ) ;
cx_clear ( MO_TS_DMACNTRL , 0x11 ) ;
cx88_sram_channel_dump ( dev - > core , & cx88_sram_channels [ SRAM_CH28 ] ) ;
}
/* risc1 y */
if ( status & 0x01 ) {
dprintk ( 1 , " wake up \n " ) ;
dprintk ( 1 , " wake up \n " ) ;
spin_lock ( & dev - > slock ) ;
count = cx_read ( MO_TS_GPCNT ) ;
cx88_wakeup ( dev - > core , & dev - > mpegq , count ) ;
@ -341,7 +337,7 @@ static void cx8802_mpeg_irq(struct cx8802_dev *dev)
/* other general errors */
if ( status & 0x1f0100 ) {
dprintk ( 0 , " general errors: 0x%08x \n " , status & 0x1f0100 ) ;
dprintk ( 0 , " general errors: 0x%08x \n " , status & 0x1f0100 ) ;
spin_lock ( & dev - > slock ) ;
cx8802_stop_dma ( dev ) ;
spin_unlock ( & dev - > slock ) ;
@ -362,9 +358,9 @@ static irqreturn_t cx8802_irq(int irq, void *dev_id)
( core - > pci_irqmask | PCI_INT_TSINT ) ;
if ( 0 = = status )
goto out ;
dprintk ( 1 , " cx8802_irq \n " ) ;
dprintk ( 1 , " loop: %d/%d \n " , loop , MAX_IRQ_LOOP ) ;
dprintk ( 1 , " status: %d \n " , status ) ;
dprintk ( 1 , " cx8802_irq \n " ) ;
dprintk ( 1 , " loop: %d/%d \n " , loop , MAX_IRQ_LOOP ) ;
dprintk ( 1 , " status: %d \n " , status ) ;
handled = 1 ;
cx_write ( MO_PCI_INTSTAT , status ) ;
@ -374,9 +370,8 @@ static irqreturn_t cx8802_irq(int irq, void *dev_id)
cx8802_mpeg_irq ( dev ) ;
}
if ( MAX_IRQ_LOOP = = loop ) {
dprintk ( 0 , " clearing mask \n " ) ;
printk ( KERN_WARNING " %s/0: irq loop -- clearing mask \n " ,
core - > name ) ;
dprintk ( 0 , " clearing mask \n " ) ;
pr_warn ( " irq loop -- clearing mask \n " ) ;
cx_write ( MO_PCI_INTMSK , 0 ) ;
}
@ -395,16 +390,16 @@ static int cx8802_init_common(struct cx8802_dev *dev)
pci_set_master ( dev - > pci ) ;
err = pci_set_dma_mask ( dev - > pci , DMA_BIT_MASK ( 32 ) ) ;
if ( err ) {
printk ( " %s/2: Oops: no 32bit PCI DMA ???\n " , dev - > core - > name ) ;
pr_err ( " Oops: no 32bit PCI DMA ??? \n " ) ;
return - EIO ;
}
dev - > pci_rev = dev - > pci - > revision ;
pci_read_config_byte ( dev - > pci , PCI_LATENCY_TIMER , & dev - > pci_lat ) ;
printk ( KERN_INFO " %s/2: found at %s, rev: %d, irq: %d, latency: %d, mmio: 0x%llx\n " ,
dev - > core - > name ,
pci_name ( dev - > pci ) , dev - > pci_rev , dev - > pci - > irq ,
dev - > pci_lat , ( unsigned long long ) pci_resource_start ( dev - > pci , 0 ) ) ;
pr_info ( " found at %s, rev: %d, irq: %d, latency: %d, mmio: 0x%llx \n " ,
pci_name ( dev - > pci ) , dev - > pci_rev , dev - > pci - > irq ,
dev - > pci_lat ,
( unsigned long long ) pci_resource_start ( dev - > pci , 0 ) ) ;
/* initialize driver struct */
spin_lock_init ( & dev - > slock ) ;
@ -416,8 +411,7 @@ static int cx8802_init_common(struct cx8802_dev *dev)
err = request_irq ( dev - > pci - > irq , cx8802_irq ,
IRQF_SHARED , dev - > core - > name , dev ) ;
if ( err < 0 ) {
printk ( KERN_ERR " %s: can't get IRQ %d \n " ,
dev - > core - > name , dev - > pci - > irq ) ;
pr_err ( " can't get IRQ %d \n " , dev - > pci - > irq ) ;
return err ;
}
cx_set ( MO_PCI_INTMSK , core - > pci_irqmask ) ;
@ -429,7 +423,7 @@ static int cx8802_init_common(struct cx8802_dev *dev)
static void cx8802_fini_common ( struct cx8802_dev * dev )
{
dprintk ( 2 , " cx8802_fini_common \n " ) ;
dprintk ( 2 , " \n " ) ;
cx8802_stop_dma ( dev ) ;
pci_disable_device ( dev - > pci ) ;
@ -442,14 +436,13 @@ static void cx8802_fini_common(struct cx8802_dev *dev)
static int cx8802_suspend_common ( struct pci_dev * pci_dev , pm_message_t state )
{
struct cx8802_dev * dev = pci_get_drvdata ( pci_dev ) ;
struct cx88_core * core = dev - > core ;
unsigned long flags ;
/* stop mpeg dma */
spin_lock_irqsave ( & dev - > slock , flags ) ;
if ( ! list_empty ( & dev - > mpegq . active ) ) {
dprintk ( 2 , " suspend \n " ) ;
printk ( " %s: suspend mpeg\n " , core - > name ) ;
dprintk ( 2 , " suspend \n " ) ;
pr_info ( " suspend mpeg \n " ) ;
cx8802_stop_dma ( dev ) ;
}
spin_unlock_irqrestore ( & dev - > slock , flags ) ;
@ -468,23 +461,20 @@ static int cx8802_suspend_common(struct pci_dev *pci_dev, pm_message_t state)
static int cx8802_resume_common ( struct pci_dev * pci_dev )
{
struct cx8802_dev * dev = pci_get_drvdata ( pci_dev ) ;
struct cx88_core * core = dev - > core ;
unsigned long flags ;
int err ;
if ( dev - > state . disabled ) {
err = pci_enable_device ( pci_dev ) ;
if ( err ) {
printk ( KERN_ERR " %s: can't enable device \n " ,
dev - > core - > name ) ;
pr_err ( " can't enable device \n " ) ;
return err ;
}
dev - > state . disabled = 0 ;
}
err = pci_set_power_state ( pci_dev , PCI_D0 ) ;
if ( err ) {
printk ( KERN_ERR " %s: can't enable device \n " ,
dev - > core - > name ) ;
pr_err ( " can't enable device \n " ) ;
pci_disable_device ( pci_dev ) ;
dev - > state . disabled = 1 ;
@ -498,7 +488,7 @@ static int cx8802_resume_common(struct pci_dev *pci_dev)
/* restart video+vbi capture */
spin_lock_irqsave ( & dev - > slock , flags ) ;
if ( ! list_empty ( & dev - > mpegq . active ) ) {
printk ( " %s: resume mpeg\n " , core - > name ) ;
pr_info ( " resume mpeg \n " ) ;
cx8802_restart_queue ( dev , & dev - > mpegq ) ;
}
spin_unlock_irqrestore ( & dev - > slock , flags ) ;
@ -550,7 +540,7 @@ static int cx8802_request_acquire(struct cx8802_driver *drv)
drv - > advise_acquire ( drv ) ;
}
mpeg_dbg ( 1 , " %s() Post acquire GPIO=%x\n " , __func__ , cx_read ( MO_GP0_IO ) ) ;
dprintk ( 1 , " Post acquire GPIO=%x \n " , cx_read ( MO_GP0_IO ) ) ;
}
return 0 ;
@ -571,7 +561,7 @@ static int cx8802_request_release(struct cx8802_driver *drv)
drv - > advise_release ( drv ) ;
core - > active_type_id = CX88_BOARD_NONE ;
mpeg_dbg ( 1 , " %s() Post release GPIO=%x\n " , __func__ , cx_read ( MO_GP0_IO ) ) ;
dprintk ( 1 , " Post release GPIO=%x \n " , cx_read ( MO_GP0_IO ) ) ;
}
return 0 ;
@ -605,24 +595,22 @@ int cx8802_register_driver(struct cx8802_driver *drv)
struct cx8802_driver * driver ;
int err , i = 0 ;
printk ( KERN_INFO
" cx88/2: registering cx8802 driver, type: %s access: %s \n " ,
drv - > type_id = = CX88_MPEG_DVB ? " dvb " : " blackbird " ,
drv - > hw_access = = CX8802_DRVCTL_SHARED ? " shared " : " exclusive " ) ;
pr_info ( " registering cx8802 driver, type: %s access: %s \n " ,
drv - > type_id = = CX88_MPEG_DVB ? " dvb " : " blackbird " ,
drv - > hw_access = = CX8802_DRVCTL_SHARED ? " shared " : " exclusive " ) ;
if ( ( err = cx8802_check_driver ( drv ) ) ! = 0 ) {
printk ( KERN_ERR " cx88/2: cx8802_driver is invalid\n " ) ;
pr_err ( " cx8802_driver is invalid \n " ) ;
return err ;
}
mutex_lock ( & cx8802_mutex ) ;
list_for_each_entry ( dev , & cx8802_devlist , devlist ) {
printk ( KERN_INFO
" %s/2: subsystem: %04x:%04x, board: %s [card=%d] \n " ,
dev - > core - > name , dev - > pci - > subsystem_vendor ,
dev - > pci - > subsystem_device , dev - > core - > board . name ,
dev - > core - > boardnr ) ;
pr_info ( " subsystem: %04x:%04x, board: %s [card=%d] \n " ,
dev - > pci - > subsystem_vendor ,
dev - > pci - > subsystem_device , dev - > core - > board . name ,
dev - > core - > boardnr ) ;
/* Bring up a new struct for each driver instance */
driver = kzalloc ( sizeof ( * drv ) , GFP_KERNEL ) ;
@ -645,9 +633,7 @@ int cx8802_register_driver(struct cx8802_driver *drv)
i + + ;
list_add_tail ( & driver - > drvlist , & dev - > drvlist ) ;
} else {
printk ( KERN_ERR
" %s/2: cx8802 probe failed, err = %d \n " ,
dev - > core - > name , err ) ;
pr_err ( " cx8802 probe failed, err = %d \n " , err ) ;
}
mutex_unlock ( & drv - > core - > lock ) ;
}
@ -664,19 +650,17 @@ int cx8802_unregister_driver(struct cx8802_driver *drv)
struct cx8802_driver * d , * dtmp ;
int err = 0 ;
printk ( KERN_INFO
" cx88/2: unregistering cx8802 driver, type: %s access: %s \n " ,
drv - > type_id = = CX88_MPEG_DVB ? " dvb " : " blackbird " ,
drv - > hw_access = = CX8802_DRVCTL_SHARED ? " shared " : " exclusive " ) ;
pr_info ( " unregistering cx8802 driver, type: %s access: %s \n " ,
drv - > type_id = = CX88_MPEG_DVB ? " dvb " : " blackbird " ,
drv - > hw_access = = CX8802_DRVCTL_SHARED ? " shared " : " exclusive " ) ;
mutex_lock ( & cx8802_mutex ) ;
list_for_each_entry ( dev , & cx8802_devlist , devlist ) {
printk ( KERN_INFO
" %s/2: subsystem: %04x:%04x, board: %s [card=%d] \n " ,
dev - > core - > name , dev - > pci - > subsystem_vendor ,
dev - > pci - > subsystem_device , dev - > core - > board . name ,
dev - > core - > boardnr ) ;
pr_info ( " subsystem: %04x:%04x, board: %s [card=%d] \n " ,
dev - > pci - > subsystem_vendor ,
dev - > pci - > subsystem_device , dev - > core - > board . name ,
dev - > core - > boardnr ) ;
mutex_lock ( & dev - > core - > lock ) ;
@ -690,8 +674,8 @@ int cx8802_unregister_driver(struct cx8802_driver *drv)
list_del ( & d - > drvlist ) ;
kfree ( d ) ;
} else
printk ( KERN_ERR " %s/2: cx8802 driver remove failed (%d)\n " ,
dev - > core - > name , err ) ;
pr_err ( " cx8802 driver remove failed (%d) \n " ,
err ) ;
}
mutex_unlock ( & dev - > core - > lock ) ;
@ -715,7 +699,7 @@ static int cx8802_probe(struct pci_dev *pci_dev,
if ( NULL = = core )
return - EINVAL ;
printk ( " %s/2: cx2388x 8802 Driver Manager\n " , core - > name ) ;
pr_info ( " cx2388x 8802 Driver Manager \n " ) ;
err = - ENODEV ;
if ( ! core - > board . mpeg )
@ -758,7 +742,7 @@ static void cx8802_remove(struct pci_dev *pci_dev)
dev = pci_get_drvdata ( pci_dev ) ;
dprintk ( 1 , " %s \n " , __func__ ) ;
dprintk ( 1 , " %s \n " , __func__ ) ;
flush_request_modules ( dev ) ;
@ -768,16 +752,15 @@ static void cx8802_remove(struct pci_dev *pci_dev)
struct cx8802_driver * drv , * tmp ;
int err ;
printk ( KERN_WARNING " %s/2: Trying to remove cx8802 driver while cx8802 sub-drivers still loaded?! \n " ,
dev - > core - > name ) ;
pr_warn ( " Trying to remove cx8802 driver while cx8802 sub-drivers still loaded?! \n " ) ;
list_for_each_entry_safe ( drv , tmp , & dev - > drvlist , drvlist ) {
err = drv - > remove ( drv ) ;
if ( err = = 0 ) {
list_del ( & drv - > drvlist ) ;
} else
printk ( KERN_ERR " %s/2: cx8802 driver remove failed (%d)\n " ,
dev - > core - > name , err ) ;
pr_err ( " cx8802 driver remove failed (%d) \n " ,
err ) ;
kfree ( drv ) ;
}
}