2012-04-08 21:17:50 -07:00
/*
* ASoC simple sound card support
*
* Copyright ( C ) 2012 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 .
*/
2013-11-20 15:25:02 +09:00
# include <linux/clk.h>
2014-02-14 09:34:36 +08:00
# include <linux/device.h>
2012-04-08 21:17:50 -07:00
# include <linux/module.h>
2013-11-20 15:25:02 +09:00
# include <linux/of.h>
2012-04-08 21:17:50 -07:00
# include <linux/platform_device.h>
2014-01-14 12:35:32 +08:00
# include <linux/string.h>
2012-04-08 21:17:50 -07:00
# include <sound/simple_card.h>
2014-02-14 09:34:36 +08:00
# include <sound/soc-dai.h>
# include <sound/soc.h>
2012-04-08 21:17:50 -07:00
2014-01-15 16:51:56 +01:00
struct simple_card_data {
struct snd_soc_card snd_card ;
2014-03-20 10:52:41 +01:00
struct simple_dai_props {
struct asoc_simple_dai cpu_dai ;
struct asoc_simple_dai codec_dai ;
} * dai_props ;
2014-05-22 17:31:49 +02:00
unsigned int mclk_fs ;
2014-03-20 10:52:41 +01:00
struct snd_soc_dai_link dai_link [ ] ; /* dynamically allocated */
2014-01-15 16:51:56 +01:00
} ;
2014-05-22 17:31:49 +02:00
static int asoc_simple_card_hw_params ( struct snd_pcm_substream * substream ,
struct snd_pcm_hw_params * params )
{
struct snd_soc_pcm_runtime * rtd = substream - > private_data ;
struct snd_soc_dai * codec_dai = rtd - > codec_dai ;
struct simple_card_data * priv = snd_soc_card_get_drvdata ( rtd - > card ) ;
unsigned int mclk ;
int ret = 0 ;
if ( priv - > mclk_fs ) {
mclk = params_rate ( params ) * priv - > mclk_fs ;
ret = snd_soc_dai_set_sysclk ( codec_dai , 0 , mclk ,
SND_SOC_CLOCK_IN ) ;
}
return ret ;
}
static struct snd_soc_ops asoc_simple_card_ops = {
. hw_params = asoc_simple_card_hw_params ,
} ;
2013-01-10 16:49:11 -08:00
static int __asoc_simple_card_dai_init ( struct snd_soc_dai * dai ,
2014-01-24 15:43:01 +08:00
struct asoc_simple_dai * set )
2013-01-10 16:49:11 -08:00
{
2014-01-24 15:43:00 +08:00
int ret ;
2013-01-10 16:49:11 -08:00
2014-01-24 15:43:01 +08:00
if ( set - > fmt ) {
ret = snd_soc_dai_set_fmt ( dai , set - > fmt ) ;
2014-01-24 15:43:00 +08:00
if ( ret & & ret ! = - ENOTSUPP ) {
dev_err ( dai - > dev , " simple-card: set_fmt error \n " ) ;
goto err ;
}
2013-10-17 22:46:49 -07:00
}
2014-01-24 15:43:00 +08:00
if ( set - > sysclk ) {
2013-01-10 16:49:11 -08:00
ret = snd_soc_dai_set_sysclk ( dai , 0 , set - > sysclk , 0 ) ;
2014-01-24 15:43:00 +08:00
if ( ret & & ret ! = - ENOTSUPP ) {
dev_err ( dai - > dev , " simple-card: set_sysclk error \n " ) ;
goto err ;
}
}
2014-02-14 09:34:36 +08:00
if ( set - > slots ) {
ret = snd_soc_dai_set_tdm_slot ( dai , 0 , 0 ,
set - > slots ,
set - > slot_width ) ;
if ( ret & & ret ! = - ENOTSUPP ) {
dev_err ( dai - > dev , " simple-card: set_tdm_slot error \n " ) ;
goto err ;
}
}
2014-01-24 15:43:00 +08:00
ret = 0 ;
2013-01-10 16:49:11 -08:00
2014-01-24 15:43:00 +08:00
err :
2013-01-10 16:49:11 -08:00
return ret ;
}
2012-04-08 21:17:50 -07:00
static int asoc_simple_card_dai_init ( struct snd_soc_pcm_runtime * rtd )
{
2014-04-24 19:14:00 +08:00
struct simple_card_data * priv = snd_soc_card_get_drvdata ( rtd - > card ) ;
2012-04-08 21:17:50 -07:00
struct snd_soc_dai * codec = rtd - > codec_dai ;
struct snd_soc_dai * cpu = rtd - > cpu_dai ;
2014-03-20 11:49:55 +01:00
struct simple_dai_props * dai_props ;
int num , ret ;
2012-04-08 21:17:50 -07:00
2014-03-20 11:49:55 +01:00
num = rtd - rtd - > card - > rtd ;
dai_props = & priv - > dai_props [ num ] ;
ret = __asoc_simple_card_dai_init ( codec , & dai_props - > codec_dai ) ;
2013-01-10 16:49:11 -08:00
if ( ret < 0 )
return ret ;
2012-04-08 21:17:50 -07:00
2014-03-20 11:49:55 +01:00
ret = __asoc_simple_card_dai_init ( cpu , & dai_props - > cpu_dai ) ;
2013-01-10 16:49:11 -08:00
if ( ret < 0 )
return ret ;
2012-04-08 21:17:50 -07:00
return 0 ;
}
2013-11-20 15:25:02 +09:00
static int
asoc_simple_card_sub_parse_of ( struct device_node * np ,
struct asoc_simple_dai * dai ,
2014-08-18 15:00:15 +08:00
struct device_node * * p_node ,
2014-01-15 16:51:48 +01:00
const char * * name )
2013-11-20 15:25:02 +09:00
{
2014-01-15 16:51:41 +01:00
struct device_node * node ;
2013-11-20 15:25:02 +09:00
struct clk * clk ;
2014-06-13 13:04:36 +03:00
u32 val ;
2013-11-20 15:25:02 +09:00
int ret ;
/*
* get node via " sound-dai = <&phandle port> "
* it will be used as xxx_of_node on soc_bind_dai_link ( )
*/
2014-01-15 16:51:41 +01:00
node = of_parse_phandle ( np , " sound-dai " , 0 ) ;
if ( ! node )
2013-11-20 15:25:02 +09:00
return - ENODEV ;
2014-01-15 16:51:41 +01:00
* p_node = node ;
2013-11-20 15:25:02 +09:00
/* get dai->name */
2014-01-15 16:51:48 +01:00
ret = snd_soc_of_get_dai_name ( np , name ) ;
2013-11-20 15:25:02 +09:00
if ( ret < 0 )
2014-03-11 10:03:40 +01:00
return ret ;
2013-11-20 15:25:02 +09:00
2014-02-14 09:34:36 +08:00
/* parse TDM slot */
ret = snd_soc_of_parse_tdm_slot ( np , & dai - > slots , & dai - > slot_width ) ;
if ( ret )
2014-03-11 10:03:40 +01:00
return ret ;
2014-02-14 09:34:36 +08:00
2013-11-20 15:25:02 +09:00
/*
* dai - > sysclk come from
* " clocks = <&xxx> " ( if system has common clock )
* or " system-clock-frequency = <xxx> "
2013-12-23 15:25:38 +08:00
* or device ' s module clock .
2013-11-20 15:25:02 +09:00
*/
2013-12-23 15:25:38 +08:00
if ( of_property_read_bool ( np , " clocks " ) ) {
clk = of_clk_get ( np , 0 ) ;
if ( IS_ERR ( clk ) ) {
ret = PTR_ERR ( clk ) ;
2014-03-11 10:03:40 +01:00
return ret ;
2013-12-23 15:25:38 +08:00
}
dai - > sysclk = clk_get_rate ( clk ) ;
2014-06-13 13:04:36 +03:00
} else if ( ! of_property_read_u32 ( np , " system-clock-frequency " , & val ) ) {
dai - > sysclk = val ;
2013-12-23 15:25:38 +08:00
} else {
2014-01-15 16:51:41 +01:00
clk = of_clk_get ( node , 0 ) ;
2014-01-06 12:34:36 +08:00
if ( ! IS_ERR ( clk ) )
dai - > sysclk = clk_get_rate ( clk ) ;
2013-12-23 15:25:38 +08:00
}
2013-11-20 15:25:02 +09:00
2014-03-11 10:03:40 +01:00
return 0 ;
2013-11-20 15:25:02 +09:00
}
2014-08-27 20:07:46 -07:00
static int asoc_simple_card_dai_link_of ( struct device_node * node ,
struct device * dev ,
struct snd_soc_dai_link * dai_link ,
struct simple_dai_props * dai_props ,
bool is_top_level_node )
2014-03-20 11:49:55 +01:00
{
2014-03-24 12:15:25 +02:00
struct device_node * np = NULL ;
struct device_node * bitclkmaster = NULL ;
struct device_node * framemaster = NULL ;
unsigned int daifmt ;
char * name ;
char prop [ 128 ] ;
char * prefix = " " ;
2014-03-20 11:49:55 +01:00
int ret ;
2014-04-24 19:42:00 +03:00
if ( is_top_level_node )
prefix = " simple-audio-card, " ;
2014-03-24 12:15:25 +02:00
daifmt = snd_soc_of_parse_daifmt ( node , prefix ,
& bitclkmaster , & framemaster ) ;
daifmt & = ~ SND_SOC_DAIFMT_MASTER_MASK ;
snprintf ( prop , sizeof ( prop ) , " %scpu " , prefix ) ;
np = of_get_child_by_name ( node , prop ) ;
if ( ! np ) {
ret = - EINVAL ;
2014-04-24 19:13:59 +08:00
dev_err ( dev , " %s: Can't find %s DT node \n " , __func__ , prop ) ;
2014-03-24 12:15:25 +02:00
goto dai_link_of_err ;
2014-03-20 11:49:55 +01:00
}
2014-03-24 12:15:25 +02:00
ret = asoc_simple_card_sub_parse_of ( np , & dai_props - > cpu_dai ,
& dai_link - > cpu_of_node ,
& dai_link - > cpu_dai_name ) ;
2014-03-20 11:49:55 +01:00
if ( ret < 0 )
2014-03-24 12:15:25 +02:00
goto dai_link_of_err ;
dai_props - > cpu_dai . fmt = daifmt ;
2014-04-24 19:14:00 +08:00
switch ( ( ( np = = bitclkmaster ) < < 4 ) | ( np = = framemaster ) ) {
2014-03-24 12:15:25 +02:00
case 0x11 :
dai_props - > cpu_dai . fmt | = SND_SOC_DAIFMT_CBS_CFS ;
break ;
case 0x10 :
dai_props - > cpu_dai . fmt | = SND_SOC_DAIFMT_CBS_CFM ;
break ;
case 0x01 :
dai_props - > cpu_dai . fmt | = SND_SOC_DAIFMT_CBM_CFS ;
break ;
default :
dai_props - > cpu_dai . fmt | = SND_SOC_DAIFMT_CBM_CFM ;
break ;
}
2014-03-20 11:49:55 +01:00
2014-03-24 12:15:25 +02:00
of_node_put ( np ) ;
snprintf ( prop , sizeof ( prop ) , " %scodec " , prefix ) ;
np = of_get_child_by_name ( node , prop ) ;
if ( ! np ) {
ret = - EINVAL ;
2014-04-24 19:13:59 +08:00
dev_err ( dev , " %s: Can't find %s DT node \n " , __func__ , prop ) ;
2014-03-24 12:15:25 +02:00
goto dai_link_of_err ;
2014-03-20 11:49:55 +01:00
}
2014-03-24 12:15:25 +02:00
ret = asoc_simple_card_sub_parse_of ( np , & dai_props - > codec_dai ,
& dai_link - > codec_of_node ,
& dai_link - > codec_dai_name ) ;
if ( ret < 0 )
goto dai_link_of_err ;
if ( strlen ( prefix ) & & ! bitclkmaster & & ! framemaster ) {
/* No dai-link level and master setting was not found from
sound node level , revert back to legacy DT parsing and
take the settings from codec node . */
dev_dbg ( dev , " %s: Revert to legacy daifmt parsing \n " ,
__func__ ) ;
dai_props - > cpu_dai . fmt = dai_props - > codec_dai . fmt =
snd_soc_of_parse_daifmt ( np , NULL , NULL , NULL ) |
( daifmt & ~ SND_SOC_DAIFMT_CLOCK_MASK ) ;
} else {
dai_props - > codec_dai . fmt = daifmt ;
2014-04-24 19:14:00 +08:00
switch ( ( ( np = = bitclkmaster ) < < 4 ) | ( np = = framemaster ) ) {
2014-03-24 12:15:25 +02:00
case 0x11 :
dai_props - > codec_dai . fmt | = SND_SOC_DAIFMT_CBM_CFM ;
break ;
case 0x10 :
dai_props - > codec_dai . fmt | = SND_SOC_DAIFMT_CBM_CFS ;
break ;
case 0x01 :
dai_props - > codec_dai . fmt | = SND_SOC_DAIFMT_CBS_CFM ;
break ;
default :
dai_props - > codec_dai . fmt | = SND_SOC_DAIFMT_CBS_CFS ;
break ;
}
}
if ( ! dai_link - > cpu_dai_name | | ! dai_link - > codec_dai_name ) {
2014-04-24 19:14:00 +08:00
ret = - EINVAL ;
goto dai_link_of_err ;
2014-03-24 12:15:25 +02:00
}
/* simple-card assumes platform == cpu */
dai_link - > platform_of_node = dai_link - > cpu_of_node ;
/* Link name is created from CPU/CODEC dai name */
name = devm_kzalloc ( dev ,
strlen ( dai_link - > cpu_dai_name ) +
strlen ( dai_link - > codec_dai_name ) + 2 ,
GFP_KERNEL ) ;
sprintf ( name , " %s-%s " , dai_link - > cpu_dai_name ,
dai_link - > codec_dai_name ) ;
dai_link - > name = dai_link - > stream_name = name ;
2014-05-22 17:31:49 +02:00
dai_link - > ops = & asoc_simple_card_ops ;
2014-03-24 12:15:25 +02:00
dev_dbg ( dev , " \t name : %s \n " , dai_link - > stream_name ) ;
dev_dbg ( dev , " \t cpu : %s / %04x / %d \n " ,
dai_link - > cpu_dai_name ,
dai_props - > cpu_dai . fmt ,
dai_props - > cpu_dai . sysclk ) ;
dev_dbg ( dev , " \t codec : %s / %04x / %d \n " ,
dai_link - > codec_dai_name ,
dai_props - > codec_dai . fmt ,
dai_props - > codec_dai . sysclk ) ;
dai_link_of_err :
if ( np )
of_node_put ( np ) ;
if ( bitclkmaster )
of_node_put ( bitclkmaster ) ;
if ( framemaster )
of_node_put ( framemaster ) ;
2014-03-20 11:49:55 +01:00
return ret ;
}
2013-11-20 15:25:02 +09:00
static int asoc_simple_card_parse_of ( struct device_node * node ,
2014-01-15 16:52:00 +01:00
struct simple_card_data * priv ,
2014-03-20 11:49:55 +01:00
struct device * dev ,
int multi )
2013-11-20 15:25:02 +09:00
{
2014-01-15 16:52:00 +01:00
struct snd_soc_dai_link * dai_link = priv - > snd_card . dai_link ;
2014-03-20 11:49:55 +01:00
struct simple_dai_props * dai_props = priv - > dai_props ;
2014-06-13 13:04:36 +03:00
u32 val ;
2013-12-23 12:57:01 +08:00
int ret ;
2013-11-20 15:25:02 +09:00
2014-01-24 15:43:02 +08:00
/* parsing the card name from DT */
snd_soc_of_parse_card_name ( & priv - > snd_card , " simple-audio-card,name " ) ;
2014-02-08 15:59:53 +08:00
/* off-codec widgets */
if ( of_property_read_bool ( node , " simple-audio-card,widgets " ) ) {
ret = snd_soc_of_parse_audio_simple_widgets ( & priv - > snd_card ,
" simple-audio-card,widgets " ) ;
if ( ret )
return ret ;
}
2013-12-23 12:57:01 +08:00
/* DAPM routes */
2014-01-07 09:15:16 +08:00
if ( of_property_read_bool ( node , " simple-audio-card,routing " ) ) {
2014-01-15 16:52:00 +01:00
ret = snd_soc_of_parse_audio_routing ( & priv - > snd_card ,
2014-01-07 09:15:16 +08:00
" simple-audio-card,routing " ) ;
2014-01-07 09:13:42 +08:00
if ( ret )
return ret ;
}
2013-12-23 12:57:01 +08:00
2014-05-22 17:31:49 +02:00
/* Factor to mclk, used in hw_params() */
2014-06-13 13:04:36 +03:00
ret = of_property_read_u32 ( node , " simple-audio-card,mclk-fs " , & val ) ;
if ( ret = = 0 )
priv - > mclk_fs = val ;
2014-05-22 17:31:49 +02:00
2014-03-24 12:15:25 +02:00
dev_dbg ( dev , " New simple-card: %s \n " , priv - > snd_card . name ?
priv - > snd_card . name : " " ) ;
if ( multi ) {
struct device_node * np = NULL ;
int i ;
for ( i = 0 ; ( np = of_get_next_child ( node , np ) ) ; i + + ) {
dev_dbg ( dev , " \t link %d: \n " , i ) ;
2014-08-27 20:07:46 -07:00
ret = asoc_simple_card_dai_link_of ( np , dev ,
dai_link + i ,
dai_props + i ,
false ) ;
2014-03-24 12:15:25 +02:00
if ( ret < 0 ) {
of_node_put ( np ) ;
return ret ;
}
2014-03-20 11:49:55 +01:00
}
2014-03-24 12:15:25 +02:00
} else {
2014-08-27 20:07:46 -07:00
ret = asoc_simple_card_dai_link_of ( node , dev ,
dai_link , dai_props , true ) ;
2014-03-20 11:49:55 +01:00
if ( ret < 0 )
2014-03-24 12:15:25 +02:00
return ret ;
2014-03-20 11:49:55 +01:00
}
2013-12-20 14:39:50 +08:00
2014-01-24 15:43:02 +08:00
if ( ! priv - > snd_card . name )
2014-03-24 12:15:25 +02:00
priv - > snd_card . name = priv - > snd_card . dai_link - > name ;
2014-02-27 18:25:24 -08:00
2013-11-20 15:25:02 +09:00
return 0 ;
}
2014-03-11 10:03:40 +01:00
/* update the reference count of the devices nodes at end of probe */
static int asoc_simple_card_unref ( struct platform_device * pdev )
{
struct snd_soc_card * card = platform_get_drvdata ( pdev ) ;
struct snd_soc_dai_link * dai_link ;
struct device_node * np ;
int num_links ;
for ( num_links = 0 , dai_link = card - > dai_link ;
num_links < card - > num_links ;
num_links + + , dai_link + + ) {
np = ( struct device_node * ) dai_link - > cpu_of_node ;
if ( np )
of_node_put ( np ) ;
np = ( struct device_node * ) dai_link - > codec_of_node ;
if ( np )
of_node_put ( np ) ;
}
return 0 ;
}
2012-04-08 21:17:50 -07:00
static int asoc_simple_card_probe ( struct platform_device * pdev )
{
2014-01-15 16:51:56 +01:00
struct simple_card_data * priv ;
2014-01-15 16:51:45 +01:00
struct snd_soc_dai_link * dai_link ;
2013-11-20 15:25:02 +09:00
struct device_node * np = pdev - > dev . of_node ;
2012-12-25 22:52:33 -08:00
struct device * dev = & pdev - > dev ;
2014-03-20 11:49:55 +01:00
int num_links , multi , ret ;
/* get the number of DAI links */
if ( np & & of_get_child_by_name ( np , " simple-audio-card,dai-link " ) ) {
num_links = of_get_child_count ( np ) ;
multi = 1 ;
} else {
num_links = 1 ;
multi = 0 ;
}
2012-04-08 21:17:50 -07:00
2014-03-20 10:52:41 +01:00
/* allocate the private data and the DAI link array */
priv = devm_kzalloc ( dev ,
2014-03-20 11:49:55 +01:00
sizeof ( * priv ) + sizeof ( * dai_link ) * num_links ,
2014-03-20 10:52:41 +01:00
GFP_KERNEL ) ;
2014-01-15 16:51:52 +01:00
if ( ! priv )
2014-01-14 12:35:32 +08:00
return - ENOMEM ;
2014-01-15 16:51:41 +01:00
/*
* init snd_soc_card
*/
2014-01-15 16:51:52 +01:00
priv - > snd_card . owner = THIS_MODULE ;
priv - > snd_card . dev = dev ;
2014-03-20 10:52:41 +01:00
dai_link = priv - > dai_link ;
2014-01-15 16:51:52 +01:00
priv - > snd_card . dai_link = dai_link ;
2014-03-20 11:49:55 +01:00
priv - > snd_card . num_links = num_links ;
2014-01-15 16:51:41 +01:00
2014-03-20 10:52:41 +01:00
/* get room for the other properties */
priv - > dai_props = devm_kzalloc ( dev ,
2014-03-20 11:49:55 +01:00
sizeof ( * priv - > dai_props ) * num_links ,
2014-03-20 10:52:41 +01:00
GFP_KERNEL ) ;
if ( ! priv - > dai_props )
return - ENOMEM ;
2013-11-20 15:25:02 +09:00
if ( np & & of_device_is_available ( np ) ) {
2014-01-14 12:35:32 +08:00
2014-03-20 11:49:55 +01:00
ret = asoc_simple_card_parse_of ( np , priv , dev , multi ) ;
2014-01-14 12:35:32 +08:00
if ( ret < 0 ) {
if ( ret ! = - EPROBE_DEFER )
dev_err ( dev , " parse error %d \n " , ret ) ;
2014-03-11 10:03:40 +01:00
goto err ;
2013-11-20 15:25:02 +09:00
}
2014-03-20 11:49:55 +01:00
/*
* soc_bind_dai_link ( ) will check cpu name
* after of_node matching if dai_link has cpu_dai_name .
* but , it will never match if name was created by fmt_single_name ( )
* remove cpu_dai_name to escape name matching .
* see
* fmt_single_name ( )
* fmt_multiple_name ( )
*/
if ( num_links = = 1 )
dai_link - > cpu_dai_name = NULL ;
2013-11-20 15:25:02 +09:00
} else {
2014-01-15 16:51:52 +01:00
struct asoc_simple_card_info * cinfo ;
cinfo = dev - > platform_data ;
if ( ! cinfo ) {
2014-01-09 17:49:40 +08:00
dev_err ( dev , " no info for asoc-simple-card \n " ) ;
return - EINVAL ;
}
2013-11-20 15:25:02 +09:00
2014-04-24 19:14:00 +08:00
if ( ! cinfo - > name | |
! cinfo - > codec_dai . name | |
! cinfo - > codec | |
! cinfo - > platform | |
2014-01-15 16:51:33 +01:00
! cinfo - > cpu_dai . name ) {
dev_err ( dev , " insufficient asoc_simple_card_info settings \n " ) ;
return - EINVAL ;
}
2014-01-15 16:51:37 +01:00
2014-03-09 19:37:56 -07:00
priv - > snd_card . name = ( cinfo - > card ) ? cinfo - > card : cinfo - > name ;
2014-01-15 16:51:45 +01:00
dai_link - > name = cinfo - > name ;
dai_link - > stream_name = cinfo - > name ;
dai_link - > platform_name = cinfo - > platform ;
dai_link - > codec_name = cinfo - > codec ;
2014-01-15 16:51:48 +01:00
dai_link - > cpu_dai_name = cinfo - > cpu_dai . name ;
dai_link - > codec_dai_name = cinfo - > codec_dai . name ;
2014-03-20 10:52:41 +01:00
memcpy ( & priv - > dai_props - > cpu_dai , & cinfo - > cpu_dai ,
sizeof ( priv - > dai_props - > cpu_dai ) ) ;
memcpy ( & priv - > dai_props - > codec_dai , & cinfo - > codec_dai ,
sizeof ( priv - > dai_props - > codec_dai ) ) ;
2014-03-02 20:32:43 -08:00
2014-03-20 10:52:41 +01:00
priv - > dai_props - > cpu_dai . fmt | = cinfo - > daifmt ;
priv - > dai_props - > codec_dai . fmt | = cinfo - > daifmt ;
2012-04-08 21:17:50 -07:00
}
/*
* init snd_soc_dai_link
*/
2014-01-15 16:51:45 +01:00
dai_link - > init = asoc_simple_card_dai_init ;
2012-04-08 21:17:50 -07:00
2014-01-15 16:51:52 +01:00
snd_soc_card_set_drvdata ( & priv - > snd_card , priv ) ;
2012-04-08 21:17:50 -07:00
2014-03-11 10:03:40 +01:00
ret = devm_snd_soc_register_card ( & pdev - > dev , & priv - > snd_card ) ;
err :
asoc_simple_card_unref ( pdev ) ;
return ret ;
2012-04-08 21:17:50 -07:00
}
2013-11-20 15:25:02 +09:00
static const struct of_device_id asoc_simple_of_match [ ] = {
{ . compatible = " simple-audio-card " , } ,
{ } ,
} ;
MODULE_DEVICE_TABLE ( of , asoc_simple_of_match ) ;
2012-04-08 21:17:50 -07:00
static struct platform_driver asoc_simple_card = {
. driver = {
2014-04-24 19:14:00 +08:00
. name = " asoc-simple-card " ,
2013-08-23 14:35:17 -03:00
. owner = THIS_MODULE ,
2013-11-20 15:25:02 +09:00
. of_match_table = asoc_simple_of_match ,
2012-04-08 21:17:50 -07:00
} ,
2014-04-24 19:14:00 +08:00
. probe = asoc_simple_card_probe ,
2012-04-08 21:17:50 -07:00
} ;
module_platform_driver ( asoc_simple_card ) ;
2013-08-23 14:35:17 -03:00
MODULE_ALIAS ( " platform:asoc-simple-card " ) ;
2012-04-08 21:17:50 -07:00
MODULE_LICENSE ( " GPL " ) ;
MODULE_DESCRIPTION ( " ASoC Simple Sound Card " ) ;
MODULE_AUTHOR ( " Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> " ) ;