PageRenderTime 78ms CodeModel.GetById 17ms app.highlight 51ms RepoModel.GetById 1ms app.codeStats 0ms

/sound/soc/codecs/hdmi-codec.c

https://codeberg.org/ddevault/linux
C | 853 lines | 695 code | 98 blank | 60 comment | 48 complexity | 4a4f14ce1cb56cd106f11643d712d1b1 MD5 | raw file
Possible License(s): GPL-2.0
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * ALSA SoC codec for HDMI encoder drivers
  4 * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/
  5 * Author: Jyri Sarha <jsarha@ti.com>
  6 */
  7#include <linux/module.h>
  8#include <linux/string.h>
  9#include <sound/core.h>
 10#include <sound/jack.h>
 11#include <sound/pcm.h>
 12#include <sound/pcm_params.h>
 13#include <sound/soc.h>
 14#include <sound/tlv.h>
 15#include <sound/pcm_drm_eld.h>
 16#include <sound/hdmi-codec.h>
 17#include <sound/pcm_iec958.h>
 18
 19#include <drm/drm_crtc.h> /* This is only to get MAX_ELD_BYTES */
 20
 21#define HDMI_CODEC_CHMAP_IDX_UNKNOWN  -1
 22
 23struct hdmi_codec_channel_map_table {
 24	unsigned char map;	/* ALSA API channel map position */
 25	unsigned long spk_mask;		/* speaker position bit mask */
 26};
 27
 28/*
 29 * CEA speaker placement for HDMI 1.4:
 30 *
 31 *  FL  FLC   FC   FRC   FR   FRW
 32 *
 33 *                                  LFE
 34 *
 35 *  RL  RLC   RC   RRC   RR
 36 *
 37 *  Speaker placement has to be extended to support HDMI 2.0
 38 */
 39enum hdmi_codec_cea_spk_placement {
 40	FL  = BIT(0),	/* Front Left           */
 41	FC  = BIT(1),	/* Front Center         */
 42	FR  = BIT(2),	/* Front Right          */
 43	FLC = BIT(3),	/* Front Left Center    */
 44	FRC = BIT(4),	/* Front Right Center   */
 45	RL  = BIT(5),	/* Rear Left            */
 46	RC  = BIT(6),	/* Rear Center          */
 47	RR  = BIT(7),	/* Rear Right           */
 48	RLC = BIT(8),	/* Rear Left Center     */
 49	RRC = BIT(9),	/* Rear Right Center    */
 50	LFE = BIT(10),	/* Low Frequency Effect */
 51};
 52
 53/*
 54 * cea Speaker allocation structure
 55 */
 56struct hdmi_codec_cea_spk_alloc {
 57	const int ca_id;
 58	unsigned int n_ch;
 59	unsigned long mask;
 60};
 61
 62/* Channel maps  stereo HDMI */
 63static const struct snd_pcm_chmap_elem hdmi_codec_stereo_chmaps[] = {
 64	{ .channels = 2,
 65	  .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR } },
 66	{ }
 67};
 68
 69/* Channel maps for multi-channel playbacks, up to 8 n_ch */
 70static const struct snd_pcm_chmap_elem hdmi_codec_8ch_chmaps[] = {
 71	{ .channels = 2, /* CA_ID 0x00 */
 72	  .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR } },
 73	{ .channels = 4, /* CA_ID 0x01 */
 74	  .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE,
 75		   SNDRV_CHMAP_NA } },
 76	{ .channels = 4, /* CA_ID 0x02 */
 77	  .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA,
 78		   SNDRV_CHMAP_FC } },
 79	{ .channels = 4, /* CA_ID 0x03 */
 80	  .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE,
 81		   SNDRV_CHMAP_FC } },
 82	{ .channels = 6, /* CA_ID 0x04 */
 83	  .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA,
 84		   SNDRV_CHMAP_NA, SNDRV_CHMAP_RC, SNDRV_CHMAP_NA } },
 85	{ .channels = 6, /* CA_ID 0x05 */
 86	  .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE,
 87		   SNDRV_CHMAP_NA, SNDRV_CHMAP_RC, SNDRV_CHMAP_NA } },
 88	{ .channels = 6, /* CA_ID 0x06 */
 89	  .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA,
 90		   SNDRV_CHMAP_FC, SNDRV_CHMAP_RC, SNDRV_CHMAP_NA } },
 91	{ .channels = 6, /* CA_ID 0x07 */
 92	  .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE,
 93		   SNDRV_CHMAP_FC, SNDRV_CHMAP_RC, SNDRV_CHMAP_NA } },
 94	{ .channels = 6, /* CA_ID 0x08 */
 95	  .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA,
 96		   SNDRV_CHMAP_NA, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR } },
 97	{ .channels = 6, /* CA_ID 0x09 */
 98	  .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE,
 99		   SNDRV_CHMAP_NA, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR } },
