2013-07-22 08:36:21 +04:00
/*
* Renesas R - Car Gen1 SRU / SSI support
*
* Copyright ( C ) 2013 Renesas Solutions Corp .
* Kuninori Morimoto < kuninori . morimoto . gx @ renesas . com >
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation .
*/
# include "rsnd.h"
struct rsnd_gen {
void __iomem * base [ RSND_BASE_MAX ] ;
struct rsnd_gen_ops * ops ;
2013-09-24 10:12:27 +04:00
struct regmap * regmap ;
struct regmap_field * regs [ RSND_REG_MAX ] ;
2013-07-22 08:36:21 +04:00
} ;
# define rsnd_priv_to_gen(p) ((struct rsnd_gen *)(p)->gen)
2013-09-24 10:12:27 +04:00
# define RSND_REG_SET(gen, id, reg_id, offset, _id_offset, _id_size) \
[ id ] = { \
. reg = ( unsigned int ) gen - > base [ reg_id ] + offset , \
. lsb = 0 , \
. msb = 31 , \
. id_size = _id_size , \
. id_offset = _id_offset , \
}
/*
* basic function
*/
static int rsnd_regmap_write32 ( void * context , const void * _data , size_t count )
{
struct rsnd_priv * priv = context ;
struct device * dev = rsnd_priv_to_dev ( priv ) ;
u32 * data = ( u32 * ) _data ;
u32 val = data [ 1 ] ;
void __iomem * reg = ( void * ) data [ 0 ] ;
iowrite32 ( val , reg ) ;
dev_dbg ( dev , " w %p : %08x \n " , reg , val ) ;
return 0 ;
}
static int rsnd_regmap_read32 ( void * context ,
const void * _data , size_t reg_size ,
void * _val , size_t val_size )
{
struct rsnd_priv * priv = context ;
struct device * dev = rsnd_priv_to_dev ( priv ) ;
u32 * data = ( u32 * ) _data ;
u32 * val = ( u32 * ) _val ;
void __iomem * reg = ( void * ) data [ 0 ] ;
* val = ioread32 ( reg ) ;
dev_dbg ( dev , " r %p : %08x \n " , reg , * val ) ;
return 0 ;
}
static struct regmap_bus rsnd_regmap_bus = {
. write = rsnd_regmap_write32 ,
. read = rsnd_regmap_read32 ,
. reg_format_endian_default = REGMAP_ENDIAN_NATIVE ,
. val_format_endian_default = REGMAP_ENDIAN_NATIVE ,
} ;
2013-11-29 06:43:13 +04:00
static int rsnd_is_accessible_reg ( struct rsnd_priv * priv ,
struct rsnd_gen * gen , enum rsnd_reg reg )
{
if ( ! gen - > regs [ reg ] ) {
struct device * dev = rsnd_priv_to_dev ( priv ) ;
dev_err ( dev , " unsupported register access %x \n " , reg ) ;
return 0 ;
}
return 1 ;
}
2013-09-24 10:12:27 +04:00
u32 rsnd_read ( struct rsnd_priv * priv ,
struct rsnd_mod * mod , enum rsnd_reg reg )
{
struct rsnd_gen * gen = rsnd_priv_to_gen ( priv ) ;
u32 val ;
2013-11-29 06:43:13 +04:00
if ( ! rsnd_is_accessible_reg ( priv , gen , reg ) )
return 0 ;
2013-09-24 10:12:27 +04:00
regmap_fields_read ( gen - > regs [ reg ] , rsnd_mod_id ( mod ) , & val ) ;
return val ;
}
void rsnd_write ( struct rsnd_priv * priv ,
struct rsnd_mod * mod ,
enum rsnd_reg reg , u32 data )
{
struct rsnd_gen * gen = rsnd_priv_to_gen ( priv ) ;
2013-11-29 06:43:13 +04:00
if ( ! rsnd_is_accessible_reg ( priv , gen , reg ) )
return ;
2013-09-24 10:12:27 +04:00
regmap_fields_write ( gen - > regs [ reg ] , rsnd_mod_id ( mod ) , data ) ;
}
void rsnd_bset ( struct rsnd_priv * priv , struct rsnd_mod * mod ,
enum rsnd_reg reg , u32 mask , u32 data )
{
struct rsnd_gen * gen = rsnd_priv_to_gen ( priv ) ;
2013-11-29 06:43:13 +04:00
if ( ! rsnd_is_accessible_reg ( priv , gen , reg ) )
return ;
2013-09-24 10:12:27 +04:00
regmap_fields_update_bits ( gen - > regs [ reg ] , rsnd_mod_id ( mod ) ,
mask , data ) ;
}
2013-11-29 06:43:01 +04:00
static int rsnd_gen_regmap_init ( struct rsnd_priv * priv ,
struct rsnd_gen * gen ,
struct reg_field * regf )
{
int i ;
struct device * dev = rsnd_priv_to_dev ( priv ) ;
struct regmap_config regc ;
memset ( & regc , 0 , sizeof ( regc ) ) ;
regc . reg_bits = 32 ;
regc . val_bits = 32 ;
gen - > regmap = devm_regmap_init ( dev , & rsnd_regmap_bus , priv , & regc ) ;
if ( IS_ERR ( gen - > regmap ) ) {
dev_err ( dev , " regmap error %ld \n " , PTR_ERR ( gen - > regmap ) ) ;
return PTR_ERR ( gen - > regmap ) ;
}
for ( i = 0 ; i < RSND_REG_MAX ; i + + ) {
2013-11-29 06:43:13 +04:00
gen - > regs [ i ] = NULL ;
if ( ! regf [ i ] . reg )
continue ;
2013-11-29 06:43:01 +04:00
gen - > regs [ i ] = devm_regmap_field_alloc ( dev , gen - > regmap , regf [ i ] ) ;
if ( IS_ERR ( gen - > regs [ i ] ) )
return PTR_ERR ( gen - > regs [ i ] ) ;
}
return 0 ;
}
2013-07-22 08:36:21 +04:00
2014-05-23 10:25:54 +04:00
/*
* DMA read / write register offset
*
* RSND_xxx_I_N for Audio DMAC input
* RSND_xxx_O_N for Audio DMAC output
* RSND_xxx_I_P for Audio DMAC peri peri input
* RSND_xxx_O_P for Audio DMAC peri peri output
*
* ex ) R - Car H2 case
* mod / DMAC in / DMAC out / DMAC PP in / DMAC pp out
* SSI : 0xec541000 / 0xec241008 / 0xec24100c / 0xec400000 / 0xec400000
* SCU : 0xec500000 / 0xec000000 / 0xec004000 / 0xec300000 / 0xec304000
* CMD : 0xec500000 / 0xec008000 0xec308000
*/
# define RDMA_SSI_I_N(addr, i) (addr ##_reg - 0x00300000 + (0x40 * i) + 0x8)
# define RDMA_SSI_O_N(addr, i) (addr ##_reg - 0x00300000 + (0x40 * i) + 0xc)
# define RDMA_SSI_I_P(addr, i) (addr ##_reg - 0x00141000 + (0x1000 * i))
# define RDMA_SSI_O_P(addr, i) (addr ##_reg - 0x00141000 + (0x1000 * i))
# define RDMA_SRC_I_N(addr, i) (addr ##_reg - 0x00500000 + (0x400 * i))
# define RDMA_SRC_O_N(addr, i) (addr ##_reg - 0x004fc000 + (0x400 * i))
# define RDMA_SRC_I_P(addr, i) (addr ##_reg - 0x00200000 + (0x400 * i))
# define RDMA_SRC_O_P(addr, i) (addr ##_reg - 0x001fc000 + (0x400 * i))
# define RDMA_CMD_O_N(addr, i) (addr ##_reg - 0x004f8000 + (0x400 * i))
# define RDMA_CMD_O_P(addr, i) (addr ##_reg - 0x001f8000 + (0x400 * i))
2014-06-18 12:54:43 +04:00
static void rsnd_gen2_dma_addr ( struct rsnd_priv * priv ,
2014-05-23 10:25:54 +04:00
struct rsnd_dma * dma ,
struct dma_slave_config * cfg ,
int is_play , int slave_id )
{
struct platform_device * pdev = rsnd_priv_to_pdev ( priv ) ;
struct device * dev = rsnd_priv_to_dev ( priv ) ;
struct rsnd_mod * mod = rsnd_dma_to_mod ( dma ) ;
struct rsnd_dai_stream * io = rsnd_mod_to_io ( mod ) ;
dma_addr_t ssi_reg = platform_get_resource ( pdev ,
IORESOURCE_MEM , RSND_GEN2_SSI ) - > start ;
dma_addr_t src_reg = platform_get_resource ( pdev ,
IORESOURCE_MEM , RSND_GEN2_SCU ) - > start ;
int is_ssi = ! ! ( rsnd_io_to_mod_ssi ( io ) = = mod ) ;
int use_src = ! ! rsnd_io_to_mod_src ( io ) ;
int use_dvc = ! ! rsnd_io_to_mod_dvc ( io ) ;
int id = rsnd_mod_id ( mod ) ;
struct dma_addr {
dma_addr_t src_addr ;
dma_addr_t dst_addr ;
} dma_addrs [ 2 ] [ 2 ] [ 3 ] = {
{ /* SRC */
/* Capture */
{ { 0 , 0 } ,
{ RDMA_SRC_O_N ( src , id ) , 0 } ,
{ RDMA_CMD_O_N ( src , id ) , 0 } } ,
/* Playback */
{ { 0 , 0 , } ,
{ 0 , RDMA_SRC_I_N ( src , id ) } ,
{ 0 , RDMA_SRC_I_N ( src , id ) } }
} , { /* SSI */
/* Capture */
{ { RDMA_SSI_O_N ( ssi , id ) , 0 } ,
{ RDMA_SSI_O_P ( ssi , id ) , RDMA_SRC_I_P ( src , id ) } ,
{ RDMA_SSI_O_P ( ssi , id ) , RDMA_SRC_I_P ( src , id ) } } ,
/* Playback */
{ { 0 , RDMA_SSI_I_N ( ssi , id ) } ,
{ RDMA_SRC_O_P ( src , id ) , RDMA_SSI_I_P ( ssi , id ) } ,
{ RDMA_CMD_O_P ( src , id ) , RDMA_SSI_I_P ( ssi , id ) } }
}
} ;
/* it shouldn't happen */
if ( use_dvc & ! use_src ) {
dev_err ( dev , " DVC is selected without SRC \n " ) ;
return ;
}
cfg - > src_addr = dma_addrs [ is_ssi ] [ is_play ] [ use_src + use_dvc ] . src_addr ;
cfg - > dst_addr = dma_addrs [ is_ssi ] [ is_play ] [ use_src + use_dvc ] . dst_addr ;
dev_dbg ( dev , " dma%d addr - src : %x / dst : %x \n " ,
id , cfg - > src_addr , cfg - > dst_addr ) ;
}
2014-06-18 12:54:43 +04:00
void rsnd_gen_dma_addr ( struct rsnd_priv * priv ,
struct rsnd_dma * dma ,
struct dma_slave_config * cfg ,
int is_play , int slave_id )
{
cfg - > slave_id = slave_id ;
cfg - > src_addr = 0 ;
cfg - > dst_addr = 0 ;
cfg - > direction = is_play ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM ;
/*
* gen1 uses default DMA addr
*/
if ( rsnd_is_gen1 ( priv ) )
return ;
rsnd_gen2_dma_addr ( priv , dma , cfg , is_play , slave_id ) ;
}
2013-11-29 06:43:23 +04:00
/*
* Gen2
*/
2013-11-29 06:43:45 +04:00
/* single address mapping */
# define RSND_GEN2_S_REG(gen, reg, id, offset) \
2013-12-10 05:26:01 +04:00
RSND_REG_SET ( gen , RSND_REG_ # # id , RSND_GEN2_ # # reg , offset , 0 , 10 )
2013-11-29 06:43:45 +04:00
/* multi address mapping */
# define RSND_GEN2_M_REG(gen, reg, id, offset, _id_offset) \
2013-12-10 05:26:01 +04:00
RSND_REG_SET ( gen , RSND_REG_ # # id , RSND_GEN2_ # # reg , offset , _id_offset , 10 )
2013-11-29 06:43:45 +04:00
static int rsnd_gen2_regmap_init ( struct rsnd_priv * priv , struct rsnd_gen * gen )
{
struct reg_field regf [ RSND_REG_MAX ] = {
RSND_GEN2_S_REG ( gen , SSIU , SSI_MODE0 , 0x800 ) ,
RSND_GEN2_S_REG ( gen , SSIU , SSI_MODE1 , 0x804 ) ,
/* FIXME: it needs SSI_MODE2/3 in the future */
2014-01-24 06:42:00 +04:00
RSND_GEN2_M_REG ( gen , SSIU , SSI_BUSIF_MODE , 0x0 , 0x80 ) ,
RSND_GEN2_M_REG ( gen , SSIU , SSI_BUSIF_ADINR , 0x4 , 0x80 ) ,
RSND_GEN2_M_REG ( gen , SSIU , SSI_CTRL , 0x10 , 0x80 ) ,
2013-11-29 06:43:45 +04:00
RSND_GEN2_M_REG ( gen , SSIU , INT_ENABLE , 0x18 , 0x80 ) ,
2014-01-24 06:42:00 +04:00
RSND_GEN2_M_REG ( gen , SCU , SRC_BUSIF_MODE , 0x0 , 0x20 ) ,
RSND_GEN2_M_REG ( gen , SCU , SRC_ROUTE_MODE0 , 0xc , 0x20 ) ,
RSND_GEN2_M_REG ( gen , SCU , SRC_CTRL , 0x10 , 0x20 ) ,
2014-05-09 04:44:49 +04:00
RSND_GEN2_M_REG ( gen , SCU , CMD_ROUTE_SLCT , 0x18c , 0x20 ) ,
RSND_GEN2_M_REG ( gen , SCU , CMD_CTRL , 0x190 , 0x20 ) ,
2014-01-24 06:42:00 +04:00
RSND_GEN2_M_REG ( gen , SCU , SRC_SWRSR , 0x200 , 0x40 ) ,
RSND_GEN2_M_REG ( gen , SCU , SRC_SRCIR , 0x204 , 0x40 ) ,
RSND_GEN2_M_REG ( gen , SCU , SRC_ADINR , 0x214 , 0x40 ) ,
RSND_GEN2_M_REG ( gen , SCU , SRC_IFSCR , 0x21c , 0x40 ) ,
RSND_GEN2_M_REG ( gen , SCU , SRC_IFSVR , 0x220 , 0x40 ) ,
RSND_GEN2_M_REG ( gen , SCU , SRC_SRCCR , 0x224 , 0x40 ) ,
RSND_GEN2_M_REG ( gen , SCU , SRC_BSDSR , 0x22c , 0x40 ) ,
RSND_GEN2_M_REG ( gen , SCU , SRC_BSISR , 0x238 , 0x40 ) ,
2014-05-09 04:44:49 +04:00
RSND_GEN2_M_REG ( gen , SCU , DVC_SWRSR , 0xe00 , 0x100 ) ,
RSND_GEN2_M_REG ( gen , SCU , DVC_DVUIR , 0xe04 , 0x100 ) ,
RSND_GEN2_M_REG ( gen , SCU , DVC_ADINR , 0xe08 , 0x100 ) ,
RSND_GEN2_M_REG ( gen , SCU , DVC_DVUCR , 0xe10 , 0x100 ) ,
RSND_GEN2_M_REG ( gen , SCU , DVC_ZCMCR , 0xe14 , 0x100 ) ,
RSND_GEN2_M_REG ( gen , SCU , DVC_VOL0R , 0xe28 , 0x100 ) ,
RSND_GEN2_M_REG ( gen , SCU , DVC_VOL1R , 0xe2c , 0x100 ) ,
RSND_GEN2_M_REG ( gen , SCU , DVC_DVUER , 0xe48 , 0x100 ) ,
2014-01-24 06:42:00 +04:00
2013-11-29 06:43:45 +04:00
RSND_GEN2_S_REG ( gen , ADG , BRRA , 0x00 ) ,
RSND_GEN2_S_REG ( gen , ADG , BRRB , 0x04 ) ,
RSND_GEN2_S_REG ( gen , ADG , SSICKR , 0x08 ) ,
RSND_GEN2_S_REG ( gen , ADG , AUDIO_CLK_SEL0 , 0x0c ) ,
RSND_GEN2_S_REG ( gen , ADG , AUDIO_CLK_SEL1 , 0x10 ) ,
RSND_GEN2_S_REG ( gen , ADG , AUDIO_CLK_SEL2 , 0x14 ) ,
2014-02-12 09:04:12 +04:00
RSND_GEN2_S_REG ( gen , ADG , DIV_EN , 0x30 ) ,
2014-01-24 06:42:00 +04:00
RSND_GEN2_S_REG ( gen , ADG , SRCIN_TIMSEL0 , 0x34 ) ,
RSND_GEN2_S_REG ( gen , ADG , SRCIN_TIMSEL1 , 0x38 ) ,
RSND_GEN2_S_REG ( gen , ADG , SRCIN_TIMSEL2 , 0x3c ) ,
RSND_GEN2_S_REG ( gen , ADG , SRCIN_TIMSEL3 , 0x40 ) ,
RSND_GEN2_S_REG ( gen , ADG , SRCIN_TIMSEL4 , 0x44 ) ,
RSND_GEN2_S_REG ( gen , ADG , SRCOUT_TIMSEL0 , 0x48 ) ,
RSND_GEN2_S_REG ( gen , ADG , SRCOUT_TIMSEL1 , 0x4c ) ,
RSND_GEN2_S_REG ( gen , ADG , SRCOUT_TIMSEL2 , 0x50 ) ,
RSND_GEN2_S_REG ( gen , ADG , SRCOUT_TIMSEL3 , 0x54 ) ,
RSND_GEN2_S_REG ( gen , ADG , SRCOUT_TIMSEL4 , 0x58 ) ,
2014-05-09 04:44:49 +04:00
RSND_GEN2_S_REG ( gen , ADG , CMDOUT_TIMSEL , 0x5c ) ,
2013-11-29 06:43:45 +04:00
RSND_GEN2_M_REG ( gen , SSI , SSICR , 0x00 , 0x40 ) ,
RSND_GEN2_M_REG ( gen , SSI , SSISR , 0x04 , 0x40 ) ,
RSND_GEN2_M_REG ( gen , SSI , SSITDR , 0x08 , 0x40 ) ,
RSND_GEN2_M_REG ( gen , SSI , SSIRDR , 0x0c , 0x40 ) ,
RSND_GEN2_M_REG ( gen , SSI , SSIWSR , 0x20 , 0x40 ) ,
} ;
return rsnd_gen_regmap_init ( priv , gen , regf ) ;
}
static int rsnd_gen2_probe ( struct platform_device * pdev ,
struct rsnd_priv * priv )
{
struct device * dev = rsnd_priv_to_dev ( priv ) ;
struct rsnd_gen * gen = rsnd_priv_to_gen ( priv ) ;
struct resource * scu_res ;
struct resource * adg_res ;
struct resource * ssiu_res ;
struct resource * ssi_res ;
int ret ;
/*
* map address
*/
scu_res = platform_get_resource ( pdev , IORESOURCE_MEM , RSND_GEN2_SCU ) ;
adg_res = platform_get_resource ( pdev , IORESOURCE_MEM , RSND_GEN2_ADG ) ;
ssiu_res = platform_get_resource ( pdev , IORESOURCE_MEM , RSND_GEN2_SSIU ) ;
ssi_res = platform_get_resource ( pdev , IORESOURCE_MEM , RSND_GEN2_SSI ) ;
gen - > base [ RSND_GEN2_SCU ] = devm_ioremap_resource ( dev , scu_res ) ;
gen - > base [ RSND_GEN2_ADG ] = devm_ioremap_resource ( dev , adg_res ) ;
gen - > base [ RSND_GEN2_SSIU ] = devm_ioremap_resource ( dev , ssiu_res ) ;
gen - > base [ RSND_GEN2_SSI ] = devm_ioremap_resource ( dev , ssi_res ) ;
if ( IS_ERR ( gen - > base [ RSND_GEN2_SCU ] ) | |
IS_ERR ( gen - > base [ RSND_GEN2_ADG ] ) | |
IS_ERR ( gen - > base [ RSND_GEN2_SSIU ] ) | |
IS_ERR ( gen - > base [ RSND_GEN2_SSI ] ) )
return - ENODEV ;
ret = rsnd_gen2_regmap_init ( priv , gen ) ;
if ( ret < 0 )
return ret ;
dev_dbg ( dev , " Gen2 device probed \n " ) ;
2014-05-13 03:10:20 +04:00
dev_dbg ( dev , " SCU : %pap => %p \n " , & scu_res - > start ,
2013-11-29 06:43:45 +04:00
gen - > base [ RSND_GEN2_SCU ] ) ;
2014-05-13 03:10:20 +04:00
dev_dbg ( dev , " ADG : %pap => %p \n " , & adg_res - > start ,
2013-11-29 06:43:45 +04:00
gen - > base [ RSND_GEN2_ADG ] ) ;
2014-05-13 03:10:20 +04:00
dev_dbg ( dev , " SSIU : %pap => %p \n " , & ssiu_res - > start ,
2013-11-29 06:43:45 +04:00
gen - > base [ RSND_GEN2_SSIU ] ) ;
2014-05-13 03:10:20 +04:00
dev_dbg ( dev , " SSI : %pap => %p \n " , & ssi_res - > start ,
2013-11-29 06:43:45 +04:00
gen - > base [ RSND_GEN2_SSI ] ) ;
return 0 ;
}
2013-11-29 06:43:23 +04:00
/*
* Gen1
*/
2013-09-24 10:12:27 +04:00
/* single address mapping */
# define RSND_GEN1_S_REG(gen, reg, id, offset) \
RSND_REG_SET ( gen , RSND_REG_ # # id , RSND_GEN1_ # # reg , offset , 0 , 9 )
2013-07-22 08:36:35 +04:00
2013-09-24 10:12:27 +04:00
/* multi address mapping */
# define RSND_GEN1_M_REG(gen, reg, id, offset, _id_offset) \
RSND_REG_SET ( gen , RSND_REG_ # # id , RSND_GEN1_ # # reg , offset , _id_offset , 9 )
static int rsnd_gen1_regmap_init ( struct rsnd_priv * priv , struct rsnd_gen * gen )
2013-07-22 08:36:35 +04:00
{
2013-09-24 10:12:27 +04:00
struct reg_field regf [ RSND_REG_MAX ] = {
RSND_GEN1_S_REG ( gen , SRU , SRC_ROUTE_SEL , 0x00 ) ,
RSND_GEN1_S_REG ( gen , SRU , SRC_TMG_SEL0 , 0x08 ) ,
RSND_GEN1_S_REG ( gen , SRU , SRC_TMG_SEL1 , 0x0c ) ,
RSND_GEN1_S_REG ( gen , SRU , SRC_TMG_SEL2 , 0x10 ) ,
2013-12-20 07:27:03 +04:00
RSND_GEN1_S_REG ( gen , SRU , SRC_ROUTE_CTRL , 0xc0 ) ,
2013-09-24 10:12:27 +04:00
RSND_GEN1_S_REG ( gen , SRU , SSI_MODE0 , 0xD0 ) ,
RSND_GEN1_S_REG ( gen , SRU , SSI_MODE1 , 0xD4 ) ,
2014-01-24 06:37:39 +04:00
RSND_GEN1_M_REG ( gen , SRU , SRC_BUSIF_MODE , 0x20 , 0x4 ) ,
2013-12-20 07:28:51 +04:00
RSND_GEN1_M_REG ( gen , SRU , SRC_ROUTE_MODE0 , 0x50 , 0x8 ) ,
RSND_GEN1_M_REG ( gen , SRU , SRC_SWRSR , 0x200 , 0x40 ) ,
RSND_GEN1_M_REG ( gen , SRU , SRC_SRCIR , 0x204 , 0x40 ) ,
2013-12-20 07:27:03 +04:00
RSND_GEN1_M_REG ( gen , SRU , SRC_ADINR , 0x214 , 0x40 ) ,
2013-12-20 07:28:51 +04:00
RSND_GEN1_M_REG ( gen , SRU , SRC_IFSCR , 0x21c , 0x40 ) ,
RSND_GEN1_M_REG ( gen , SRU , SRC_IFSVR , 0x220 , 0x40 ) ,
RSND_GEN1_M_REG ( gen , SRU , SRC_SRCCR , 0x224 , 0x40 ) ,
RSND_GEN1_M_REG ( gen , SRU , SRC_MNFSR , 0x228 , 0x40 ) ,
2013-09-24 10:12:27 +04:00
RSND_GEN1_S_REG ( gen , ADG , BRRA , 0x00 ) ,
RSND_GEN1_S_REG ( gen , ADG , BRRB , 0x04 ) ,
RSND_GEN1_S_REG ( gen , ADG , SSICKR , 0x08 ) ,
RSND_GEN1_S_REG ( gen , ADG , AUDIO_CLK_SEL0 , 0x0c ) ,
RSND_GEN1_S_REG ( gen , ADG , AUDIO_CLK_SEL1 , 0x10 ) ,
2013-12-20 07:28:51 +04:00
RSND_GEN1_S_REG ( gen , ADG , AUDIO_CLK_SEL3 , 0x18 ) ,
RSND_GEN1_S_REG ( gen , ADG , AUDIO_CLK_SEL4 , 0x1c ) ,
RSND_GEN1_S_REG ( gen , ADG , AUDIO_CLK_SEL5 , 0x20 ) ,
2013-09-24 10:12:27 +04:00
RSND_GEN1_M_REG ( gen , SSI , SSICR , 0x00 , 0x40 ) ,
RSND_GEN1_M_REG ( gen , SSI , SSISR , 0x04 , 0x40 ) ,
RSND_GEN1_M_REG ( gen , SSI , SSITDR , 0x08 , 0x40 ) ,
RSND_GEN1_M_REG ( gen , SSI , SSIRDR , 0x0c , 0x40 ) ,
RSND_GEN1_M_REG ( gen , SSI , SSIWSR , 0x20 , 0x40 ) ,
} ;
2013-11-29 06:43:01 +04:00
return rsnd_gen_regmap_init ( priv , gen , regf ) ;
2013-07-22 08:36:35 +04:00
}
2013-07-22 08:36:21 +04:00
static int rsnd_gen1_probe ( struct platform_device * pdev ,
struct rsnd_priv * priv )
{
2013-07-22 08:36:35 +04:00
struct device * dev = rsnd_priv_to_dev ( priv ) ;
struct rsnd_gen * gen = rsnd_priv_to_gen ( priv ) ;
struct resource * sru_res ;
2013-07-22 08:36:46 +04:00
struct resource * adg_res ;
2013-07-22 08:36:57 +04:00
struct resource * ssi_res ;
2013-09-24 10:12:27 +04:00
int ret ;
2013-07-22 08:36:35 +04:00
/*
* map address
*/
sru_res = platform_get_resource ( pdev , IORESOURCE_MEM , RSND_GEN1_SRU ) ;
2013-07-22 08:36:46 +04:00
adg_res = platform_get_resource ( pdev , IORESOURCE_MEM , RSND_GEN1_ADG ) ;
2013-07-22 08:36:57 +04:00
ssi_res = platform_get_resource ( pdev , IORESOURCE_MEM , RSND_GEN1_SSI ) ;
2013-07-22 08:36:35 +04:00
gen - > base [ RSND_GEN1_SRU ] = devm_ioremap_resource ( dev , sru_res ) ;
2013-07-22 08:36:46 +04:00
gen - > base [ RSND_GEN1_ADG ] = devm_ioremap_resource ( dev , adg_res ) ;
2013-07-22 08:36:57 +04:00
gen - > base [ RSND_GEN1_SSI ] = devm_ioremap_resource ( dev , ssi_res ) ;
2013-07-30 03:51:37 +04:00
if ( IS_ERR ( gen - > base [ RSND_GEN1_SRU ] ) | |
IS_ERR ( gen - > base [ RSND_GEN1_ADG ] ) | |
IS_ERR ( gen - > base [ RSND_GEN1_SSI ] ) )
2013-07-22 08:36:35 +04:00
return - ENODEV ;
2013-09-24 10:12:27 +04:00
ret = rsnd_gen1_regmap_init ( priv , gen ) ;
if ( ret < 0 )
return ret ;
2013-07-22 08:36:35 +04:00
dev_dbg ( dev , " Gen1 device probed \n " ) ;
2014-05-13 03:10:20 +04:00
dev_dbg ( dev , " SRU : %pap => %p \n " , & sru_res - > start ,
2013-07-22 08:36:35 +04:00
gen - > base [ RSND_GEN1_SRU ] ) ;
2014-05-13 03:10:20 +04:00
dev_dbg ( dev , " ADG : %pap => %p \n " , & adg_res - > start ,
2013-07-22 08:36:46 +04:00
gen - > base [ RSND_GEN1_ADG ] ) ;
2014-05-13 03:10:20 +04:00
dev_dbg ( dev , " SSI : %pap => %p \n " , & ssi_res - > start ,
2013-07-22 08:36:57 +04:00
gen - > base [ RSND_GEN1_SSI ] ) ;
2013-07-22 08:36:35 +04:00
2013-07-22 08:36:21 +04:00
return 0 ;
2013-07-22 08:36:57 +04:00
2013-07-22 08:36:21 +04:00
}
/*
* Gen
*/
2014-03-18 06:29:55 +04:00
static void rsnd_of_parse_gen ( struct platform_device * pdev ,
const struct rsnd_of_data * of_data ,
struct rsnd_priv * priv )
{
struct rcar_snd_info * info = priv - > info ;
if ( ! of_data )
return ;
info - > flags = of_data - > flags ;
}
2013-07-22 08:36:21 +04:00
int rsnd_gen_probe ( struct platform_device * pdev ,
2014-03-18 06:29:55 +04:00
const struct rsnd_of_data * of_data ,
2013-07-22 08:36:21 +04:00
struct rsnd_priv * priv )
{
struct device * dev = rsnd_priv_to_dev ( priv ) ;
struct rsnd_gen * gen ;
2013-11-29 06:43:34 +04:00
int ret ;
2013-07-22 08:36:21 +04:00
2014-03-18 06:29:55 +04:00
rsnd_of_parse_gen ( pdev , of_data , priv ) ;
2013-07-22 08:36:21 +04:00
gen = devm_kzalloc ( dev , sizeof ( * gen ) , GFP_KERNEL ) ;
if ( ! gen ) {
dev_err ( dev , " GEN allocate failed \n " ) ;
return - ENOMEM ;
}
2013-11-29 06:43:34 +04:00
priv - > gen = gen ;
2013-09-02 07:31:16 +04:00
2013-11-29 06:43:45 +04:00
ret = - ENODEV ;
if ( rsnd_is_gen1 ( priv ) )
2014-02-25 10:15:00 +04:00
ret = rsnd_gen1_probe ( pdev , priv ) ;
2013-11-29 06:43:45 +04:00
else if ( rsnd_is_gen2 ( priv ) )
2014-02-25 10:15:00 +04:00
ret = rsnd_gen2_probe ( pdev , priv ) ;
2013-11-29 06:43:45 +04:00
if ( ret < 0 )
2013-09-02 07:31:16 +04:00
dev_err ( dev , " unknown generation R-Car sound device \n " ) ;
2013-11-29 06:43:34 +04:00
return ret ;
2013-07-22 08:36:21 +04:00
}