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>
2014-10-01 14:25:20 -07:00
# include <linux/gpio.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>
2014-10-01 14:25:20 -07:00
# include <linux/of_gpio.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>
2014-10-01 14:25:20 -07:00
# include <sound/jack.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
2016-05-31 08:59:46 +00:00
struct asoc_simple_jack {
struct snd_soc_jack jack ;
struct snd_soc_jack_pin pin ;
struct snd_soc_jack_gpio gpio ;
} ;
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 ;
2015-06-05 10:19:05 +02:00
unsigned int mclk_fs ;
2014-03-20 10:52:41 +01:00
} * dai_props ;
2014-05-22 17:31:49 +02:00
unsigned int mclk_fs ;
2016-05-31 08:59:46 +00:00
struct asoc_simple_jack hp_jack ;
struct asoc_simple_jack mic_jack ;
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-09-09 21:37:57 -07:00
# define simple_priv_to_dev(priv) ((priv)->snd_card.dev)
2016-08-26 03:06:23 +00:00
# define simple_priv_to_link(priv, i) ((priv)->snd_card.dai_link + (i))
# define simple_priv_to_props(priv, i) ((priv)->dai_props + (i))
2014-09-09 21:37:57 -07:00
2016-08-08 06:02:07 +00:00
# define DAI "sound-dai"
# define CELL "#sound-dai-cells"
2016-05-31 08:59:01 +00:00
# define PREFIX "simple-audio-card,"
2016-05-31 08:59:46 +00:00
# define asoc_simple_card_init_hp(card, sjack, prefix)\
asoc_simple_card_init_jack ( card , sjack , 1 , prefix )
# define asoc_simple_card_init_mic(card, sjack, prefix)\
asoc_simple_card_init_jack ( card , sjack , 0 , prefix )
static int asoc_simple_card_init_jack ( struct snd_soc_card * card ,
struct asoc_simple_jack * sjack ,
int is_hp , char * prefix )
{
struct device * dev = card - > dev ;
enum of_gpio_flags flags ;
char prop [ 128 ] ;
char * pin_name ;
char * gpio_name ;
int mask ;
int det ;
sjack - > gpio . gpio = - ENOENT ;
if ( is_hp ) {
snprintf ( prop , sizeof ( prop ) , " %shp-det-gpio " , prefix ) ;
pin_name = " Headphones " ;
gpio_name = " Headphone detection " ;
mask = SND_JACK_HEADPHONE ;
} else {
snprintf ( prop , sizeof ( prop ) , " %smic-det-gpio " , prefix ) ;
pin_name = " Mic Jack " ;
gpio_name = " Mic detection " ;
mask = SND_JACK_MICROPHONE ;
}
det = of_get_named_gpio_flags ( dev - > of_node , prop , 0 , & flags ) ;
if ( det = = - EPROBE_DEFER )
return - EPROBE_DEFER ;
if ( gpio_is_valid ( det ) ) {
sjack - > pin . pin = pin_name ;
sjack - > pin . mask = mask ;
sjack - > gpio . name = gpio_name ;
sjack - > gpio . report = mask ;
sjack - > gpio . gpio = det ;
sjack - > gpio . invert = ! ! ( flags & OF_GPIO_ACTIVE_LOW ) ;
sjack - > gpio . debounce_time = 150 ;
snd_soc_card_jack_new ( card , pin_name , mask ,
& sjack - > jack ,
& sjack - > pin , 1 ) ;
snd_soc_jack_add_gpios ( & sjack - > jack , 1 ,
& sjack - > gpio ) ;
}
return 0 ;
}
static void asoc_simple_card_remove_jack ( struct asoc_simple_jack * sjack )
{
if ( gpio_is_valid ( sjack - > gpio . gpio ) )
snd_soc_jack_free_gpios ( & sjack - > jack , 1 , & sjack - > gpio ) ;
}
2015-01-13 21:16:34 +02:00
static int asoc_simple_card_startup ( struct snd_pcm_substream * substream )
{
struct snd_soc_pcm_runtime * rtd = substream - > private_data ;
struct simple_card_data * priv = snd_soc_card_get_drvdata ( rtd - > card ) ;
struct simple_dai_props * dai_props =
2016-08-26 03:06:51 +00:00
simple_priv_to_props ( priv , rtd - > num ) ;
2015-01-13 21:16:34 +02:00
int ret ;
ret = clk_prepare_enable ( dai_props - > cpu_dai . clk ) ;
if ( ret )
return ret ;
2016-08-26 03:07:59 +00:00
2015-01-13 21:16:34 +02:00
ret = clk_prepare_enable ( dai_props - > codec_dai . clk ) ;
if ( ret )
clk_disable_unprepare ( dai_props - > cpu_dai . clk ) ;
return ret ;
}
static void asoc_simple_card_shutdown ( struct snd_pcm_substream * substream )
{
struct snd_soc_pcm_runtime * rtd = substream - > private_data ;
struct simple_card_data * priv = snd_soc_card_get_drvdata ( rtd - > card ) ;
struct simple_dai_props * dai_props =
2016-08-26 03:06:51 +00:00
simple_priv_to_props ( priv , rtd - > num ) ;
2015-01-13 21:16:34 +02:00
clk_disable_unprepare ( dai_props - > cpu_dai . clk ) ;
clk_disable_unprepare ( dai_props - > codec_dai . clk ) ;
}
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 ;
2015-06-05 10:19:06 +02:00
struct snd_soc_dai * cpu_dai = rtd - > cpu_dai ;
2014-05-22 17:31:49 +02:00
struct simple_card_data * priv = snd_soc_card_get_drvdata ( rtd - > card ) ;
2016-08-26 03:06:51 +00:00
struct simple_dai_props * dai_props =
simple_priv_to_props ( priv , rtd - > num ) ;
2015-06-05 10:19:05 +02:00
unsigned int mclk , mclk_fs = 0 ;
2014-05-22 17:31:49 +02:00
int ret = 0 ;
2015-06-05 10:19:05 +02:00
if ( priv - > mclk_fs )
mclk_fs = priv - > mclk_fs ;
else if ( dai_props - > mclk_fs )
mclk_fs = dai_props - > mclk_fs ;
if ( mclk_fs ) {
mclk = params_rate ( params ) * mclk_fs ;
2014-05-22 17:31:49 +02:00
ret = snd_soc_dai_set_sysclk ( codec_dai , 0 , mclk ,
SND_SOC_CLOCK_IN ) ;
2015-06-05 10:19:06 +02:00
if ( ret & & ret ! = - ENOTSUPP )
goto err ;
ret = snd_soc_dai_set_sysclk ( cpu_dai , 0 , mclk ,
SND_SOC_CLOCK_OUT ) ;
if ( ret & & ret ! = - ENOTSUPP )
goto err ;
2014-05-22 17:31:49 +02:00
}
2016-01-24 00:36:40 +02:00
return 0 ;
2015-06-05 10:19:06 +02:00
err :
2014-05-22 17:31:49 +02:00
return ret ;
}
static struct snd_soc_ops asoc_simple_card_ops = {
2015-01-13 21:16:34 +02:00
. startup = asoc_simple_card_startup ,
. shutdown = asoc_simple_card_shutdown ,
2014-05-22 17:31:49 +02:00
. hw_params = asoc_simple_card_hw_params ,
} ;
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 ;
2016-08-26 03:06:51 +00:00
struct simple_dai_props * dai_props =
simple_priv_to_props ( priv , rtd - > num ) ;
2015-11-18 02:34:11 -05:00
int ret ;
2012-04-08 21:17:50 -07:00
2016-08-09 05:48:53 +00:00
ret = asoc_simple_card_init_dai ( 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
2016-08-09 05:48:53 +00:00
ret = asoc_simple_card_init_dai ( 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
2016-05-31 08:59:46 +00:00
ret = asoc_simple_card_init_hp ( rtd - > card , & priv - > hp_jack , PREFIX ) ;
if ( ret < 0 )
return ret ;
ret = asoc_simple_card_init_mic ( rtd - > card , & priv - > hp_jack , PREFIX ) ;
if ( ret < 0 )
return ret ;
2014-10-01 14:25:20 -07:00
2012-04-08 21:17:50 -07:00
return 0 ;
}
2014-08-27 20:07:46 -07:00
static int asoc_simple_card_dai_link_of ( struct device_node * node ,
2014-09-09 21:37:57 -07:00
struct simple_card_data * priv ,
2014-09-09 21:38:24 -07:00
int idx ,
2014-08-27 20:07:46 -07:00
bool is_top_level_node )
2014-03-20 11:49:55 +01:00
{
2014-09-09 21:37:57 -07:00
struct device * dev = simple_priv_to_dev ( priv ) ;
2014-09-09 21:38:24 -07:00
struct snd_soc_dai_link * dai_link = simple_priv_to_link ( priv , idx ) ;
struct simple_dai_props * dai_props = simple_priv_to_props ( priv , idx ) ;
2016-07-19 02:53:13 +00:00
struct asoc_simple_dai * cpu_dai = & dai_props - > cpu_dai ;
struct asoc_simple_dai * codec_dai = & dai_props - > codec_dai ;
2014-10-27 18:04:52 -07:00
struct device_node * cpu = NULL ;
2015-04-29 18:11:07 +08:00
struct device_node * plat = NULL ;
2014-10-27 18:04:52 -07:00
struct device_node * codec = NULL ;
2014-03-24 12:15:25 +02:00
char prop [ 128 ] ;
char * prefix = " " ;
2016-08-08 06:02:07 +00:00
int ret , single_cpu ;
2014-03-20 11:49:55 +01:00
2014-09-03 10:23:39 +08:00
/* For single DAI link & old style of DT node */
2014-04-24 19:42:00 +03:00
if ( is_top_level_node )
2016-05-31 08:59:01 +00:00
prefix = PREFIX ;
2014-03-24 12:15:25 +02:00
snprintf ( prop , sizeof ( prop ) , " %scpu " , prefix ) ;
2014-10-27 18:04:52 -07:00
cpu = of_get_child_by_name ( node , prop ) ;
2015-04-29 18:11:07 +08:00
snprintf ( prop , sizeof ( prop ) , " %splat " , prefix ) ;
plat = of_get_child_by_name ( node , prop ) ;
2014-10-27 18:04:52 -07:00
snprintf ( prop , sizeof ( prop ) , " %scodec " , prefix ) ;
codec = of_get_child_by_name ( node , prop ) ;
if ( ! cpu | | ! codec ) {
2014-03-24 12:15:25 +02:00
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
2016-06-30 06:02:46 +00:00
ret = asoc_simple_card_parse_daifmt ( dev , node , codec ,
prefix , & dai_link - > dai_fmt ) ;
2014-10-27 18:04:52 -07:00
if ( ret < 0 )
goto dai_link_of_err ;
2016-08-26 03:05:58 +00:00
of_property_read_u32 ( node , " mclk-fs " , & dai_props - > mclk_fs ) ;
2015-06-05 10:19:05 +02:00
2016-08-08 06:02:07 +00:00
ret = asoc_simple_card_parse_cpu ( cpu , dai_link ,
DAI , CELL , & single_cpu ) ;
if ( ret < 0 )
goto dai_link_of_err ;
ret = asoc_simple_card_parse_codec ( codec , dai_link , DAI , CELL ) ;
if ( ret < 0 )
goto dai_link_of_err ;
ret = asoc_simple_card_parse_platform ( plat , dai_link , DAI , CELL ) ;
if ( ret < 0 )
goto dai_link_of_err ;
2016-08-08 06:03:35 +00:00
ret = snd_soc_of_parse_tdm_slot ( cpu , & cpu_dai - > tx_slot_mask ,
& cpu_dai - > rx_slot_mask ,
& cpu_dai - > slots ,
& cpu_dai - > slot_width ) ;
2014-03-24 12:15:25 +02:00
if ( ret < 0 )
goto dai_link_of_err ;
2016-08-08 06:03:35 +00:00
ret = snd_soc_of_parse_tdm_slot ( codec , & codec_dai - > tx_slot_mask ,
& codec_dai - > rx_slot_mask ,
& codec_dai - > slots ,
& codec_dai - > slot_width ) ;
2016-05-20 09:40:41 +00:00
if ( ret < 0 )
goto dai_link_of_err ;
2016-07-19 02:53:13 +00:00
ret = asoc_simple_card_parse_clk_cpu ( cpu , dai_link , cpu_dai ) ;
if ( ret < 0 )
goto dai_link_of_err ;
ret = asoc_simple_card_parse_clk_codec ( codec , dai_link , codec_dai ) ;
if ( ret < 0 )
goto dai_link_of_err ;
2016-08-09 05:50:02 +00:00
ret = asoc_simple_card_canonicalize_dailink ( dai_link ) ;
if ( ret < 0 )
2014-04-24 19:14:00 +08:00
goto dai_link_of_err ;
2014-03-24 12:15:25 +02:00
2016-07-11 23:57:34 +00:00
ret = asoc_simple_card_set_dailink_name ( dev , dai_link ,
" %s-%s " ,
dai_link - > cpu_dai_name ,
dai_link - > codec_dai_name ) ;
if ( ret < 0 )
2015-03-03 18:59:00 +05:30
goto dai_link_of_err ;
2014-05-22 17:31:49 +02:00
dai_link - > ops = & asoc_simple_card_ops ;
2014-08-27 20:08:27 -07:00
dai_link - > init = asoc_simple_card_dai_init ;
2014-03-24 12:15:25 +02:00
dev_dbg ( dev , " \t name : %s \n " , dai_link - > stream_name ) ;
2015-03-24 01:07:08 +00:00
dev_dbg ( dev , " \t format : %04x \n " , dai_link - > dai_fmt ) ;
dev_dbg ( dev , " \t cpu : %s / %d \n " ,
2014-03-24 12:15:25 +02:00
dai_link - > cpu_dai_name ,
dai_props - > cpu_dai . sysclk ) ;
2015-03-24 01:07:08 +00:00
dev_dbg ( dev , " \t codec : %s / %d \n " ,
2014-03-24 12:15:25 +02:00
dai_link - > codec_dai_name ,
dai_props - > codec_dai . sysclk ) ;
2016-08-10 02:20:43 +00:00
asoc_simple_card_canonicalize_cpu ( dai_link , single_cpu ) ;
2014-08-27 20:08:06 -07:00
2014-03-24 12:15:25 +02:00
dai_link_of_err :
2014-10-27 18:04:52 -07:00
of_node_put ( cpu ) ;
of_node_put ( codec ) ;
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-09-09 21:37:57 -07:00
struct simple_card_data * priv )
2013-11-20 15:25:02 +09:00
{
2014-09-09 21:37:57 -07:00
struct device * dev = simple_priv_to_dev ( priv ) ;
2016-08-26 03:05:16 +00:00
struct device_node * dai_link ;
2013-12-23 12:57:01 +08:00
int ret ;
2013-11-20 15:25:02 +09:00
2014-09-03 10:23:39 +08:00
if ( ! node )
return - EINVAL ;
2016-08-26 03:05:16 +00:00
dai_link = of_get_child_by_name ( node , PREFIX " dai-link " ) ;
2014-09-10 09:59:55 +08:00
/* The off-codec widgets */
2016-05-31 08:59:01 +00:00
if ( of_property_read_bool ( node , PREFIX " widgets " ) ) {
2014-02-08 15:59:53 +08:00
ret = snd_soc_of_parse_audio_simple_widgets ( & priv - > snd_card ,
2016-05-31 08:59:01 +00:00
PREFIX " widgets " ) ;
2014-02-08 15:59:53 +08:00
if ( ret )
2016-08-26 03:05:16 +00:00
goto card_parse_end ;
2014-02-08 15:59:53 +08:00
}
2013-12-23 12:57:01 +08:00
/* DAPM routes */
2016-05-31 08:59:01 +00:00
if ( of_property_read_bool ( node , PREFIX " routing " ) ) {
2014-01-15 16:52:00 +01:00
ret = snd_soc_of_parse_audio_routing ( & priv - > snd_card ,
2016-05-31 08:59:01 +00:00
PREFIX " routing " ) ;
2014-01-07 09:13:42 +08:00
if ( ret )
2016-08-26 03:05:16 +00:00
goto card_parse_end ;
2014-01-07 09:13:42 +08:00
}
2013-12-23 12:57:01 +08:00
2014-05-22 17:31:49 +02:00
/* Factor to mclk, used in hw_params() */
2016-08-26 03:05:58 +00:00
of_property_read_u32 ( node , PREFIX " mclk-fs " , & priv - > mclk_fs ) ;
2014-05-22 17:31:49 +02:00
2014-09-03 10:23:39 +08:00
/* Single/Muti DAI link(s) & New style of DT node */
2016-08-26 03:05:16 +00:00
if ( dai_link ) {
2014-03-24 12:15:25 +02:00
struct device_node * np = NULL ;
2014-08-27 20:08:47 -07:00
int i = 0 ;
for_each_child_of_node ( node , np ) {
2014-03-24 12:15:25 +02:00
dev_dbg ( dev , " \t link %d: \n " , i ) ;
2014-09-09 21:37:57 -07:00
ret = asoc_simple_card_dai_link_of ( np , priv ,
2014-09-09 21:38:24 -07:00
i , false ) ;
2014-03-24 12:15:25 +02:00
if ( ret < 0 ) {
of_node_put ( np ) ;
2016-08-26 03:05:16 +00:00
goto card_parse_end ;
2014-03-24 12:15:25 +02:00
}
2014-08-27 20:08:47 -07:00
i + + ;
2014-03-20 11:49:55 +01:00
}
2014-03-24 12:15:25 +02:00
} else {
2014-09-03 10:23:39 +08:00
/* For single DAI link & old style of DT node */
2014-09-09 21:38:24 -07:00
ret = asoc_simple_card_dai_link_of ( node , priv , 0 , true ) ;
2014-03-20 11:49:55 +01:00
if ( ret < 0 )
2016-08-26 03:05:16 +00:00
goto card_parse_end ;
2014-03-20 11:49:55 +01:00
}
2013-12-20 14:39:50 +08:00
2016-07-11 23:59:40 +00:00
ret = asoc_simple_card_parse_card_name ( & priv - > snd_card , PREFIX ) ;
2014-02-27 18:25:24 -08:00
2016-08-26 03:05:16 +00:00
card_parse_end :
of_node_put ( dai_link ) ;
return ret ;
2013-11-20 15:25:02 +09:00
}
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-09-03 10:23:39 +08:00
int num_links , ret ;
2014-03-20 11:49:55 +01:00
2014-09-10 09:59:55 +08:00
/* Get the number of DAI links */
2016-05-31 08:59:01 +00:00
if ( np & & of_get_child_by_name ( np , PREFIX " dai-link " ) )
2014-03-20 11:49:55 +01:00
num_links = of_get_child_count ( np ) ;
2014-09-03 10:23:39 +08:00
else
2014-03-20 11:49:55 +01:00
num_links = 1 ;
2012-04-08 21:17:50 -07:00
2014-09-10 09:59:55 +08:00
/* Allocate the private data and the DAI link array */
2014-03-20 10:52:41 +01:00
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-09-10 09:59:55 +08: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-09-10 09:59:55 +08:00
/* Get room for the other properties */
2014-03-20 10:52:41 +01:00
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-09-09 21:37:57 -07:00
ret = asoc_simple_card_parse_of ( np , priv ) ;
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
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 ;
2015-03-24 01:07:08 +00:00
dai_link - > dai_fmt = cinfo - > daifmt ;
2014-08-27 20:08:27 -07:00
dai_link - > init = asoc_simple_card_dai_init ;
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 ) ) ;
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 ) ;
2014-09-01 14:46:52 +08:00
if ( ret > = 0 )
return ret ;
2014-03-11 10:03:40 +01:00
err :
2016-08-10 02:21:42 +00:00
asoc_simple_card_clean_reference ( & priv - > snd_card ) ;
2016-08-26 03:07:59 +00:00
2014-03-11 10:03:40 +01:00
return ret ;
2012-04-08 21:17:50 -07:00
}
2014-09-01 14:46:52 +08:00
static int asoc_simple_card_remove ( struct platform_device * pdev )
{
2014-10-01 14:25:20 -07:00
struct snd_soc_card * card = platform_get_drvdata ( pdev ) ;
struct simple_card_data * priv = snd_soc_card_get_drvdata ( card ) ;
2016-05-31 08:59:46 +00:00
asoc_simple_card_remove_jack ( & priv - > hp_jack ) ;
asoc_simple_card_remove_jack ( & priv - > mic_jack ) ;
2014-10-01 14:25:20 -07:00
2016-08-10 02:21:42 +00:00
return asoc_simple_card_clean_reference ( card ) ;
2014-09-01 14:46:52 +08: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 " ,
2016-05-09 13:38:10 +03:00
. pm = & snd_soc_pm_ops ,
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 ,
2014-09-01 14:46:52 +08:00
. remove = asoc_simple_card_remove ,
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 " ) ;
2016-08-26 03:07:28 +00:00
MODULE_LICENSE ( " GPL v2 " ) ;
2012-04-08 21:17:50 -07:00
MODULE_DESCRIPTION ( " ASoC Simple Sound Card " ) ;
MODULE_AUTHOR ( " Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> " ) ;