2005-05-17 08:54:10 +04:00
/*
* This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII ( b ) / III
*
* flexcop - dma . c - methods for configuring and controlling the DMA of the FlexCop .
*
* see flexcop . c for copyright information .
*/
# include "flexcop.h"
int flexcop_dma_allocate ( struct pci_dev * pdev , struct flexcop_dma * dma , u32 size )
{
u8 * tcpu ;
dma_addr_t tdma ;
if ( size % 2 ) {
err ( " dma buffersize has to be even. " ) ;
return - EINVAL ;
}
if ( ( tcpu = pci_alloc_consistent ( pdev , size , & tdma ) ) ! = NULL ) {
dma - > pdev = pdev ;
dma - > cpu_addr0 = tcpu ;
dma - > dma_addr0 = tdma ;
dma - > cpu_addr1 = tcpu + size / 2 ;
dma - > dma_addr1 = tdma + size / 2 ;
dma - > size = size / 2 ;
return 0 ;
}
return - ENOMEM ;
}
EXPORT_SYMBOL ( flexcop_dma_allocate ) ;
void flexcop_dma_free ( struct flexcop_dma * dma )
{
pci_free_consistent ( dma - > pdev , dma - > size * 2 , dma - > cpu_addr0 , dma - > dma_addr0 ) ;
memset ( dma , 0 , sizeof ( struct flexcop_dma ) ) ;
}
EXPORT_SYMBOL ( flexcop_dma_free ) ;
2005-07-08 04:57:49 +04:00
int flexcop_dma_config ( struct flexcop_device * fc ,
struct flexcop_dma * dma ,
flexcop_dma_index_t dma_idx )
2005-05-17 08:54:10 +04:00
{
2005-07-08 04:57:49 +04:00
flexcop_ibi_value v0x0 , v0x4 , v0xc ;
v0x0 . raw = v0x4 . raw = v0xc . raw = 0 ;
2005-05-17 08:54:10 +04:00
2005-07-08 04:57:49 +04:00
v0x0 . dma_0x0 . dma_address0 = dma - > dma_addr0 > > 2 ;
v0xc . dma_0xc . dma_address1 = dma - > dma_addr1 > > 2 ;
v0x4 . dma_0x4_write . dma_addr_size = dma - > size / 4 ;
2005-05-17 08:54:10 +04:00
2005-07-08 04:57:49 +04:00
if ( ( dma_idx & FC_DMA_1 ) = = dma_idx ) {
fc - > write_ibi_reg ( fc , dma1_000 , v0x0 ) ;
fc - > write_ibi_reg ( fc , dma1_004 , v0x4 ) ;
fc - > write_ibi_reg ( fc , dma1_00c , v0xc ) ;
} else if ( ( dma_idx & FC_DMA_2 ) = = dma_idx ) {
fc - > write_ibi_reg ( fc , dma2_010 , v0x0 ) ;
fc - > write_ibi_reg ( fc , dma2_014 , v0x4 ) ;
fc - > write_ibi_reg ( fc , dma2_01c , v0xc ) ;
} else {
err ( " either DMA1 or DMA2 can be configured at the within one flexcop_dma_config call. " ) ;
return - EINVAL ;
}
2005-05-17 08:54:10 +04:00
return 0 ;
}
2005-07-08 04:57:49 +04:00
EXPORT_SYMBOL ( flexcop_dma_config ) ;
/* start the DMA transfers, but not the DMA IRQs */
int flexcop_dma_xfer_control ( struct flexcop_device * fc ,
flexcop_dma_index_t dma_idx ,
flexcop_dma_addr_index_t index ,
int onoff )
{
flexcop_ibi_value v0x0 , v0xc ;
flexcop_ibi_register r0x0 , r0xc ;
if ( ( dma_idx & FC_DMA_1 ) = = dma_idx ) {
r0x0 = dma1_000 ;
r0xc = dma1_00c ;
} else if ( ( dma_idx & FC_DMA_2 ) = = dma_idx ) {
r0x0 = dma2_010 ;
r0xc = dma2_01c ;
} else {
err ( " either transfer DMA1 or DMA2 can be started within one flexcop_dma_xfer_control call. " ) ;
return - EINVAL ;
}
v0x0 = fc - > read_ibi_reg ( fc , r0x0 ) ;
v0xc = fc - > read_ibi_reg ( fc , r0xc ) ;
deb_rdump ( " reg: %03x: %x \n " , r0x0 , v0x0 . raw ) ;
deb_rdump ( " reg: %03x: %x \n " , r0xc , v0xc . raw ) ;
if ( index & FC_DMA_SUBADDR_0 )
v0x0 . dma_0x0 . dma_0start = onoff ;
if ( index & FC_DMA_SUBADDR_1 )
v0xc . dma_0xc . dma_1start = onoff ;
fc - > write_ibi_reg ( fc , r0x0 , v0x0 ) ;
fc - > write_ibi_reg ( fc , r0xc , v0xc ) ;
deb_rdump ( " reg: %03x: %x \n " , r0x0 , v0x0 . raw ) ;
deb_rdump ( " reg: %03x: %x \n " , r0xc , v0xc . raw ) ;
return 0 ;
}
EXPORT_SYMBOL ( flexcop_dma_xfer_control ) ;
static int flexcop_dma_remap ( struct flexcop_device * fc ,
flexcop_dma_index_t dma_idx ,
int onoff )
{
flexcop_ibi_register r = ( dma_idx & FC_DMA_1 ) ? dma1_00c : dma2_01c ;
flexcop_ibi_value v = fc - > read_ibi_reg ( fc , r ) ;
deb_info ( " %s \n " , __FUNCTION__ ) ;
v . dma_0xc . remap_enable = onoff ;
fc - > write_ibi_reg ( fc , r , v ) ;
return 0 ;
}
2005-05-17 08:54:10 +04:00
2005-07-08 04:57:49 +04:00
int flexcop_dma_control_size_irq ( struct flexcop_device * fc ,
flexcop_dma_index_t no ,
int onoff )
2005-05-17 08:54:10 +04:00
{
flexcop_ibi_value v = fc - > read_ibi_reg ( fc , ctrl_208 ) ;
if ( no & FC_DMA_1 )
v . ctrl_208 . DMA1_IRQ_Enable_sig = onoff ;
if ( no & FC_DMA_2 )
v . ctrl_208 . DMA2_IRQ_Enable_sig = onoff ;
fc - > write_ibi_reg ( fc , ctrl_208 , v ) ;
return 0 ;
}
EXPORT_SYMBOL ( flexcop_dma_control_size_irq ) ;
2005-07-08 04:57:49 +04:00
int flexcop_dma_control_timer_irq ( struct flexcop_device * fc ,
flexcop_dma_index_t no ,
int onoff )
2005-05-17 08:54:10 +04:00
{
flexcop_ibi_value v = fc - > read_ibi_reg ( fc , ctrl_208 ) ;
if ( no & FC_DMA_1 )
2005-07-08 04:57:49 +04:00
v . ctrl_208 . DMA1_Timer_Enable_sig = onoff ;
2005-05-17 08:54:10 +04:00
if ( no & FC_DMA_2 )
2005-07-08 04:57:49 +04:00
v . ctrl_208 . DMA2_Timer_Enable_sig = onoff ;
2005-05-17 08:54:10 +04:00
fc - > write_ibi_reg ( fc , ctrl_208 , v ) ;
return 0 ;
}
2005-07-08 04:57:49 +04:00
EXPORT_SYMBOL ( flexcop_dma_control_timer_irq ) ;
2005-05-17 08:54:10 +04:00
2005-07-08 04:57:49 +04:00
/* 1 cycles = 1.97 msec */
int flexcop_dma_config_timer ( struct flexcop_device * fc ,
flexcop_dma_index_t dma_idx ,
u8 cycles )
2005-05-17 08:54:10 +04:00
{
2005-07-08 04:57:49 +04:00
flexcop_ibi_register r = ( dma_idx & FC_DMA_1 ) ? dma1_004 : dma2_014 ;
flexcop_ibi_value v = fc - > read_ibi_reg ( fc , r ) ;
2005-05-17 08:54:10 +04:00
2005-07-08 04:57:49 +04:00
flexcop_dma_remap ( fc , dma_idx , 0 ) ;
2005-05-17 08:54:10 +04:00
2005-07-08 04:57:49 +04:00
deb_info ( " %s \n " , __FUNCTION__ ) ;
v . dma_0x4_write . dmatimer = cycles ;
2005-05-17 08:54:10 +04:00
fc - > write_ibi_reg ( fc , r , v ) ;
return 0 ;
}
2005-07-08 04:57:49 +04:00
EXPORT_SYMBOL ( flexcop_dma_config_timer ) ;
2005-05-17 08:54:10 +04:00