2017-11-22 20:43:17 +09:00
// SPDX-License-Identifier: GPL-2.0
2018-02-22 08:42:32 +09:00
//
// Socionext UniPhier EVEA ADC/DAC codec driver.
//
// Copyright (c) 2016-2017 Socionext Inc.
2017-11-22 20:43:17 +09:00
# include <linux/clk.h>
# include <linux/module.h>
# include <linux/of.h>
# include <linux/regmap.h>
# include <linux/reset.h>
# include <sound/pcm.h>
# include <sound/soc.h>
# define DRV_NAME "evea"
# define EVEA_RATES SNDRV_PCM_RATE_48000
# define EVEA_FORMATS SNDRV_PCM_FMTBIT_S32_LE
# define AADCPOW(n) (0x0078 + 0x04 * (n))
# define AADCPOW_AADC_POWD BIT(0)
2018-03-14 21:39:00 +09:00
# define ALINSW1 0x0088
# define ALINSW1_SEL1_SHIFT 3
2017-11-22 20:43:17 +09:00
# define AHPOUTPOW 0x0098
# define AHPOUTPOW_HP_ON BIT(4)
# define ALINEPOW 0x009c
# define ALINEPOW_LIN2_POWD BIT(3)
# define ALINEPOW_LIN1_POWD BIT(4)
# define ALO1OUTPOW 0x00a8
# define ALO1OUTPOW_LO1_ON BIT(4)
# define ALO2OUTPOW 0x00ac
# define ALO2OUTPOW_ADAC2_MUTE BIT(0)
# define ALO2OUTPOW_LO2_ON BIT(4)
# define AANAPOW 0x00b8
# define AANAPOW_A_POWD BIT(4)
# define ADACSEQ1(n) (0x0144 + 0x40 * (n))
# define ADACSEQ1_MMUTE BIT(1)
# define ADACSEQ2(n) (0x0160 + 0x40 * (n))
# define ADACSEQ2_ADACIN_FIX BIT(0)
# define ADAC1ODC 0x0200
# define ADAC1ODC_HP_DIS_RES_MASK GENMASK(2, 1)
# define ADAC1ODC_HP_DIS_RES_OFF (0x0 << 1)
# define ADAC1ODC_HP_DIS_RES_ON (0x3 << 1)
# define ADAC1ODC_ADAC_RAMPCLT_MASK GENMASK(8, 7)
# define ADAC1ODC_ADAC_RAMPCLT_NORMAL (0x0 << 7)
# define ADAC1ODC_ADAC_RAMPCLT_REDUCE (0x1 << 7)
struct evea_priv {
struct clk * clk , * clk_exiv ;
struct reset_control * rst , * rst_exiv , * rst_adamv ;
struct regmap * regmap ;
int switch_lin ;
int switch_lo ;
int switch_hp ;
} ;
2018-05-08 17:45:09 +09:00
static const char * const linsw1_sel1_text [ ] = {
" LIN1 " , " LIN2 " , " LIN3 "
} ;
static SOC_ENUM_SINGLE_DECL ( linsw1_sel1_enum ,
ALINSW1 , ALINSW1_SEL1_SHIFT ,
linsw1_sel1_text ) ;
static const struct snd_kcontrol_new linesw1_mux [ ] = {
SOC_DAPM_ENUM ( " Line In 1 Source " , linsw1_sel1_enum ) ,
} ;
2017-11-22 20:43:17 +09:00
static const struct snd_soc_dapm_widget evea_widgets [ ] = {
2018-05-08 17:45:09 +09:00
SND_SOC_DAPM_ADC ( " ADC " , NULL , SND_SOC_NOPM , 0 , 0 ) ,
SND_SOC_DAPM_MUX ( " Line In 1 Mux " , SND_SOC_NOPM , 0 , 0 , linesw1_mux ) ,
2017-11-22 20:43:17 +09:00
SND_SOC_DAPM_INPUT ( " LIN1_LP " ) ,
SND_SOC_DAPM_INPUT ( " LIN1_RP " ) ,
SND_SOC_DAPM_INPUT ( " LIN2_LP " ) ,
SND_SOC_DAPM_INPUT ( " LIN2_RP " ) ,
SND_SOC_DAPM_INPUT ( " LIN3_LP " ) ,
SND_SOC_DAPM_INPUT ( " LIN3_RP " ) ,
2018-05-08 17:45:09 +09:00
SND_SOC_DAPM_DAC ( " DAC HP " , NULL , SND_SOC_NOPM , 0 , 0 ) ,
SND_SOC_DAPM_DAC ( " DAC LO1 " , NULL , SND_SOC_NOPM , 0 , 0 ) ,
SND_SOC_DAPM_DAC ( " DAC LO2 " , NULL , SND_SOC_NOPM , 0 , 0 ) ,
2017-11-22 20:43:17 +09:00
SND_SOC_DAPM_OUTPUT ( " HP1_L " ) ,
SND_SOC_DAPM_OUTPUT ( " HP1_R " ) ,
SND_SOC_DAPM_OUTPUT ( " LO2_L " ) ,
SND_SOC_DAPM_OUTPUT ( " LO2_R " ) ,
} ;
static const struct snd_soc_dapm_route evea_routes [ ] = {
2018-05-08 17:45:09 +09:00
{ " Line In 1 " , NULL , " ADC " } ,
{ " ADC " , NULL , " Line In 1 Mux " } ,
{ " Line In 1 Mux " , " LIN1 " , " LIN1_LP " } ,
{ " Line In 1 Mux " , " LIN1 " , " LIN1_RP " } ,
{ " Line In 1 Mux " , " LIN2 " , " LIN2_LP " } ,
{ " Line In 1 Mux " , " LIN2 " , " LIN2_RP " } ,
{ " Line In 1 Mux " , " LIN3 " , " LIN3_LP " } ,
{ " Line In 1 Mux " , " LIN3 " , " LIN3_RP " } ,
{ " DAC HP " , NULL , " Headphone 1 " } ,
{ " DAC LO1 " , NULL , " Line Out 1 " } ,
{ " DAC LO2 " , NULL , " Line Out 2 " } ,
{ " HP1_L " , NULL , " DAC HP " } ,
{ " HP1_R " , NULL , " DAC HP " } ,
{ " LO2_L " , NULL , " DAC LO2 " } ,
{ " LO2_R " , NULL , " DAC LO2 " } ,
2017-11-22 20:43:17 +09:00
} ;
static void evea_set_power_state_on ( struct evea_priv * evea )
{
struct regmap * map = evea - > regmap ;
regmap_update_bits ( map , AANAPOW , AANAPOW_A_POWD ,
AANAPOW_A_POWD ) ;
regmap_update_bits ( map , ADAC1ODC , ADAC1ODC_HP_DIS_RES_MASK ,
ADAC1ODC_HP_DIS_RES_ON ) ;
regmap_update_bits ( map , ADAC1ODC , ADAC1ODC_ADAC_RAMPCLT_MASK ,
ADAC1ODC_ADAC_RAMPCLT_REDUCE ) ;
regmap_update_bits ( map , ADACSEQ2 ( 0 ) , ADACSEQ2_ADACIN_FIX , 0 ) ;
regmap_update_bits ( map , ADACSEQ2 ( 1 ) , ADACSEQ2_ADACIN_FIX , 0 ) ;
regmap_update_bits ( map , ADACSEQ2 ( 2 ) , ADACSEQ2_ADACIN_FIX , 0 ) ;
}
static void evea_set_power_state_off ( struct evea_priv * evea )
{
struct regmap * map = evea - > regmap ;
regmap_update_bits ( map , ADAC1ODC , ADAC1ODC_HP_DIS_RES_MASK ,
ADAC1ODC_HP_DIS_RES_ON ) ;
regmap_update_bits ( map , ADACSEQ1 ( 0 ) , ADACSEQ1_MMUTE ,
ADACSEQ1_MMUTE ) ;
regmap_update_bits ( map , ADACSEQ1 ( 1 ) , ADACSEQ1_MMUTE ,
ADACSEQ1_MMUTE ) ;
regmap_update_bits ( map , ADACSEQ1 ( 2 ) , ADACSEQ1_MMUTE ,
ADACSEQ1_MMUTE ) ;
regmap_update_bits ( map , ALO1OUTPOW , ALO1OUTPOW_LO1_ON , 0 ) ;
regmap_update_bits ( map , ALO2OUTPOW , ALO2OUTPOW_LO2_ON , 0 ) ;
regmap_update_bits ( map , AHPOUTPOW , AHPOUTPOW_HP_ON , 0 ) ;
}
static int evea_update_switch_lin ( struct evea_priv * evea )
{
struct regmap * map = evea - > regmap ;
if ( evea - > switch_lin ) {
regmap_update_bits ( map , ALINEPOW ,
ALINEPOW_LIN2_POWD | ALINEPOW_LIN1_POWD ,
ALINEPOW_LIN2_POWD | ALINEPOW_LIN1_POWD ) ;
regmap_update_bits ( map , AADCPOW ( 0 ) , AADCPOW_AADC_POWD ,
AADCPOW_AADC_POWD ) ;
regmap_update_bits ( map , AADCPOW ( 1 ) , AADCPOW_AADC_POWD ,
AADCPOW_AADC_POWD ) ;
} else {
regmap_update_bits ( map , AADCPOW ( 0 ) , AADCPOW_AADC_POWD , 0 ) ;
regmap_update_bits ( map , AADCPOW ( 1 ) , AADCPOW_AADC_POWD , 0 ) ;
regmap_update_bits ( map , ALINEPOW ,
ALINEPOW_LIN2_POWD | ALINEPOW_LIN1_POWD , 0 ) ;
}
return 0 ;
}
static int evea_update_switch_lo ( struct evea_priv * evea )
{
struct regmap * map = evea - > regmap ;
if ( evea - > switch_lo ) {
regmap_update_bits ( map , ADACSEQ1 ( 0 ) , ADACSEQ1_MMUTE , 0 ) ;
regmap_update_bits ( map , ADACSEQ1 ( 2 ) , ADACSEQ1_MMUTE , 0 ) ;
regmap_update_bits ( map , ALO1OUTPOW , ALO1OUTPOW_LO1_ON ,
ALO1OUTPOW_LO1_ON ) ;
regmap_update_bits ( map , ALO2OUTPOW ,
ALO2OUTPOW_ADAC2_MUTE | ALO2OUTPOW_LO2_ON ,
ALO2OUTPOW_ADAC2_MUTE | ALO2OUTPOW_LO2_ON ) ;
} else {
regmap_update_bits ( map , ADACSEQ1 ( 0 ) , ADACSEQ1_MMUTE ,
ADACSEQ1_MMUTE ) ;
regmap_update_bits ( map , ADACSEQ1 ( 2 ) , ADACSEQ1_MMUTE ,
ADACSEQ1_MMUTE ) ;
regmap_update_bits ( map , ALO1OUTPOW , ALO1OUTPOW_LO1_ON , 0 ) ;
regmap_update_bits ( map , ALO2OUTPOW ,
ALO2OUTPOW_ADAC2_MUTE | ALO2OUTPOW_LO2_ON ,
0 ) ;
}
return 0 ;
}
static int evea_update_switch_hp ( struct evea_priv * evea )
{
struct regmap * map = evea - > regmap ;
if ( evea - > switch_hp ) {
regmap_update_bits ( map , ADACSEQ1 ( 1 ) , ADACSEQ1_MMUTE , 0 ) ;
regmap_update_bits ( map , AHPOUTPOW , AHPOUTPOW_HP_ON ,
AHPOUTPOW_HP_ON ) ;
regmap_update_bits ( map , ADAC1ODC , ADAC1ODC_HP_DIS_RES_MASK ,
ADAC1ODC_HP_DIS_RES_OFF ) ;
} else {
regmap_update_bits ( map , ADAC1ODC , ADAC1ODC_HP_DIS_RES_MASK ,
ADAC1ODC_HP_DIS_RES_ON ) ;
regmap_update_bits ( map , ADACSEQ1 ( 1 ) , ADACSEQ1_MMUTE ,
ADACSEQ1_MMUTE ) ;
regmap_update_bits ( map , AHPOUTPOW , AHPOUTPOW_HP_ON , 0 ) ;
}
return 0 ;
}
static void evea_update_switch_all ( struct evea_priv * evea )
{
evea_update_switch_lin ( evea ) ;
evea_update_switch_lo ( evea ) ;
evea_update_switch_hp ( evea ) ;
}
static int evea_get_switch_lin ( struct snd_kcontrol * kcontrol ,
struct snd_ctl_elem_value * ucontrol )
{
2018-01-29 04:47:19 +00:00
struct snd_soc_component * component = snd_soc_kcontrol_component ( kcontrol ) ;
struct evea_priv * evea = snd_soc_component_get_drvdata ( component ) ;
2017-11-22 20:43:17 +09:00
ucontrol - > value . integer . value [ 0 ] = evea - > switch_lin ;
return 0 ;
}
static int evea_set_switch_lin ( struct snd_kcontrol * kcontrol ,
struct snd_ctl_elem_value * ucontrol )
{
2018-01-29 04:47:19 +00:00
struct snd_soc_component * component = snd_soc_kcontrol_component ( kcontrol ) ;
struct evea_priv * evea = snd_soc_component_get_drvdata ( component ) ;
2017-11-22 20:43:17 +09:00
if ( evea - > switch_lin = = ucontrol - > value . integer . value [ 0 ] )
return 0 ;
evea - > switch_lin = ucontrol - > value . integer . value [ 0 ] ;
return evea_update_switch_lin ( evea ) ;
}
static int evea_get_switch_lo ( struct snd_kcontrol * kcontrol ,
struct snd_ctl_elem_value * ucontrol )
{
2018-01-29 04:47:19 +00:00
struct snd_soc_component * component = snd_soc_kcontrol_component ( kcontrol ) ;
struct evea_priv * evea = snd_soc_component_get_drvdata ( component ) ;
2017-11-22 20:43:17 +09:00
ucontrol - > value . integer . value [ 0 ] = evea - > switch_lo ;
return 0 ;
}
static int evea_set_switch_lo ( struct snd_kcontrol * kcontrol ,
struct snd_ctl_elem_value * ucontrol )
{
2018-01-29 04:47:19 +00:00
struct snd_soc_component * component = snd_soc_kcontrol_component ( kcontrol ) ;
struct evea_priv * evea = snd_soc_component_get_drvdata ( component ) ;
2017-11-22 20:43:17 +09:00
if ( evea - > switch_lo = = ucontrol - > value . integer . value [ 0 ] )
return 0 ;
evea - > switch_lo = ucontrol - > value . integer . value [ 0 ] ;
return evea_update_switch_lo ( evea ) ;
}
static int evea_get_switch_hp ( struct snd_kcontrol * kcontrol ,
struct snd_ctl_elem_value * ucontrol )
{
2018-01-29 04:47:19 +00:00
struct snd_soc_component * component = snd_soc_kcontrol_component ( kcontrol ) ;
struct evea_priv * evea = snd_soc_component_get_drvdata ( component ) ;
2017-11-22 20:43:17 +09:00
ucontrol - > value . integer . value [ 0 ] = evea - > switch_hp ;
return 0 ;
}
static int evea_set_switch_hp ( struct snd_kcontrol * kcontrol ,
struct snd_ctl_elem_value * ucontrol )
{
2018-01-29 04:47:19 +00:00
struct snd_soc_component * component = snd_soc_kcontrol_component ( kcontrol ) ;
struct evea_priv * evea = snd_soc_component_get_drvdata ( component ) ;
2017-11-22 20:43:17 +09:00
if ( evea - > switch_hp = = ucontrol - > value . integer . value [ 0 ] )
return 0 ;
evea - > switch_hp = ucontrol - > value . integer . value [ 0 ] ;
return evea_update_switch_hp ( evea ) ;
}
2018-02-20 18:53:10 +09:00
static const struct snd_kcontrol_new evea_controls [ ] = {
2017-11-22 20:43:17 +09:00
SOC_SINGLE_BOOL_EXT ( " Line Capture Switch " , 0 ,
evea_get_switch_lin , evea_set_switch_lin ) ,
SOC_SINGLE_BOOL_EXT ( " Line Playback Switch " , 0 ,
evea_get_switch_lo , evea_set_switch_lo ) ,
SOC_SINGLE_BOOL_EXT ( " Headphone Playback Switch " , 0 ,
evea_get_switch_hp , evea_set_switch_hp ) ,
} ;
2018-01-29 04:47:19 +00:00
static int evea_codec_probe ( struct snd_soc_component * component )
2017-11-22 20:43:17 +09:00
{
2018-01-29 04:47:19 +00:00
struct evea_priv * evea = snd_soc_component_get_drvdata ( component ) ;
2017-11-22 20:43:17 +09:00
evea - > switch_lin = 1 ;
evea - > switch_lo = 1 ;
evea - > switch_hp = 1 ;
evea_set_power_state_on ( evea ) ;
evea_update_switch_all ( evea ) ;
return 0 ;
}
2018-01-29 04:47:19 +00:00
static int evea_codec_suspend ( struct snd_soc_component * component )
2017-11-22 20:43:17 +09:00
{
2018-01-29 04:47:19 +00:00
struct evea_priv * evea = snd_soc_component_get_drvdata ( component ) ;
2017-11-22 20:43:17 +09:00
evea_set_power_state_off ( evea ) ;
reset_control_assert ( evea - > rst_adamv ) ;
reset_control_assert ( evea - > rst_exiv ) ;
reset_control_assert ( evea - > rst ) ;
clk_disable_unprepare ( evea - > clk_exiv ) ;
clk_disable_unprepare ( evea - > clk ) ;
return 0 ;
}
2018-01-29 04:47:19 +00:00
static int evea_codec_resume ( struct snd_soc_component * component )
2017-11-22 20:43:17 +09:00
{
2018-01-29 04:47:19 +00:00
struct evea_priv * evea = snd_soc_component_get_drvdata ( component ) ;
2017-11-22 20:43:17 +09:00
int ret ;
ret = clk_prepare_enable ( evea - > clk ) ;
if ( ret )
return ret ;
ret = clk_prepare_enable ( evea - > clk_exiv ) ;
if ( ret )
goto err_out_clock ;
ret = reset_control_deassert ( evea - > rst ) ;
if ( ret )
goto err_out_clock_exiv ;
ret = reset_control_deassert ( evea - > rst_exiv ) ;
if ( ret )
goto err_out_reset ;
ret = reset_control_deassert ( evea - > rst_adamv ) ;
if ( ret )
goto err_out_reset_exiv ;
evea_set_power_state_on ( evea ) ;
evea_update_switch_all ( evea ) ;
return 0 ;
err_out_reset_exiv :
reset_control_assert ( evea - > rst_exiv ) ;
err_out_reset :
reset_control_assert ( evea - > rst ) ;
err_out_clock_exiv :
clk_disable_unprepare ( evea - > clk_exiv ) ;
err_out_clock :
clk_disable_unprepare ( evea - > clk ) ;
return ret ;
}
2018-01-29 04:47:19 +00:00
static struct snd_soc_component_driver soc_codec_evea = {
. probe = evea_codec_probe ,
. suspend = evea_codec_suspend ,
. resume = evea_codec_resume ,
. dapm_widgets = evea_widgets ,
. num_dapm_widgets = ARRAY_SIZE ( evea_widgets ) ,
. dapm_routes = evea_routes ,
. num_dapm_routes = ARRAY_SIZE ( evea_routes ) ,
2018-02-20 18:53:10 +09:00
. controls = evea_controls ,
. num_controls = ARRAY_SIZE ( evea_controls ) ,
2018-01-29 04:47:19 +00:00
. idle_bias_on = 1 ,
. use_pmdown_time = 1 ,
. endianness = 1 ,
. non_legacy_dai_naming = 1 ,
2017-11-22 20:43:17 +09:00
} ;
static struct snd_soc_dai_driver soc_dai_evea [ ] = {
{
. name = DRV_NAME " -line1 " ,
. playback = {
. stream_name = " Line Out 1 " ,
. formats = EVEA_FORMATS ,
. rates = EVEA_RATES ,
. channels_min = 2 ,
. channels_max = 2 ,
} ,
. capture = {
. stream_name = " Line In 1 " ,
. formats = EVEA_FORMATS ,
. rates = EVEA_RATES ,
. channels_min = 2 ,
. channels_max = 2 ,
} ,
} ,
{
. name = DRV_NAME " -hp1 " ,
. playback = {
. stream_name = " Headphone 1 " ,
. formats = EVEA_FORMATS ,
. rates = EVEA_RATES ,
. channels_min = 2 ,
. channels_max = 2 ,
} ,
} ,
{
. name = DRV_NAME " -lo2 " ,
. playback = {
. stream_name = " Line Out 2 " ,
. formats = EVEA_FORMATS ,
. rates = EVEA_RATES ,
. channels_min = 2 ,
. channels_max = 2 ,
} ,
} ,
} ;
static const struct regmap_config evea_regmap_config = {
. reg_bits = 32 ,
. reg_stride = 4 ,
. val_bits = 32 ,
. max_register = 0xffc ,
. cache_type = REGCACHE_NONE ,
} ;
static int evea_probe ( struct platform_device * pdev )
{
struct evea_priv * evea ;
void __iomem * preg ;
int ret ;
evea = devm_kzalloc ( & pdev - > dev , sizeof ( struct evea_priv ) , GFP_KERNEL ) ;
if ( ! evea )
return - ENOMEM ;
evea - > clk = devm_clk_get ( & pdev - > dev , " evea " ) ;
if ( IS_ERR ( evea - > clk ) )
return PTR_ERR ( evea - > clk ) ;
evea - > clk_exiv = devm_clk_get ( & pdev - > dev , " exiv " ) ;
if ( IS_ERR ( evea - > clk_exiv ) )
return PTR_ERR ( evea - > clk_exiv ) ;
evea - > rst = devm_reset_control_get_shared ( & pdev - > dev , " evea " ) ;
if ( IS_ERR ( evea - > rst ) )
return PTR_ERR ( evea - > rst ) ;
evea - > rst_exiv = devm_reset_control_get_shared ( & pdev - > dev , " exiv " ) ;
if ( IS_ERR ( evea - > rst_exiv ) )
return PTR_ERR ( evea - > rst_exiv ) ;
2019-07-27 23:07:25 +08:00
preg = devm_platform_ioremap_resource ( pdev , 0 ) ;
2017-11-22 20:43:17 +09:00
if ( IS_ERR ( preg ) )
return PTR_ERR ( preg ) ;
evea - > regmap = devm_regmap_init_mmio ( & pdev - > dev , preg ,
& evea_regmap_config ) ;
if ( IS_ERR ( evea - > regmap ) )
return PTR_ERR ( evea - > regmap ) ;
ret = clk_prepare_enable ( evea - > clk ) ;
if ( ret )
return ret ;
ret = clk_prepare_enable ( evea - > clk_exiv ) ;
if ( ret )
goto err_out_clock ;
ret = reset_control_deassert ( evea - > rst ) ;
if ( ret )
goto err_out_clock_exiv ;
ret = reset_control_deassert ( evea - > rst_exiv ) ;
if ( ret )
goto err_out_reset ;
/* ADAMV will hangup if EXIV reset is asserted */
evea - > rst_adamv = devm_reset_control_get_shared ( & pdev - > dev , " adamv " ) ;
if ( IS_ERR ( evea - > rst_adamv ) ) {
ret = PTR_ERR ( evea - > rst_adamv ) ;
goto err_out_reset_exiv ;
}
ret = reset_control_deassert ( evea - > rst_adamv ) ;
if ( ret )
goto err_out_reset_exiv ;
platform_set_drvdata ( pdev , evea ) ;
2018-01-29 04:47:19 +00:00
ret = devm_snd_soc_register_component ( & pdev - > dev , & soc_codec_evea ,
2017-11-22 20:43:17 +09:00
soc_dai_evea , ARRAY_SIZE ( soc_dai_evea ) ) ;
if ( ret )
goto err_out_reset_adamv ;
return 0 ;
err_out_reset_adamv :
reset_control_assert ( evea - > rst_adamv ) ;
err_out_reset_exiv :
reset_control_assert ( evea - > rst_exiv ) ;
err_out_reset :
reset_control_assert ( evea - > rst ) ;
err_out_clock_exiv :
clk_disable_unprepare ( evea - > clk_exiv ) ;
err_out_clock :
clk_disable_unprepare ( evea - > clk ) ;
return ret ;
}
static int evea_remove ( struct platform_device * pdev )
{
struct evea_priv * evea = platform_get_drvdata ( pdev ) ;
reset_control_assert ( evea - > rst_adamv ) ;
reset_control_assert ( evea - > rst_exiv ) ;
reset_control_assert ( evea - > rst ) ;
clk_disable_unprepare ( evea - > clk_exiv ) ;
clk_disable_unprepare ( evea - > clk ) ;
return 0 ;
}
2020-11-25 17:44:26 +01:00
static const struct of_device_id evea_of_match [ ] __maybe_unused = {
2017-11-22 20:43:17 +09:00
{ . compatible = " socionext,uniphier-evea " , } ,
{ }
} ;
MODULE_DEVICE_TABLE ( of , evea_of_match ) ;
static struct platform_driver evea_codec_driver = {
. driver = {
. name = DRV_NAME ,
. of_match_table = of_match_ptr ( evea_of_match ) ,
} ,
. probe = evea_probe ,
. remove = evea_remove ,
} ;
module_platform_driver ( evea_codec_driver ) ;
MODULE_AUTHOR ( " Katsuhiro Suzuki <suzuki.katsuhiro@socionext.com> " ) ;
MODULE_DESCRIPTION ( " UniPhier EVEA codec driver " ) ;
MODULE_LICENSE ( " GPL v2 " ) ;