2 * ALSA SoC codec for HDMI encoder drivers
3 * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/
4 * Author: Jyri Sarha <jsarha@ti.com>
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * version 2 as published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
15 #include <linux/module.h>
16 #include <linux/string.h>
17 #include <sound/core.h>
18 #include <sound/pcm.h>
19 #include <sound/pcm_params.h>
20 #include <sound/soc.h>
21 #include <sound/pcm_drm_eld.h>
22 #include <sound/hdmi-codec.h>
23 #include <sound/pcm_iec958.h>
25 #include <drm/drm_crtc.h> /* This is only to get MAX_ELD_BYTES */
27 struct hdmi_codec_priv
{
28 struct hdmi_codec_pdata hcd
;
29 struct snd_soc_dai_driver
*daidrv
;
30 struct hdmi_codec_daifmt daifmt
[2];
31 struct mutex current_stream_lock
;
32 struct snd_pcm_substream
*current_stream
;
33 struct snd_pcm_hw_constraint_list ratec
;
34 uint8_t eld
[MAX_ELD_BYTES
];
37 static const struct snd_soc_dapm_widget hdmi_widgets
[] = {
38 SND_SOC_DAPM_OUTPUT("TX"),
41 static const struct snd_soc_dapm_route hdmi_routes
[] = {
42 { "TX", NULL
, "Playback" },
50 static int hdmi_eld_ctl_info(struct snd_kcontrol
*kcontrol
,
51 struct snd_ctl_elem_info
*uinfo
)
53 struct snd_soc_component
*component
= snd_kcontrol_chip(kcontrol
);
54 struct hdmi_codec_priv
*hcp
= snd_soc_component_get_drvdata(component
);
56 uinfo
->type
= SNDRV_CTL_ELEM_TYPE_BYTES
;
57 uinfo
->count
= sizeof(hcp
->eld
);
62 static int hdmi_eld_ctl_get(struct snd_kcontrol
*kcontrol
,
63 struct snd_ctl_elem_value
*ucontrol
)
65 struct snd_soc_component
*component
= snd_kcontrol_chip(kcontrol
);
66 struct hdmi_codec_priv
*hcp
= snd_soc_component_get_drvdata(component
);
68 memcpy(ucontrol
->value
.bytes
.data
, hcp
->eld
, sizeof(hcp
->eld
));
73 static const struct snd_kcontrol_new hdmi_controls
[] = {
75 .access
= SNDRV_CTL_ELEM_ACCESS_READ
|
76 SNDRV_CTL_ELEM_ACCESS_VOLATILE
,
77 .iface
= SNDRV_CTL_ELEM_IFACE_PCM
,
79 .info
= hdmi_eld_ctl_info
,
80 .get
= hdmi_eld_ctl_get
,
84 static int hdmi_codec_new_stream(struct snd_pcm_substream
*substream
,
85 struct snd_soc_dai
*dai
)
87 struct hdmi_codec_priv
*hcp
= snd_soc_dai_get_drvdata(dai
);
90 mutex_lock(&hcp
->current_stream_lock
);
91 if (!hcp
->current_stream
) {
92 hcp
->current_stream
= substream
;
93 } else if (hcp
->current_stream
!= substream
) {
94 dev_err(dai
->dev
, "Only one simultaneous stream supported!\n");
97 mutex_unlock(&hcp
->current_stream_lock
);
102 static int hdmi_codec_startup(struct snd_pcm_substream
*substream
,
103 struct snd_soc_dai
*dai
)
105 struct hdmi_codec_priv
*hcp
= snd_soc_dai_get_drvdata(dai
);
108 dev_dbg(dai
->dev
, "%s()\n", __func__
);
110 ret
= hdmi_codec_new_stream(substream
, dai
);
114 if (hcp
->hcd
.ops
->audio_startup
) {
115 ret
= hcp
->hcd
.ops
->audio_startup(dai
->dev
->parent
, hcp
->hcd
.data
);
117 mutex_lock(&hcp
->current_stream_lock
);
118 hcp
->current_stream
= NULL
;
119 mutex_unlock(&hcp
->current_stream_lock
);
124 if (hcp
->hcd
.ops
->get_eld
) {
125 ret
= hcp
->hcd
.ops
->get_eld(dai
->dev
->parent
, hcp
->hcd
.data
,
126 hcp
->eld
, sizeof(hcp
->eld
));
129 ret
= snd_pcm_hw_constraint_eld(substream
->runtime
,
138 static void hdmi_codec_shutdown(struct snd_pcm_substream
*substream
,
139 struct snd_soc_dai
*dai
)
141 struct hdmi_codec_priv
*hcp
= snd_soc_dai_get_drvdata(dai
);
143 dev_dbg(dai
->dev
, "%s()\n", __func__
);
145 WARN_ON(hcp
->current_stream
!= substream
);
147 hcp
->hcd
.ops
->audio_shutdown(dai
->dev
->parent
, hcp
->hcd
.data
);
149 mutex_lock(&hcp
->current_stream_lock
);
150 hcp
->current_stream
= NULL
;
151 mutex_unlock(&hcp
->current_stream_lock
);
154 static int hdmi_codec_hw_params(struct snd_pcm_substream
*substream
,
155 struct snd_pcm_hw_params
*params
,
156 struct snd_soc_dai
*dai
)
158 struct hdmi_codec_priv
*hcp
= snd_soc_dai_get_drvdata(dai
);
159 struct hdmi_codec_params hp
= {
164 .dig_subframe
= { 0 },
169 dev_dbg(dai
->dev
, "%s() width %d rate %d channels %d\n", __func__
,
170 params_width(params
), params_rate(params
),
171 params_channels(params
));
173 if (params_width(params
) > 24)
176 ret
= snd_pcm_create_iec958_consumer_hw_params(params
, hp
.iec
.status
,
177 sizeof(hp
.iec
.status
));
179 dev_err(dai
->dev
, "Creating IEC958 channel status failed %d\n",
184 ret
= hdmi_codec_new_stream(substream
, dai
);
188 hdmi_audio_infoframe_init(&hp
.cea
);
189 hp
.cea
.channels
= params_channels(params
);
190 hp
.cea
.coding_type
= HDMI_AUDIO_CODING_TYPE_STREAM
;
191 hp
.cea
.sample_size
= HDMI_AUDIO_SAMPLE_SIZE_STREAM
;
192 hp
.cea
.sample_frequency
= HDMI_AUDIO_SAMPLE_FREQUENCY_STREAM
;
194 hp
.sample_width
= params_width(params
);
195 hp
.sample_rate
= params_rate(params
);
196 hp
.channels
= params_channels(params
);
198 return hcp
->hcd
.ops
->hw_params(dai
->dev
->parent
, hcp
->hcd
.data
,
199 &hcp
->daifmt
[dai
->id
], &hp
);
202 static int hdmi_codec_set_fmt(struct snd_soc_dai
*dai
,
205 struct hdmi_codec_priv
*hcp
= snd_soc_dai_get_drvdata(dai
);
206 struct hdmi_codec_daifmt cf
= { 0 };
209 dev_dbg(dai
->dev
, "%s()\n", __func__
);
211 if (dai
->id
== DAI_ID_SPDIF
) {
214 switch (fmt
& SND_SOC_DAIFMT_MASTER_MASK
) {
215 case SND_SOC_DAIFMT_CBM_CFM
:
216 cf
.bit_clk_master
= 1;
217 cf
.frame_clk_master
= 1;
219 case SND_SOC_DAIFMT_CBS_CFM
:
220 cf
.frame_clk_master
= 1;
222 case SND_SOC_DAIFMT_CBM_CFS
:
223 cf
.bit_clk_master
= 1;
225 case SND_SOC_DAIFMT_CBS_CFS
:
231 switch (fmt
& SND_SOC_DAIFMT_INV_MASK
) {
232 case SND_SOC_DAIFMT_NB_NF
:
234 case SND_SOC_DAIFMT_NB_IF
:
235 cf
.frame_clk_inv
= 1;
237 case SND_SOC_DAIFMT_IB_NF
:
240 case SND_SOC_DAIFMT_IB_IF
:
241 cf
.frame_clk_inv
= 1;
246 switch (fmt
& SND_SOC_DAIFMT_FORMAT_MASK
) {
247 case SND_SOC_DAIFMT_I2S
:
250 case SND_SOC_DAIFMT_DSP_A
:
253 case SND_SOC_DAIFMT_DSP_B
:
256 case SND_SOC_DAIFMT_RIGHT_J
:
257 cf
.fmt
= HDMI_RIGHT_J
;
259 case SND_SOC_DAIFMT_LEFT_J
:
260 cf
.fmt
= HDMI_LEFT_J
;
262 case SND_SOC_DAIFMT_AC97
:
266 dev_err(dai
->dev
, "Invalid DAI interface format\n");
271 hcp
->daifmt
[dai
->id
] = cf
;
276 static int hdmi_codec_digital_mute(struct snd_soc_dai
*dai
, int mute
)
278 struct hdmi_codec_priv
*hcp
= snd_soc_dai_get_drvdata(dai
);
280 dev_dbg(dai
->dev
, "%s()\n", __func__
);
282 if (hcp
->hcd
.ops
->digital_mute
)
283 return hcp
->hcd
.ops
->digital_mute(dai
->dev
->parent
,
284 hcp
->hcd
.data
, mute
);
289 static const struct snd_soc_dai_ops hdmi_dai_ops
= {
290 .startup
= hdmi_codec_startup
,
291 .shutdown
= hdmi_codec_shutdown
,
292 .hw_params
= hdmi_codec_hw_params
,
293 .set_fmt
= hdmi_codec_set_fmt
,
294 .digital_mute
= hdmi_codec_digital_mute
,
298 #define HDMI_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\
299 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |\
300 SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 |\
301 SNDRV_PCM_RATE_192000)
303 #define SPDIF_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE |\
304 SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S20_3BE |\
305 SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_3BE |\
306 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE)
309 * This list is only for formats allowed on the I2S bus. So there is
310 * some formats listed that are not supported by HDMI interface. For
311 * instance allowing the 32-bit formats enables 24-precision with CPU
312 * DAIs that do not support 24-bit formats. If the extra formats cause
313 * problems, we should add the video side driver an option to disable
316 #define I2S_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE |\
317 SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S20_3BE |\
318 SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_3BE |\
319 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE |\
320 SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE)
322 static struct snd_soc_dai_driver hdmi_i2s_dai
= {
326 .stream_name
= "Playback",
330 .formats
= I2S_FORMATS
,
333 .ops
= &hdmi_dai_ops
,
336 static const struct snd_soc_dai_driver hdmi_spdif_dai
= {
337 .name
= "spdif-hifi",
340 .stream_name
= "Playback",
344 .formats
= SPDIF_FORMATS
,
346 .ops
= &hdmi_dai_ops
,
349 static struct snd_soc_codec_driver hdmi_codec
= {
350 .controls
= hdmi_controls
,
351 .num_controls
= ARRAY_SIZE(hdmi_controls
),
352 .dapm_widgets
= hdmi_widgets
,
353 .num_dapm_widgets
= ARRAY_SIZE(hdmi_widgets
),
354 .dapm_routes
= hdmi_routes
,
355 .num_dapm_routes
= ARRAY_SIZE(hdmi_routes
),
358 static int hdmi_codec_probe(struct platform_device
*pdev
)
360 struct hdmi_codec_pdata
*hcd
= pdev
->dev
.platform_data
;
361 struct device
*dev
= &pdev
->dev
;
362 struct hdmi_codec_priv
*hcp
;
363 int dai_count
, i
= 0;
366 dev_dbg(dev
, "%s()\n", __func__
);
369 dev_err(dev
, "%s: No plalform data\n", __func__
);
373 dai_count
= hcd
->i2s
+ hcd
->spdif
;
374 if (dai_count
< 1 || !hcd
->ops
|| !hcd
->ops
->hw_params
||
375 !hcd
->ops
->audio_shutdown
) {
376 dev_err(dev
, "%s: Invalid parameters\n", __func__
);
380 hcp
= devm_kzalloc(dev
, sizeof(*hcp
), GFP_KERNEL
);
385 mutex_init(&hcp
->current_stream_lock
);
387 hcp
->daidrv
= devm_kzalloc(dev
, dai_count
* sizeof(*hcp
->daidrv
),
393 hcp
->daidrv
[i
] = hdmi_i2s_dai
;
394 hcp
->daidrv
[i
].playback
.channels_max
=
395 hcd
->max_i2s_channels
;
400 hcp
->daidrv
[i
] = hdmi_spdif_dai
;
402 ret
= snd_soc_register_codec(dev
, &hdmi_codec
, hcp
->daidrv
,
405 dev_err(dev
, "%s: snd_soc_register_codec() failed (%d)\n",
410 dev_set_drvdata(dev
, hcp
);
414 static int hdmi_codec_remove(struct platform_device
*pdev
)
416 snd_soc_unregister_codec(&pdev
->dev
);
420 static struct platform_driver hdmi_codec_driver
= {
422 .name
= HDMI_CODEC_DRV_NAME
,
424 .probe
= hdmi_codec_probe
,
425 .remove
= hdmi_codec_remove
,
428 module_platform_driver(hdmi_codec_driver
);
430 MODULE_AUTHOR("Jyri Sarha <jsarha@ti.com>");
431 MODULE_DESCRIPTION("HDMI Audio Codec Driver");
432 MODULE_LICENSE("GPL");
433 MODULE_ALIAS("platform:" HDMI_CODEC_DRV_NAME
);