100	{ .channels = 6, /* CA_ID 0x0A */
101	  .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA,
102		   SNDRV_CHMAP_FC, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR } },
103	{ .channels = 6, /* CA_ID 0x0B */
104	  .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE,
105		   SNDRV_CHMAP_FC, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR } },
106	{ .channels = 8, /* CA_ID 0x0C */
107	  .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA,
108		   SNDRV_CHMAP_NA, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR,
109		   SNDRV_CHMAP_RC, SNDRV_CHMAP_NA } },
110	{ .channels = 8, /* CA_ID 0x0D */
111	  .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE,
112		   SNDRV_CHMAP_NA, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR,
113		   SNDRV_CHMAP_RC, SNDRV_CHMAP_NA } },
114	{ .channels = 8, /* CA_ID 0x0E */
115	  .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA,
116		   SNDRV_CHMAP_FC, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR,
117		   SNDRV_CHMAP_RC, SNDRV_CHMAP_NA } },
118	{ .channels = 8, /* CA_ID 0x0F */
119	  .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE,
120		   SNDRV_CHMAP_FC, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR,
121		   SNDRV_CHMAP_RC, SNDRV_CHMAP_NA } },
122	{ .channels = 8, /* CA_ID 0x10 */
123	  .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA,
124		   SNDRV_CHMAP_NA, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR,
125		   SNDRV_CHMAP_RLC, SNDRV_CHMAP_RRC } },
126	{ .channels = 8, /* CA_ID 0x11 */
127	  .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE,
128		   SNDRV_CHMAP_NA, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR,
129		   SNDRV_CHMAP_RLC, SNDRV_CHMAP_RRC } },
130	{ .channels = 8, /* CA_ID 0x12 */
131	  .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA,
132		   SNDRV_CHMAP_FC, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR,
133		   SNDRV_CHMAP_RLC, SNDRV_CHMAP_RRC } },
134	{ .channels = 8, /* CA_ID 0x13 */
135	  .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE,
136		   SNDRV_CHMAP_FC, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR,
137		   SNDRV_CHMAP_RLC, SNDRV_CHMAP_RRC } },
138	{ .channels = 8, /* CA_ID 0x14 */
139	  .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA,
140		   SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, SNDRV_CHMAP_NA,
141		   SNDRV_CHMAP_FLC, SNDRV_CHMAP_FRC } },
142	{ .channels = 8, /* CA_ID 0x15 */
143	  .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE,
144		   SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, SNDRV_CHMAP_NA,
145		   SNDRV_CHMAP_FLC, SNDRV_CHMAP_FRC } },
146	{ .channels = 8, /* CA_ID 0x16 */
147	  .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA,
148		   SNDRV_CHMAP_FC, SNDRV_CHMAP_NA, SNDRV_CHMAP_NA,
149		   SNDRV_CHMAP_FLC, SNDRV_CHMAP_FRC } },
150	{ .channels = 8, /* CA_ID 0x17 */
151	  .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE,
152		   SNDRV_CHMAP_FC, SNDRV_CHMAP_NA, SNDRV_CHMAP_NA,
153		   SNDRV_CHMAP_FLC, SNDRV_CHMAP_FRC } },
154	{ .channels = 8, /* CA_ID 0x18 */
155	  .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA,
156		   SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, SNDRV_CHMAP_NA,
157		   SNDRV_CHMAP_FLC, SNDRV_CHMAP_FRC } },
158	{ .channels = 8, /* CA_ID 0x19 */
159	  .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE,
160		   SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, SNDRV_CHMAP_NA,
161		   SNDRV_CHMAP_FLC, SNDRV_CHMAP_FRC } },
162	{ .channels = 8, /* CA_ID 0x1A */
163	  .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA,
164		   SNDRV_CHMAP_FC, SNDRV_CHMAP_NA, SNDRV_CHMAP_NA,
165		   SNDRV_CHMAP_FLC, SNDRV_CHMAP_FRC } },
166	{ .channels = 8, /* CA_ID 0x1B */
167	  .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE,
168		   SNDRV_CHMAP_FC, SNDRV_CHMAP_NA, SNDRV_CHMAP_NA,
169		   SNDRV_CHMAP_FLC, SNDRV_CHMAP_FRC } },
170	{ .channels = 8, /* CA_ID 0x1C */
171	  .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA,
172		   SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, SNDRV_CHMAP_NA,
173		   SNDRV_CHMAP_FLC, SNDRV_CHMAP_FRC } },
174	{ .channels = 8, /* CA_ID 0x1D */
175	  .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE,
176		   SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, SNDRV_CHMAP_NA,
177		   SNDRV_CHMAP_FLC, SNDRV_CHMAP_FRC } },
178	{ .channels = 8, /* CA_ID 0x1E */
179	  .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA,
180		   SNDRV_CHMAP_FC, SNDRV_CHMAP_NA, SNDRV_CHMAP_NA,
181		   SNDRV_CHMAP_FLC, SNDRV_CHMAP_FRC } },
182	{ .channels = 8, /* CA_ID 0x1F */
183	  .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE,
184		   SNDRV_CHMAP_FC, SNDRV_CHMAP_NA, SNDRV_CHMAP_NA,
185		   SNDRV_CHMAP_FLC, SNDRV_CHMAP_FRC } },
186	{ }
187};
188
189/*
190 * hdmi_codec_channel_alloc: speaker configuration available for CEA
191 *
192 * This is an ordered list that must match with hdmi_codec_8ch_chmaps struct
193 * The preceding ones have better chances to be selected by
194 * hdmi_codec_get_ch_alloc_table_idx().
195 */
196static const struct hdmi_codec_cea_spk_alloc hdmi_codec_channel_alloc[] = {
197	{ .ca_id = 0x00, .n_ch = 2,
198	  .mask = FL | FR},
199	/* 2.1 */
200	{ .ca_id = 0x01, .n_ch = 4,
201	  .mask = FL | FR | LFE},
202	/* Dolby Surround */
203	{ .ca_id = 0x02, .n_ch = 4,
204	  .mask = FL | FR | FC },
205	/* surround51 */
206	{ .ca_id = 0x0b, .n_ch = 6,
207	  .mask = FL | FR | LFE | FC | RL | RR},
208	/* surround40 */
209	{ .ca_id = 0x08, .n_ch = 6,
210	  .mask = FL | FR | RL | RR },
211	/* surround41 */
212	{ .ca_id = 0x09, .n_ch = 6,
213	  .mask = FL | FR | LFE | RL | RR },
214	/* surround50 */
215	{ .ca_id = 0x0a, .n_ch = 6,
216	  .mask = FL | FR | FC | RL | RR },
217	/* 6.1 */
218	{ .ca_id = 0x0f, .n_ch = 8,
219	  .mask = FL | FR | LFE | FC | RL | RR | RC },
220	/* surround71 */
221	{ .ca_id = 0x13, .n_ch = 8,
222	  .mask = FL | FR | LFE | FC | RL | RR | RLC | RRC },
223	/* others */
224	{ .ca_id = 0x03, .n_ch = 8,
225	  .mask = FL | FR | LFE | FC },
226	{ .ca_id = 0x04, .n_ch = 8,
227	  .mask = FL | FR | RC},
228	{ .ca_id = 0x05, .n_ch = 8,
229	  .mask = FL | FR | LFE | RC },
230	{ .ca_id = 0x06, .n_ch = 8,
231	  .mask = FL | FR | FC | RC },
232	{ .ca_id = 0x07, .n_ch = 8,
233	  .mask = FL | FR | LFE | FC | RC },
234	{ .ca_id = 0x0c, .n_ch = 8,
235	  .mask = FL | FR | RC | RL | RR },
236	{ .ca_id = 0x0d, .n_ch = 8,
237	  .mask = FL | FR | LFE | RL | RR | RC },
238	{ .ca_id = 0x0e, .n_ch = 8,
239	  .mask = FL | FR | FC | RL | RR | RC },
240	{ .ca_id = 0x10, .n_ch = 8,
241	  .mask = FL | FR | RL | RR | RLC | RRC },
242	{ .ca_id = 0x11, .n_ch = 8,
243	  .mask = FL | FR | LFE | RL | RR | RLC | RRC },
244	{ .ca_id = 0x12, .n_ch = 8,
245	  .mask = FL | FR | FC | RL | RR | RLC | RRC },
246	{ .ca_id = 0x14, .n_ch = 8,
247	  .mask = FL | FR | FLC | FRC },
248	{ .ca_id = 0x15, .n_ch = 8,
249	  .mask = FL | FR | LFE | FLC | FRC },
250	{ .ca_id = 0x16, .n_ch = 8,
251	  .mask = FL | FR | FC | FLC | FRC },
252	{ .ca_id = 0x17, .n_ch = 8,
253	  .mask = FL | FR | LFE | FC | FLC | FRC },
254	{ .ca_id = 0x18, .n_ch = 8,
255	  .mask = FL | FR | RC | FLC | FRC },
256	{ .ca_id = 0x19, .n_ch = 8,
257	  .mask = FL | FR | LFE | RC | FLC | FRC },
258	{ .ca_id = 0x1a, .n_ch = 8,
259	  .mask = FL | FR | RC | FC | FLC | FRC },
260	{ .ca_id = 0x1b, .n_ch = 8,
261	  .mask = FL | FR | LFE | RC | FC | FLC | FRC },
262	{ .ca_id = 0x1c, .n_ch = 8,
263	  .mask = FL | FR | RL | RR | FLC | FRC },
264	{ .ca_id = 0x1d, .n_ch = 8,
265	  .mask = FL | FR | LFE | RL | RR | FLC | FRC },
266	{ .ca_id = 0x1e, .n_ch = 8,
267	  .mask = FL | FR | FC | RL | RR | FLC | FRC },
268	{ .ca_id = 0x1f, .n_ch = 8,
269	  .mask = FL | FR | LFE | FC | RL | RR | FLC | FRC },
270};
271
272struct hdmi_codec_priv {
273	struct hdmi_codec_pdata hcd;
274	uint8_t eld[MAX_ELD_BYTES];
275	struct snd_pcm_chmap *chmap_info;
276	unsigned int chmap_idx;
277	struct mutex lock;
278	struct snd_soc_jack *jack;
279	unsigned int jack_status;
280};
281
282static const struct snd_soc_dapm_widget hdmi_widgets[] = {
283	SND_SOC_DAPM_OUTPUT("TX"),
284};
285
286enum {
287	DAI_ID_I2S = 0,
288	DAI_ID_SPDIF,
289};
290
291static int hdmi_eld_ctl_info(struct snd_kcontrol *kcontrol,
292			     struct snd_ctl_elem_info *uinfo)
293{
294	uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
295	uinfo->count = FIELD_SIZEOF(struct hdmi_codec_priv, eld);
296
297	return 0;
298}
299
300static int hdmi_eld_ctl_get(struct snd_kcontrol *kcontrol,
301			    struct snd_ctl_elem_value *ucontrol)
302{
303	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
304	struct hdmi_codec_priv *hcp = snd_soc_component_get_drvdata(component);
305
306	memcpy(ucontrol->value.bytes.data, hcp->eld, sizeof(hcp->eld));
307
308	return 0;
309}
310
311static unsigned long hdmi_codec_spk_mask_from_alloc(int spk_alloc)
312{
313	int i;
314	static const unsigned long hdmi_codec_eld_spk_alloc_bits[] = {
315		[0] = FL | FR, [1] = LFE, [2] = FC, [3] = RL | RR,
316		[4] = RC, [5] = FLC | FRC, [6] = RLC | RRC,
317	};
318	unsigned long spk_mask = 0;
319
320	for (i = 0; i < ARRAY_SIZE(hdmi_codec_eld_spk_alloc_bits); i++) {
321		if (spk_alloc & (1 << i))
322			spk_mask |= hdmi_codec_eld_spk_alloc_bits[i];
323	}
324
325	return spk_mask;
326}
327
328static void hdmi_codec_eld_chmap(struct hdmi_codec_priv *hcp)
329{
330	u8 spk_alloc;
331	unsigned long spk_mask;
332
333	spk_alloc = drm_eld_get_spk_alloc(hcp->eld);
334	spk_mask = hdmi_codec_spk_mask_from_alloc(spk_alloc);
335
336	/* Detect if only stereo supported, else return 8 channels mappings */
337	if ((spk_mask & ~(FL | FR)) && hcp->chmap_info->max_channels > 2)
338		hcp->chmap_info->chmap = hdmi_codec_8ch_chmaps;
339	else
340		hcp->chmap_info->chmap = hdmi_codec_stereo_chmaps;
341}
342
343static int hdmi_codec_get_ch_alloc_table_idx(struct hdmi_codec_priv *hcp,
344					     unsigned char channels)
345{
346	int i;
347	u8 spk_alloc;
348	unsigned long spk_mask;
349	const struct hdmi_codec_cea_spk_alloc *cap = hdmi_codec_channel_alloc;
350
351	spk_alloc = drm_eld_get_spk_alloc(hcp->eld);
352	spk_mask = hdmi_codec_spk_mask_from_alloc(spk_alloc);
353
354	for (i = 0; i < ARRAY_SIZE(hdmi_codec_channel_alloc); i++, cap++) {
355		/* If spk_alloc == 0, HDMI is unplugged return stereo config*/
356		if (!spk_alloc && cap->ca_id == 0)
357			return i;
358		if (cap->n_ch != channels)
359			continue;
360		if (!(cap->mask == (spk_mask & cap->mask)))
361			continue;
362		return i;
363	}
364
365	return -EINVAL;
366}
367static int hdmi_codec_chmap_ctl_get(struct snd_kcontrol *kcontrol,
368			      struct snd_ctl_elem_value *ucontrol)
369{
370	unsigned const char *map;
371	unsigned int i;
372	struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol);
373	struct hdmi_codec_priv *hcp = info->private_data;
374
375	map = info->chmap[hcp->chmap_idx].map;
376
377	for (i = 0; i < info->max_channels; i++) {
378		if (hcp->chmap_idx == HDMI_CODEC_CHMAP_IDX_UNKNOWN)
379			ucontrol->value.integer.value[i] = 0;
380		else
381			ucontrol->value.integer.value[i] = map[i];
382	}
383
384	return 0;
385}
386
387static int hdmi_codec_startup(struct snd_pcm_substream *substream,
388			      struct snd_soc_dai *dai)
389{
390	struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai);
391	int ret = 0;
392
393	ret = mutex_trylock(&hcp->lock);
394	if (!ret) {
395		dev_err(dai->dev, "Only one simultaneous stream supported!\n");
396		return -EINVAL;
397	}
398
399	if (hcp->hcd.ops->audio_startup) {
400		ret = hcp->hcd.ops->audio_startup(dai->dev->parent, hcp->hcd.data);
401		if (ret)
402			goto err;
403	}
404
405	if (hcp->hcd.ops->get_eld) {
406		ret = hcp->hcd.ops->get_eld(dai->dev->parent, hcp->hcd.data,
407					    hcp->eld, sizeof(hcp->eld));
408
409		if (!ret) {
410			ret = snd_pcm_hw_constraint_eld(substream->runtime,
411							hcp->eld);
412			if (ret)
413				goto err;
414		}
415		/* Select chmap supported */
416		hdmi_codec_eld_chmap(hcp);
417	}
418	return 0;
419
420err:
421	/* Release the exclusive lock on error */
422	mutex_unlock(&hcp->lock);
423	return ret;
424}
425
426static void hdmi_codec_shutdown(struct snd_pcm_substream *substream,
427				struct snd_soc_dai *dai)
428{
429	struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai);
430
431	hcp->chmap_idx = HDMI_CODEC_CHMAP_IDX_UNKNOWN;
432	hcp->hcd.ops->audio_shutdown(dai->dev->parent, hcp->hcd.data);
433
434	mutex_unlock(&hcp->lock);
435}
436
437static int hdmi_codec_hw_params(struct snd_pcm_substream *substream,
438				struct snd_pcm_hw_params *params,
439				struct snd_soc_dai *dai)
440{
441	struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai);
442	struct hdmi_codec_daifmt *cf = dai->playback_dma_data;
443	struct hdmi_codec_params hp = {
444		.iec = {
445			.status = { 0 },
446			.subcode = { 0 },
447			.pad = 0,
448			.dig_subframe = { 0 },
449		}
450	};
451	int ret, idx;
452
453	dev_dbg(dai->dev, "%s() width %d rate %d channels %d\n", __func__,
454		params_width(params), params_rate(params),
455		params_channels(params));
456
457	ret = snd_pcm_create_iec958_consumer_hw_params(params, hp.iec.status,
458						       sizeof(hp.iec.status));
459	if (ret < 0) {
460		dev_err(dai->dev, "Creating IEC958 channel status failed %d\n",
461			ret);
462		return ret;
463	}
464
465	hdmi_audio_infoframe_init(&hp.cea);
466	hp.cea.channels = params_channels(params);
467	hp.cea.coding_type = HDMI_AUDIO_CODING_TYPE_STREAM;
468	hp.cea.sample_size = HDMI_AUDIO_SAMPLE_SIZE_STREAM;
469	hp.cea.sample_frequency = HDMI_AUDIO_SAMPLE_FREQUENCY_STREAM;
470
471	/* Select a channel allocation that matches with ELD and pcm channels */
472	idx = hdmi_codec_get_ch_alloc_table_idx(hcp, hp.cea.channels);
473	if (idx < 0) {
474		dev_err(dai->dev, "Not able to map channels to speakers (%d)\n",
475			idx);
476		hcp->chmap_idx = HDMI_CODEC_CHMAP_IDX_UNKNOWN;
477		return idx;
478	}
479	hp.cea.channel_allocation = hdmi_codec_channel_alloc[idx].ca_id;
480	hcp->chmap_idx = hdmi_codec_channel_alloc[idx].ca_id;
481
482	hp.sample_width = params_width(params);
483	hp.sample_rate = params_rate(params);
484	hp.channels = params_channels(params);
485
486	return hcp->hcd.ops->hw_params(dai->dev->parent, hcp->hcd.data,
487				       cf, &hp);
488}
489
490static int hdmi_codec_i2s_set_fmt(struct snd_soc_dai *dai,
491				  unsigned int fmt)
492{
493	struct hdmi_codec_daifmt *cf = dai->playback_dma_data;
494
495	/* Reset daifmt */
496	memset(cf, 0, sizeof(*cf));
497
498	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
499	case SND_SOC_DAIFMT_CBM_CFM:
500		cf->bit_clk_master = 1;
501		cf->frame_clk_master = 1;
502		break;
503	case SND_SOC_DAIFMT_CBS_CFM:
504		cf->frame_clk_master = 1;
505		break;
506	case SND_SOC_DAIFMT_CBM_CFS:
507		cf->bit_clk_master = 1;
508		break;
509	case SND_SOC_DAIFMT_CBS_CFS:
510		break;
511	default:
512		return -EINVAL;
513	}
514
515	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
516	case SND_SOC_DAIFMT_NB_NF:
517		break;
518	case SND_SOC_DAIFMT_NB_IF:
519		cf->frame_clk_inv = 1;
520		break;
521	case SND_SOC_DAIFMT_IB_NF:
522		cf->bit_clk_inv = 1;
523		break;
524	case SND_SOC_DAIFMT_IB_IF:
525		cf->frame_clk_inv = 1;
526		cf->bit_clk_inv = 1;
527		break;
528	}
529
530	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
531	case SND_SOC_DAIFMT_I2S:
532		cf->fmt = HDMI_I2S;
533		break;
534	case SND_SOC_DAIFMT_DSP_A:
535		cf->fmt = HDMI_DSP_A;
536		break;
537	case SND_SOC_DAIFMT_DSP_B:
538		cf->fmt = HDMI_DSP_B;
539		break;
540	case SND_SOC_DAIFMT_RIGHT_J:
541		cf->fmt = HDMI_RIGHT_J;
542		break;
543	case SND_SOC_DAIFMT_LEFT_J:
544		cf->fmt = HDMI_LEFT_J;
545		break;
546	case SND_SOC_DAIFMT_AC97:
547		cf->fmt = HDMI_AC97;
548		break;
549	default:
550		dev_err(dai->dev, "Invalid DAI interface format\n");
551		return -EINVAL;
552	}
553
554	return 0;
555}
556
557static int hdmi_codec_digital_mute(struct snd_soc_dai *dai, int mute)
558{
559	struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai);
560
561	if (hcp->hcd.ops->digital_mute)
562		return hcp->hcd.ops->digital_mute(dai->dev->parent,
563						  hcp->hcd.data, mute);
564
565	return 0;
566}
567
568static const struct snd_soc_dai_ops hdmi_codec_i2s_dai_ops = {
569	.startup	= hdmi_codec_startup,
570	.shutdown	= hdmi_codec_shutdown,
571	.hw_params	= hdmi_codec_hw_params,
572	.set_fmt	= hdmi_codec_i2s_set_fmt,
573	.digital_mute	= hdmi_codec_digital_mute,
574};
575
576static const struct snd_soc_dai_ops hdmi_codec_spdif_dai_ops = {
577	.startup	= hdmi_codec_startup,
578	.shutdown	= hdmi_codec_shutdown,
579	.hw_params	= hdmi_codec_hw_params,
580	.digital_mute	= hdmi_codec_digital_mute,
581};
582
583#define HDMI_RATES	(SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\
584			 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |\
585			 SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 |\
586			 SNDRV_PCM_RATE_192000)
587
588#define SPDIF_FORMATS	(SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE |\
589			 SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S20_3BE |\
590			 SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_3BE |\
591			 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE)
592
593/*
594 * This list is only for formats allowed on the I2S bus. So there is
595 * some formats listed that are not supported by HDMI interface. For
596 * instance allowing the 32-bit formats enables 24-precision with CPU
597 * DAIs that do not support 24-bit formats. If the extra formats cause
598 * problems, we should add the video side driver an option to disable
599 * them.
600 */
601#define I2S_FORMATS	(SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE |\
602			 SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S20_3BE |\
603			 SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_3BE |\
604			 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE |\
605			 SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE)
606
607static int hdmi_codec_pcm_new(struct snd_soc_pcm_runtime *rtd,
608			      struct snd_soc_dai *dai)
609{
610	struct snd_soc_dai_driver *drv = dai->driver;
611	struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai);
612	struct snd_kcontrol *kctl;
613	struct snd_kcontrol_new hdmi_eld_ctl = {
614		.access	= SNDRV_CTL_ELEM_ACCESS_READ |
615			  SNDRV_CTL_ELEM_ACCESS_VOLATILE,
616		.iface	= SNDRV_CTL_ELEM_IFACE_PCM,
617		.name	= "ELD",
618		.info	= hdmi_eld_ctl_info,
619		.get	= hdmi_eld_ctl_get,
620		.device	= rtd->pcm->device,
621	};
622	int ret;
623
624	ret =  snd_pcm_add_chmap_ctls(rtd->pcm, SNDRV_PCM_STREAM_PLAYBACK,
625				      NULL, drv->playback.channels_max, 0,
626				      &hcp->chmap_info);
627	if (ret < 0)
628		return ret;
629
630	/* override handlers */
631	hcp->chmap_info->private_data = hcp;
632	hcp->chmap_info->kctl->get = hdmi_codec_chmap_ctl_get;
633
634	/* default chmap supported is stereo */
635	hcp->chmap_info->chmap = hdmi_codec_stereo_chmaps;
636	hcp->chmap_idx = HDMI_CODEC_CHMAP_IDX_UNKNOWN;
637
638	/* add ELD ctl with the device number corresponding to the PCM stream */
639	kctl = snd_ctl_new1(&hdmi_eld_ctl, dai->component);
640	if (!kctl)
641		return -ENOMEM;
642
643	return snd_ctl_add(rtd->card->snd_card, kctl);
644}
645
646static int hdmi_dai_probe(struct snd_soc_dai *dai)
647{
648	struct snd_soc_dapm_context *dapm;
649	struct hdmi_codec_daifmt *daifmt;
650	struct snd_soc_dapm_route route = {
651		.sink = "TX",
652		.source = dai->driver->playback.stream_name,
653	};
654	int ret;
655
656	dapm = snd_soc_component_get_dapm(dai->component);
657	ret = snd_soc_dapm_add_routes(dapm, &route, 1);
658	if (ret)
659		return ret;
660
661	daifmt = kzalloc(sizeof(*daifmt), GFP_KERNEL);
662	if (!daifmt)
663		return -ENOMEM;
664
665	dai->playback_dma_data = daifmt;
666	return 0;
667}
668
669static void hdmi_codec_jack_report(struct hdmi_codec_priv *hcp,
670				   unsigned int jack_status)
671{
672	if (hcp->jack && jack_status != hcp->jack_status) {
673		snd_soc_jack_report(hcp->jack, jack_status, SND_JACK_LINEOUT);
674		hcp->jack_status = jack_status;
675	}
676}
677
678static void plugged_cb(struct device *dev, bool plugged)
679{
680	struct hdmi_codec_priv *hcp = dev_get_drvdata(dev);
681
682	if (plugged)
683		hdmi_codec_jack_report(hcp, SND_JACK_LINEOUT);
684	else
685		hdmi_codec_jack_report(hcp, 0);
686}
687
688/**
689 * hdmi_codec_set_jack_detect - register HDMI plugged callback
690 * @component: the hdmi-codec instance
691 * @jack: ASoC jack to report (dis)connection events on
692 */
693int hdmi_codec_set_jack_detect(struct snd_soc_component *component,
694			       struct snd_soc_jack *jack)
695{
696	struct hdmi_codec_priv *hcp = snd_soc_component_get_drvdata(component);
697	int ret = -EOPNOTSUPP;
698
699	if (hcp->hcd.ops->hook_plugged_cb) {
700		hcp->jack = jack;
701		ret = hcp->hcd.ops->hook_plugged_cb(component->dev->parent,
702						    hcp->hcd.data,
703						    plugged_cb,
704						    component->dev);
705		if (ret)
706			hcp->jack = NULL;
707	}
708	return ret;
709}
710EXPORT_SYMBOL_GPL(hdmi_codec_set_jack_detect);
711
712static int hdmi_dai_spdif_probe(struct snd_soc_dai *dai)
713{
714	struct hdmi_codec_daifmt *cf = dai->playback_dma_data;
715	int ret;
716
717	ret = hdmi_dai_probe(dai);
718	if (ret)
719		return ret;
720
721	cf = dai->playback_dma_data;
722	cf->fmt = HDMI_SPDIF;
723
724	return 0;
725}
726
727static int hdmi_codec_dai_remove(struct snd_soc_dai *dai)
728{
729	kfree(dai->playback_dma_data);
730	return 0;
731}
732
733static const struct snd_soc_dai_driver hdmi_i2s_dai = {
734	.name = "i2s-hifi",
735	.id = DAI_ID_I2S,
736	.probe = hdmi_dai_probe,
737	.remove = hdmi_codec_dai_remove,
738	.playback = {
739		.stream_name = "I2S Playback",
740		.channels_min = 2,
741		.channels_max = 8,
742		.rates = HDMI_RATES,
743		.formats = I2S_FORMATS,
744		.sig_bits = 24,
745	},
746	.ops = &hdmi_codec_i2s_dai_ops,
747	.pcm_new = hdmi_codec_pcm_new,
748};
749
750static const struct snd_soc_dai_driver hdmi_spdif_dai = {
751	.name = "spdif-hifi",
752	.id = DAI_ID_SPDIF,
753	.probe = hdmi_dai_spdif_probe,
754	.remove = hdmi_codec_dai_remove,
755	.playback = {
756		.stream_name = "SPDIF Playback",
757		.channels_min = 2,
758		.channels_max = 2,
759		.rates = HDMI_RATES,
760		.formats = SPDIF_FORMATS,
761	},
762	.ops = &hdmi_codec_spdif_dai_ops,
763	.pcm_new = hdmi_codec_pcm_new,
764};
765
766static int hdmi_of_xlate_dai_id(struct snd_soc_component *component,
767				 struct device_node *endpoint)
768{
769	struct hdmi_codec_priv *hcp = snd_soc_component_get_drvdata(component);
770	int ret = -ENOTSUPP; /* see snd_soc_get_dai_id() */
771
772	if (hcp->hcd.ops->get_dai_id)
773		ret = hcp->hcd.ops->get_dai_id(component, endpoint);
774
775	return ret;
776}
777
778static const struct snd_soc_component_driver hdmi_driver = {
779	.dapm_widgets		= hdmi_widgets,
780	.num_dapm_widgets	= ARRAY_SIZE(hdmi_widgets),
781	.of_xlate_dai_id	= hdmi_of_xlate_dai_id,
782	.idle_bias_on		= 1,
783	.use_pmdown_time	= 1,
784	.endianness		= 1,
785	.non_legacy_dai_naming	= 1,
786};
787
788static int hdmi_codec_probe(struct platform_device *pdev)
789{
790	struct hdmi_codec_pdata *hcd = pdev->dev.platform_data;
791	struct snd_soc_dai_driver *daidrv;
792	struct device *dev = &pdev->dev;
793	struct hdmi_codec_priv *hcp;
794	int dai_count, i = 0;
795	int ret;
796
797	if (!hcd) {
798		dev_err(dev, "%s: No platform data\n", __func__);
799		return -EINVAL;
800	}
801
802	dai_count = hcd->i2s + hcd->spdif;
803	if (dai_count < 1 || !hcd->ops || !hcd->ops->hw_params ||
804	    !hcd->ops->audio_shutdown) {
805		dev_err(dev, "%s: Invalid parameters\n", __func__);
806		return -EINVAL;
807	}
808
809	hcp = devm_kzalloc(dev, sizeof(*hcp), GFP_KERNEL);
810	if (!hcp)
811		return -ENOMEM;
812
813	hcp->hcd = *hcd;
814	mutex_init(&hcp->lock);
815
816	daidrv = devm_kcalloc(dev, dai_count, sizeof(*daidrv), GFP_KERNEL);
817	if (!daidrv)
818		return -ENOMEM;
819
820	if (hcd->i2s) {
821		daidrv[i] = hdmi_i2s_dai;
822		daidrv[i].playback.channels_max = hcd->max_i2s_channels;
823		i++;
824	}
825
826	if (hcd->spdif)
827		daidrv[i] = hdmi_spdif_dai;
828
829	dev_set_drvdata(dev, hcp);
830
831	ret = devm_snd_soc_register_component(dev, &hdmi_driver, daidrv,
832					      dai_count);
833	if (ret) {
834		dev_err(dev, "%s: snd_soc_register_component() failed (%d)\n",
835			__func__, ret);
836		return ret;
837	}
838	return 0;
839}
840
841static struct platform_driver hdmi_codec_driver = {
842	.driver = {
843		.name = HDMI_CODEC_DRV_NAME,
844	},
845	.probe = hdmi_codec_probe,
846};
847
848module_platform_driver(hdmi_codec_driver);
849
850MODULE_AUTHOR("Jyri Sarha <jsarha@ti.com>");
851MODULE_DESCRIPTION("HDMI Audio Codec Driver");
852MODULE_LICENSE("GPL");
853MODULE_ALIAS("platform:" HDMI_CODEC_DRV_NAME);