@ -131,6 +131,25 @@
typedef int ( * set_rate_func ) ( struct device * dev , int rate , int enable ) ;
/*
* bus options
*
* 0x000000BA
*
* A : sample widtht 16 bit setting
* B : sample widtht 24 bit setting
*/
# define SHIFT_16DATA 0
# define SHIFT_24DATA 4
# define PACKAGE_24BITBUS_BACK 0
# define PACKAGE_24BITBUS_FRONT 1
# define PACKAGE_16BITBUS_STREAM 2
# define BUSOP_SET(s, a) ((a) << SHIFT_ ## s ## DATA)
# define BUSOP_GET(s, a) (((a) >> SHIFT_ ## s ## DATA) & 0xF)
/*
* FSI driver use below type name for variable
*
@ -188,6 +207,11 @@ struct fsi_stream {
int uerr_num ;
int oerr_num ;
/*
* bus options
*/
u32 bus_option ;
/*
* thse are initialized by fsi_handler_init ( )
*/
@ -498,6 +522,7 @@ static void fsi_stream_init(struct fsi_priv *fsi,
io - > period_samples = fsi_frame2sample ( fsi , runtime - > period_size ) ;
io - > period_pos = 0 ;
io - > sample_width = samples_to_bytes ( runtime , 1 ) ;
io - > bus_option = 0 ;
io - > oerr_num = - 1 ; /* ignore 1st err */
io - > uerr_num = - 1 ; /* ignore 1st err */
fsi_stream_handler_call ( io , init , fsi , io ) ;
@ -525,6 +550,7 @@ static void fsi_stream_quit(struct fsi_priv *fsi, struct fsi_stream *io)
io - > period_samples = 0 ;
io - > period_pos = 0 ;
io - > sample_width = 0 ;
io - > bus_option = 0 ;
io - > oerr_num = 0 ;
io - > uerr_num = 0 ;
spin_unlock_irqrestore ( & master - > lock , flags ) ;
@ -583,6 +609,53 @@ static int fsi_stream_remove(struct fsi_priv *fsi)
return 0 ;
}
/*
* format / bus / dma setting
*/
static void fsi_format_bus_setup ( struct fsi_priv * fsi , struct fsi_stream * io ,
u32 bus , struct device * dev )
{
struct fsi_master * master = fsi_get_master ( fsi ) ;
int is_play = fsi_stream_is_play ( fsi , io ) ;
u32 fmt = fsi - > fmt ;
if ( fsi_version ( master ) > = 2 ) {
u32 dma = 0 ;
/*
* FSI2 needs DMA / Bus setting
*/
switch ( bus ) {
case PACKAGE_24BITBUS_FRONT :
fmt | = CR_BWS_24 ;
dma | = VDMD_FRONT ;
dev_dbg ( dev , " 24bit bus / package in front \n " ) ;
break ;
case PACKAGE_16BITBUS_STREAM :
fmt | = CR_BWS_16 ;
dma | = VDMD_STREAM ;
dev_dbg ( dev , " 16bit bus / stream mode \n " ) ;
break ;
case PACKAGE_24BITBUS_BACK :
default :
fmt | = CR_BWS_24 ;
dma | = VDMD_BACK ;
dev_dbg ( dev , " 24bit bus / package in back \n " ) ;
break ;
}
if ( is_play )
fsi_reg_write ( fsi , OUT_DMAC , dma ) ;
else
fsi_reg_write ( fsi , IN_DMAC , dma ) ;
}
if ( is_play )
fsi_reg_write ( fsi , DO_FMT , fmt ) ;
else
fsi_reg_write ( fsi , DI_FMT , fmt ) ;
}
/*
* irq function
*/
@ -718,11 +791,26 @@ static int fsi_set_master_clk(struct device *dev, struct fsi_priv *fsi,
*/
static void fsi_pio_push16 ( struct fsi_priv * fsi , u8 * _buf , int samples )
{
u16 * buf = ( u16 * ) _buf ;
u32 enable_stream = fsi_get_info_flags ( fsi ) & SH_FSI_ENABLE_STREAM_MODE ;
int i ;
for ( i = 0 ; i < samples ; i + + )
fsi_reg_write ( fsi , DODT , ( ( u32 ) * ( buf + i ) < < 8 ) ) ;
if ( enable_stream ) {
/*
* stream mode
* see
* fsi_pio_push_init ( )
*/
u32 * buf = ( u32 * ) _buf ;
for ( i = 0 ; i < samples / 2 ; i + + )
fsi_reg_write ( fsi , DODT , buf [ i ] ) ;
} else {
/* normal mode */
u16 * buf = ( u16 * ) _buf ;
for ( i = 0 ; i < samples ; i + + )
fsi_reg_write ( fsi , DODT , ( ( u32 ) * ( buf + i ) < < 8 ) ) ;
}
}
static void fsi_pio_pop16 ( struct fsi_priv * fsi , u8 * _buf , int samples )
@ -862,12 +950,44 @@ static void fsi_pio_start_stop(struct fsi_priv *fsi, struct fsi_stream *io,
fsi_master_mask_set ( master , CLK_RST , clk , ( enable ) ? clk : 0 ) ;
}
static int fsi_pio_push_init ( struct fsi_priv * fsi , struct fsi_stream * io )
{
u32 enable_stream = fsi_get_info_flags ( fsi ) & SH_FSI_ENABLE_STREAM_MODE ;
/*
* we can use 16 bit stream mode
* when " playback " and " 16bit data "
* and platform allows " stream mode "
* see
* fsi_pio_push16 ( )
*/
if ( enable_stream )
io - > bus_option = BUSOP_SET ( 24 , PACKAGE_24BITBUS_BACK ) |
BUSOP_SET ( 16 , PACKAGE_16BITBUS_STREAM ) ;
else
io - > bus_option = BUSOP_SET ( 24 , PACKAGE_24BITBUS_BACK ) |
BUSOP_SET ( 16 , PACKAGE_24BITBUS_BACK ) ;
return 0 ;
}
static int fsi_pio_pop_init ( struct fsi_priv * fsi , struct fsi_stream * io )
{
/*
* always 24 bit bus , package back when " capture "
*/
io - > bus_option = BUSOP_SET ( 24 , PACKAGE_24BITBUS_BACK ) |
BUSOP_SET ( 16 , PACKAGE_24BITBUS_BACK ) ;
return 0 ;
}
static struct fsi_stream_handler fsi_pio_push_handler = {
. init = fsi_pio_push_init ,
. transfer = fsi_pio_push ,
. start_stop = fsi_pio_start_stop ,
} ;
static struct fsi_stream_handler fsi_pio_pop_handler = {
. init = fsi_pio_pop_init ,
. transfer = fsi_pio_pop ,
. start_stop = fsi_pio_start_stop ,
} ;
@ -909,6 +1029,13 @@ static int fsi_dma_init(struct fsi_priv *fsi, struct fsi_stream *io)
enum dma_data_direction dir = fsi_stream_is_play ( fsi , io ) ?
DMA_TO_DEVICE : DMA_FROM_DEVICE ;
/*
* 24 bit data : 24 bit bus / package in back
* 16 bit data : 16 bit bus / stream mode
*/
io - > bus_option = BUSOP_SET ( 24 , PACKAGE_24BITBUS_BACK ) |
BUSOP_SET ( 16 , PACKAGE_16BITBUS_STREAM ) ;
io - > dma = dma_map_single ( dai - > dev , runtime - > dma_area ,
snd_pcm_lib_buffer_bytes ( io - > substream ) , dir ) ;
return 0 ;
@ -1045,25 +1172,9 @@ static int fsi_dma_transfer(struct fsi_priv *fsi, struct fsi_stream *io)
static void fsi_dma_push_start_stop ( struct fsi_priv * fsi , struct fsi_stream * io ,
int start )
{
u32 bws ;
u32 dma ;
u32 enable = start ? DMA_ON : 0 ;
switch ( io - > sample_width * start ) {
case 2 :
bws = CR_BWS_16 ;
dma = VDMD_STREAM | DMA_ON ;
break ;
case 4 :
bws = CR_BWS_24 ;
dma = VDMD_BACK | DMA_ON ;
break ;
default :
bws = 0 ;
dma = 0 ;
}
fsi_reg_mask_set ( fsi , DO_FMT , CR_BWS_MASK , bws ) ;
fsi_reg_write ( fsi , OUT_DMAC , dma ) ;
fsi_reg_mask_set ( fsi , OUT_DMAC , DMA_ON , enable ) ;
}
static int fsi_dma_probe ( struct fsi_priv * fsi , struct fsi_stream * io )
@ -1166,7 +1277,6 @@ static int fsi_hw_startup(struct fsi_priv *fsi,
struct fsi_stream * io ,
struct device * dev )
{
struct fsi_master * master = fsi_get_master ( fsi ) ;
u32 flags = fsi_get_info_flags ( fsi ) ;
u32 data = 0 ;
@ -1189,10 +1299,6 @@ static int fsi_hw_startup(struct fsi_priv *fsi,
fsi_reg_write ( fsi , CKG2 , data ) ;
/* set format */
fsi_reg_write ( fsi , DO_FMT , fsi - > fmt ) ;
fsi_reg_write ( fsi , DI_FMT , fsi - > fmt ) ;
/* spdif ? */
if ( fsi_is_spdif ( fsi ) ) {
fsi_spdif_clk_ctrl ( fsi , 1 ) ;
@ -1200,15 +1306,18 @@ static int fsi_hw_startup(struct fsi_priv *fsi,
}
/*
* FIXME
*
* FSI driver assumed that data package is in - back .
* FSI2 chip can select it .
* get bus settings
*/
if ( fsi_version ( master ) > = 2 ) {
fsi_reg_write ( fsi , OUT_DMAC , VDMD_BACK ) ;
fsi_reg_write ( fsi , IN_DMAC , VDMD_BACK ) ;
data = 0 ;
switch ( io - > sample_width ) {
case 2 :
data = BUSOP_GET ( 16 , io - > bus_option ) ;
break ;
case 4 :
data = BUSOP_GET ( 24 , io - > bus_option ) ;
break ;
}
fsi_format_bus_setup ( fsi , io , data , dev ) ;
/* irq clear */
fsi_irq_disable ( fsi , io ) ;
@ -1295,7 +1404,7 @@ static int fsi_set_fmt_spdif(struct fsi_priv *fsi)
if ( fsi_version ( master ) < 2 )
return - EINVAL ;
fsi - > fmt = CR_BWS_16 | CR_ DTMD_SPDIF_PCM | CR_PCM ;
fsi - > fmt = CR_DTMD_SPDIF_PCM | CR_PCM ;
fsi - > chan_num = 2 ;
fsi - > spdif = 1 ;