diff options
author | Ricardo Neri <ricardo.neri@ti.com> | 2012-05-18 02:42:38 -0400 |
---|---|---|
committer | Liam Girdwood <lrg@ti.com> | 2012-05-22 12:33:23 -0400 |
commit | 7e6aa220798efd5cd95737b7493b904dddbf413d (patch) | |
tree | ae5d51cc80ad9273570365fc8be6e24f3b1214a9 /sound | |
parent | a48d9b75869604580e0aeb077d93e8eac9636c4a (diff) |
ASoC: OMAP: HDMI: Expand configuration of hw_params
Expand the configuration of the hw_params to include the IEC-60958
channel status word and the CEA-861 audio infoframe. The configuration
of such structures depends on the snd_pcm_hw_params received. A
omap_dss_audio is used to pass the configuration parameters to DSS.
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/omap-hdmi.c | 116 |
1 files changed, 115 insertions, 1 deletions
diff --git a/sound/soc/omap/omap-hdmi.c b/sound/soc/omap/omap-hdmi.c index ff6132a9b7e8..fc4815a6efb1 100644 --- a/sound/soc/omap/omap-hdmi.c +++ b/sound/soc/omap/omap-hdmi.c | |||
@@ -30,6 +30,8 @@ | |||
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 <sound/asound.h> | ||
34 | #include <sound/asoundef.h> | ||
33 | #include <video/omapdss.h> | 35 | #include <video/omapdss.h> |
34 | 36 | ||
35 | #include <plat/dma.h> | 37 | #include <plat/dma.h> |
@@ -40,6 +42,9 @@ | |||
40 | 42 | ||
41 | struct hdmi_priv { | 43 | struct hdmi_priv { |
42 | struct omap_pcm_dma_data dma_params; | 44 | struct omap_pcm_dma_data dma_params; |
45 | struct omap_dss_audio dss_audio; | ||
46 | struct snd_aes_iec958 iec; | ||
47 | struct snd_cea_861_aud_if cea; | ||
43 | struct omap_dss_device *dssdev; | 48 | struct omap_dss_device *dssdev; |
44 | }; | 49 | }; |
45 | 50 | ||
@@ -72,6 +77,8 @@ static int omap_hdmi_dai_hw_params(struct snd_pcm_substream *substream, | |||
72 | struct snd_soc_dai *dai) | 77 | struct snd_soc_dai *dai) |
73 | { | 78 | { |
74 | struct hdmi_priv *priv = snd_soc_dai_get_drvdata(dai); | 79 | struct hdmi_priv *priv = snd_soc_dai_get_drvdata(dai); |
80 | struct snd_aes_iec958 *iec = &priv->iec; | ||
81 | struct snd_cea_861_aud_if *cea = &priv->cea; | ||
75 | int err = 0; | 82 | int err = 0; |
76 | 83 | ||
77 | switch (params_format(params)) { | 84 | switch (params_format(params)) { |
@@ -82,7 +89,8 @@ static int omap_hdmi_dai_hw_params(struct snd_pcm_substream *substream, | |||
82 | priv->dma_params.packet_size = 32; | 89 | priv->dma_params.packet_size = 32; |
83 | break; | 90 | break; |
84 | default: | 91 | default: |
85 | err = -EINVAL; | 92 | dev_err(dai->dev, "format not supported!\n"); |
93 | return -EINVAL; | ||
86 | } | 94 | } |
87 | 95 | ||
88 | priv->dma_params.data_type = OMAP_DMA_DATA_TYPE_S32; | 96 | priv->dma_params.data_type = OMAP_DMA_DATA_TYPE_S32; |
@@ -90,6 +98,109 @@ static int omap_hdmi_dai_hw_params(struct snd_pcm_substream *substream, | |||
90 | snd_soc_dai_set_dma_data(dai, substream, | 98 | snd_soc_dai_set_dma_data(dai, substream, |
91 | &priv->dma_params); | 99 | &priv->dma_params); |
92 | 100 | ||
101 | /* | ||
102 | * fill the IEC-60958 channel status word | ||
103 | */ | ||
104 | |||
105 | /* specify IEC-60958-3 (commercial use) */ | ||
106 | iec->status[0] &= ~IEC958_AES0_PROFESSIONAL; | ||
107 | |||
108 | /* specify that the audio is LPCM*/ | ||
109 | iec->status[0] &= ~IEC958_AES0_NONAUDIO; | ||
110 | |||
111 | iec->status[0] |= IEC958_AES0_CON_NOT_COPYRIGHT; | ||
112 | |||
113 | iec->status[0] |= IEC958_AES0_CON_EMPHASIS_NONE; | ||
114 | |||
115 | iec->status[0] |= IEC958_AES1_PRO_MODE_NOTID; | ||
116 | |||
117 | iec->status[1] = IEC958_AES1_CON_GENERAL; | ||
118 | |||
119 | iec->status[2] |= IEC958_AES2_CON_SOURCE_UNSPEC; | ||
120 | |||
121 | iec->status[2] |= IEC958_AES2_CON_CHANNEL_UNSPEC; | ||
122 | |||
123 | switch (params_rate(params)) { | ||
124 | case 32000: | ||
125 | iec->status[3] |= IEC958_AES3_CON_FS_32000; | ||
126 | break; | ||
127 | case 44100: | ||
128 | iec->status[3] |= IEC958_AES3_CON_FS_44100; | ||
129 | break; | ||
130 | case 48000: | ||
131 | iec->status[3] |= IEC958_AES3_CON_FS_48000; | ||
132 | break; | ||
133 | case 88200: | ||
134 | iec->status[3] |= IEC958_AES3_CON_FS_88200; | ||
135 | break; | ||
136 | case 96000: | ||
137 | iec->status[3] |= IEC958_AES3_CON_FS_96000; | ||
138 | break; | ||
139 | case 176400: | ||
140 | iec->status[3] |= IEC958_AES3_CON_FS_176400; | ||
141 | break; | ||
142 | case 192000: | ||
143 | iec->status[3] |= IEC958_AES3_CON_FS_192000; | ||
144 | break; | ||
145 | default: | ||
146 | dev_err(dai->dev, "rate not supported!\n"); | ||
147 | return -EINVAL; | ||
148 | } | ||
149 | |||
150 | /* specify the clock accuracy */ | ||
151 | iec->status[3] |= IEC958_AES3_CON_CLOCK_1000PPM; | ||
152 | |||
153 | /* | ||
154 | * specify the word length. The same word length value can mean | ||
155 | * two different lengths. Hence, we need to specify the maximum | ||
156 | * word length as well. | ||
157 | */ | ||
158 | switch (params_format(params)) { | ||
159 | case SNDRV_PCM_FORMAT_S16_LE: | ||
160 | iec->status[4] |= IEC958_AES4_CON_WORDLEN_20_16; | ||
161 | iec->status[4] &= ~IEC958_AES4_CON_MAX_WORDLEN_24; | ||
162 | break; | ||
163 | case SNDRV_PCM_FORMAT_S24_LE: | ||
164 | iec->status[4] |= IEC958_AES4_CON_WORDLEN_24_20; | ||
165 | iec->status[4] |= IEC958_AES4_CON_MAX_WORDLEN_24; | ||
166 | break; | ||
167 | default: | ||
168 | dev_err(dai->dev, "format not supported!\n"); | ||
169 | return -EINVAL; | ||
170 | } | ||
171 | |||
172 | /* | ||
173 | * Fill the CEA-861 audio infoframe (see spec for details) | ||
174 | */ | ||
175 | |||
176 | cea->db1_ct_cc = (params_channels(params) - 1) | ||
177 | & CEA861_AUDIO_INFOFRAME_DB1CC; | ||
178 | cea->db1_ct_cc |= CEA861_AUDIO_INFOFRAME_DB1CT_FROM_STREAM; | ||
179 | |||
180 | cea->db2_sf_ss = CEA861_AUDIO_INFOFRAME_DB2SF_FROM_STREAM; | ||
181 | cea->db2_sf_ss |= CEA861_AUDIO_INFOFRAME_DB2SS_FROM_STREAM; | ||
182 | |||
183 | cea->db3 = 0; /* not used, all zeros */ | ||
184 | |||
185 | /* | ||
186 | * The OMAP HDMI IP requires to use the 8-channel channel code when | ||
187 | * transmitting more than two channels. | ||
188 | */ | ||
189 | if (params_channels(params) == 2) | ||
190 | cea->db4_ca = 0x0; | ||
191 | else | ||
192 | cea->db4_ca = 0x13; | ||
193 | |||
194 | cea->db5_dminh_lsv = CEA861_AUDIO_INFOFRAME_DB5_DM_INH_PROHIBITED; | ||
195 | /* the expression is trivial but makes clear what we are doing */ | ||
196 | cea->db5_dminh_lsv |= (0 & CEA861_AUDIO_INFOFRAME_DB5_LSV); | ||
197 | |||
198 | priv->dss_audio.iec = iec; | ||
199 | priv->dss_audio.cea = cea; | ||
200 | |||
201 | err = priv->dssdev->driver->audio_config(priv->dssdev, | ||
202 | &priv->dss_audio); | ||
203 | |||
93 | return err; | 204 | return err; |
94 | } | 205 | } |
95 | 206 | ||
@@ -127,6 +238,9 @@ static void omap_hdmi_dai_shutdown(struct snd_pcm_substream *substream, | |||
127 | static const struct snd_soc_dai_ops omap_hdmi_dai_ops = { | 238 | static const struct snd_soc_dai_ops omap_hdmi_dai_ops = { |
128 | .startup = omap_hdmi_dai_startup, | 239 | .startup = omap_hdmi_dai_startup, |
129 | .hw_params = omap_hdmi_dai_hw_params, | 240 | .hw_params = omap_hdmi_dai_hw_params, |
241 | .prepare = omap_hdmi_dai_prepare, | ||
242 | .trigger = omap_hdmi_dai_trigger, | ||
243 | .shutdown = omap_hdmi_dai_shutdown, | ||
130 | }; | 244 | }; |
131 | 245 | ||
132 | static struct snd_soc_dai_driver omap_hdmi_dai = { | 246 | static struct snd_soc_dai_driver omap_hdmi_dai = { |