summaryrefslogtreecommitdiff
path: root/sound/soc/ux500/ux500_av8100.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/ux500/ux500_av8100.c')
-rw-r--r--sound/soc/ux500/ux500_av8100.c159
1 files changed, 121 insertions, 38 deletions
diff --git a/sound/soc/ux500/ux500_av8100.c b/sound/soc/ux500/ux500_av8100.c
index b6cced7f1e5..5317670c3b4 100644
--- a/sound/soc/ux500/ux500_av8100.c
+++ b/sound/soc/ux500/ux500_av8100.c
@@ -24,56 +24,139 @@
static struct platform_device *ux500_av8100_platform_device;
-static int ux500_av8100_hw_params(
- struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
+static int ux500_av8100_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->dai->codec_dai;
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+
+ unsigned int tx_mask, fmt;
+ enum hdmi_channel_allocation hdmi_ca;
+ enum hdmi_audio_channel_count hdmi_cc;
+ struct hdmi_audio_settings as;
+
+ int channels = params_channels(params);
int ret = 0;
- pr_debug("%s: Enter.\n", __func__);
+ pr_debug("%s: Enter (TDM-mode, channels = %d, name = %s, number = %d).\n",
+ __func__,
+ channels,
+ substream->name,
+ substream->number);
pr_debug("%s: substream->pcm->name = %s.\n", __func__, substream->pcm->name);
pr_debug("%s: substream->pcm->id = %s.\n", __func__, substream->pcm->id);
- pr_debug("%s: substream->name = %s.\n", __func__, substream->name);
- pr_debug("%s: substream->number = %d.\n", __func__, substream->number);
-
- if (cpu_dai->ops->set_fmt) {
- dev_dbg(&ux500_av8100_platform_device->dev,
- "%s: Setting format on codec_dai: "
- "SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM.",
- __func__);
- ret = snd_soc_dai_set_fmt(
- codec_dai,
- SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM);
- if (ret < 0) {
- dev_dbg(&ux500_av8100_platform_device->dev,
- "%s: snd_soc_dai_set_fmt failed with %d.\n",
- __func__,
- ret);
- return ret;
- }
- dev_dbg(&ux500_av8100_platform_device->dev,
- "%s: Setting format on cpu_dai: "
- "SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM.",
- __func__);
- ret = snd_soc_dai_set_fmt(
- cpu_dai,
- SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM);
- if (ret < 0) {
- dev_dbg(&ux500_av8100_platform_device->dev,
- "%s: snd_soc_dai_set_fmt failed with %d.\n",
- __func__,
- ret);
- return ret;
- }
+ switch (channels) {
+ case 1:
+ hdmi_cc = AV8100_CODEC_CC_2CH;
+ hdmi_ca = AV8100_CODEC_CA_FL_FR; /* Stereo-setup */
+ tx_mask = AV8100_CODEC_MASK_MONO;
+ break;
+ case 2:
+ hdmi_cc = AV8100_CODEC_CC_2CH;
+ hdmi_ca = AV8100_CODEC_CA_FL_FR; /* Stereo */
+ tx_mask = AV8100_CODEC_MASK_STEREO;
+ break;
+ case 3:
+ hdmi_cc = AV8100_CODEC_CC_6CH;
+ hdmi_ca = AV8100_CODEC_CA_FL_FR_LFE_FC_RL_RR; /* 5.1-setup */
+ tx_mask = AV8100_CODEC_MASK_2DOT1;
+ break;
+ case 4:
+ hdmi_cc = AV8100_CODEC_CC_6CH;
+ hdmi_ca = AV8100_CODEC_CA_FL_FR_LFE_FC_RL_RR; /* 5.1-setup */
+ tx_mask = AV8100_CODEC_MASK_QUAD;
+ break;
+ case 5:
+ hdmi_cc = AV8100_CODEC_CC_6CH;
+ hdmi_ca = AV8100_CODEC_CA_FL_FR_LFE_FC_RL_RR; /* 5.1-setup */
+ tx_mask = AV8100_CODEC_MASK_5DOT0;
+ break;
+ case 6:
+ hdmi_cc = AV8100_CODEC_CC_6CH;
+ hdmi_ca = AV8100_CODEC_CA_FL_FR_LFE_FC_RL_RR; /* 5.1 */
+ tx_mask = AV8100_CODEC_MASK_5DOT1;
+ break;
+ case 8:
+ hdmi_cc = AV8100_CODEC_CC_6CH;
+ hdmi_ca = AV8100_CODEC_CA_FL_FR_LFE_FC_RL_RR_FLC_FRC; /* 7.1 */
+ tx_mask = AV8100_CODEC_MASK_7DOT1;
+ break;
+ default:
+ pr_err("%s: Unsupported number of channels (channels = %d)!\n",
+ __func__,
+ channels);
+ return -EINVAL;
+ }
+
+ /* Change HDMI audio-settings for codec-DAI. */
+ pr_debug("%s: Change HDMI audio-settings for codec-DAI.\n", __func__);
+ as.audio_coding_type = AV8100_CODEC_CT_IEC60958_PCM;
+ as.audio_channel_count = hdmi_cc;
+ as.sampling_frequency = AV8100_CODEC_SF_48KHZ;
+ as.sample_size = AV8100_CODEC_SS_16BIT;
+ as.channel_allocation = hdmi_ca;
+ as.level_shift_value = AV8100_CODEC_LSV_0DB;
+ as.downmix_inhibit = false;
+ ret = av8100_codec_change_hdmi_audio_settings(substream, &as);
+ if (ret < 0) {
+ pr_err("%s: Unable to change HDMI audio-settings for codec-DAI "
+ "(av8100_codec_change_hdmi_audio_settings returned %d)!\n",
+ __func__,
+ ret);
+ return ret;
+ }
+
+ /* Set format for codec-DAI */
+ fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM;
+ pr_debug("%s: Setting format for codec-DAI (fmt = %d).\n",
+ __func__,
+ fmt);
+ ret = snd_soc_dai_set_fmt(codec_dai, fmt);
+ if (ret < 0) {
+ pr_err("%s: Unable to set format for codec-DAI "
+ "(snd_soc_dai_set_tdm_slot returned %d)!\n",
+ __func__,
+ ret);
+ return ret;
}
- return ret;
+
+ /* Set TDM-slot for CPU-DAI */
+ pr_debug("%s: Setting TDM-slot for codec-DAI (tx_mask = %d).\n",
+ __func__,
+ tx_mask);
+ ret = snd_soc_dai_set_tdm_slot(cpu_dai, tx_mask, 0, 16, 16);
+ if (ret < 0) {
+ pr_err("%s: Unable to set TDM-slot for codec-DAI "
+ "(snd_soc_dai_set_tdm_slot returned %d)!\n",
+ __func__,
+ ret);
+ return ret;
+ }
+
+ /* Set format for CPU-DAI */
+ fmt = SND_SOC_DAIFMT_DSP_B |
+ SND_SOC_DAIFMT_CBM_CFM |
+ SND_SOC_DAIFMT_NB_IF;
+ pr_debug("%s: Setting DAI-format for Ux500-platform (fmt = %d).\n",
+ __func__,
+ fmt);
+ ret = snd_soc_dai_set_fmt(cpu_dai, fmt);
+ if (ret < 0) {
+ pr_err("%s: Unable to set DAI-format for Ux500-platform "
+ "(snd_soc_dai_set_fmt returned %d).\n",
+ __func__,
+ ret);
+ return ret;
+ }
+
+ return ret;
}
+
+
struct snd_soc_dai_link ux500_av8100_dai_links[] = {
{
.name = "hdmi",
@@ -161,4 +244,4 @@ static void __exit ux500_av8100_soc_exit(void)
module_init(ux500_av8100_soc_init);
module_exit(ux500_av8100_soc_exit);
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");