2019-04-05 14:50:08 +03:00
// SPDX-License-Identifier: GPL-2.0
//
// Phytec pcm030 driver for the PSC of the Freescale MPC52xx
// configured as AC97 interface
//
// Copyright 2008 Jon Smirl, Digispeaker
// Author: Jon Smirl <jonsmirl@gmail.com>
2009-05-26 16:34:12 +04:00
# include <linux/init.h>
# include <linux/module.h>
# include <linux/device.h>
# include <linux/of_device.h>
# include <linux/of_platform.h>
# include <sound/soc.h>
# include "mpc5200_dma.h"
2009-08-07 18:33:53 +04:00
# define DRV_NAME "pcm030-audio-fabric"
2012-09-20 18:36:45 +04:00
struct pcm030_audio_data {
struct snd_soc_card * card ;
struct platform_device * codec_device ;
} ;
2019-06-06 07:16:14 +03:00
SND_SOC_DAILINK_DEFS ( analog ,
DAILINK_COMP_ARRAY ( COMP_CPU ( " mpc5200-psc-ac97.0 " ) ) ,
DAILINK_COMP_ARRAY ( COMP_CODEC ( " wm9712-codec " , " wm9712-hifi " ) ) ,
DAILINK_COMP_ARRAY ( COMP_EMPTY ( ) ) ) ;
SND_SOC_DAILINK_DEFS ( iec958 ,
DAILINK_COMP_ARRAY ( COMP_CPU ( " mpc5200-psc-ac97.1 " ) ) ,
DAILINK_COMP_ARRAY ( COMP_CODEC ( " wm9712-codec " , " wm9712-aux " ) ) ,
DAILINK_COMP_ARRAY ( COMP_EMPTY ( ) ) ) ;
2009-05-26 16:34:12 +04:00
static struct snd_soc_dai_link pcm030_fabric_dai [ ] = {
{
2012-10-10 18:10:08 +04:00
. name = " AC97.0 " ,
2009-05-26 16:34:12 +04:00
. stream_name = " AC97 Analog " ,
2019-06-06 07:16:14 +03:00
SND_SOC_DAILINK_REG ( analog ) ,
2009-05-26 16:34:12 +04:00
} ,
{
2012-10-10 18:10:08 +04:00
. name = " AC97.1 " ,
2009-05-26 16:34:12 +04:00
. stream_name = " AC97 IEC958 " ,
2019-06-06 07:16:14 +03:00
SND_SOC_DAILINK_REG ( iec958 ) ,
2009-05-26 16:34:12 +04:00
} ,
} ;
2012-09-20 18:36:44 +04:00
static struct snd_soc_card pcm030_card = {
2011-12-22 17:04:54 +04:00
. name = " pcm030 " ,
. owner = THIS_MODULE ,
. dai_link = pcm030_fabric_dai ,
. num_links = ARRAY_SIZE ( pcm030_fabric_dai ) ,
} ;
2013-03-10 22:33:06 +04:00
static int pcm030_fabric_probe ( struct platform_device * op )
2009-05-26 16:34:12 +04:00
{
2012-09-20 18:36:44 +04:00
struct device_node * np = op - > dev . of_node ;
struct device_node * platform_np ;
struct snd_soc_card * card = & pcm030_card ;
2012-09-20 18:36:45 +04:00
struct pcm030_audio_data * pdata ;
2018-09-18 04:28:49 +03:00
struct snd_soc_dai_link * dai_link ;
2012-09-20 18:36:44 +04:00
int ret ;
int i ;
2009-05-26 16:34:12 +04:00
2010-02-02 07:34:14 +03:00
if ( ! of_machine_is_compatible ( " phytec,pcm030 " ) )
2009-05-26 16:34:12 +04:00
return - ENODEV ;
2012-09-20 18:36:45 +04:00
pdata = devm_kzalloc ( & op - > dev , sizeof ( struct pcm030_audio_data ) ,
GFP_KERNEL ) ;
if ( ! pdata )
return - ENOMEM ;
2012-09-20 18:36:44 +04:00
card - > dev = & op - > dev ;
2012-09-20 18:36:45 +04:00
pdata - > card = card ;
2012-09-20 18:36:44 +04:00
platform_np = of_parse_phandle ( np , " asoc-platform " , 0 ) ;
if ( ! platform_np ) {
dev_err ( & op - > dev , " ac97 not registered \n " ) ;
2009-05-26 16:34:12 +04:00
return - ENODEV ;
}
2018-09-18 04:28:49 +03:00
for_each_card_prelinks ( card , i , dai_link )
2019-06-06 07:16:14 +03:00
dai_link - > platforms - > of_node = platform_np ;
2009-05-26 16:34:12 +04:00
2012-09-20 18:36:45 +04:00
ret = request_module ( " snd-soc-wm9712 " ) ;
if ( ret )
dev_err ( & op - > dev , " request_module returned: %d \n " , ret ) ;
pdata - > codec_device = platform_device_alloc ( " wm9712-codec " , - 1 ) ;
if ( ! pdata - > codec_device )
dev_err ( & op - > dev , " platform_device_alloc() failed \n " ) ;
ret = platform_device_add ( pdata - > codec_device ) ;
2022-01-27 16:13:34 +03:00
if ( ret ) {
2012-09-20 18:36:45 +04:00
dev_err ( & op - > dev , " platform_device_add() failed: %d \n " , ret ) ;
2022-01-27 16:13:34 +03:00
platform_device_put ( pdata - > codec_device ) ;
}
2012-09-20 18:36:45 +04:00
2012-09-20 18:36:44 +04:00
ret = snd_soc_register_card ( card ) ;
2022-01-27 16:13:34 +03:00
if ( ret ) {
2012-09-20 18:36:44 +04:00
dev_err ( & op - > dev , " snd_soc_register_card() failed: %d \n " , ret ) ;
2022-07-04 10:51:34 +03:00
platform_device_unregister ( pdata - > codec_device ) ;
2022-01-27 16:13:34 +03:00
}
2012-09-20 18:36:44 +04:00
2013-11-09 04:41:14 +04:00
platform_set_drvdata ( op , pdata ) ;
2012-09-20 18:36:44 +04:00
return ret ;
2022-01-27 16:13:34 +03:00
2009-05-26 16:34:12 +04:00
}
2012-12-07 18:26:16 +04:00
static int pcm030_fabric_remove ( struct platform_device * op )
2012-09-20 18:36:44 +04:00
{
2012-09-20 18:36:45 +04:00
struct pcm030_audio_data * pdata = platform_get_drvdata ( op ) ;
2012-09-20 18:36:44 +04:00
2022-06-21 17:58:34 +03:00
snd_soc_unregister_card ( pdata - > card ) ;
2012-09-20 18:36:45 +04:00
platform_device_unregister ( pdata - > codec_device ) ;
2012-09-20 18:36:44 +04:00
2022-06-21 17:58:34 +03:00
return 0 ;
2012-09-20 18:36:44 +04:00
}
2015-03-18 19:48:57 +03:00
static const struct of_device_id pcm030_audio_match [ ] = {
2012-09-20 18:36:44 +04:00
{ . compatible = " phytec,pcm030-audio-fabric " , } ,
{ }
} ;
MODULE_DEVICE_TABLE ( of , pcm030_audio_match ) ;
static struct platform_driver pcm030_fabric_driver = {
. probe = pcm030_fabric_probe ,
2012-12-07 18:26:16 +04:00
. remove = pcm030_fabric_remove ,
2012-09-20 18:36:44 +04:00
. driver = {
. name = DRV_NAME ,
. of_match_table = pcm030_audio_match ,
} ,
} ;
module_platform_driver ( pcm030_fabric_driver ) ;
2009-05-26 16:34:12 +04:00
MODULE_AUTHOR ( " Jon Smirl <jonsmirl@gmail.com> " ) ;
MODULE_DESCRIPTION ( DRV_NAME " : mpc5200 pcm030 fabric driver " ) ;
MODULE_LICENSE ( " GPL " ) ;