2019-06-04 11:11:33 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2012-06-12 10:50:08 +04:00
/*
* Copyright ( C ) ST - Ericsson SA 2012
*
* Author : Ola Lilja ( ola . o . lilja @ stericsson . com )
* for ST - Ericsson .
*/
# include <asm/mach-types.h>
# include <linux/module.h>
# include <linux/io.h>
# include <linux/spi/spi.h>
2012-07-26 19:48:34 +04:00
# include <linux/of.h>
2012-06-12 10:50:08 +04:00
# include <sound/soc.h>
# include <sound/initval.h>
# include "ux500_pcm.h"
# include "ux500_msp_dai.h"
2013-01-31 16:34:00 +04:00
# include "mop500_ab8500.h"
2012-06-12 10:50:08 +04:00
/* Define the whole MOP500 soundcard, linking platform to the codec-drivers */
2019-06-06 07:18:14 +03:00
SND_SOC_DAILINK_DEFS ( link1 ,
DAILINK_COMP_ARRAY ( COMP_CPU ( " ux500-msp-i2s.1 " ) ) ,
2019-06-28 04:49:40 +03:00
DAILINK_COMP_ARRAY ( COMP_CODEC ( " ab8500-codec.0 " , " ab8500-codec-dai.0 " ) ) ,
DAILINK_COMP_ARRAY ( COMP_PLATFORM ( " ux500-msp-i2s.1 " ) ) ) ;
2019-06-06 07:18:14 +03:00
SND_SOC_DAILINK_DEFS ( link2 ,
DAILINK_COMP_ARRAY ( COMP_CPU ( " ux500-msp-i2s.3 " ) ) ,
2019-06-28 04:49:40 +03:00
DAILINK_COMP_ARRAY ( COMP_CODEC ( " ab8500-codec.0 " , " ab8500-codec-dai.1 " ) ) ,
DAILINK_COMP_ARRAY ( COMP_PLATFORM ( " ux500-msp-i2s.3 " ) ) ) ;
2019-06-06 07:18:14 +03:00
2013-05-15 00:19:55 +04:00
static struct snd_soc_dai_link mop500_dai_links [ ] = {
2012-06-12 10:50:08 +04:00
{
. name = " ab8500_0 " ,
. stream_name = " ab8500_0 " ,
. init = mop500_ab8500_machine_init ,
. ops = mop500_ab8500_ops ,
2019-06-06 07:18:14 +03:00
SND_SOC_DAILINK_REG ( link1 ) ,
2012-06-12 10:50:08 +04:00
} ,
{
. name = " ab8500_1 " ,
. stream_name = " ab8500_1 " ,
. init = NULL ,
. ops = mop500_ab8500_ops ,
2019-06-06 07:18:14 +03:00
SND_SOC_DAILINK_REG ( link2 ) ,
2012-06-12 10:50:08 +04:00
} ,
} ;
static struct snd_soc_card mop500_card = {
. name = " MOP500-card " ,
2013-07-02 13:25:37 +04:00
. owner = THIS_MODULE ,
2012-06-12 10:50:08 +04:00
. probe = NULL ,
. dai_link = mop500_dai_links ,
. num_links = ARRAY_SIZE ( mop500_dai_links ) ,
} ;
2012-10-15 17:13:25 +04:00
static void mop500_of_node_put ( void )
{
int i ;
2020-05-12 13:07:05 +03:00
for ( i = 0 ; i < 2 ; i + + )
2019-06-06 07:18:14 +03:00
of_node_put ( mop500_dai_links [ i ] . cpus - > of_node ) ;
2020-05-12 13:07:05 +03:00
/* Both links use the same codec, which is refcounted only once */
of_node_put ( mop500_dai_links [ 0 ] . codecs - > of_node ) ;
2012-10-15 17:13:25 +04:00
}
2012-12-07 18:26:35 +04:00
static int mop500_of_probe ( struct platform_device * pdev ,
struct device_node * np )
2012-07-26 19:48:34 +04:00
{
struct device_node * codec_np , * msp_np [ 2 ] ;
int i ;
msp_np [ 0 ] = of_parse_phandle ( np , " stericsson,cpu-dai " , 0 ) ;
msp_np [ 1 ] = of_parse_phandle ( np , " stericsson,cpu-dai " , 1 ) ;
codec_np = of_parse_phandle ( np , " stericsson,audio-codec " , 0 ) ;
if ( ! ( msp_np [ 0 ] & & msp_np [ 1 ] & & codec_np ) ) {
dev_err ( & pdev - > dev , " Phandle missing or invalid \n " ) ;
2020-05-12 13:07:05 +03:00
for ( i = 0 ; i < 2 ; i + + )
of_node_put ( msp_np [ i ] ) ;
of_node_put ( codec_np ) ;
2012-07-26 19:48:34 +04:00
return - EINVAL ;
}
for ( i = 0 ; i < 2 ; i + + ) {
2019-06-06 07:18:14 +03:00
mop500_dai_links [ i ] . cpus - > of_node = msp_np [ i ] ;
mop500_dai_links [ i ] . cpus - > dai_name = NULL ;
2019-06-28 04:49:40 +03:00
mop500_dai_links [ i ] . platforms - > of_node = msp_np [ i ] ;
mop500_dai_links [ i ] . platforms - > name = NULL ;
2019-06-06 07:18:14 +03:00
mop500_dai_links [ i ] . codecs - > of_node = codec_np ;
mop500_dai_links [ i ] . codecs - > name = NULL ;
2012-07-26 19:48:34 +04:00
}
snd_soc_of_parse_card_name ( & mop500_card , " stericsson,card-name " ) ;
return 0 ;
}
2012-10-15 17:13:25 +04:00
2012-12-07 18:26:35 +04:00
static int mop500_probe ( struct platform_device * pdev )
2012-06-12 10:50:08 +04:00
{
2012-07-26 19:48:34 +04:00
struct device_node * np = pdev - > dev . of_node ;
2012-06-12 10:50:08 +04:00
int ret ;
dev_dbg ( & pdev - > dev , " %s: Enter. \n " , __func__ ) ;
mop500_card . dev = & pdev - > dev ;
2012-07-26 19:48:34 +04:00
if ( np ) {
ret = mop500_of_probe ( pdev , np ) ;
if ( ret )
return ret ;
}
2012-06-12 10:50:08 +04:00
dev_dbg ( & pdev - > dev , " %s: Card %s: Set platform drvdata. \n " ,
__func__ , mop500_card . name ) ;
snd_soc_card_set_drvdata ( & mop500_card , NULL ) ;
dev_dbg ( & pdev - > dev , " %s: Card %s: num_links = %d \n " ,
__func__ , mop500_card . name , mop500_card . num_links ) ;
dev_dbg ( & pdev - > dev , " %s: Card %s: DAI-link 0: name = %s \n " ,
__func__ , mop500_card . name , mop500_card . dai_link [ 0 ] . name ) ;
dev_dbg ( & pdev - > dev , " %s: Card %s: DAI-link 0: stream_name = %s \n " ,
__func__ , mop500_card . name ,
mop500_card . dai_link [ 0 ] . stream_name ) ;
ret = snd_soc_register_card ( & mop500_card ) ;
if ( ret )
dev_err ( & pdev - > dev ,
2012-08-21 13:06:44 +04:00
" Error: snd_soc_register_card failed (%d)! \n " , ret ) ;
2012-06-12 10:50:08 +04:00
return ret ;
}
2012-12-07 18:26:35 +04:00
static int mop500_remove ( struct platform_device * pdev )
2012-06-12 10:50:08 +04:00
{
2021-03-27 00:59:26 +03:00
struct snd_soc_card * card = platform_get_drvdata ( pdev ) ;
2012-06-12 10:50:08 +04:00
pr_debug ( " %s: Enter. \n " , __func__ ) ;
2021-03-27 00:59:26 +03:00
snd_soc_unregister_card ( card ) ;
mop500_ab8500_remove ( card ) ;
2012-10-15 17:13:25 +04:00
mop500_of_node_put ( ) ;
2012-08-21 13:06:44 +04:00
2012-06-12 10:50:08 +04:00
return 0 ;
}
2012-07-26 19:48:34 +04:00
static const struct of_device_id snd_soc_mop500_match [ ] = {
{ . compatible = " stericsson,snd-soc-mop500 " , } ,
{ } ,
} ;
2015-09-03 14:00:40 +03:00
MODULE_DEVICE_TABLE ( of , snd_soc_mop500_match ) ;
2012-07-26 19:48:34 +04:00
2012-06-12 10:50:08 +04:00
static struct platform_driver snd_soc_mop500_driver = {
. driver = {
. name = " snd-soc-mop500 " ,
2012-07-26 19:48:34 +04:00
. of_match_table = snd_soc_mop500_match ,
2012-06-12 10:50:08 +04:00
} ,
. probe = mop500_probe ,
2012-12-07 18:26:35 +04:00
. remove = mop500_remove ,
2012-06-12 10:50:08 +04:00
} ;
module_platform_driver ( snd_soc_mop500_driver ) ;
2018-01-10 19:34:45 +03:00
MODULE_LICENSE ( " GPL v2 " ) ;
MODULE_DESCRIPTION ( " ASoC MOP500 board driver " ) ;
MODULE_AUTHOR ( " Ola Lilja " ) ;