@@ -90,16 +90,21 @@
#define SUN8I_SYSCLK_CTL_AIF2CLK_SRC_MASK GENMASK(5, 4)
#define SUN8I_SYS_SR_CTRL_AIF1_FS_MASK GENMASK(15, 12)
#define SUN8I_SYS_SR_CTRL_AIF2_FS_MASK GENMASK(11, 8)
#define SUN8I_AIF1CLK_CTRL_AIF1_BCLK_DIV_MASK GENMASK(12, 9)
#define SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV_MASK GENMASK(8, 6)
#define SUN8I_AIF1CLK_CTRL_AIF1_WORD_SIZ_MASK GENMASK(5, 4)
#define SUN8I_AIF1CLK_CTRL_AIF1_DATA_FMT_MASK GENMASK(3, 2)
+enum {
+ SUN8I_CODEC_AIF1,
+ SUN8I_CODEC_NAIFS
+};
+
struct sun8i_codec_quirks {
bool legacy_widgets : 1;
bool lrck_inversion : 1;
};
struct sun8i_codec {
struct regmap *regmap;
struct clk *clk_module;
@@ -160,17 +165,17 @@ static int sun8i_codec_get_hw_rate(struct snd_pcm_hw_params *params)
return 0x9;
case 192000:
return 0xa;
default:
return -EINVAL;
}
}
-static int sun8i_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+static int sun8i_codec_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
{
struct sun8i_codec *scodec = snd_soc_dai_get_drvdata(dai);
u32 value;
/* clock masters */
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBS_CFS: /* Codec slave, DAI master */
value = 0x1;
@@ -331,16 +336,46 @@ static int sun8i_codec_hw_params(struct snd_pcm_substream *substream,
regmap_update_bits(scodec->regmap, SUN8I_SYS_SR_CTRL,
SUN8I_SYS_SR_CTRL_AIF1_FS_MASK,
sample_rate << SUN8I_SYS_SR_CTRL_AIF1_FS);
return 0;
}
+static const struct snd_soc_dai_ops sun8i_codec_dai_ops = {
+ .set_fmt = sun8i_codec_set_fmt,
+ .hw_params = sun8i_codec_hw_params,
+};
+
+static struct snd_soc_dai_driver sun8i_codec_dais[] = {
+ {
+ .name = "sun8i-codec-aif1",
+ .id = SUN8I_CODEC_AIF1,
+ .ops = &sun8i_codec_dai_ops,
+ /* capture capabilities */
+ .capture = {
+ .stream_name = "AIF1 Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_8000_192000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .sig_bits = 24,
+ },
+ /* playback capabilities */
+ .playback = {
+ .stream_name = "AIF1 Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_8000_192000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ },
+ },
+};
+
static const char *const sun8i_aif_stereo_mux_enum_values[] = {
"Stereo", "Reverse Stereo", "Sum Mono", "Mix Mono"
};
static SOC_ENUM_DOUBLE_DECL(sun8i_aif1_ad0_stereo_mux_enum,
SUN8I_AIF1_ADCDAT_CTRL,
SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0L_SRC,
SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0R_SRC,
@@ -433,20 +468,20 @@ static const struct snd_soc_dapm_widget sun8i_codec_dapm_widgets[] = {
SND_SOC_DAPM_SUPPLY("ADC",
SUN8I_ADC_DIG_CTRL,
SUN8I_ADC_DIG_CTRL_ENAD, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("DAC",
SUN8I_DAC_DIG_CTRL,
SUN8I_DAC_DIG_CTRL_ENDA, 0, NULL, 0),
/* AIF "ADC" Outputs */
- SND_SOC_DAPM_AIF_OUT("AIF1 AD0L", "Capture", 0,
+ SND_SOC_DAPM_AIF_OUT("AIF1 AD0L", "AIF1 Capture", 0,
SUN8I_AIF1_ADCDAT_CTRL,
SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0L_ENA, 0),
- SND_SOC_DAPM_AIF_OUT("AIF1 AD0R", "Capture", 1,
+ SND_SOC_DAPM_AIF_OUT("AIF1 AD0R", "AIF1 Capture", 1,
SUN8I_AIF1_ADCDAT_CTRL,
SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0R_ENA, 0),
/* AIF "ADC" Mono/Stereo Muxes */
SND_SOC_DAPM_MUX("AIF1 AD0L Stereo Mux", SND_SOC_NOPM, 0, 0,
&sun8i_aif1_ad0_stereo_mux_control),
SND_SOC_DAPM_MUX("AIF1 AD0R Stereo Mux", SND_SOC_NOPM, 0, 0,
&sun8i_aif1_ad0_stereo_mux_control),
@@ -459,20 +494,20 @@ static const struct snd_soc_dapm_widget sun8i_codec_dapm_widgets[] = {
/* AIF "DAC" Mono/Stereo Muxes */
SND_SOC_DAPM_MUX("AIF1 DA0L Stereo Mux", SND_SOC_NOPM, 0, 0,
&sun8i_aif1_da0_stereo_mux_control),
SND_SOC_DAPM_MUX("AIF1 DA0R Stereo Mux", SND_SOC_NOPM, 0, 0,
&sun8i_aif1_da0_stereo_mux_control),
/* AIF "DAC" Inputs */
- SND_SOC_DAPM_AIF_IN("AIF1 DA0L", "Playback", 0,
+ SND_SOC_DAPM_AIF_IN("AIF1 DA0L", "AIF1 Playback", 0,
SUN8I_AIF1_DACDAT_CTRL,
SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0L_ENA, 0),
- SND_SOC_DAPM_AIF_IN("AIF1 DA0R", "Playback", 1,
+ SND_SOC_DAPM_AIF_IN("AIF1 DA0R", "AIF1 Playback", 1,
SUN8I_AIF1_DACDAT_CTRL,
SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0R_ENA, 0),
/* ADC Inputs (connected to analog codec DAPM context) */
SND_SOC_DAPM_ADC("ADCL", NULL, SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_ADC("ADCR", NULL, SND_SOC_NOPM, 0, 0),
/* DAC Outputs (connected to analog codec DAPM context) */
@@ -619,44 +654,16 @@ static int sun8i_codec_component_probe(struct snd_soc_component *component)
/* Use AIF1CLK as the SYSCLK parent since AIF1 is used most often. */
regmap_update_bits(scodec->regmap, SUN8I_SYSCLK_CTL,
BIT(SUN8I_SYSCLK_CTL_SYSCLK_SRC),
SUN8I_SYSCLK_CTL_SYSCLK_SRC_AIF1CLK);
return 0;
}
-static const struct snd_soc_dai_ops sun8i_codec_dai_ops = {
- .hw_params = sun8i_codec_hw_params,
- .set_fmt = sun8i_set_fmt,
-};
-
-static struct snd_soc_dai_driver sun8i_codec_dai = {
- .name = "sun8i",
- /* playback capabilities */
- .playback = {
- .stream_name = "Playback",
- .channels_min = 1,
- .channels_max = 2,
- .rates = SNDRV_PCM_RATE_8000_192000,
- .formats = SNDRV_PCM_FMTBIT_S16_LE,
- },
- /* capture capabilities */
- .capture = {
- .stream_name = "Capture",
- .channels_min = 1,
- .channels_max = 2,
- .rates = SNDRV_PCM_RATE_8000_192000,
- .formats = SNDRV_PCM_FMTBIT_S16_LE,
- .sig_bits = 24,
- },
- /* pcm operations */
- .ops = &sun8i_codec_dai_ops,
-};
-
static const struct snd_soc_component_driver sun8i_soc_component = {
.dapm_widgets = sun8i_codec_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(sun8i_codec_dapm_widgets),
.dapm_routes = sun8i_codec_dapm_routes,
.num_dapm_routes = ARRAY_SIZE(sun8i_codec_dapm_routes),
.probe = sun8i_codec_component_probe,
.idle_bias_on = 1,
.use_pmdown_time = 1,
@@ -709,17 +716,18 @@ static int sun8i_codec_probe(struct platform_device *pdev)
pm_runtime_enable(&pdev->dev);
if (!pm_runtime_enabled(&pdev->dev)) {
ret = sun8i_codec_runtime_resume(&pdev->dev);
if (ret)
goto err_pm_disable;
}
ret = devm_snd_soc_register_component(&pdev->dev, &sun8i_soc_component,
- &sun8i_codec_dai, 1);
+ sun8i_codec_dais,
+ ARRAY_SIZE(sun8i_codec_dais));
if (ret) {
dev_err(&pdev->dev, "Failed to register codec\n");
goto err_suspend;
}
return ret;
err_suspend: