aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorRicardo Neri <ricardo.neri@ti.com>2012-05-18 02:42:37 -0400
committerLiam Girdwood <lrg@ti.com>2012-05-22 12:33:23 -0400
commita48d9b75869604580e0aeb077d93e8eac9636c4a (patch)
tree752c2e0038c79c32e4ba3e9636e620965c608b73 /sound
parent2603915336352e5491c02b0befa3b890ea13d6ef (diff)
ASoC: OMAP: HDMI: Use the DSS audio interface
Instead of accessing the HDMI IP directly, the CPU DAI driver takes advantage of the audio interface provided by the DSS device driver. The ASoC driver will link the DSS audio functionality with ALSA by calling the appropriate DSS device driver functions at the relevant moments. For this, three new DAI operations are added: trigger, prepare and shutdown operations. At the moment, it is assumed that only one HDMI display is available in the system, as it is the case in OMAP4. However, in the future, one DAI for each HDMI display should be provided. Signed-off-by: Ricardo Neri <ricardo.neri@ti.com> Acked-by: Mark Brown <broonie@opensource.wolfsonmicro.com> Signed-off-by: Liam Girdwood <lrg@ti.com>
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/omap/Kconfig1
-rw-r--r--sound/soc/omap/omap-hdmi.c77
2 files changed, 78 insertions, 0 deletions
diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig
index 9ccfa5e1c11b..13afb2c68dcd 100644
--- a/sound/soc/omap/Kconfig
+++ b/sound/soc/omap/Kconfig
@@ -114,6 +114,7 @@ config SND_OMAP_SOC_OMAP4_HDMI
114 depends on SND_OMAP_SOC && OMAP4_DSS_HDMI && OMAP2_DSS && ARCH_OMAP4 114 depends on SND_OMAP_SOC && OMAP4_DSS_HDMI && OMAP2_DSS && ARCH_OMAP4
115 select SND_OMAP_SOC_HDMI 115 select SND_OMAP_SOC_HDMI
116 select SND_SOC_OMAP_HDMI_CODEC 116 select SND_SOC_OMAP_HDMI_CODEC
117 select OMAP4_DSS_HDMI_AUDIO
117 help 118 help
118 Say Y if you want to add support for SoC HDMI audio on Texas Instruments 119 Say Y if you want to add support for SoC HDMI audio on Texas Instruments
119 OMAP4 chips 120 OMAP4 chips
diff --git a/sound/soc/omap/omap-hdmi.c b/sound/soc/omap/omap-hdmi.c
index a6656b2a7353..ff6132a9b7e8 100644
--- a/sound/soc/omap/omap-hdmi.c
+++ b/sound/soc/omap/omap-hdmi.c
@@ -30,6 +30,7 @@
30#include <sound/pcm_params.h> 30#include <sound/pcm_params.h>
31#include <sound/initval.h> 31#include <sound/initval.h>
32#include <sound/soc.h> 32#include <sound/soc.h>
33#include <video/omapdss.h>
33 34
34#include <plat/dma.h> 35#include <plat/dma.h>
35#include "omap-pcm.h" 36#include "omap-pcm.h"
@@ -39,6 +40,7 @@
39 40
40struct hdmi_priv { 41struct hdmi_priv {
41 struct omap_pcm_dma_data dma_params; 42 struct omap_pcm_dma_data dma_params;
43 struct omap_dss_device *dssdev;
42}; 44};
43 45
44static int omap_hdmi_dai_startup(struct snd_pcm_substream *substream, 46static int omap_hdmi_dai_startup(struct snd_pcm_substream *substream,
@@ -57,6 +59,14 @@ static int omap_hdmi_dai_startup(struct snd_pcm_substream *substream,
57 return 0; 59 return 0;
58} 60}
59 61
62static int omap_hdmi_dai_prepare(struct snd_pcm_substream *substream,
63 struct snd_soc_dai *dai)
64{
65 struct hdmi_priv *priv = snd_soc_dai_get_drvdata(dai);
66
67 return priv->dssdev->driver->audio_enable(priv->dssdev);
68}
69
60static int omap_hdmi_dai_hw_params(struct snd_pcm_substream *substream, 70static int omap_hdmi_dai_hw_params(struct snd_pcm_substream *substream,
61 struct snd_pcm_hw_params *params, 71 struct snd_pcm_hw_params *params,
62 struct snd_soc_dai *dai) 72 struct snd_soc_dai *dai)
@@ -83,6 +93,37 @@ static int omap_hdmi_dai_hw_params(struct snd_pcm_substream *substream,
83 return err; 93 return err;
84} 94}
85 95
96static int omap_hdmi_dai_trigger(struct snd_pcm_substream *substream, int cmd,
97 struct snd_soc_dai *dai)
98{
99 struct hdmi_priv *priv = snd_soc_dai_get_drvdata(dai);
100 int err = 0;
101
102 switch (cmd) {
103 case SNDRV_PCM_TRIGGER_START:
104 case SNDRV_PCM_TRIGGER_RESUME:
105 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
106 err = priv->dssdev->driver->audio_start(priv->dssdev);
107 break;
108 case SNDRV_PCM_TRIGGER_STOP:
109 case SNDRV_PCM_TRIGGER_SUSPEND:
110 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
111 priv->dssdev->driver->audio_stop(priv->dssdev);
112 break;
113 default:
114 err = -EINVAL;
115 }
116 return err;
117}
118
119static void omap_hdmi_dai_shutdown(struct snd_pcm_substream *substream,
120 struct snd_soc_dai *dai)
121{
122 struct hdmi_priv *priv = snd_soc_dai_get_drvdata(dai);
123
124 priv->dssdev->driver->audio_disable(priv->dssdev);
125}
126
86static const struct snd_soc_dai_ops omap_hdmi_dai_ops = { 127static const struct snd_soc_dai_ops omap_hdmi_dai_ops = {
87 .startup = omap_hdmi_dai_startup, 128 .startup = omap_hdmi_dai_startup,
88 .hw_params = omap_hdmi_dai_hw_params, 129 .hw_params = omap_hdmi_dai_hw_params,
@@ -103,6 +144,7 @@ static __devinit int omap_hdmi_probe(struct platform_device *pdev)
103 int ret; 144 int ret;
104 struct resource *hdmi_rsrc; 145 struct resource *hdmi_rsrc;
105 struct hdmi_priv *hdmi_data; 146 struct hdmi_priv *hdmi_data;
147 bool hdmi_dev_found = false;
106 148
107 hdmi_data = devm_kzalloc(&pdev->dev, sizeof(*hdmi_data), GFP_KERNEL); 149 hdmi_data = devm_kzalloc(&pdev->dev, sizeof(*hdmi_data), GFP_KERNEL);
108 if (hdmi_data == NULL) { 150 if (hdmi_data == NULL) {
@@ -129,14 +171,49 @@ static __devinit int omap_hdmi_probe(struct platform_device *pdev)
129 hdmi_data->dma_params.name = "HDMI playback"; 171 hdmi_data->dma_params.name = "HDMI playback";
130 hdmi_data->dma_params.sync_mode = OMAP_DMA_SYNC_PACKET; 172 hdmi_data->dma_params.sync_mode = OMAP_DMA_SYNC_PACKET;
131 173
174 /*
175 * TODO: We assume that there is only one DSS HDMI device. Future
176 * OMAP implementations may support more than one HDMI devices and
177 * we should provided separate audio support for all of them.
178 */
179 /* Find an HDMI device. */
180 for_each_dss_dev(hdmi_data->dssdev) {
181 omap_dss_get_device(hdmi_data->dssdev);
182
183 if (!hdmi_data->dssdev->driver) {
184 omap_dss_put_device(hdmi_data->dssdev);
185 continue;
186 }
187
188 if (hdmi_data->dssdev->type == OMAP_DISPLAY_TYPE_HDMI) {
189 hdmi_dev_found = true;
190 break;
191 }
192 }
193
194 if (!hdmi_dev_found) {
195 dev_err(&pdev->dev, "no driver for HDMI display found\n");
196 return -ENODEV;
197 }
198
132 dev_set_drvdata(&pdev->dev, hdmi_data); 199 dev_set_drvdata(&pdev->dev, hdmi_data);
133 ret = snd_soc_register_dai(&pdev->dev, &omap_hdmi_dai); 200 ret = snd_soc_register_dai(&pdev->dev, &omap_hdmi_dai);
201
134 return ret; 202 return ret;
135} 203}
136 204
137static int __devexit omap_hdmi_remove(struct platform_device *pdev) 205static int __devexit omap_hdmi_remove(struct platform_device *pdev)
138{ 206{
207 struct hdmi_priv *hdmi_data = dev_get_drvdata(&pdev->dev);
208
139 snd_soc_unregister_dai(&pdev->dev); 209 snd_soc_unregister_dai(&pdev->dev);
210
211 if (hdmi_data == NULL) {
212 dev_err(&pdev->dev, "cannot obtain HDMi data\n");
213 return -ENODEV;
214 }
215
216 omap_dss_put_device(hdmi_data->dssdev);
140 return 0; 217 return 0;
141} 218}
142 219