2009-12-18 22:13:26 -03:00
/*
* ngene . c : nGene PCIe bridge driver
*
* Copyright ( C ) 2005 - 2007 Micronas
*
* Copyright ( C ) 2008 - 2009 Ralph Metzler < rjkm @ metzlerbros . de >
* Modifications for new nGene firmware ,
* support for EEPROM - copying ,
* support for new dual DVB - S2 card prototype
*
*
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU General Public License
* version 2 only , as published by the Free Software Foundation .
*
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
2016-10-28 09:31:20 -02:00
* To obtain the license , point your browser to
* http : //www.gnu.org/copyleft/gpl.html
2009-12-18 22:13:26 -03:00
*/
# include <linux/module.h>
# include <linux/init.h>
# include <linux/delay.h>
# include <linux/poll.h>
2010-02-03 18:59:20 -03:00
# include <linux/io.h>
2009-12-18 22:13:26 -03:00
# include <asm/div64.h>
# include <linux/pci.h>
# include <linux/timer.h>
# include <linux/byteorder/generic.h>
# include <linux/firmware.h>
2010-02-05 02:46:47 -03:00
# include <linux/vmalloc.h>
2009-12-18 22:13:26 -03:00
# include "ngene.h"
2011-07-03 13:56:28 -03:00
static int one_adapter ;
2009-12-23 05:55:02 -03:00
module_param ( one_adapter , int , 0444 ) ;
MODULE_PARM_DESC ( one_adapter , " Use only one adapter. " ) ;
2011-01-10 06:36:16 -03:00
static int shutdown_workaround ;
module_param ( shutdown_workaround , int , 0644 ) ;
2011-01-10 06:36:20 -03:00
MODULE_PARM_DESC ( shutdown_workaround , " Activate workaround for shutdown problem with some chipsets. " ) ;
2011-01-10 06:36:16 -03:00
2009-12-18 22:13:26 -03:00
static int debug ;
module_param ( debug , int , 0444 ) ;
MODULE_PARM_DESC ( debug , " Print debugging information. " ) ;
2009-12-19 04:54:44 -03:00
DVB_DEFINE_MOD_OPT_ADAPTER_NR ( adapter_nr ) ;
2014-08-20 17:43:22 -03:00
# define ngwriteb(dat, adr) writeb((dat), dev->iomem + (adr))
# define ngwritel(dat, adr) writel((dat), dev->iomem + (adr))
# define ngwriteb(dat, adr) writeb((dat), dev->iomem + (adr))
2009-12-18 22:13:26 -03:00
# define ngreadl(adr) readl(dev->iomem + (adr))
# define ngreadb(adr) readb(dev->iomem + (adr))
2014-08-20 17:43:22 -03:00
# define ngcpyto(adr, src, count) memcpy_toio(dev->iomem + (adr), (src), (count))
# define ngcpyfrom(dst, adr, count) memcpy_fromio((dst), dev->iomem + (adr), (count))
2009-12-18 22:13:26 -03:00
/****************************************************************************/
/* nGene interrupt handler **************************************************/
/****************************************************************************/
static void event_tasklet ( unsigned long data )
{
struct ngene * dev = ( struct ngene * ) data ;
while ( dev - > EventQueueReadIndex ! = dev - > EventQueueWriteIndex ) {
struct EVENT_BUFFER Event =
dev - > EventQueue [ dev - > EventQueueReadIndex ] ;
dev - > EventQueueReadIndex =
( dev - > EventQueueReadIndex + 1 ) & ( EVENT_QUEUE_SIZE - 1 ) ;
if ( ( Event . UARTStatus & 0x01 ) & & ( dev - > TxEventNotify ) )
dev - > TxEventNotify ( dev , Event . TimeStamp ) ;
if ( ( Event . UARTStatus & 0x02 ) & & ( dev - > RxEventNotify ) )
dev - > RxEventNotify ( dev , Event . TimeStamp ,
Event . RXCharacter ) ;
}
}
static void demux_tasklet ( unsigned long data )
{
struct ngene_channel * chan = ( struct ngene_channel * ) data ;
2018-02-25 07:31:30 -05:00
struct device * pdev = & chan - > dev - > pci_dev - > dev ;
2009-12-18 22:13:26 -03:00
struct SBufferHeader * Cur = chan - > nextBuffer ;
spin_lock_irq ( & chan - > state_lock ) ;
while ( Cur - > ngeneBuffer . SR . Flags & 0x80 ) {
if ( chan - > mode & NGENE_IO_TSOUT ) {
u32 Flags = chan - > DataFormatFlags ;
if ( Cur - > ngeneBuffer . SR . Flags & 0x20 )
Flags | = BEF_OVERFLOW ;
if ( chan - > pBufferExchange ) {
if ( ! chan - > pBufferExchange ( chan ,
Cur - > Buffer1 ,
chan - > Capture1Length ,
Cur - > ngeneBuffer . SR .
Clock , Flags ) ) {
/*
We didn ' t get data
Clear in service flag to make sure we
get called on next interrupt again .
leave fill / empty ( 0x80 ) flag alone
to avoid hardware running out of
buffers during startup , we hold only
in run state ( the source may be late
delivering data )
*/
if ( chan - > HWState = = HWSTATE_RUN ) {
Cur - > ngeneBuffer . SR . Flags & =
~ 0x40 ;
break ;
2011-03-30 22:57:33 -03:00
/* Stop processing stream */
2009-12-18 22:13:26 -03:00
}
} else {
/* We got a valid buffer,
so switch to run state */
chan - > HWState = HWSTATE_RUN ;
}
} else {
2018-02-25 07:31:30 -05:00
dev_err ( pdev , " OOPS \n " ) ;
2009-12-18 22:13:26 -03:00
if ( chan - > HWState = = HWSTATE_RUN ) {
Cur - > ngeneBuffer . SR . Flags & = ~ 0x40 ;
2011-03-30 22:57:33 -03:00
break ; /* Stop processing stream */
2009-12-18 22:13:26 -03:00
}
}
if ( chan - > AudioDTOUpdated ) {
2018-02-25 07:31:30 -05:00
dev_info ( pdev , " Update AudioDTO = %d \n " ,
chan - > AudioDTOValue ) ;
2009-12-18 22:13:26 -03:00
Cur - > ngeneBuffer . SR . DTOUpdate =
chan - > AudioDTOValue ;
chan - > AudioDTOUpdated = 0 ;
}
} else {
if ( chan - > HWState = = HWSTATE_RUN ) {
2011-01-10 06:36:12 -03:00
u32 Flags = chan - > DataFormatFlags ;
2010-05-16 05:17:49 -03:00
IBufferExchange * exch1 = chan - > pBufferExchange ;
IBufferExchange * exch2 = chan - > pBufferExchange2 ;
2009-12-18 22:13:26 -03:00
if ( Cur - > ngeneBuffer . SR . Flags & 0x01 )
Flags | = BEF_EVEN_FIELD ;
if ( Cur - > ngeneBuffer . SR . Flags & 0x20 )
Flags | = BEF_OVERFLOW ;
2010-05-16 05:17:49 -03:00
spin_unlock_irq ( & chan - > state_lock ) ;
if ( exch1 )
exch1 ( chan , Cur - > Buffer1 ,
chan - > Capture1Length ,
Cur - > ngeneBuffer . SR . Clock ,
Flags ) ;
if ( exch2 )
exch2 ( chan , Cur - > Buffer2 ,
chan - > Capture2Length ,
Cur - > ngeneBuffer . SR . Clock ,
Flags ) ;
spin_lock_irq ( & chan - > state_lock ) ;
2009-12-18 22:13:26 -03:00
} else if ( chan - > HWState ! = HWSTATE_STOP )
chan - > HWState = HWSTATE_RUN ;
}
Cur - > ngeneBuffer . SR . Flags = 0x00 ;
Cur = Cur - > Next ;
}
chan - > nextBuffer = Cur ;
spin_unlock_irq ( & chan - > state_lock ) ;
}
static irqreturn_t irq_handler ( int irq , void * dev_id )
{
struct ngene * dev = ( struct ngene * ) dev_id ;
2018-02-25 07:31:30 -05:00
struct device * pdev = & dev - > pci_dev - > dev ;
2009-12-18 22:13:26 -03:00
u32 icounts = 0 ;
irqreturn_t rc = IRQ_NONE ;
u32 i = MAX_STREAM ;
u8 * tmpCmdDoneByte ;
if ( dev - > BootFirmware ) {
icounts = ngreadl ( NGENE_INT_COUNTS ) ;
if ( icounts ! = dev - > icounts ) {
ngwritel ( 0 , FORCE_NMI ) ;
dev - > cmd_done = 1 ;
wake_up ( & dev - > cmd_wq ) ;
dev - > icounts = icounts ;
rc = IRQ_HANDLED ;
}
return rc ;
}
ngwritel ( 0 , FORCE_NMI ) ;
spin_lock ( & dev - > cmd_lock ) ;
tmpCmdDoneByte = dev - > CmdDoneByte ;
if ( tmpCmdDoneByte & &
( * tmpCmdDoneByte | |
( dev - > ngenetohost [ 0 ] = = 1 & & dev - > ngenetohost [ 1 ] ! = 0 ) ) ) {
dev - > CmdDoneByte = NULL ;
dev - > cmd_done = 1 ;
wake_up ( & dev - > cmd_wq ) ;
rc = IRQ_HANDLED ;
}
spin_unlock ( & dev - > cmd_lock ) ;
if ( dev - > EventBuffer - > EventStatus & 0x80 ) {
u8 nextWriteIndex =
( dev - > EventQueueWriteIndex + 1 ) &
( EVENT_QUEUE_SIZE - 1 ) ;
if ( nextWriteIndex ! = dev - > EventQueueReadIndex ) {
dev - > EventQueue [ dev - > EventQueueWriteIndex ] =
* ( dev - > EventBuffer ) ;
dev - > EventQueueWriteIndex = nextWriteIndex ;
} else {
2018-02-25 07:31:30 -05:00
dev_err ( pdev , " event overflow \n " ) ;
2009-12-18 22:13:26 -03:00
dev - > EventQueueOverflowCount + = 1 ;
dev - > EventQueueOverflowFlag = 1 ;
}
dev - > EventBuffer - > EventStatus & = ~ 0x80 ;
tasklet_schedule ( & dev - > event_tasklet ) ;
rc = IRQ_HANDLED ;
}
while ( i > 0 ) {
i - - ;
spin_lock ( & dev - > channel [ i ] . state_lock ) ;
/* if (dev->channel[i].State>=KSSTATE_RUN) { */
if ( dev - > channel [ i ] . nextBuffer ) {
if ( ( dev - > channel [ i ] . nextBuffer - >
ngeneBuffer . SR . Flags & 0xC0 ) = = 0x80 ) {
dev - > channel [ i ] . nextBuffer - >
ngeneBuffer . SR . Flags | = 0x40 ;
tasklet_schedule (
& dev - > channel [ i ] . demux_tasklet ) ;
rc = IRQ_HANDLED ;
}
}
spin_unlock ( & dev - > channel [ i ] . state_lock ) ;
}
2010-01-20 19:03:22 -03:00
/* Request might have been processed by a previous call. */
return IRQ_HANDLED ;
2009-12-18 22:13:26 -03:00
}
/****************************************************************************/
/* nGene command interface **************************************************/
/****************************************************************************/
2010-01-20 18:06:51 -03:00
static void dump_command_io ( struct ngene * dev )
{
2018-02-25 07:31:30 -05:00
struct device * pdev = & dev - > pci_dev - > dev ;
2010-01-20 18:06:51 -03:00
u8 buf [ 8 ] , * b ;
ngcpyfrom ( buf , HOST_TO_NGENE , 8 ) ;
2018-02-25 07:31:30 -05:00
dev_err ( pdev , " host_to_ngene (%04x): %*ph \n " , HOST_TO_NGENE , 8 , buf ) ;
2010-01-20 18:06:51 -03:00
ngcpyfrom ( buf , NGENE_TO_HOST , 8 ) ;
2018-02-25 07:31:30 -05:00
dev_err ( pdev , " ngene_to_host (%04x): %*ph \n " , NGENE_TO_HOST , 8 , buf ) ;
2010-01-20 18:06:51 -03:00
b = dev - > hosttongene ;
2018-02-25 07:31:30 -05:00
dev_err ( pdev , " dev->hosttongene (%p): %*ph \n " , b , 8 , b ) ;
2010-01-20 18:06:51 -03:00
b = dev - > ngenetohost ;
2018-02-25 07:31:30 -05:00
dev_err ( pdev , " dev->ngenetohost (%p): %*ph \n " , b , 8 , b ) ;
2010-01-20 18:06:51 -03:00
}
2009-12-18 22:13:26 -03:00
static int ngene_command_mutex ( struct ngene * dev , struct ngene_command * com )
{
2018-02-25 07:31:30 -05:00
struct device * pdev = & dev - > pci_dev - > dev ;
2009-12-18 22:13:26 -03:00
int ret ;
u8 * tmpCmdDoneByte ;
dev - > cmd_done = 0 ;
if ( com - > cmd . hdr . Opcode = = CMD_FWLOAD_PREPARE ) {
dev - > BootFirmware = 1 ;
dev - > icounts = ngreadl ( NGENE_INT_COUNTS ) ;
ngwritel ( 0 , NGENE_COMMAND ) ;
ngwritel ( 0 , NGENE_COMMAND_HI ) ;
ngwritel ( 0 , NGENE_STATUS ) ;
ngwritel ( 0 , NGENE_STATUS_HI ) ;
ngwritel ( 0 , NGENE_EVENT ) ;
ngwritel ( 0 , NGENE_EVENT_HI ) ;
} else if ( com - > cmd . hdr . Opcode = = CMD_FWLOAD_FINISH ) {
u64 fwio = dev - > PAFWInterfaceBuffer ;
ngwritel ( fwio & 0xffffffff , NGENE_COMMAND ) ;
ngwritel ( fwio > > 32 , NGENE_COMMAND_HI ) ;
ngwritel ( ( fwio + 256 ) & 0xffffffff , NGENE_STATUS ) ;
ngwritel ( ( fwio + 256 ) > > 32 , NGENE_STATUS_HI ) ;
ngwritel ( ( fwio + 512 ) & 0xffffffff , NGENE_EVENT ) ;
ngwritel ( ( fwio + 512 ) > > 32 , NGENE_EVENT_HI ) ;
}
memcpy ( dev - > FWInterfaceBuffer , com - > cmd . raw8 , com - > in_len + 2 ) ;
if ( dev - > BootFirmware )
ngcpyto ( HOST_TO_NGENE , com - > cmd . raw8 , com - > in_len + 2 ) ;
spin_lock_irq ( & dev - > cmd_lock ) ;
tmpCmdDoneByte = dev - > ngenetohost + com - > out_len ;
if ( ! com - > out_len )
tmpCmdDoneByte + + ;
* tmpCmdDoneByte = 0 ;
dev - > ngenetohost [ 0 ] = 0 ;
dev - > ngenetohost [ 1 ] = 0 ;
dev - > CmdDoneByte = tmpCmdDoneByte ;
spin_unlock_irq ( & dev - > cmd_lock ) ;
/* Notify 8051. */
ngwritel ( 1 , FORCE_INT ) ;
ret = wait_event_timeout ( dev - > cmd_wq , dev - > cmd_done = = 1 , 2 * HZ ) ;
if ( ! ret ) {
/*ngwritel(0, FORCE_NMI);*/
2018-02-25 07:31:30 -05:00
dev_err ( pdev , " Command timeout cmd=%02x prev=%02x \n " ,
com - > cmd . hdr . Opcode , dev - > prev_cmd ) ;
2010-01-20 18:06:51 -03:00
dump_command_io ( dev ) ;
2009-12-18 22:13:26 -03:00
return - 1 ;
}
if ( com - > cmd . hdr . Opcode = = CMD_FWLOAD_FINISH )
dev - > BootFirmware = 0 ;
dev - > prev_cmd = com - > cmd . hdr . Opcode ;
if ( ! com - > out_len )
return 0 ;
memcpy ( com - > cmd . raw8 , dev - > ngenetohost , com - > out_len ) ;
return 0 ;
}
2010-03-13 17:10:24 -03:00
int ngene_command ( struct ngene * dev , struct ngene_command * com )
2009-12-18 22:13:26 -03:00
{
int result ;
2017-06-13 05:58:48 -03:00
mutex_lock ( & dev - > cmd_mutex ) ;
2009-12-18 22:13:26 -03:00
result = ngene_command_mutex ( dev , com ) ;
2017-06-13 05:58:48 -03:00
mutex_unlock ( & dev - > cmd_mutex ) ;
2009-12-18 22:13:26 -03:00
return result ;
}
static int ngene_command_load_firmware ( struct ngene * dev ,
u8 * ngene_fw , u32 size )
{
# define FIRSTCHUNK (1024)
u32 cleft ;
struct ngene_command com ;
com . cmd . hdr . Opcode = CMD_FWLOAD_PREPARE ;
com . cmd . hdr . Length = 0 ;
com . in_len = 0 ;
com . out_len = 0 ;
ngene_command ( dev , & com ) ;
cleft = ( size + 3 ) & ~ 3 ;
if ( cleft > FIRSTCHUNK ) {
ngcpyto ( PROGRAM_SRAM + FIRSTCHUNK , ngene_fw + FIRSTCHUNK ,
cleft - FIRSTCHUNK ) ;
cleft = FIRSTCHUNK ;
}
ngcpyto ( DATA_FIFO_AREA , ngene_fw , cleft ) ;
memset ( & com , 0 , sizeof ( struct ngene_command ) ) ;
com . cmd . hdr . Opcode = CMD_FWLOAD_FINISH ;
com . cmd . hdr . Length = 4 ;
com . cmd . FWLoadFinish . Address = DATA_FIFO_AREA ;
com . cmd . FWLoadFinish . Length = ( unsigned short ) cleft ;
com . in_len = 4 ;
com . out_len = 0 ;
return ngene_command ( dev , & com ) ;
}
static int ngene_command_config_buf ( struct ngene * dev , u8 config )
{
struct ngene_command com ;
com . cmd . hdr . Opcode = CMD_CONFIGURE_BUFFER ;
com . cmd . hdr . Length = 1 ;
com . cmd . ConfigureBuffers . config = config ;
com . in_len = 1 ;
com . out_len = 0 ;
if ( ngene_command ( dev , & com ) < 0 )
return - EIO ;
return 0 ;
}
static int ngene_command_config_free_buf ( struct ngene * dev , u8 * config )
{
struct ngene_command com ;
com . cmd . hdr . Opcode = CMD_CONFIGURE_FREE_BUFFER ;
com . cmd . hdr . Length = 6 ;
memcpy ( & com . cmd . ConfigureBuffers . config , config , 6 ) ;
com . in_len = 6 ;
com . out_len = 0 ;
if ( ngene_command ( dev , & com ) < 0 )
return - EIO ;
return 0 ;
}
2010-03-13 17:10:24 -03:00
int ngene_command_gpio_set ( struct ngene * dev , u8 select , u8 level )
2009-12-18 22:13:26 -03:00
{
struct ngene_command com ;
com . cmd . hdr . Opcode = CMD_SET_GPIO_PIN ;
com . cmd . hdr . Length = 1 ;
com . cmd . SetGpioPin . select = select | ( level < < 7 ) ;
com . in_len = 1 ;
com . out_len = 0 ;
return ngene_command ( dev , & com ) ;
}
/*
02000640 is sample on rising edge .
02000740 is sample on falling edge .
02000040 is ignore " valid " signal
0 : FD_CTL1 Bit 7 , 6 must be 0 , 1
7 disable ( fw controlled )
6 0 - AUX , 1 - TS
5 0 - par , 1 - ser
4 0 - lsb / 1 - msb
3 , 2 reserved
1 , 0 0 - no sync , 1 - use ext . start , 2 - use 0x47 , 3 - both
1 : FD_CTL2 has 3 - valid must be hi , 2 - use valid , 1 - edge
2 : FD_STA is read - only . 0 - sync
3 : FD_INSYNC is number of 47 s to trigger " in sync " .
4 : FD_OUTSYNC is number of 47 s to trigger " out of sync " .
5 : FD_MAXBYTE1 is low - order of bytes per packet .
6 : FD_MAXBYTE2 is high - order of bytes per packet .
7 : Top byte is unused .
*/
/****************************************************************************/
2010-03-13 16:43:18 -03:00
static u8 TSFeatureDecoderSetup [ 8 * 5 ] = {
2009-12-18 22:13:26 -03:00
0x42 , 0x00 , 0x00 , 0x02 , 0x02 , 0xbc , 0x00 , 0x00 ,
0x40 , 0x06 , 0x00 , 0x02 , 0x02 , 0xbc , 0x00 , 0x00 , /* DRXH */
0x71 , 0x07 , 0x00 , 0x02 , 0x02 , 0xbc , 0x00 , 0x00 , /* DRXHser */
2011-07-03 13:55:06 -03:00
0x72 , 0x00 , 0x00 , 0x02 , 0x02 , 0xbc , 0x00 , 0x00 , /* S2ser */
2010-03-13 16:43:18 -03:00
0x40 , 0x07 , 0x00 , 0x02 , 0x02 , 0xbc , 0x00 , 0x00 , /* LGDT3303 */
2009-12-18 22:13:26 -03:00
} ;
/* Set NGENE I2S Config to 16 bit packed */
static u8 I2SConfiguration [ ] = {
0x00 , 0x10 , 0x00 , 0x00 ,
0x80 , 0x10 , 0x00 , 0x00 ,
} ;
static u8 SPDIFConfiguration [ 10 ] = {
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00
} ;
/* Set NGENE I2S Config to transport stream compatible mode */
2011-01-10 06:36:12 -03:00
static u8 TS_I2SConfiguration [ 4 ] = { 0x3E , 0x18 , 0x00 , 0x00 } ;
2009-12-18 22:13:26 -03:00
2011-01-10 06:36:15 -03:00
static u8 TS_I2SOutConfiguration [ 4 ] = { 0x80 , 0x04 , 0x00 , 0x00 } ;
2009-12-18 22:13:26 -03:00
static u8 ITUDecoderSetup [ 4 ] [ 16 ] = {
{ 0x1c , 0x13 , 0x01 , 0x68 , 0x3d , 0x90 , 0x14 , 0x20 , /* SDTV */
0x00 , 0x00 , 0x01 , 0xb0 , 0x9c , 0x00 , 0x00 , 0x00 } ,
{ 0x9c , 0x03 , 0x23 , 0xC0 , 0x60 , 0x0E , 0x13 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x01 , 0xB0 , 0x00 , 0x00 , 0x00 } ,
{ 0x9f , 0x00 , 0x23 , 0xC0 , 0x60 , 0x0F , 0x13 , 0x00 , /* HDTV 1080i50 */
0x00 , 0x00 , 0x00 , 0x01 , 0xB0 , 0x00 , 0x00 , 0x00 } ,
{ 0x9c , 0x01 , 0x23 , 0xC0 , 0x60 , 0x0E , 0x13 , 0x00 , /* HDTV 1080i60 */
0x00 , 0x00 , 0x00 , 0x01 , 0xB0 , 0x00 , 0x00 , 0x00 } ,
} ;
/*
* 50 48 60 gleich
* 27 p50 9f 00 22 80 42 69 18 . . .
* 27 p60 93 00 22 80 82 69 1 c . . .
*/
/* Maxbyte to 1144 (for raw data) */
static u8 ITUFeatureDecoderSetup [ 8 ] = {
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x78 , 0x04 , 0x00
} ;
2010-03-13 23:10:13 -03:00
void FillTSBuffer ( void * Buffer , int Length , u32 Flags )
2009-12-18 22:13:26 -03:00
{
u32 * ptr = Buffer ;
2011-07-03 14:04:46 -03:00
memset ( Buffer , TS_FILLER , Length ) ;
2009-12-18 22:13:26 -03:00
while ( Length > 0 ) {
if ( Flags & DF_SWAP32 )
* ptr = 0x471FFF10 ;
else
* ptr = 0x10FF1F47 ;
ptr + = ( 188 / 4 ) ;
Length - = 188 ;
}
}
static void flush_buffers ( struct ngene_channel * chan )
{
u8 val ;
do {
msleep ( 1 ) ;
spin_lock_irq ( & chan - > state_lock ) ;
val = chan - > nextBuffer - > ngeneBuffer . SR . Flags & 0x80 ;
spin_unlock_irq ( & chan - > state_lock ) ;
} while ( val ) ;
}
static void clear_buffers ( struct ngene_channel * chan )
{
struct SBufferHeader * Cur = chan - > nextBuffer ;
do {
memset ( & Cur - > ngeneBuffer . SR , 0 , sizeof ( Cur - > ngeneBuffer . SR ) ) ;
if ( chan - > mode & NGENE_IO_TSOUT )
FillTSBuffer ( Cur - > Buffer1 ,
chan - > Capture1Length ,
chan - > DataFormatFlags ) ;
Cur = Cur - > Next ;
} while ( Cur ! = chan - > nextBuffer ) ;
if ( chan - > mode & NGENE_IO_TSOUT ) {
chan - > nextBuffer - > ngeneBuffer . SR . DTOUpdate =
chan - > AudioDTOValue ;
chan - > AudioDTOUpdated = 0 ;
Cur = chan - > TSIdleBuffer . Head ;
do {
memset ( & Cur - > ngeneBuffer . SR , 0 ,
sizeof ( Cur - > ngeneBuffer . SR ) ) ;
FillTSBuffer ( Cur - > Buffer1 ,
chan - > Capture1Length ,
chan - > DataFormatFlags ) ;
Cur = Cur - > Next ;
} while ( Cur ! = chan - > TSIdleBuffer . Head ) ;
}
}
2009-12-23 16:26:17 -03:00
static int ngene_command_stream_control ( struct ngene * dev , u8 stream ,
u8 control , u8 mode , u8 flags )
2009-12-18 22:13:26 -03:00
{
2018-02-25 07:31:30 -05:00
struct device * pdev = & dev - > pci_dev - > dev ;
2009-12-18 22:13:26 -03:00
struct ngene_channel * chan = & dev - > channel [ stream ] ;
struct ngene_command com ;
u16 BsUVI = ( ( stream & 1 ) ? 0x9400 : 0x9300 ) ;
u16 BsSDI = ( ( stream & 1 ) ? 0x9600 : 0x9500 ) ;
u16 BsSPI = ( ( stream & 1 ) ? 0x9800 : 0x9700 ) ;
u16 BsSDO = 0x9B00 ;
memset ( & com , 0 , sizeof ( com ) ) ;
com . cmd . hdr . Opcode = CMD_CONTROL ;
com . cmd . hdr . Length = sizeof ( struct FW_STREAM_CONTROL ) - 2 ;
com . cmd . StreamControl . Stream = stream | ( control ? 8 : 0 ) ;
if ( chan - > mode & NGENE_IO_TSOUT )
com . cmd . StreamControl . Stream | = 0x07 ;
com . cmd . StreamControl . Control = control |
( flags & SFLAG_ORDER_LUMA_CHROMA ) ;
com . cmd . StreamControl . Mode = mode ;
com . in_len = sizeof ( struct FW_STREAM_CONTROL ) ;
com . out_len = 0 ;
2018-02-25 07:31:30 -05:00
dev_dbg ( pdev , " Stream=%02x, Control=%02x, Mode=%02x \n " ,
2009-12-20 02:30:52 -03:00
com . cmd . StreamControl . Stream , com . cmd . StreamControl . Control ,
com . cmd . StreamControl . Mode ) ;
2009-12-18 22:13:26 -03:00
chan - > Mode = mode ;
if ( ! ( control & 0x80 ) ) {
spin_lock_irq ( & chan - > state_lock ) ;
if ( chan - > State = = KSSTATE_RUN ) {
chan - > State = KSSTATE_ACQUIRE ;
chan - > HWState = HWSTATE_STOP ;
spin_unlock_irq ( & chan - > state_lock ) ;
2017-06-13 05:58:49 -03:00
if ( ngene_command ( dev , & com ) < 0 )
2009-12-18 22:13:26 -03:00
return - 1 ;
/* clear_buffers(chan); */
flush_buffers ( chan ) ;
return 0 ;
}
spin_unlock_irq ( & chan - > state_lock ) ;
return 0 ;
}
if ( mode & SMODE_AUDIO_CAPTURE ) {
com . cmd . StreamControl . CaptureBlockCount =
chan - > Capture1Length / AUDIO_BLOCK_SIZE ;
com . cmd . StreamControl . Buffer_Address = chan - > RingBuffer . PAHead ;
} else if ( mode & SMODE_TRANSPORT_STREAM ) {
com . cmd . StreamControl . CaptureBlockCount =
chan - > Capture1Length / TS_BLOCK_SIZE ;
com . cmd . StreamControl . MaxLinesPerField =
chan - > Capture1Length / TS_BLOCK_SIZE ;
com . cmd . StreamControl . Buffer_Address =
chan - > TSRingBuffer . PAHead ;
if ( chan - > mode & NGENE_IO_TSOUT ) {
com . cmd . StreamControl . BytesPerVBILine =
chan - > Capture1Length / TS_BLOCK_SIZE ;
com . cmd . StreamControl . Stream | = 0x07 ;
}
} else {
com . cmd . StreamControl . BytesPerVideoLine = chan - > nBytesPerLine ;
com . cmd . StreamControl . MaxLinesPerField = chan - > nLines ;
com . cmd . StreamControl . MinLinesPerField = 100 ;
com . cmd . StreamControl . Buffer_Address = chan - > RingBuffer . PAHead ;
if ( mode & SMODE_VBI_CAPTURE ) {
com . cmd . StreamControl . MaxVBILinesPerField =
chan - > nVBILines ;
com . cmd . StreamControl . MinVBILinesPerField = 0 ;
com . cmd . StreamControl . BytesPerVBILine =
chan - > nBytesPerVBILine ;
}
if ( flags & SFLAG_COLORBAR )
com . cmd . StreamControl . Stream | = 0x04 ;
}
spin_lock_irq ( & chan - > state_lock ) ;
if ( mode & SMODE_AUDIO_CAPTURE ) {
chan - > nextBuffer = chan - > RingBuffer . Head ;
if ( mode & SMODE_AUDIO_SPDIF ) {
com . cmd . StreamControl . SetupDataLen =
sizeof ( SPDIFConfiguration ) ;
com . cmd . StreamControl . SetupDataAddr = BsSPI ;
memcpy ( com . cmd . StreamControl . SetupData ,
SPDIFConfiguration , sizeof ( SPDIFConfiguration ) ) ;
} else {
com . cmd . StreamControl . SetupDataLen = 4 ;
com . cmd . StreamControl . SetupDataAddr = BsSDI ;
memcpy ( com . cmd . StreamControl . SetupData ,
I2SConfiguration +
4 * dev - > card_info - > i2s [ stream ] , 4 ) ;
}
} else if ( mode & SMODE_TRANSPORT_STREAM ) {
chan - > nextBuffer = chan - > TSRingBuffer . Head ;
if ( stream > = STREAM_AUDIOIN1 ) {
if ( chan - > mode & NGENE_IO_TSOUT ) {
com . cmd . StreamControl . SetupDataLen =
sizeof ( TS_I2SOutConfiguration ) ;
com . cmd . StreamControl . SetupDataAddr = BsSDO ;
memcpy ( com . cmd . StreamControl . SetupData ,
TS_I2SOutConfiguration ,
sizeof ( TS_I2SOutConfiguration ) ) ;
} else {
com . cmd . StreamControl . SetupDataLen =
sizeof ( TS_I2SConfiguration ) ;
com . cmd . StreamControl . SetupDataAddr = BsSDI ;
memcpy ( com . cmd . StreamControl . SetupData ,
TS_I2SConfiguration ,
sizeof ( TS_I2SConfiguration ) ) ;
}
} else {
com . cmd . StreamControl . SetupDataLen = 8 ;
com . cmd . StreamControl . SetupDataAddr = BsUVI + 0x10 ;
memcpy ( com . cmd . StreamControl . SetupData ,
TSFeatureDecoderSetup +
8 * dev - > card_info - > tsf [ stream ] , 8 ) ;
}
} else {
chan - > nextBuffer = chan - > RingBuffer . Head ;
com . cmd . StreamControl . SetupDataLen =
16 + sizeof ( ITUFeatureDecoderSetup ) ;
com . cmd . StreamControl . SetupDataAddr = BsUVI ;
memcpy ( com . cmd . StreamControl . SetupData ,
ITUDecoderSetup [ chan - > itumode ] , 16 ) ;
memcpy ( com . cmd . StreamControl . SetupData + 16 ,
ITUFeatureDecoderSetup , sizeof ( ITUFeatureDecoderSetup ) ) ;
}
clear_buffers ( chan ) ;
chan - > State = KSSTATE_RUN ;
if ( mode & SMODE_TRANSPORT_STREAM )
chan - > HWState = HWSTATE_RUN ;
else
chan - > HWState = HWSTATE_STARTUP ;
spin_unlock_irq ( & chan - > state_lock ) ;
2017-06-13 05:58:49 -03:00
if ( ngene_command ( dev , & com ) < 0 )
2009-12-18 22:13:26 -03:00
return - 1 ;
2017-06-13 05:58:49 -03:00
2009-12-18 22:13:26 -03:00
return 0 ;
}
2010-03-13 23:10:13 -03:00
void set_transfer ( struct ngene_channel * chan , int state )
2009-12-18 22:13:26 -03:00
{
2018-02-25 07:31:30 -05:00
struct device * pdev = & chan - > dev - > pci_dev - > dev ;
2009-12-18 22:13:26 -03:00
u8 control = 0 , mode = 0 , flags = 0 ;
struct ngene * dev = chan - > dev ;
int ret ;
/*
2018-02-25 07:31:30 -05:00
dev_info ( pdev , " st %d \n " , state ) ;
2009-12-18 22:13:26 -03:00
msleep ( 100 ) ;
*/
if ( state ) {
if ( chan - > running ) {
2018-02-25 07:31:30 -05:00
dev_info ( pdev , " already running \n " ) ;
2009-12-18 22:13:26 -03:00
return ;
}
} else {
if ( ! chan - > running ) {
2018-02-25 07:31:30 -05:00
dev_info ( pdev , " already stopped \n " ) ;
2009-12-18 22:13:26 -03:00
return ;
}
}
if ( dev - > card_info - > switch_ctrl )
dev - > card_info - > switch_ctrl ( chan , 1 , state ^ 1 ) ;
if ( state ) {
spin_lock_irq ( & chan - > state_lock ) ;
2018-02-25 07:31:30 -05:00
/* dev_info(pdev, "lock=%08x\n",
2009-12-18 22:13:26 -03:00
ngreadl ( 0x9310 ) ) ; */
2009-12-22 04:37:53 -03:00
dvb_ringbuffer_flush ( & dev - > tsout_rbuf ) ;
2009-12-18 22:13:26 -03:00
control = 0x80 ;
if ( chan - > mode & ( NGENE_IO_TSIN | NGENE_IO_TSOUT ) ) {
chan - > Capture1Length = 512 * 188 ;
mode = SMODE_TRANSPORT_STREAM ;
}
if ( chan - > mode & NGENE_IO_TSOUT ) {
chan - > pBufferExchange = tsout_exchange ;
/* 0x66666666 = 50MHz *2^33 /250MHz */
2011-01-10 06:36:15 -03:00
chan - > AudioDTOValue = 0x80000000 ;
chan - > AudioDTOUpdated = 1 ;
2009-12-18 22:13:26 -03:00
}
if ( chan - > mode & NGENE_IO_TSIN )
chan - > pBufferExchange = tsin_exchange ;
spin_unlock_irq ( & chan - > state_lock ) ;
2012-10-27 16:17:39 -03:00
}
2018-02-25 07:31:30 -05:00
/* else dev_info(pdev, "lock=%08x\n",
2009-12-18 22:13:26 -03:00
ngreadl ( 0x9310 ) ) ; */
2017-06-13 05:58:49 -03:00
mutex_lock ( & dev - > stream_mutex ) ;
2009-12-18 22:13:26 -03:00
ret = ngene_command_stream_control ( dev , chan - > number ,
control , mode , flags ) ;
2017-06-13 05:58:49 -03:00
mutex_unlock ( & dev - > stream_mutex ) ;
2009-12-18 22:13:26 -03:00
if ( ! ret )
chan - > running = state ;
else
2018-02-25 07:31:30 -05:00
dev_err ( pdev , " %s %d failed \n " , __func__ , state ) ;
2009-12-18 22:13:26 -03:00
if ( ! state ) {
spin_lock_irq ( & chan - > state_lock ) ;
2010-02-28 11:34:35 -03:00
chan - > pBufferExchange = NULL ;
2009-12-22 04:37:53 -03:00
dvb_ringbuffer_flush ( & dev - > tsout_rbuf ) ;
2009-12-18 22:13:26 -03:00
spin_unlock_irq ( & chan - > state_lock ) ;
}
}
/****************************************************************************/
/* nGene hardware init and release functions ********************************/
/****************************************************************************/
2009-12-23 16:26:17 -03:00
static void free_ringbuffer ( struct ngene * dev , struct SRingBufferDescriptor * rb )
2009-12-18 22:13:26 -03:00
{
struct SBufferHeader * Cur = rb - > Head ;
u32 j ;
if ( ! Cur )
return ;
for ( j = 0 ; j < rb - > NumBuffers ; j + + , Cur = Cur - > Next ) {
if ( Cur - > Buffer1 )
pci_free_consistent ( dev - > pci_dev ,
rb - > Buffer1Length ,
Cur - > Buffer1 ,
Cur - > scList1 - > Address ) ;
if ( Cur - > Buffer2 )
pci_free_consistent ( dev - > pci_dev ,
rb - > Buffer2Length ,
Cur - > Buffer2 ,
Cur - > scList2 - > Address ) ;
}
if ( rb - > SCListMem )
pci_free_consistent ( dev - > pci_dev , rb - > SCListMemSize ,
rb - > SCListMem , rb - > PASCListMem ) ;
pci_free_consistent ( dev - > pci_dev , rb - > MemSize , rb - > Head , rb - > PAHead ) ;
}
2009-12-23 16:26:17 -03:00
static void free_idlebuffer ( struct ngene * dev ,
2009-12-18 22:13:26 -03:00
struct SRingBufferDescriptor * rb ,
struct SRingBufferDescriptor * tb )
{
int j ;
struct SBufferHeader * Cur = tb - > Head ;
if ( ! rb - > Head )
return ;
free_ringbuffer ( dev , rb ) ;
for ( j = 0 ; j < tb - > NumBuffers ; j + + , Cur = Cur - > Next ) {
2010-02-28 11:34:35 -03:00
Cur - > Buffer2 = NULL ;
Cur - > scList2 = NULL ;
2009-12-18 22:13:26 -03:00
Cur - > ngeneBuffer . Address_of_first_entry_2 = 0 ;
Cur - > ngeneBuffer . Number_of_entries_2 = 0 ;
}
}
2009-12-23 16:26:17 -03:00
static void free_common_buffers ( struct ngene * dev )
2009-12-18 22:13:26 -03:00
{
u32 i ;
struct ngene_channel * chan ;
for ( i = STREAM_VIDEOIN1 ; i < MAX_STREAM ; i + + ) {
chan = & dev - > channel [ i ] ;
free_idlebuffer ( dev , & chan - > TSIdleBuffer , & chan - > TSRingBuffer ) ;
free_ringbuffer ( dev , & chan - > RingBuffer ) ;
free_ringbuffer ( dev , & chan - > TSRingBuffer ) ;
}
if ( dev - > OverflowBuffer )
pci_free_consistent ( dev - > pci_dev ,
OVERFLOW_BUFFER_SIZE ,
dev - > OverflowBuffer , dev - > PAOverflowBuffer ) ;
if ( dev - > FWInterfaceBuffer )
pci_free_consistent ( dev - > pci_dev ,
4096 ,
dev - > FWInterfaceBuffer ,
dev - > PAFWInterfaceBuffer ) ;
}
/****************************************************************************/
/* Ring buffer handling *****************************************************/
/****************************************************************************/
2009-12-23 16:26:17 -03:00
static int create_ring_buffer ( struct pci_dev * pci_dev ,
2009-12-18 22:13:26 -03:00
struct SRingBufferDescriptor * descr , u32 NumBuffers )
{
dma_addr_t tmp ;
struct SBufferHeader * Head ;
u32 i ;
u32 MemSize = SIZEOF_SBufferHeader * NumBuffers ;
u64 PARingBufferHead ;
u64 PARingBufferCur ;
u64 PARingBufferNext ;
struct SBufferHeader * Cur , * Next ;
2010-02-28 11:34:35 -03:00
descr - > Head = NULL ;
2009-12-18 22:13:26 -03:00
descr - > MemSize = 0 ;
descr - > PAHead = 0 ;
descr - > NumBuffers = 0 ;
if ( MemSize < 4096 )
MemSize = 4096 ;
Head = pci_alloc_consistent ( pci_dev , MemSize , & tmp ) ;
PARingBufferHead = tmp ;
if ( ! Head )
return - ENOMEM ;
memset ( Head , 0 , MemSize ) ;
PARingBufferCur = PARingBufferHead ;
Cur = Head ;
for ( i = 0 ; i < NumBuffers - 1 ; i + + ) {
Next = ( struct SBufferHeader * )
( ( ( u8 * ) Cur ) + SIZEOF_SBufferHeader ) ;
PARingBufferNext = PARingBufferCur + SIZEOF_SBufferHeader ;
Cur - > Next = Next ;
Cur - > ngeneBuffer . Next = PARingBufferNext ;
Cur = Next ;
PARingBufferCur = PARingBufferNext ;
}
/* Last Buffer points back to first one */
Cur - > Next = Head ;
Cur - > ngeneBuffer . Next = PARingBufferHead ;
descr - > Head = Head ;
descr - > MemSize = MemSize ;
descr - > PAHead = PARingBufferHead ;
descr - > NumBuffers = NumBuffers ;
return 0 ;
}
static int AllocateRingBuffers ( struct pci_dev * pci_dev ,
dma_addr_t of ,
struct SRingBufferDescriptor * pRingBuffer ,
u32 Buffer1Length , u32 Buffer2Length )
{
dma_addr_t tmp ;
u32 i , j ;
u32 SCListMemSize = pRingBuffer - > NumBuffers
* ( ( Buffer2Length ! = 0 ) ? ( NUM_SCATTER_GATHER_ENTRIES * 2 ) :
NUM_SCATTER_GATHER_ENTRIES )
* sizeof ( struct HW_SCATTER_GATHER_ELEMENT ) ;
u64 PASCListMem ;
2010-02-03 18:59:20 -03:00
struct HW_SCATTER_GATHER_ELEMENT * SCListEntry ;
2009-12-18 22:13:26 -03:00
u64 PASCListEntry ;
struct SBufferHeader * Cur ;
void * SCListMem ;
if ( SCListMemSize < 4096 )
SCListMemSize = 4096 ;
SCListMem = pci_alloc_consistent ( pci_dev , SCListMemSize , & tmp ) ;
PASCListMem = tmp ;
if ( SCListMem = = NULL )
return - ENOMEM ;
memset ( SCListMem , 0 , SCListMemSize ) ;
pRingBuffer - > SCListMem = SCListMem ;
pRingBuffer - > PASCListMem = PASCListMem ;
pRingBuffer - > SCListMemSize = SCListMemSize ;
pRingBuffer - > Buffer1Length = Buffer1Length ;
pRingBuffer - > Buffer2Length = Buffer2Length ;
2010-02-03 18:59:20 -03:00
SCListEntry = SCListMem ;
2009-12-18 22:13:26 -03:00
PASCListEntry = PASCListMem ;
Cur = pRingBuffer - > Head ;
for ( i = 0 ; i < pRingBuffer - > NumBuffers ; i + = 1 , Cur = Cur - > Next ) {
u64 PABuffer ;
void * Buffer = pci_alloc_consistent ( pci_dev , Buffer1Length ,
& tmp ) ;
PABuffer = tmp ;
if ( Buffer = = NULL )
return - ENOMEM ;
Cur - > Buffer1 = Buffer ;
SCListEntry - > Address = PABuffer ;
SCListEntry - > Length = Buffer1Length ;
Cur - > scList1 = SCListEntry ;
Cur - > ngeneBuffer . Address_of_first_entry_1 = PASCListEntry ;
Cur - > ngeneBuffer . Number_of_entries_1 =
NUM_SCATTER_GATHER_ENTRIES ;
SCListEntry + = 1 ;
PASCListEntry + = sizeof ( struct HW_SCATTER_GATHER_ELEMENT ) ;
# if NUM_SCATTER_GATHER_ENTRIES > 1
for ( j = 0 ; j < NUM_SCATTER_GATHER_ENTRIES - 1 ; j + = 1 ) {
SCListEntry - > Address = of ;
SCListEntry - > Length = OVERFLOW_BUFFER_SIZE ;
SCListEntry + = 1 ;
PASCListEntry + =
sizeof ( struct HW_SCATTER_GATHER_ELEMENT ) ;
}
# endif
if ( ! Buffer2Length )
continue ;
Buffer = pci_alloc_consistent ( pci_dev , Buffer2Length , & tmp ) ;
PABuffer = tmp ;
if ( Buffer = = NULL )
return - ENOMEM ;
Cur - > Buffer2 = Buffer ;
SCListEntry - > Address = PABuffer ;
SCListEntry - > Length = Buffer2Length ;
Cur - > scList2 = SCListEntry ;
Cur - > ngeneBuffer . Address_of_first_entry_2 = PASCListEntry ;
Cur - > ngeneBuffer . Number_of_entries_2 =
NUM_SCATTER_GATHER_ENTRIES ;
SCListEntry + = 1 ;
PASCListEntry + = sizeof ( struct HW_SCATTER_GATHER_ELEMENT ) ;
# if NUM_SCATTER_GATHER_ENTRIES > 1
for ( j = 0 ; j < NUM_SCATTER_GATHER_ENTRIES - 1 ; j + + ) {
SCListEntry - > Address = of ;
SCListEntry - > Length = OVERFLOW_BUFFER_SIZE ;
SCListEntry + = 1 ;
PASCListEntry + =
sizeof ( struct HW_SCATTER_GATHER_ELEMENT ) ;
}
# endif
}
2014-05-31 13:30:52 -03:00
return 0 ;
2009-12-18 22:13:26 -03:00
}
static int FillTSIdleBuffer ( struct SRingBufferDescriptor * pIdleBuffer ,
struct SRingBufferDescriptor * pRingBuffer )
{
/* Copy pointer to scatter gather list in TSRingbuffer
structure for buffer 2
Load number of buffer
*/
u32 n = pRingBuffer - > NumBuffers ;
/* Point to first buffer entry */
struct SBufferHeader * Cur = pRingBuffer - > Head ;
int i ;
/* Loop thru all buffer and set Buffer 2 pointers to TSIdlebuffer */
for ( i = 0 ; i < n ; i + + ) {
Cur - > Buffer2 = pIdleBuffer - > Head - > Buffer1 ;
Cur - > scList2 = pIdleBuffer - > Head - > scList1 ;
Cur - > ngeneBuffer . Address_of_first_entry_2 =
pIdleBuffer - > Head - > ngeneBuffer .
Address_of_first_entry_1 ;
Cur - > ngeneBuffer . Number_of_entries_2 =
pIdleBuffer - > Head - > ngeneBuffer . Number_of_entries_1 ;
Cur = Cur - > Next ;
}
2014-05-31 13:30:52 -03:00
return 0 ;
2009-12-18 22:13:26 -03:00
}
static u32 RingBufferSizes [ MAX_STREAM ] = {
RING_SIZE_VIDEO ,
RING_SIZE_VIDEO ,
RING_SIZE_AUDIO ,
RING_SIZE_AUDIO ,
RING_SIZE_AUDIO ,
} ;
static u32 Buffer1Sizes [ MAX_STREAM ] = {
MAX_VIDEO_BUFFER_SIZE ,
MAX_VIDEO_BUFFER_SIZE ,
MAX_AUDIO_BUFFER_SIZE ,
MAX_AUDIO_BUFFER_SIZE ,
MAX_AUDIO_BUFFER_SIZE
} ;
static u32 Buffer2Sizes [ MAX_STREAM ] = {
MAX_VBI_BUFFER_SIZE ,
MAX_VBI_BUFFER_SIZE ,
0 ,
0 ,
0
} ;
static int AllocCommonBuffers ( struct ngene * dev )
{
int status = 0 , i ;
dev - > FWInterfaceBuffer = pci_alloc_consistent ( dev - > pci_dev , 4096 ,
& dev - > PAFWInterfaceBuffer ) ;
if ( ! dev - > FWInterfaceBuffer )
return - ENOMEM ;
dev - > hosttongene = dev - > FWInterfaceBuffer ;
dev - > ngenetohost = dev - > FWInterfaceBuffer + 256 ;
dev - > EventBuffer = dev - > FWInterfaceBuffer + 512 ;
2014-08-08 14:24:21 -07:00
dev - > OverflowBuffer = pci_zalloc_consistent ( dev - > pci_dev ,
OVERFLOW_BUFFER_SIZE ,
& dev - > PAOverflowBuffer ) ;
2009-12-18 22:13:26 -03:00
if ( ! dev - > OverflowBuffer )
return - ENOMEM ;
for ( i = STREAM_VIDEOIN1 ; i < MAX_STREAM ; i + + ) {
int type = dev - > card_info - > io_type [ i ] ;
dev - > channel [ i ] . State = KSSTATE_STOP ;
if ( type & ( NGENE_IO_TV | NGENE_IO_HDTV | NGENE_IO_AIN ) ) {
status = create_ring_buffer ( dev - > pci_dev ,
& dev - > channel [ i ] . RingBuffer ,
RingBufferSizes [ i ] ) ;
if ( status < 0 )
break ;
if ( type & ( NGENE_IO_TV | NGENE_IO_AIN ) ) {
status = AllocateRingBuffers ( dev - > pci_dev ,
dev - >
PAOverflowBuffer ,
& dev - > channel [ i ] .
RingBuffer ,
Buffer1Sizes [ i ] ,
Buffer2Sizes [ i ] ) ;
if ( status < 0 )
break ;
} else if ( type & NGENE_IO_HDTV ) {
status = AllocateRingBuffers ( dev - > pci_dev ,
dev - >
PAOverflowBuffer ,
& dev - > channel [ i ] .
RingBuffer ,
MAX_HDTV_BUFFER_SIZE ,
0 ) ;
if ( status < 0 )
break ;
}
}
if ( type & ( NGENE_IO_TSIN | NGENE_IO_TSOUT ) ) {
status = create_ring_buffer ( dev - > pci_dev ,
& dev - > channel [ i ] .
TSRingBuffer , RING_SIZE_TS ) ;
if ( status < 0 )
break ;
status = AllocateRingBuffers ( dev - > pci_dev ,
dev - > PAOverflowBuffer ,
& dev - > channel [ i ] .
TSRingBuffer ,
MAX_TS_BUFFER_SIZE , 0 ) ;
if ( status )
break ;
}
if ( type & NGENE_IO_TSOUT ) {
status = create_ring_buffer ( dev - > pci_dev ,
& dev - > channel [ i ] .
TSIdleBuffer , 1 ) ;
if ( status < 0 )
break ;
status = AllocateRingBuffers ( dev - > pci_dev ,
dev - > PAOverflowBuffer ,
& dev - > channel [ i ] .
TSIdleBuffer ,
MAX_TS_BUFFER_SIZE , 0 ) ;
if ( status )
break ;
FillTSIdleBuffer ( & dev - > channel [ i ] . TSIdleBuffer ,
& dev - > channel [ i ] . TSRingBuffer ) ;
}
}
return status ;
}
static void ngene_release_buffers ( struct ngene * dev )
{
if ( dev - > iomem )
iounmap ( dev - > iomem ) ;
free_common_buffers ( dev ) ;
vfree ( dev - > tsout_buf ) ;
2011-01-10 06:36:15 -03:00
vfree ( dev - > tsin_buf ) ;
2009-12-18 22:13:26 -03:00
vfree ( dev - > ain_buf ) ;
vfree ( dev - > vin_buf ) ;
vfree ( dev ) ;
}
static int ngene_get_buffers ( struct ngene * dev )
{
if ( AllocCommonBuffers ( dev ) )
return - ENOMEM ;
if ( dev - > card_info - > io_type [ 4 ] & NGENE_IO_TSOUT ) {
dev - > tsout_buf = vmalloc ( TSOUT_BUF_SIZE ) ;
if ( ! dev - > tsout_buf )
return - ENOMEM ;
dvb_ringbuffer_init ( & dev - > tsout_rbuf ,
dev - > tsout_buf , TSOUT_BUF_SIZE ) ;
}
2011-01-10 06:36:15 -03:00
if ( dev - > card_info - > io_type [ 2 ] & NGENE_IO_TSIN ) {
dev - > tsin_buf = vmalloc ( TSIN_BUF_SIZE ) ;
if ( ! dev - > tsin_buf )
return - ENOMEM ;
dvb_ringbuffer_init ( & dev - > tsin_rbuf ,
dev - > tsin_buf , TSIN_BUF_SIZE ) ;
}
2009-12-18 22:13:26 -03:00
if ( dev - > card_info - > io_type [ 2 ] & NGENE_IO_AIN ) {
dev - > ain_buf = vmalloc ( AIN_BUF_SIZE ) ;
if ( ! dev - > ain_buf )
return - ENOMEM ;
dvb_ringbuffer_init ( & dev - > ain_rbuf , dev - > ain_buf , AIN_BUF_SIZE ) ;
}
if ( dev - > card_info - > io_type [ 0 ] & NGENE_IO_HDTV ) {
dev - > vin_buf = vmalloc ( VIN_BUF_SIZE ) ;
if ( ! dev - > vin_buf )
return - ENOMEM ;
dvb_ringbuffer_init ( & dev - > vin_rbuf , dev - > vin_buf , VIN_BUF_SIZE ) ;
}
dev - > iomem = ioremap ( pci_resource_start ( dev - > pci_dev , 0 ) ,
pci_resource_len ( dev - > pci_dev , 0 ) ) ;
if ( ! dev - > iomem )
return - ENOMEM ;
return 0 ;
}
static void ngene_init ( struct ngene * dev )
{
2018-02-25 07:31:30 -05:00
struct device * pdev = & dev - > pci_dev - > dev ;
2009-12-18 22:13:26 -03:00
int i ;
tasklet_init ( & dev - > event_tasklet , event_tasklet , ( unsigned long ) dev ) ;
memset_io ( dev - > iomem + 0xc000 , 0x00 , 0x220 ) ;
memset_io ( dev - > iomem + 0xc400 , 0x00 , 0x100 ) ;
for ( i = 0 ; i < MAX_STREAM ; i + + ) {
dev - > channel [ i ] . dev = dev ;
dev - > channel [ i ] . number = i ;
}
dev - > fw_interface_version = 0 ;
ngwritel ( 0 , NGENE_INT_ENABLE ) ;
dev - > icounts = ngreadl ( NGENE_INT_COUNTS ) ;
dev - > device_version = ngreadl ( DEV_VER ) & 0x0f ;
2018-02-25 07:31:30 -05:00
dev_info ( pdev , " Device version %d \n " , dev - > device_version ) ;
2009-12-18 22:13:26 -03:00
}
static int ngene_load_firm ( struct ngene * dev )
{
2018-02-25 07:31:30 -05:00
struct device * pdev = & dev - > pci_dev - > dev ;
2009-12-18 22:13:26 -03:00
u32 size ;
const struct firmware * fw = NULL ;
u8 * ngene_fw ;
char * fw_name ;
int err , version ;
version = dev - > card_info - > fw_version ;
switch ( version ) {
default :
case 15 :
version = 15 ;
2009-12-19 06:38:05 -03:00
size = 23466 ;
2009-12-18 22:13:26 -03:00
fw_name = " ngene_15.fw " ;
2010-05-16 06:07:07 -03:00
dev - > cmd_timeout_workaround = true ;
2009-12-18 22:13:26 -03:00
break ;
case 16 :
2009-12-19 06:38:05 -03:00
size = 23498 ;
2009-12-18 22:13:26 -03:00
fw_name = " ngene_16.fw " ;
2010-05-16 06:07:07 -03:00
dev - > cmd_timeout_workaround = true ;
2009-12-18 22:13:26 -03:00
break ;
case 17 :
2009-12-19 06:38:05 -03:00
size = 24446 ;
2009-12-18 22:13:26 -03:00
fw_name = " ngene_17.fw " ;
2010-05-16 06:07:07 -03:00
dev - > cmd_timeout_workaround = true ;
2009-12-18 22:13:26 -03:00
break ;
2011-01-10 06:36:11 -03:00
case 18 :
size = 0 ;
fw_name = " ngene_18.fw " ;
break ;
2009-12-18 22:13:26 -03:00
}
if ( request_firmware ( & fw , fw_name , & dev - > pci_dev - > dev ) < 0 ) {
2018-02-25 07:31:30 -05:00
dev_err ( pdev , " Could not load firmware file %s. \n " , fw_name ) ;
dev_info ( pdev , " Copy %s to your hotplug directory! \n " ,
fw_name ) ;
2009-12-18 22:13:26 -03:00
return - 1 ;
}
2011-01-10 06:36:11 -03:00
if ( size = = 0 )
size = fw - > size ;
2009-12-19 06:38:05 -03:00
if ( size ! = fw - > size ) {
2018-02-25 07:31:30 -05:00
dev_err ( pdev , " Firmware %s has invalid size! " , fw_name ) ;
2009-12-19 06:38:05 -03:00
err = - 1 ;
} else {
2018-02-25 07:31:30 -05:00
dev_info ( pdev , " Loading firmware file %s. \n " , fw_name ) ;
2009-12-19 06:38:05 -03:00
ngene_fw = ( u8 * ) fw - > data ;
err = ngene_command_load_firmware ( dev , ngene_fw , size ) ;
}
2009-12-18 22:13:26 -03:00
release_firmware ( fw ) ;
2009-12-19 06:38:05 -03:00
2009-12-18 22:13:26 -03:00
return err ;
}
static void ngene_stop ( struct ngene * dev )
{
2017-06-13 05:58:48 -03:00
mutex_destroy ( & dev - > cmd_mutex ) ;
2009-12-18 22:13:26 -03:00
i2c_del_adapter ( & ( dev - > channel [ 0 ] . i2c_adapter ) ) ;
i2c_del_adapter ( & ( dev - > channel [ 1 ] . i2c_adapter ) ) ;
ngwritel ( 0 , NGENE_INT_ENABLE ) ;
ngwritel ( 0 , NGENE_COMMAND ) ;
ngwritel ( 0 , NGENE_COMMAND_HI ) ;
ngwritel ( 0 , NGENE_STATUS ) ;
ngwritel ( 0 , NGENE_STATUS_HI ) ;
ngwritel ( 0 , NGENE_EVENT ) ;
ngwritel ( 0 , NGENE_EVENT_HI ) ;
free_irq ( dev - > pci_dev - > irq , dev ) ;
2010-05-19 04:15:44 -03:00
# ifdef CONFIG_PCI_MSI
2010-05-16 05:29:14 -03:00
if ( dev - > msi_enabled )
pci_disable_msi ( dev - > pci_dev ) ;
2010-05-19 04:15:44 -03:00
# endif
2009-12-18 22:13:26 -03:00
}
2011-01-10 06:36:15 -03:00
static int ngene_buffer_config ( struct ngene * dev )
{
int stat ;
if ( dev - > card_info - > fw_version > = 17 ) {
u8 tsin12_config [ 6 ] = { 0x60 , 0x60 , 0x00 , 0x00 , 0x00 , 0x00 } ;
u8 tsin1234_config [ 6 ] = { 0x30 , 0x30 , 0x00 , 0x30 , 0x30 , 0x00 } ;
u8 tsio1235_config [ 6 ] = { 0x30 , 0x30 , 0x00 , 0x28 , 0x00 , 0x38 } ;
u8 * bconf = tsin12_config ;
if ( dev - > card_info - > io_type [ 2 ] & NGENE_IO_TSIN & &
dev - > card_info - > io_type [ 3 ] & NGENE_IO_TSIN ) {
bconf = tsin1234_config ;
if ( dev - > card_info - > io_type [ 4 ] & NGENE_IO_TSOUT & &
dev - > ci . en )
bconf = tsio1235_config ;
}
stat = ngene_command_config_free_buf ( dev , bconf ) ;
} else {
int bconf = BUFFER_CONFIG_4422 ;
if ( dev - > card_info - > io_type [ 3 ] = = NGENE_IO_TSIN )
bconf = BUFFER_CONFIG_3333 ;
stat = ngene_command_config_buf ( dev , bconf ) ;
}
return stat ;
}
2009-12-18 22:13:26 -03:00
static int ngene_start ( struct ngene * dev )
{
2018-02-25 07:31:30 -05:00
struct device * pdev = & dev - > pci_dev - > dev ;
2009-12-18 22:13:26 -03:00
int stat ;
int i ;
pci_set_master ( dev - > pci_dev ) ;
ngene_init ( dev ) ;
stat = request_irq ( dev - > pci_dev - > irq , irq_handler ,
IRQF_SHARED , " nGene " ,
( void * ) dev ) ;
if ( stat < 0 )
return stat ;
init_waitqueue_head ( & dev - > cmd_wq ) ;
init_waitqueue_head ( & dev - > tx_wq ) ;
init_waitqueue_head ( & dev - > rx_wq ) ;
2017-06-13 05:58:48 -03:00
mutex_init ( & dev - > cmd_mutex ) ;
2017-06-13 05:58:49 -03:00
mutex_init ( & dev - > stream_mutex ) ;
2009-12-18 22:13:26 -03:00
sema_init ( & dev - > pll_mutex , 1 ) ;
2017-06-13 05:58:50 -03:00
mutex_init ( & dev - > i2c_switch_mutex ) ;
2009-12-18 22:13:26 -03:00
spin_lock_init ( & dev - > cmd_lock ) ;
for ( i = 0 ; i < MAX_STREAM ; i + + )
spin_lock_init ( & dev - > channel [ i ] . state_lock ) ;
ngwritel ( 1 , TIMESTAMPS ) ;
ngwritel ( 1 , NGENE_INT_ENABLE ) ;
stat = ngene_load_firm ( dev ) ;
if ( stat < 0 )
goto fail ;
2010-05-16 05:29:14 -03:00
# ifdef CONFIG_PCI_MSI
/* enable MSI if kernel and card support it */
2010-05-19 04:15:44 -03:00
if ( pci_msi_enabled ( ) & & dev - > card_info - > msi_supported ) {
2010-12-31 12:25:32 -03:00
unsigned long flags ;
2010-05-16 05:29:14 -03:00
ngwritel ( 0 , NGENE_INT_ENABLE ) ;
free_irq ( dev - > pci_dev - > irq , dev ) ;
stat = pci_enable_msi ( dev - > pci_dev ) ;
if ( stat ) {
2018-02-25 07:31:30 -05:00
dev_info ( pdev , " MSI not available \n " ) ;
2010-05-16 05:29:14 -03:00
flags = IRQF_SHARED ;
} else {
flags = 0 ;
dev - > msi_enabled = true ;
}
stat = request_irq ( dev - > pci_dev - > irq , irq_handler ,
flags , " nGene " , dev ) ;
if ( stat < 0 )
goto fail2 ;
ngwritel ( 1 , NGENE_INT_ENABLE ) ;
}
# endif
2009-12-18 22:13:26 -03:00
stat = ngene_i2c_init ( dev , 0 ) ;
if ( stat < 0 )
goto fail ;
stat = ngene_i2c_init ( dev , 1 ) ;
if ( stat < 0 )
goto fail ;
2012-04-20 09:15:02 -03:00
return 0 ;
2010-05-16 05:29:14 -03:00
2009-12-18 22:13:26 -03:00
fail :
ngwritel ( 0 , NGENE_INT_ENABLE ) ;
free_irq ( dev - > pci_dev - > irq , dev ) ;
2010-05-19 04:15:44 -03:00
# ifdef CONFIG_PCI_MSI
2010-05-16 05:29:14 -03:00
fail2 :
if ( dev - > msi_enabled )
pci_disable_msi ( dev - > pci_dev ) ;
2010-05-19 04:15:44 -03:00
# endif
2009-12-18 22:13:26 -03:00
return stat ;
}
2009-12-19 04:54:44 -03:00
/****************************************************************************/
/****************************************************************************/
/****************************************************************************/
static void release_channel ( struct ngene_channel * chan )
2009-12-18 22:13:26 -03:00
{
struct dvb_demux * dvbdemux = & chan - > demux ;
struct ngene * dev = chan - > dev ;
2018-02-25 07:31:32 -05:00
struct i2c_client * client ;
2009-12-18 22:13:26 -03:00
2011-01-10 06:36:23 -03:00
if ( chan - > running )
2010-01-20 18:06:51 -03:00
set_transfer ( chan , 0 ) ;
2009-12-18 22:13:26 -03:00
tasklet_kill ( & chan - > demux_tasklet ) ;
2011-01-10 06:36:23 -03:00
if ( chan - > ci_dev ) {
dvb_unregister_device ( chan - > ci_dev ) ;
chan - > ci_dev = NULL ;
}
2011-01-10 06:36:15 -03:00
2011-07-03 13:56:28 -03:00
if ( chan - > fe2 )
2011-07-03 13:55:06 -03:00
dvb_unregister_frontend ( chan - > fe2 ) ;
2011-07-03 13:56:28 -03:00
2011-01-10 06:36:23 -03:00
if ( chan - > fe ) {
dvb_unregister_frontend ( chan - > fe ) ;
2018-02-25 07:31:32 -05:00
/* release I2C client (tuner) if needed */
client = chan - > i2c_client [ 0 ] ;
if ( chan - > i2c_client_fe & & client ) {
module_put ( client - > dev . driver - > owner ) ;
i2c_unregister_device ( client ) ;
chan - > i2c_client [ 0 ] = NULL ;
client = NULL ;
}
2011-01-10 06:36:23 -03:00
dvb_frontend_detach ( chan - > fe ) ;
chan - > fe = NULL ;
}
if ( chan - > has_demux ) {
2011-01-10 06:36:17 -03:00
dvb_net_release ( & chan - > dvbnet ) ;
2009-12-18 22:13:26 -03:00
dvbdemux - > dmx . close ( & dvbdemux - > dmx ) ;
dvbdemux - > dmx . remove_frontend ( & dvbdemux - > dmx ,
& chan - > hw_frontend ) ;
dvbdemux - > dmx . remove_frontend ( & dvbdemux - > dmx ,
& chan - > mem_frontend ) ;
dvb_dmxdev_release ( & chan - > dmxdev ) ;
dvb_dmx_release ( & chan - > demux ) ;
2011-01-10 06:36:23 -03:00
chan - > has_demux = false ;
}
2009-12-23 05:55:02 -03:00
2011-01-10 06:36:23 -03:00
if ( chan - > has_adapter ) {
dvb_unregister_adapter ( & dev - > adapter [ chan - > number ] ) ;
chan - > has_adapter = false ;
2009-12-18 22:13:26 -03:00
}
}
static int init_channel ( struct ngene_channel * chan )
{
int ret = 0 , nr = chan - > number ;
2009-12-22 03:34:29 -03:00
struct dvb_adapter * adapter = NULL ;
2009-12-18 22:13:26 -03:00
struct dvb_demux * dvbdemux = & chan - > demux ;
struct ngene * dev = chan - > dev ;
struct ngene_info * ni = dev - > card_info ;
int io = ni - > io_type [ nr ] ;
tasklet_init ( & chan - > demux_tasklet , demux_tasklet , ( unsigned long ) chan ) ;
chan - > users = 0 ;
chan - > type = io ;
chan - > mode = chan - > type ; /* for now only one mode */
2018-02-25 07:31:32 -05:00
chan - > i2c_client_fe = 0 ; /* be sure this is set to zero */
2009-12-18 22:13:26 -03:00
2011-01-10 06:36:23 -03:00
if ( io & NGENE_IO_TSIN ) {
chan - > fe = NULL ;
if ( ni - > demod_attach [ nr ] ) {
ret = ni - > demod_attach [ nr ] ( chan ) ;
if ( ret < 0 )
goto err ;
}
if ( chan - > fe & & ni - > tuner_attach [ nr ] ) {
ret = ni - > tuner_attach [ nr ] ( chan ) ;
if ( ret < 0 )
goto err ;
}
}
if ( ! dev - > ci . en & & ( io & NGENE_IO_TSOUT ) )
return 0 ;
2009-12-18 22:13:26 -03:00
if ( io & ( NGENE_IO_TSIN | NGENE_IO_TSOUT ) ) {
if ( nr > = STREAM_AUDIOIN1 )
chan - > DataFormatFlags = DF_SWAP32 ;
2011-01-10 06:36:15 -03:00
2010-03-13 16:40:46 -03:00
if ( nr = = 0 | | ! one_adapter | | dev - > first_adapter = = NULL ) {
2009-12-23 05:55:02 -03:00
adapter = & dev - > adapter [ nr ] ;
ret = dvb_register_adapter ( adapter , " nGene " ,
THIS_MODULE ,
& chan - > dev - > pci_dev - > dev ,
adapter_nr ) ;
if ( ret < 0 )
2011-01-10 06:36:23 -03:00
goto err ;
2010-03-13 16:40:46 -03:00
if ( dev - > first_adapter = = NULL )
dev - > first_adapter = adapter ;
2011-01-10 06:36:23 -03:00
chan - > has_adapter = true ;
} else
2010-03-13 16:40:46 -03:00
adapter = dev - > first_adapter ;
2011-01-10 06:36:23 -03:00
}
if ( dev - > ci . en & & ( io & NGENE_IO_TSOUT ) ) {
dvb_ca_en50221_init ( adapter , dev - > ci . en , 0 , 1 ) ;
set_transfer ( chan , 1 ) ;
2011-03-29 17:35:24 -03:00
chan - > dev - > channel [ 2 ] . DataFormatFlags = DF_SWAP32 ;
2011-01-10 06:36:23 -03:00
set_transfer ( & chan - > dev - > channel [ 2 ] , 1 ) ;
dvb_register_device ( adapter , & chan - > ci_dev ,
& ngene_dvbdev_ci , ( void * ) chan ,
2015-08-21 16:18:18 -03:00
DVB_DEVICE_SEC , 0 ) ;
2011-01-10 06:36:23 -03:00
if ( ! chan - > ci_dev )
goto err ;
}
2009-12-23 05:55:02 -03:00
2011-01-10 06:36:23 -03:00
if ( chan - > fe ) {
if ( dvb_register_frontend ( adapter , chan - > fe ) < 0 )
goto err ;
chan - > has_demux = true ;
}
2011-07-03 13:55:06 -03:00
if ( chan - > fe2 ) {
if ( dvb_register_frontend ( adapter , chan - > fe2 ) < 0 )
goto err ;
2015-04-28 10:02:07 -03:00
if ( chan - > fe ) {
chan - > fe2 - > tuner_priv = chan - > fe - > tuner_priv ;
memcpy ( & chan - > fe2 - > ops . tuner_ops ,
& chan - > fe - > ops . tuner_ops ,
sizeof ( struct dvb_tuner_ops ) ) ;
}
2011-07-03 13:55:06 -03:00
}
2011-01-10 06:36:23 -03:00
if ( chan - > has_demux ) {
2009-12-18 22:13:26 -03:00
ret = my_dvb_dmx_ts_card_init ( dvbdemux , " SW demux " ,
ngene_start_feed ,
ngene_stop_feed , chan ) ;
ret = my_dvb_dmxdev_ts_card_init ( & chan - > dmxdev , & chan - > demux ,
& chan - > hw_frontend ,
& chan - > mem_frontend , adapter ) ;
2011-01-10 06:36:17 -03:00
ret = dvb_net_init ( adapter , & chan - > dvbnet , & chan - > demux . dmx ) ;
2009-12-18 22:13:26 -03:00
}
return ret ;
2011-01-10 06:36:14 -03:00
2011-01-10 06:36:23 -03:00
err :
2011-01-10 06:36:14 -03:00
if ( chan - > fe ) {
dvb_frontend_detach ( chan - > fe ) ;
chan - > fe = NULL ;
}
2011-01-10 06:36:23 -03:00
release_channel ( chan ) ;
2011-01-10 06:36:14 -03:00
return 0 ;
2009-12-18 22:13:26 -03:00
}
static int init_channels ( struct ngene * dev )
{
int i , j ;
for ( i = 0 ; i < MAX_STREAM ; i + + ) {
2010-03-13 16:40:46 -03:00
dev - > channel [ i ] . number = i ;
2009-12-18 22:13:26 -03:00
if ( init_channel ( & dev - > channel [ i ] ) < 0 ) {
2009-12-23 05:55:02 -03:00
for ( j = i - 1 ; j > = 0 ; j - - )
2009-12-18 22:13:26 -03:00
release_channel ( & dev - > channel [ j ] ) ;
return - 1 ;
}
}
return 0 ;
}
2018-02-08 14:53:15 -05:00
static const struct cxd2099_cfg cxd_cfgtmpl = {
2011-07-03 14:03:49 -03:00
. bitrate = 62000 ,
. polarity = 0 ,
. clock_mode = 0 ,
} ;
2011-01-10 06:36:15 -03:00
static void cxd_attach ( struct ngene * dev )
{
2018-02-25 07:31:30 -05:00
struct device * pdev = & dev - > pci_dev - > dev ;
2011-01-10 06:36:15 -03:00
struct ngene_ci * ci = & dev - > ci ;
2018-02-08 14:53:15 -05:00
struct cxd2099_cfg cxd_cfg = cxd_cfgtmpl ;
struct i2c_client * client ;
struct i2c_board_info board_info = {
. type = " cxd2099 " ,
. addr = 0x40 ,
. platform_data = & cxd_cfg ,
} ;
2018-02-25 07:31:37 -05:00
int ret ;
u8 type ;
/* check for CXD2099AR presence before attaching */
ret = ngene_port_has_cxd2099 ( & dev - > channel [ 0 ] . i2c_adapter , & type ) ;
if ( ! ret ) {
dev_dbg ( pdev , " No CXD2099AR found \n " ) ;
return ;
}
if ( type ! = 1 ) {
dev_warn ( pdev , " CXD2099AR is uninitialized! \n " ) ;
return ;
}
2018-02-08 14:53:15 -05:00
cxd_cfg . en = & ci - > en ;
request_module ( board_info . type ) ;
client = i2c_new_device ( & dev - > channel [ 0 ] . i2c_adapter , & board_info ) ;
if ( ! client | | ! client - > dev . driver )
goto err_ret ;
if ( ! try_module_get ( client - > dev . driver - > owner ) )
goto err_i2c ;
if ( ! ci - > en )
goto err_i2c ;
2011-01-10 06:36:15 -03:00
ci - > dev = dev ;
2018-02-08 14:53:15 -05:00
dev - > channel [ 0 ] . i2c_client [ 0 ] = client ;
return ;
err_i2c :
i2c_unregister_device ( client ) ;
err_ret :
2018-02-25 07:31:30 -05:00
dev_err ( pdev , " CXD2099AR attach failed \n " ) ;
2011-01-10 06:36:15 -03:00
return ;
}
static void cxd_detach ( struct ngene * dev )
{
struct ngene_ci * ci = & dev - > ci ;
2018-02-08 14:53:15 -05:00
struct i2c_client * client ;
2011-01-10 06:36:15 -03:00
dvb_ca_en50221_release ( ci - > en ) ;
2018-02-08 14:53:15 -05:00
client = dev - > channel [ 0 ] . i2c_client [ 0 ] ;
if ( client ) {
module_put ( client - > dev . driver - > owner ) ;
i2c_unregister_device ( client ) ;
}
2014-08-20 17:43:22 -03:00
ci - > en = NULL ;
2011-01-10 06:36:15 -03:00
}
2011-01-10 06:36:16 -03:00
/***********************************/
/* workaround for shutdown failure */
/***********************************/
static void ngene_unlink ( struct ngene * dev )
{
struct ngene_command com ;
com . cmd . hdr . Opcode = CMD_MEM_WRITE ;
com . cmd . hdr . Length = 3 ;
com . cmd . MemoryWrite . address = 0x910c ;
com . cmd . MemoryWrite . data = 0xff ;
com . in_len = 3 ;
com . out_len = 1 ;
2017-06-13 05:58:48 -03:00
mutex_lock ( & dev - > cmd_mutex ) ;
2011-01-10 06:36:16 -03:00
ngwritel ( 0 , NGENE_INT_ENABLE ) ;
ngene_command_mutex ( dev , & com ) ;
2017-06-13 05:58:48 -03:00
mutex_unlock ( & dev - > cmd_mutex ) ;
2011-01-10 06:36:16 -03:00
}
void ngene_shutdown ( struct pci_dev * pdev )
{
2013-09-09 02:55:14 -03:00
struct ngene * dev = pci_get_drvdata ( pdev ) ;
2011-01-10 06:36:16 -03:00
if ( ! dev | | ! shutdown_workaround )
return ;
2018-02-25 07:31:30 -05:00
dev_info ( & pdev - > dev , " shutdown workaround... \n " ) ;
2011-01-10 06:36:16 -03:00
ngene_unlink ( dev ) ;
pci_disable_device ( pdev ) ;
}
2009-12-18 22:13:26 -03:00
/****************************************************************************/
/* device probe/remove calls ************************************************/
/****************************************************************************/
2012-12-21 13:17:53 -08:00
void ngene_remove ( struct pci_dev * pdev )
2009-12-18 22:13:26 -03:00
{
2010-11-15 17:13:54 -03:00
struct ngene * dev = pci_get_drvdata ( pdev ) ;
2009-12-18 22:13:26 -03:00
int i ;
tasklet_kill ( & dev - > event_tasklet ) ;
2009-12-23 05:55:02 -03:00
for ( i = MAX_STREAM - 1 ; i > = 0 ; i - - )
2009-12-18 22:13:26 -03:00
release_channel ( & dev - > channel [ i ] ) ;
2011-01-10 06:36:15 -03:00
if ( dev - > ci . en )
cxd_detach ( dev ) ;
2009-12-18 22:13:26 -03:00
ngene_stop ( dev ) ;
ngene_release_buffers ( dev ) ;
pci_disable_device ( pdev ) ;
}
2012-12-21 13:17:53 -08:00
int ngene_probe ( struct pci_dev * pci_dev , const struct pci_device_id * id )
2009-12-18 22:13:26 -03:00
{
struct ngene * dev ;
int stat = 0 ;
if ( pci_enable_device ( pci_dev ) < 0 )
return - ENODEV ;
2010-11-05 00:07:39 -03:00
dev = vzalloc ( sizeof ( struct ngene ) ) ;
2009-12-19 22:48:14 -03:00
if ( dev = = NULL ) {
stat = - ENOMEM ;
goto fail0 ;
}
2009-12-18 22:13:26 -03:00
dev - > pci_dev = pci_dev ;
dev - > card_info = ( struct ngene_info * ) id - > driver_data ;
2018-02-25 07:31:30 -05:00
dev_info ( & pci_dev - > dev , " Found %s \n " , dev - > card_info - > name ) ;
2009-12-18 22:13:26 -03:00
pci_set_drvdata ( pci_dev , dev ) ;
/* Alloc buffers and start nGene */
stat = ngene_get_buffers ( dev ) ;
if ( stat < 0 )
goto fail1 ;
stat = ngene_start ( dev ) ;
if ( stat < 0 )
goto fail1 ;
2011-01-10 06:36:15 -03:00
cxd_attach ( dev ) ;
stat = ngene_buffer_config ( dev ) ;
if ( stat < 0 )
goto fail1 ;
2009-12-18 22:13:26 -03:00
dev - > i2c_current_bus = - 1 ;
/* Register DVB adapters and devices for both channels */
2012-09-06 11:23:54 -03:00
stat = init_channels ( dev ) ;
if ( stat < 0 )
2009-12-18 22:13:26 -03:00
goto fail2 ;
return 0 ;
fail2 :
ngene_stop ( dev ) ;
fail1 :
ngene_release_buffers ( dev ) ;
2009-12-19 22:48:14 -03:00
fail0 :
pci_disable_device ( pci_dev ) ;
2009-12-18 22:13:26 -03:00
return stat ;
}