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 mutex_lock(&hcp
->eld_lock
);
69 memcpy(ucontrol
->value
.bytes
.data
, hcp
->eld
, sizeof(hcp
->eld
));
70 mutex_unlock(&hcp
->eld_lock
);
75 static const struct snd_kcontrol_new hdmi_controls
[] = {
77 .access
= SNDRV_CTL_ELEM_ACCESS_READ
|
78 SNDRV_CTL_ELEM_ACCESS_VOLATILE
,
79 .iface
= SNDRV_CTL_ELEM_IFACE_PCM
,
81 .info
= hdmi_eld_ctl_info
,
82 .get
= hdmi_eld_ctl_get
,
86 static int hdmi_codec_new_stream(struct snd_pcm_substream
*substream
,
87 struct snd_soc_dai
*dai
)
89 struct hdmi_codec_priv
*hcp
= snd_soc_dai_get_drvdata(dai
);
92 mutex_lock(&hcp
->current_stream_lock
);
93 if (!hcp
->current_stream
) {
94 hcp
->current_stream
= substream
;
95 } else if (hcp
->current_stream
!= substream
) {
96 dev_err(dai
->dev
, "Only one simultaneous stream supported!\n");
99 mutex_unlock(&hcp
->current_stream_lock
);
104 static int hdmi_codec_startup(struct snd_pcm_substream
*substream
,
105 struct snd_soc_dai
*dai
)
107 struct hdmi_codec_priv
*hcp
= snd_soc_dai_get_drvdata(dai
);
110 dev_dbg(dai
->dev
, "%s()\n", __func__
);
112 ret
= hdmi_codec_new_stream(substream
, dai
);
116 if (hcp
->hcd
.ops
->audio_startup
) {
117 ret
= hcp
->hcd
.ops
->audio_startup(dai
->dev
->parent
);
119 mutex_lock(&hcp
->current_stream_lock
);
120 hcp
->current_stream
= NULL
;
121 mutex_unlock(&hcp
->current_stream_lock
);
126 if (hcp
->hcd
.ops
->get_eld
) {
127 ret
= hcp
->hcd
.ops
->get_eld(dai
->dev
->parent
, hcp
->eld
,
131 ret
= snd_pcm_hw_constraint_eld(substream
->runtime
,
140 static void hdmi_codec_shutdown(struct snd_pcm_substream
*substream
,
141 struct snd_soc_dai
*dai
)
143 struct hdmi_codec_priv
*hcp
= snd_soc_dai_get_drvdata(dai
);
145 dev_dbg(dai
->dev
, "%s()\n", __func__
);
147 WARN_ON(hcp
->current_stream
!= substream
);
149 hcp
->hcd
.ops
->audio_shutdown(dai
->dev
->parent
);
151 mutex_lock(&hcp
->current_stream_lock
);
152 hcp
->current_stream
= NULL
;
153 mutex_unlock(&hcp
->current_stream_lock
);
156 static int hdmi_codec_hw_params(struct snd_pcm_substream
*substream
,
157 struct snd_pcm_hw_params
*params
,
158 struct snd_soc_dai
*dai
)
160 struct hdmi_codec_priv
*hcp
= snd_soc_dai_get_drvdata(dai
);
161 struct hdmi_codec_params hp
= {
166 .dig_subframe
= { 0 },
171 dev_dbg(dai
->dev
, "%s() width %d rate %d channels %d\n", __func__
,
172 params_width(params
), params_rate(params
),
173 params_channels(params
));
175 if (params_width(params
) > 24)
178 ret
= snd_pcm_create_iec958_consumer_hw_params(params
, hp
.iec
.status
,
179 sizeof(hp
.iec
.status
));
181 dev_err(dai
->dev
, "Creating IEC958 channel status failed %d\n",
186 ret
= hdmi_codec_new_stream(substream
, dai
);
190 hdmi_audio_infoframe_init(&hp
.cea
);
191 hp
.cea
.channels
= params_channels(params
);
192 hp
.cea
.coding_type
= HDMI_AUDIO_CODING_TYPE_STREAM
;
193 hp
.cea
.sample_size
= HDMI_AUDIO_SAMPLE_SIZE_STREAM
;
194 hp
.cea
.sample_frequency
= HDMI_AUDIO_SAMPLE_FREQUENCY_STREAM
;
196 hp
.sample_width
= params_width(params
);
197 hp
.sample_rate
= params_rate(params
);
198 hp
.channels
= params_channels(params
);
200 return hcp
->hcd
.ops
->hw_params(dai
->dev
->parent
, &hcp
->daifmt
[dai
->id
],
204 static int hdmi_codec_set_fmt(struct snd_soc_dai
*dai
,
207 struct hdmi_codec_priv
*hcp
= snd_soc_dai_get_drvdata(dai
);
208 struct hdmi_codec_daifmt cf
= { 0 };
211 dev_dbg(dai
->dev
, "%s()\n", __func__
);
213 if (dai
->id
== DAI_ID_SPDIF
) {
216 switch (fmt
& SND_SOC_DAIFMT_MASTER_MASK
) {
217 case SND_SOC_DAIFMT_CBM_CFM
:
218 cf
.bit_clk_master
= 1;
219 cf
.frame_clk_master
= 1;
221 case SND_SOC_DAIFMT_CBS_CFM
:
222 cf
.frame_clk_master
= 1;
224 case SND_SOC_DAIFMT_CBM_CFS
:
225 cf
.bit_clk_master
= 1;
227 case SND_SOC_DAIFMT_CBS_CFS
:
233 switch (fmt
& SND_SOC_DAIFMT_INV_MASK
) {
234 case SND_SOC_DAIFMT_NB_NF
:
236 case SND_SOC_DAIFMT_NB_IF
:
237 cf
.frame_clk_inv
= 1;
239 case SND_SOC_DAIFMT_IB_NF
:
242 case SND_SOC_DAIFMT_IB_IF
:
243 cf
.frame_clk_inv
= 1;
248 switch (fmt
& SND_SOC_DAIFMT_FORMAT_MASK
) {
249 case SND_SOC_DAIFMT_I2S
:
252 case SND_SOC_DAIFMT_DSP_A
:
255 case SND_SOC_DAIFMT_DSP_B
:
258 case SND_SOC_DAIFMT_RIGHT_J
:
259 cf
.fmt
= HDMI_RIGHT_J
;
261 case SND_SOC_DAIFMT_LEFT_J
:
262 cf
.fmt
= HDMI_LEFT_J
;
264 case SND_SOC_DAIFMT_AC97
:
268 dev_err(dai
->dev
, "Invalid DAI interface format\n");
273 hcp
->daifmt
[dai
->id
] = cf
;
278 static int hdmi_codec_digital_mute(struct snd_soc_dai
*dai
, int mute
)
280 struct hdmi_codec_priv
*hcp
= snd_soc_dai_get_drvdata(dai
);
282 dev_dbg(dai
->dev
, "%s()\n", __func__
);
284 if (hcp
->hcd
.ops
->digital_mute
)
285 return hcp
->hcd
.ops
->digital_mute(dai
->dev
->parent
, mute
);
290 static const struct snd_soc_dai_ops hdmi_dai_ops
= {
291 .startup
= hdmi_codec_startup
,
292 .shutdown
= hdmi_codec_shutdown
,
293 .hw_params
= hdmi_codec_hw_params
,
294 .set_fmt
= hdmi_codec_set_fmt
,
295 .digital_mute
= hdmi_codec_digital_mute
,
299 #define HDMI_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\
300 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |\
301 SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 |\
302 SNDRV_PCM_RATE_192000)
304 #define SPDIF_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE |\
305 SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S20_3BE |\
306 SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_3BE |\
307 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE)
310 * This list is only for formats allowed on the I2S bus. So there is
311 * some formats listed that are not supported by HDMI interface. For
312 * instance allowing the 32-bit formats enables 24-precision with CPU
313 * DAIs that do not support 24-bit formats. If the extra formats cause
314 * problems, we should add the video side driver an option to disable
317 #define I2S_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE |\
318 SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S20_3BE |\
319 SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_3BE |\
320 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE |\
321 SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE)
323 static struct snd_soc_dai_driver hdmi_i2s_dai
= {
327 .stream_name
= "Playback",
331 .formats
= I2S_FORMATS
,
334 .ops
= &hdmi_dai_ops
,
337 static const struct snd_soc_dai_driver hdmi_spdif_dai
= {
338 .name
= "spdif-hifi",
341 .stream_name
= "Playback",
345 .formats
= SPDIF_FORMATS
,
347 .ops
= &hdmi_dai_ops
,
350 static struct snd_soc_codec_driver hdmi_codec
= {
351 .controls
= hdmi_controls
,
352 .num_controls
= ARRAY_SIZE(hdmi_controls
),
353 .dapm_widgets
= hdmi_widgets
,
354 .num_dapm_widgets
= ARRAY_SIZE(hdmi_widgets
),
355 .dapm_routes
= hdmi_routes
,
356 .num_dapm_routes
= ARRAY_SIZE(hdmi_routes
),
359 static int hdmi_codec_probe(struct platform_device
*pdev
)
361 struct hdmi_codec_pdata
*hcd
= pdev
->dev
.platform_data
;
362 struct device
*dev
= &pdev
->dev
;
363 struct hdmi_codec_priv
*hcp
;
364 int dai_count
, i
= 0;
367 dev_dbg(dev
, "%s()\n", __func__
);
370 dev_err(dev
, "%s: No plalform data\n", __func__
);
374 dai_count
= hcd
->i2s
+ hcd
->spdif
;
375 if (dai_count
< 1 || !hcd
->ops
|| !hcd
->ops
->hw_params
||
376 !hcd
->ops
->audio_shutdown
) {
377 dev_err(dev
, "%s: Invalid parameters\n", __func__
);
381 hcp
= devm_kzalloc(dev
, sizeof(*hcp
), GFP_KERNEL
);
386 mutex_init(&hcp
->current_stream_lock
);
388 hcp
->daidrv
= devm_kzalloc(dev
, dai_count
* sizeof(*hcp
->daidrv
),
394 hcp
->daidrv
[i
] = hdmi_i2s_dai
;
395 hcp
->daidrv
[i
].playback
.channels_max
=
396 hcd
->max_i2s_channels
;
401 hcp
->daidrv
[i
] = hdmi_spdif_dai
;
403 ret
= snd_soc_register_codec(dev
, &hdmi_codec
, hcp
->daidrv
,
406 dev_err(dev
, "%s: snd_soc_register_codec() failed (%d)\n",
411 dev_set_drvdata(dev
, hcp
);
415 static int hdmi_codec_remove(struct platform_device
*pdev
)
417 snd_soc_unregister_codec(&pdev
->dev
);
421 static struct platform_driver hdmi_codec_driver
= {
423 .name
= HDMI_CODEC_DRV_NAME
,
425 .probe
= hdmi_codec_probe
,
426 .remove
= hdmi_codec_remove
,
429 module_platform_driver(hdmi_codec_driver
);
431 MODULE_AUTHOR("Jyri Sarha <jsarha@ti.com>");
432 MODULE_DESCRIPTION("HDMI Audio Codec Driver");
433 MODULE_LICENSE("GPL");
434 MODULE_ALIAS("platform:" HDMI_CODEC_DRV_NAME
);