summaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/codecs/mxc_hdmi.c143
-rw-r--r--sound/soc/imx/imx-hdmi-dma.c14
-rw-r--r--sound/soc/imx/imx-hdmi.h10
3 files changed, 135 insertions, 32 deletions
diff --git a/sound/soc/codecs/mxc_hdmi.c b/sound/soc/codecs/mxc_hdmi.c
index c6a6bcbdbfd9..70c9b8c9bfe0 100644
--- a/sound/soc/codecs/mxc_hdmi.c
+++ b/sound/soc/codecs/mxc_hdmi.c
@@ -1,7 +1,7 @@
/*
* MXC HDMI ALSA Soc Codec Driver
*
- * Copyright (C) 2011 Freescale Semiconductor, Inc.
+ * Copyright (C) 2011-2012 Freescale Semiconductor, Inc.
*/
/*
@@ -42,6 +42,7 @@
#include <mach/hardware.h>
#include <linux/mfd/mxc-hdmi-core.h>
+#include <mach/mxc_edid.h>
#include <mach/mxc_hdmi.h>
#include "../imx/imx-hdmi.h"
@@ -53,6 +54,16 @@ struct mxc_hdmi_priv {
struct clk *iahb_clk;
};
+static struct mxc_edid_cfg edid_cfg;
+
+static unsigned int playback_rates[HDMI_MAX_RATES];
+static unsigned int playback_sample_size[HDMI_MAX_SAMPLE_SIZE];
+static unsigned int playback_channels[HDMI_MAX_CHANNEL_CONSTRAINTS];
+
+static struct snd_pcm_hw_constraint_list playback_constraint_rates;
+static struct snd_pcm_hw_constraint_list playback_constraint_bits;
+static struct snd_pcm_hw_constraint_list playback_constraint_channels;
+
#ifdef DEBUG
static void dumpregs(void)
{
@@ -100,19 +111,126 @@ static void hdmi_set_audio_infoframe(void)
hdmi_writeb(0x00, HDMI_FC_AUDICONF2);
}
-static unsigned int hdmi_playback_rates[] = { 32000, 44100, 48000, 88200, 96000 };
-
-static struct snd_pcm_hw_constraint_list playback_rate_constraints = {
- .count = ARRAY_SIZE(hdmi_playback_rates),
- .list = hdmi_playback_rates,
- .mask = 0,
+static int cea_audio_rates[HDMI_MAX_RATES] = {
+ 32000,
+ 44100,
+ 48000,
+ 88200,
+ 96000,
+ 176400,
+ 192000,
};
+static void mxc_hdmi_get_playback_rates(void)
+{
+ int i, count = 0;
+ u8 rates;
+
+ /* always assume basic audio support */
+ rates = edid_cfg.sample_rates | 0x7;
+
+ for (i = 0 ; i < HDMI_MAX_RATES ; i++)
+ if ((rates & (1 << i)) != 0)
+ playback_rates[count++] = cea_audio_rates[i];
+
+ playback_constraint_rates.list = playback_rates;
+ playback_constraint_rates.count = count;
+
+#ifdef DEBUG
+ for (i = 0 ; i < playback_constraint_rates.count ; i++)
+ pr_debug("%s: constraint = %d Hz\n", __func__,
+ playback_rates[i]);
+#endif
+}
+
+static void mxc_hdmi_get_playback_sample_size(void)
+{
+ int i = 0;
+
+ /* always assume basic audio support */
+ playback_sample_size[i++] = 16;
+
+ if (edid_cfg.sample_sizes & 0x2)
+ playback_sample_size[i++] = 20;
+
+ if (edid_cfg.sample_sizes & 0x4)
+ playback_sample_size[i++] = 24;
+
+ playback_constraint_bits.list = playback_sample_size;
+ playback_constraint_bits.count = i;
+
+#ifdef DEBUG
+ for (i = 0 ; i < playback_constraint_bits.count ; i++)
+ pr_debug("%s: constraint = %d bits\n", __func__,
+ playback_sample_size[i]);
+#endif
+}
+
+static void mxc_hdmi_get_playback_channels(void)
+{
+ int channels = 2, i = 0;
+
+ /* always assume basic audio support */
+ playback_channels[i++] = channels;
+ channels += 2;
+
+ while ((i < HDMI_MAX_CHANNEL_CONSTRAINTS) &&
+ (channels <= edid_cfg.max_channels)) {
+ playback_channels[i++] = channels;
+ channels += 2;
+ }
+
+ playback_constraint_channels.list = playback_channels;
+ playback_constraint_channels.count = i;
+
+#ifdef DEBUG
+ for (i = 0 ; i < playback_constraint_channels.count ; i++)
+ pr_debug("%s: constraint = %d channels\n", __func__,
+ playback_channels[i]);
+#endif
+}
+
+static int mxc_hdmi_update_constraints(struct mxc_hdmi_priv *priv,
+ struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ int ret;
+
+ hdmi_get_edid_cfg(&edid_cfg);
+
+ mxc_hdmi_get_playback_rates();
+ ret = snd_pcm_hw_constraint_list(substream->runtime, 0,
+ SNDRV_PCM_HW_PARAM_RATE,
+ &playback_constraint_rates);
+ if (ret < 0)
+ return ret;
+
+ mxc_hdmi_get_playback_sample_size();
+ ret = snd_pcm_hw_constraint_list(substream->runtime, 0,
+ SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
+ &playback_constraint_bits);
+ if (ret < 0)
+ return ret;
+
+ mxc_hdmi_get_playback_channels();
+ ret = snd_pcm_hw_constraint_list(runtime, 0,
+ SNDRV_PCM_HW_PARAM_CHANNELS,
+ &playback_constraint_channels);
+ if (ret < 0)
+ return ret;
+
+ ret = snd_pcm_hw_constraint_integer(substream->runtime,
+ SNDRV_PCM_HW_PARAM_PERIODS);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
static int mxc_hdmi_codec_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct mxc_hdmi_priv *hdmi_priv = snd_soc_dai_get_drvdata(dai);
- struct snd_pcm_runtime *runtime = substream->runtime;
int ret;
clk_enable(hdmi_priv->isfr_clk);
@@ -122,14 +240,7 @@ static int mxc_hdmi_codec_startup(struct snd_pcm_substream *substream,
(int)clk_get_rate(hdmi_priv->isfr_clk),
(int)clk_get_rate(hdmi_priv->iahb_clk));
- ret = snd_pcm_hw_constraint_list(runtime, 0,
- SNDRV_PCM_HW_PARAM_RATE,
- &playback_rate_constraints);
- if (ret < 0)
- return ret;
-
- ret = snd_pcm_hw_constraint_integer(runtime,
- SNDRV_PCM_HW_PARAM_PERIODS);
+ ret = mxc_hdmi_update_constraints(hdmi_priv, substream);
if (ret < 0)
return ret;
diff --git a/sound/soc/imx/imx-hdmi-dma.c b/sound/soc/imx/imx-hdmi-dma.c
index 9ce99efccc1b..d0c4d52e9c56 100644
--- a/sound/soc/imx/imx-hdmi-dma.c
+++ b/sound/soc/imx/imx-hdmi-dma.c
@@ -649,14 +649,6 @@ static struct snd_pcm_hardware snd_imx_hardware = {
.fifo_size = 0,
};
-static unsigned int hw_channels[] = {2, 4, 6, 8};
-
-static struct snd_pcm_hw_constraint_list hw_constraint_channels = {
- .count = ARRAY_SIZE(hw_channels),
- .list = hw_channels,
- .mask = 0,
-};
-
static void hdmi_dma_irq_enable(struct imx_hdmi_dma_runtime_data *rtd)
{
unsigned long flags;
@@ -712,12 +704,6 @@ static int hdmi_dma_open(struct snd_pcm_substream *substream)
if (ret < 0)
return ret;
- ret = snd_pcm_hw_constraint_list(runtime, 0,
- SNDRV_PCM_HW_PARAM_CHANNELS,
- &hw_constraint_channels);
- if (ret < 0)
- return ret;
-
snd_soc_set_runtime_hwparams(substream, &snd_imx_hardware);
hdmi_dma_irq_enable(hdmi_dma_priv);
diff --git a/sound/soc/imx/imx-hdmi.h b/sound/soc/imx/imx-hdmi.h
index 52c58dd516d5..11737579af31 100644
--- a/sound/soc/imx/imx-hdmi.h
+++ b/sound/soc/imx/imx-hdmi.h
@@ -1,7 +1,7 @@
/*
* MXC HDMI ALSA Soc Codec Driver
*
- * Copyright (C) 2011 Freescale Semiconductor, Inc.
+ * Copyright (C) 2011-2012 Freescale Semiconductor, Inc.
*/
/*
@@ -31,11 +31,17 @@ struct imx_hdmi {
struct platform_device *soc_platform_pdev;
};
+#define HDMI_MAX_RATES 7
+#define HDMI_MAX_SAMPLE_SIZE 3
+#define HDMI_MAX_CHANNEL_CONSTRAINTS 4
+
#define MXC_HDMI_RATES_PLAYBACK (SNDRV_PCM_RATE_32000 | \
SNDRV_PCM_RATE_44100 | \
SNDRV_PCM_RATE_48000 | \
SNDRV_PCM_RATE_88200 | \
- SNDRV_PCM_RATE_96000)
+ SNDRV_PCM_RATE_96000 | \
+ SNDRV_PCM_RATE_176400 | \
+ SNDRV_PCM_RATE_192000)
#define MXC_HDMI_FORMATS_PLAYBACK (SNDRV_PCM_FMTBIT_S16_LE | \
SNDRV_PCM_FMTBIT_S24_LE)