@ -65,6 +65,10 @@
# define ERR_UNDER 0x00000001
# define ST_ERR (ERR_OVER | ERR_UNDER)
/* CKG1 */
# define ACKMD_MASK 0x00007000
# define BPFMD_MASK 0x00000700
/* CLK_RST */
# define B_CLK 0x00000010
# define A_CLK 0x00000001
@ -734,12 +738,6 @@ static int fsi_dai_startup(struct snd_pcm_substream *substream,
}
fsi_reg_write ( fsi , reg , data ) ;
/*
* clear clk reset if master mode
*/
if ( is_master )
fsi_clk_ctrl ( fsi , 1 ) ;
/* irq clear */
fsi_irq_disable ( fsi , is_play ) ;
fsi_irq_clear_status ( fsi ) ;
@ -786,10 +784,98 @@ static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd,
return ret ;
}
static int fsi_dai_hw_params ( struct snd_pcm_substream * substream ,
struct snd_pcm_hw_params * params ,
struct snd_soc_dai * dai )
{
struct fsi_priv * fsi = fsi_get_priv ( substream ) ;
struct fsi_master * master = fsi_get_master ( fsi ) ;
int ( * set_rate ) ( int is_porta , int rate ) = master - > info - > set_rate ;
int fsi_ver = master - > core - > ver ;
int is_play = ( substream - > stream = = SNDRV_PCM_STREAM_PLAYBACK ) ;
int ret ;
/* if slave mode, set_rate is not needed */
if ( ! fsi_is_master_mode ( fsi , is_play ) )
return 0 ;
/* it is error if no set_rate */
if ( ! set_rate )
return - EIO ;
/* clock stop */
pm_runtime_put_sync ( dai - > dev ) ;
fsi_clk_ctrl ( fsi , 0 ) ;
ret = set_rate ( fsi_is_port_a ( fsi ) , params_rate ( params ) ) ;
if ( ret > 0 ) {
u32 data = 0 ;
switch ( ret & SH_FSI_ACKMD_MASK ) {
default :
/* FALL THROUGH */
case SH_FSI_ACKMD_512 :
data | = ( 0x0 < < 12 ) ;
break ;
case SH_FSI_ACKMD_256 :
data | = ( 0x1 < < 12 ) ;
break ;
case SH_FSI_ACKMD_128 :
data | = ( 0x2 < < 12 ) ;
break ;
case SH_FSI_ACKMD_64 :
data | = ( 0x3 < < 12 ) ;
break ;
case SH_FSI_ACKMD_32 :
if ( fsi_ver < 2 )
dev_err ( dai - > dev , " unsupported ACKMD \n " ) ;
else
data | = ( 0x4 < < 12 ) ;
break ;
}
switch ( ret & SH_FSI_BPFMD_MASK ) {
default :
/* FALL THROUGH */
case SH_FSI_BPFMD_32 :
data | = ( 0x0 < < 8 ) ;
break ;
case SH_FSI_BPFMD_64 :
data | = ( 0x1 < < 8 ) ;
break ;
case SH_FSI_BPFMD_128 :
data | = ( 0x2 < < 8 ) ;
break ;
case SH_FSI_BPFMD_256 :
data | = ( 0x3 < < 8 ) ;
break ;
case SH_FSI_BPFMD_512 :
data | = ( 0x4 < < 8 ) ;
break ;
case SH_FSI_BPFMD_16 :
if ( fsi_ver < 2 )
dev_err ( dai - > dev , " unsupported ACKMD \n " ) ;
else
data | = ( 0x7 < < 8 ) ;
break ;
}
fsi_reg_mask_set ( fsi , CKG1 , ( ACKMD_MASK | BPFMD_MASK ) , data ) ;
udelay ( 10 ) ;
fsi_clk_ctrl ( fsi , 1 ) ;
ret = 0 ;
}
pm_runtime_get_sync ( dai - > dev ) ;
return ret ;
}
static struct snd_soc_dai_ops fsi_dai_ops = {
. startup = fsi_dai_startup ,
. shutdown = fsi_dai_shutdown ,
. trigger = fsi_dai_trigger ,
. hw_params = fsi_dai_hw_params ,
} ;
/************************************************************************