Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.5.6.
  1/*
  2 * HDMI Channel map support helpers
  3 */
  4
  5#include <linux/module.h>
  6#include <sound/control.h>
  7#include <sound/tlv.h>
  8#include <sound/hda_chmap.h>
  9
 10/*
 11 * CEA speaker placement:
 12 *
 13 *        FLH       FCH        FRH
 14 *  FLW    FL  FLC   FC   FRC   FR   FRW
 15 *
 16 *                                  LFE
 17 *                     TC
 18 *
 19 *          RL  RLC   RC   RRC   RR
 20 *
 21 * The Left/Right Surround channel _notions_ LS/RS in SMPTE 320M corresponds to
 22 * CEA RL/RR; The SMPTE channel _assignment_ C/LFE is swapped to CEA LFE/FC.
 23 */
 24enum cea_speaker_placement {
 25	FL  = (1 <<  0),	/* Front Left           */
 26	FC  = (1 <<  1),	/* Front Center         */
 27	FR  = (1 <<  2),	/* Front Right          */
 28	FLC = (1 <<  3),	/* Front Left Center    */
 29	FRC = (1 <<  4),	/* Front Right Center   */
 30	RL  = (1 <<  5),	/* Rear Left            */
 31	RC  = (1 <<  6),	/* Rear Center          */
 32	RR  = (1 <<  7),	/* Rear Right           */
 33	RLC = (1 <<  8),	/* Rear Left Center     */
 34	RRC = (1 <<  9),	/* Rear Right Center    */
 35	LFE = (1 << 10),	/* Low Frequency Effect */
 36	FLW = (1 << 11),	/* Front Left Wide      */
 37	FRW = (1 << 12),	/* Front Right Wide     */
 38	FLH = (1 << 13),	/* Front Left High      */
 39	FCH = (1 << 14),	/* Front Center High    */
 40	FRH = (1 << 15),	/* Front Right High     */
 41	TC  = (1 << 16),	/* Top Center           */
 42};
 43
 44static const char * const cea_speaker_allocation_names[] = {
 45	/*  0 */ "FL/FR",
 46	/*  1 */ "LFE",
 47	/*  2 */ "FC",
 48	/*  3 */ "RL/RR",
 49	/*  4 */ "RC",
 50	/*  5 */ "FLC/FRC",
 51	/*  6 */ "RLC/RRC",
 52	/*  7 */ "FLW/FRW",
 53	/*  8 */ "FLH/FRH",
 54	/*  9 */ "TC",
 55	/* 10 */ "FCH",
 56};
 57
 58/*
 59 * ELD SA bits in the CEA Speaker Allocation data block
 60 */
 61static int eld_speaker_allocation_bits[] = {
 62	[0] = FL | FR,
 63	[1] = LFE,
 64	[2] = FC,
 65	[3] = RL | RR,
 66	[4] = RC,
 67	[5] = FLC | FRC,
 68	[6] = RLC | RRC,
 69	/* the following are not defined in ELD yet */
 70	[7] = FLW | FRW,
 71	[8] = FLH | FRH,
 72	[9] = TC,
 73	[10] = FCH,
 74};
 75
 76/*
 77 * ALSA sequence is:
 78 *
 79 *       surround40   surround41   surround50   surround51   surround71
 80 * ch0   front left   =            =            =            =
 81 * ch1   front right  =            =            =            =
 82 * ch2   rear left    =            =            =            =
 83 * ch3   rear right   =            =            =            =
 84 * ch4                LFE          center       center       center
 85 * ch5                                          LFE          LFE
 86 * ch6                                                       side left
 87 * ch7                                                       side right
 88 *
 89 * surround71 = {FL, FR, RLC, RRC, FC, LFE, RL, RR}
 90 */
 91static int hdmi_channel_mapping[0x32][8] = {
 92	/* stereo */
 93	[0x00] = { 0x00, 0x11, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 },
 94	/* 2.1 */
 95	[0x01] = { 0x00, 0x11, 0x22, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 },
 96	/* Dolby Surround */
 97	[0x02] = { 0x00, 0x11, 0x23, 0xf2, 0xf4, 0xf5, 0xf6, 0xf7 },
 98	/* surround40 */
 99	[0x08] = { 0x00, 0x11, 0x24, 0x35, 0xf3, 0xf2, 0xf6, 0xf7 },
100	/* 4ch */
101	[0x03] = { 0x00, 0x11, 0x23, 0x32, 0x44, 0xf5, 0xf6, 0xf7 },
102	/* surround41 */
103	[0x09] = { 0x00, 0x11, 0x24, 0x35, 0x42, 0xf3, 0xf6, 0xf7 },
104	/* surround50 */
105	[0x0a] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0xf2, 0xf6, 0xf7 },
106	/* surround51 */
107	[0x0b] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0x52, 0xf6, 0xf7 },
108	/* 7.1 */
109	[0x13] = { 0x00, 0x11, 0x26, 0x37, 0x43, 0x52, 0x64, 0x75 },
110};
111
112/*
113 * This is an ordered list!
114 *
115 * The preceding ones have better chances to be selected by
116 * hdmi_channel_allocation().
117 */
118static struct hdac_cea_channel_speaker_allocation channel_allocations[] = {
119/*			  channel:   7     6    5    4    3     2    1    0  */
120{ .ca_index = 0x00,  .speakers = {   0,    0,   0,   0,   0,    0,  FR,  FL } },
121				 /* 2.1 */
122{ .ca_index = 0x01,  .speakers = {   0,    0,   0,   0,   0,  LFE,  FR,  FL } },
123				 /* Dolby Surround */
124{ .ca_index = 0x02,  .speakers = {   0,    0,   0,   0,  FC,    0,  FR,  FL } },
125				 /* surround40 */
126{ .ca_index = 0x08,  .speakers = {   0,    0,  RR,  RL,   0,    0,  FR,  FL } },
127				 /* surround41 */
128{ .ca_index = 0x09,  .speakers = {   0,    0,  RR,  RL,   0,  LFE,  FR,  FL } },
129				 /* surround50 */
130{ .ca_index = 0x0a,  .speakers = {   0,    0,  RR,  RL,  FC,    0,  FR,  FL } },
131				 /* surround51 */
132{ .ca_index = 0x0b,  .speakers = {   0,    0,  RR,  RL,  FC,  LFE,  FR,  FL } },
133				 /* 6.1 */
134{ .ca_index = 0x0f,  .speakers = {   0,   RC,  RR,  RL,  FC,  LFE,  FR,  FL } },
135				 /* surround71 */
136{ .ca_index = 0x13,  .speakers = { RRC,  RLC,  RR,  RL,  FC,  LFE,  FR,  FL } },
137
138{ .ca_index = 0x03,  .speakers = {   0,    0,   0,   0,  FC,  LFE,  FR,  FL } },
139{ .ca_index = 0x04,  .speakers = {   0,    0,   0,  RC,   0,    0,  FR,  FL } },
140{ .ca_index = 0x05,  .speakers = {   0,    0,   0,  RC,   0,  LFE,  FR,  FL } },
141{ .ca_index = 0x06,  .speakers = {   0,    0,   0,  RC,  FC,    0,  FR,  FL } },
142{ .ca_index = 0x07,  .speakers = {   0,    0,   0,  RC,  FC,  LFE,  FR,  FL } },
143{ .ca_index = 0x0c,  .speakers = {   0,   RC,  RR,  RL,   0,    0,  FR,  FL } },
144{ .ca_index = 0x0d,  .speakers = {   0,   RC,  RR,  RL,   0,  LFE,  FR,  FL } },
145{ .ca_index = 0x0e,  .speakers = {   0,   RC,  RR,  RL,  FC,    0,  FR,  FL } },
146{ .ca_index = 0x10,  .speakers = { RRC,  RLC,  RR,  RL,   0,    0,  FR,  FL } },
147{ .ca_index = 0x11,  .speakers = { RRC,  RLC,  RR,  RL,   0,  LFE,  FR,  FL } },
148{ .ca_index = 0x12,  .speakers = { RRC,  RLC,  RR,  RL,  FC,    0,  FR,  FL } },
149{ .ca_index = 0x14,  .speakers = { FRC,  FLC,   0,   0,   0,    0,  FR,  FL } },
150{ .ca_index = 0x15,  .speakers = { FRC,  FLC,   0,   0,   0,  LFE,  FR,  FL } },
151{ .ca_index = 0x16,  .speakers = { FRC,  FLC,   0,   0,  FC,    0,  FR,  FL } },
152{ .ca_index = 0x17,  .speakers = { FRC,  FLC,   0,   0,  FC,  LFE,  FR,  FL } },
153{ .ca_index = 0x18,  .speakers = { FRC,  FLC,   0,  RC,   0,    0,  FR,  FL } },
154{ .ca_index = 0x19,  .speakers = { FRC,  FLC,   0,  RC,   0,  LFE,  FR,  FL } },
155{ .ca_index = 0x1a,  .speakers = { FRC,  FLC,   0,  RC,  FC,    0,  FR,  FL } },
156{ .ca_index = 0x1b,  .speakers = { FRC,  FLC,   0,  RC,  FC,  LFE,  FR,  FL } },
157{ .ca_index = 0x1c,  .speakers = { FRC,  FLC,  RR,  RL,   0,    0,  FR,  FL } },
158{ .ca_index = 0x1d,  .speakers = { FRC,  FLC,  RR,  RL,   0,  LFE,  FR,  FL } },
159{ .ca_index = 0x1e,  .speakers = { FRC,  FLC,  RR,  RL,  FC,    0,  FR,  FL } },
160{ .ca_index = 0x1f,  .speakers = { FRC,  FLC,  RR,  RL,  FC,  LFE,  FR,  FL } },
161{ .ca_index = 0x20,  .speakers = {   0,  FCH,  RR,  RL,  FC,    0,  FR,  FL } },
162{ .ca_index = 0x21,  .speakers = {   0,  FCH,  RR,  RL,  FC,  LFE,  FR,  FL } },
163{ .ca_index = 0x22,  .speakers = {  TC,    0,  RR,  RL,  FC,    0,  FR,  FL } },
164{ .ca_index = 0x23,  .speakers = {  TC,    0,  RR,  RL,  FC,  LFE,  FR,  FL } },
165{ .ca_index = 0x24,  .speakers = { FRH,  FLH,  RR,  RL,   0,    0,  FR,  FL } },
166{ .ca_index = 0x25,  .speakers = { FRH,  FLH,  RR,  RL,   0,  LFE,  FR,  FL } },
167{ .ca_index = 0x26,  .speakers = { FRW,  FLW,  RR,  RL,   0,    0,  FR,  FL } },
168{ .ca_index = 0x27,  .speakers = { FRW,  FLW,  RR,  RL,   0,  LFE,  FR,  FL } },
169{ .ca_index = 0x28,  .speakers = {  TC,   RC,  RR,  RL,  FC,    0,  FR,  FL } },
170{ .ca_index = 0x29,  .speakers = {  TC,   RC,  RR,  RL,  FC,  LFE,  FR,  FL } },
171{ .ca_index = 0x2a,  .speakers = { FCH,   RC,  RR,  RL,  FC,    0,  FR,  FL } },
172{ .ca_index = 0x2b,  .speakers = { FCH,   RC,  RR,  RL,  FC,  LFE,  FR,  FL } },
173{ .ca_index = 0x2c,  .speakers = {  TC,  FCH,  RR,  RL,  FC,    0,  FR,  FL } },
174{ .ca_index = 0x2d,  .speakers = {  TC,  FCH,  RR,  RL,  FC,  LFE,  FR,  FL } },
175{ .ca_index = 0x2e,  .speakers = { FRH,  FLH,  RR,  RL,  FC,    0,  FR,  FL } },
176{ .ca_index = 0x2f,  .speakers = { FRH,  FLH,  RR,  RL,  FC,  LFE,  FR,  FL } },
177{ .ca_index = 0x30,  .speakers = { FRW,  FLW,  RR,  RL,  FC,    0,  FR,  FL } },
178{ .ca_index = 0x31,  .speakers = { FRW,  FLW,  RR,  RL,  FC,  LFE,  FR,  FL } },
179};
180
181static int hdmi_pin_set_slot_channel(struct hdac_device *codec,
182		hda_nid_t pin_nid, int asp_slot, int channel)
183{
184	return snd_hdac_codec_write(codec, pin_nid, 0,
185				AC_VERB_SET_HDMI_CHAN_SLOT,
186				(channel << 4) | asp_slot);
187}
188
189static int hdmi_pin_get_slot_channel(struct hdac_device *codec,
190			hda_nid_t pin_nid, int asp_slot)
191{
192	return (snd_hdac_codec_read(codec, pin_nid, 0,
193				   AC_VERB_GET_HDMI_CHAN_SLOT,
194				   asp_slot) & 0xf0) >> 4;
195}
196
197static int hdmi_get_channel_count(struct hdac_device *codec, hda_nid_t cvt_nid)
198{
199	return 1 + snd_hdac_codec_read(codec, cvt_nid, 0,
200					AC_VERB_GET_CVT_CHAN_COUNT, 0);
201}
202
203static void hdmi_set_channel_count(struct hdac_device *codec,
204				   hda_nid_t cvt_nid, int chs)
205{
206	if (chs != hdmi_get_channel_count(codec, cvt_nid))
207		snd_hdac_codec_write(codec, cvt_nid, 0,
208				    AC_VERB_SET_CVT_CHAN_COUNT, chs - 1);
209}
210
211/*
212 * Channel mapping routines
213 */
214
215/*
216 * Compute derived values in channel_allocations[].
217 */
218static void init_channel_allocations(void)
219{
220	int i, j;
221	struct hdac_cea_channel_speaker_allocation *p;
222
223	for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
224		p = channel_allocations + i;
225		p->channels = 0;
226		p->spk_mask = 0;
227		for (j = 0; j < ARRAY_SIZE(p->speakers); j++)
228			if (p->speakers[j]) {
229				p->channels++;
230				p->spk_mask |= p->speakers[j];
231			}
232	}
233}
234
235static int get_channel_allocation_order(int ca)
236{
237	int i;
238
239	for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
240		if (channel_allocations[i].ca_index == ca)
241			break;
242	}
243	return i;
244}
245
246void snd_hdac_print_channel_allocation(int spk_alloc, char *buf, int buflen)
247{
248	int i, j;
249
250	for (i = 0, j = 0; i < ARRAY_SIZE(cea_speaker_allocation_names); i++) {
251		if (spk_alloc & (1 << i))
252			j += snprintf(buf + j, buflen - j,  " %s",
253					cea_speaker_allocation_names[i]);
254	}
255	buf[j] = '\0';	/* necessary when j == 0 */
256}
257EXPORT_SYMBOL_GPL(snd_hdac_print_channel_allocation);
258
259/*
260 * The transformation takes two steps:
261 *
262 *	eld->spk_alloc => (eld_speaker_allocation_bits[]) => spk_mask
263 *	      spk_mask => (channel_allocations[])         => ai->CA
264 *
265 * TODO: it could select the wrong CA from multiple candidates.
266*/
267static int hdmi_channel_allocation_spk_alloc_blk(struct hdac_device *codec,
268				   int spk_alloc, int channels)
269{
270	int i;
271	int ca = 0;
272	int spk_mask = 0;
273	char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE];
274
275	/*
276	 * CA defaults to 0 for basic stereo audio
277	 */
278	if (channels <= 2)
279		return 0;
280
281	/*
282	 * expand ELD's speaker allocation mask
283	 *
284	 * ELD tells the speaker mask in a compact(paired) form,
285	 * expand ELD's notions to match the ones used by Audio InfoFrame.
286	 */
287	for (i = 0; i < ARRAY_SIZE(eld_speaker_allocation_bits); i++) {
288		if (spk_alloc & (1 << i))
289			spk_mask |= eld_speaker_allocation_bits[i];
290	}
291
292	/* search for the first working match in the CA table */
293	for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
294		if (channels == channel_allocations[i].channels &&
295		    (spk_mask & channel_allocations[i].spk_mask) ==
296				channel_allocations[i].spk_mask) {
297			ca = channel_allocations[i].ca_index;
298			break;
299		}
300	}
301
302	if (!ca) {
303		/*
304		 * if there was no match, select the regular ALSA channel
305		 * allocation with the matching number of channels
306		 */
307		for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
308			if (channels == channel_allocations[i].channels) {
309				ca = channel_allocations[i].ca_index;
310				break;
311			}
312		}
313	}
314
315	snd_hdac_print_channel_allocation(spk_alloc, buf, sizeof(buf));
316	dev_dbg(&codec->dev, "HDMI: select CA 0x%x for %d-channel allocation: %s\n",
317		    ca, channels, buf);
318
319	return ca;
320}
321
322static void hdmi_debug_channel_mapping(struct hdac_chmap *chmap,
323				       hda_nid_t pin_nid)
324{
325#ifdef CONFIG_SND_DEBUG_VERBOSE
326	int i;
327	int channel;
328
329	for (i = 0; i < 8; i++) {
330		channel = chmap->ops.pin_get_slot_channel(
331				chmap->hdac, pin_nid, i);
332		dev_dbg(&chmap->hdac->dev, "HDMI: ASP channel %d => slot %d\n",
333						channel, i);
334	}
335#endif
336}
337
338static void hdmi_std_setup_channel_mapping(struct hdac_chmap *chmap,
339				       hda_nid_t pin_nid,
340				       bool non_pcm,
341				       int ca)
342{
343	struct hdac_cea_channel_speaker_allocation *ch_alloc;
344	int i;
345	int err;
346	int order;
347	int non_pcm_mapping[8];
348
349	order = get_channel_allocation_order(ca);
350	ch_alloc = &channel_allocations[order];
351
352	if (hdmi_channel_mapping[ca][1] == 0) {
353		int hdmi_slot = 0;
354		/* fill actual channel mappings in ALSA channel (i) order */
355		for (i = 0; i < ch_alloc->channels; i++) {
356			while (!ch_alloc->speakers[7 - hdmi_slot] && !WARN_ON(hdmi_slot >= 8))
357				hdmi_slot++; /* skip zero slots */
358
359			hdmi_channel_mapping[ca][i] = (i << 4) | hdmi_slot++;
360		}
361		/* fill the rest of the slots with ALSA channel 0xf */
362		for (hdmi_slot = 0; hdmi_slot < 8; hdmi_slot++)
363			if (!ch_alloc->speakers[7 - hdmi_slot])
364				hdmi_channel_mapping[ca][i++] = (0xf << 4) | hdmi_slot;
365	}
366
367	if (non_pcm) {
368		for (i = 0; i < ch_alloc->channels; i++)
369			non_pcm_mapping[i] = (i << 4) | i;
370		for (; i < 8; i++)
371			non_pcm_mapping[i] = (0xf << 4) | i;
372	}
373
374	for (i = 0; i < 8; i++) {
375		int slotsetup = non_pcm ? non_pcm_mapping[i] : hdmi_channel_mapping[ca][i];
376		int hdmi_slot = slotsetup & 0x0f;
377		int channel = (slotsetup & 0xf0) >> 4;
378
379		err = chmap->ops.pin_set_slot_channel(chmap->hdac,
380				pin_nid, hdmi_slot, channel);
381		if (err) {
382			dev_dbg(&chmap->hdac->dev, "HDMI: channel mapping failed\n");
383			break;
384		}
385	}
386}
387
388struct channel_map_table {
389	unsigned char map;		/* ALSA API channel map position */
390	int spk_mask;			/* speaker position bit mask */
391};
392
393static struct channel_map_table map_tables[] = {
394	{ SNDRV_CHMAP_FL,	FL },
395	{ SNDRV_CHMAP_FR,	FR },
396	{ SNDRV_CHMAP_RL,	RL },
397	{ SNDRV_CHMAP_RR,	RR },
398	{ SNDRV_CHMAP_LFE,	LFE },
399	{ SNDRV_CHMAP_FC,	FC },
400	{ SNDRV_CHMAP_RLC,	RLC },
401	{ SNDRV_CHMAP_RRC,	RRC },
402	{ SNDRV_CHMAP_RC,	RC },
403	{ SNDRV_CHMAP_FLC,	FLC },
404	{ SNDRV_CHMAP_FRC,	FRC },
405	{ SNDRV_CHMAP_TFL,	FLH },
406	{ SNDRV_CHMAP_TFR,	FRH },
407	{ SNDRV_CHMAP_FLW,	FLW },
408	{ SNDRV_CHMAP_FRW,	FRW },
409	{ SNDRV_CHMAP_TC,	TC },
410	{ SNDRV_CHMAP_TFC,	FCH },
411	{} /* terminator */
412};
413
414/* from ALSA API channel position to speaker bit mask */
415int snd_hdac_chmap_to_spk_mask(unsigned char c)
416{
417	struct channel_map_table *t = map_tables;
418
419	for (; t->map; t++) {
420		if (t->map == c)
421			return t->spk_mask;
422	}
423	return 0;
424}
425EXPORT_SYMBOL_GPL(snd_hdac_chmap_to_spk_mask);
426
427/* from ALSA API channel position to CEA slot */
428static int to_cea_slot(int ordered_ca, unsigned char pos)
429{
430	int mask = snd_hdac_chmap_to_spk_mask(pos);
431	int i;
432
433	if (mask) {
434		for (i = 0; i < 8; i++) {
435			if (channel_allocations[ordered_ca].speakers[7 - i] == mask)
436				return i;
437		}
438	}
439
440	return -1;
441}
442
443/* from speaker bit mask to ALSA API channel position */
444int snd_hdac_spk_to_chmap(int spk)
445{
446	struct channel_map_table *t = map_tables;
447
448	for (; t->map; t++) {
449		if (t->spk_mask == spk)
450			return t->map;
451	}
452	return 0;
453}
454EXPORT_SYMBOL_GPL(snd_hdac_spk_to_chmap);
455
456/* from CEA slot to ALSA API channel position */
457static int from_cea_slot(int ordered_ca, unsigned char slot)
458{
459	int mask = channel_allocations[ordered_ca].speakers[7 - slot];
460
461	return snd_hdac_spk_to_chmap(mask);
462}
463
464/* get the CA index corresponding to the given ALSA API channel map */
465static int hdmi_manual_channel_allocation(int chs, unsigned char *map)
466{
467	int i, spks = 0, spk_mask = 0;
468
469	for (i = 0; i < chs; i++) {
470		int mask = snd_hdac_chmap_to_spk_mask(map[i]);
471
472		if (mask) {
473			spk_mask |= mask;
474			spks++;
475		}
476	}
477
478	for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
479		if ((chs == channel_allocations[i].channels ||
480		     spks == channel_allocations[i].channels) &&
481		    (spk_mask & channel_allocations[i].spk_mask) ==
482				channel_allocations[i].spk_mask)
483			return channel_allocations[i].ca_index;
484	}
485	return -1;
486}
487
488/* set up the channel slots for the given ALSA API channel map */
489static int hdmi_manual_setup_channel_mapping(struct hdac_chmap *chmap,
490					     hda_nid_t pin_nid,
491					     int chs, unsigned char *map,
492					     int ca)
493{
494	int ordered_ca = get_channel_allocation_order(ca);
495	int alsa_pos, hdmi_slot;
496	int assignments[8] = {[0 ... 7] = 0xf};
497
498	for (alsa_pos = 0; alsa_pos < chs; alsa_pos++) {
499
500		hdmi_slot = to_cea_slot(ordered_ca, map[alsa_pos]);
501
502		if (hdmi_slot < 0)
503			continue; /* unassigned channel */
504
505		assignments[hdmi_slot] = alsa_pos;
506	}
507
508	for (hdmi_slot = 0; hdmi_slot < 8; hdmi_slot++) {
509		int err;
510
511		err = chmap->ops.pin_set_slot_channel(chmap->hdac,
512				pin_nid, hdmi_slot, assignments[hdmi_slot]);
513		if (err)
514			return -EINVAL;
515	}
516	return 0;
517}
518
519/* store ALSA API channel map from the current default map */
520static void hdmi_setup_fake_chmap(unsigned char *map, int ca)
521{
522	int i;
523	int ordered_ca = get_channel_allocation_order(ca);
524
525	for (i = 0; i < 8; i++) {
526		if (i < channel_allocations[ordered_ca].channels)
527			map[i] = from_cea_slot(ordered_ca, hdmi_channel_mapping[ca][i] & 0x0f);
528		else
529			map[i] = 0;
530	}
531}
532
533void snd_hdac_setup_channel_mapping(struct hdac_chmap *chmap,
534				       hda_nid_t pin_nid, bool non_pcm, int ca,
535				       int channels, unsigned char *map,
536				       bool chmap_set)
537{
538	if (!non_pcm && chmap_set) {
539		hdmi_manual_setup_channel_mapping(chmap, pin_nid,
540						  channels, map, ca);
541	} else {
542		hdmi_std_setup_channel_mapping(chmap, pin_nid, non_pcm, ca);
543		hdmi_setup_fake_chmap(map, ca);
544	}
545
546	hdmi_debug_channel_mapping(chmap, pin_nid);
547}
548EXPORT_SYMBOL_GPL(snd_hdac_setup_channel_mapping);
549
550int snd_hdac_get_active_channels(int ca)
551{
552	int ordered_ca = get_channel_allocation_order(ca);
553
554	return channel_allocations[ordered_ca].channels;
555}
556EXPORT_SYMBOL_GPL(snd_hdac_get_active_channels);
557
558struct hdac_cea_channel_speaker_allocation *snd_hdac_get_ch_alloc_from_ca(int ca)
559{
560	return &channel_allocations[get_channel_allocation_order(ca)];
561}
562EXPORT_SYMBOL_GPL(snd_hdac_get_ch_alloc_from_ca);
563
564int snd_hdac_channel_allocation(struct hdac_device *hdac, int spk_alloc,
565		int channels, bool chmap_set, bool non_pcm, unsigned char *map)
566{
567	int ca;
568
569	if (!non_pcm && chmap_set)
570		ca = hdmi_manual_channel_allocation(channels, map);
571	else
572		ca = hdmi_channel_allocation_spk_alloc_blk(hdac,
573					spk_alloc, channels);
574
575	if (ca < 0)
576		ca = 0;
577
578	return ca;
579}
580EXPORT_SYMBOL_GPL(snd_hdac_channel_allocation);
581
582/*
583 * ALSA API channel-map control callbacks
584 */
585static int hdmi_chmap_ctl_info(struct snd_kcontrol *kcontrol,
586			       struct snd_ctl_elem_info *uinfo)
587{
588	struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol);
589	struct hdac_chmap *chmap = info->private_data;
590
591	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
592	uinfo->count = chmap->channels_max;
593	uinfo->value.integer.min = 0;
594	uinfo->value.integer.max = SNDRV_CHMAP_LAST;
595	return 0;
596}
597
598static int hdmi_chmap_cea_alloc_validate_get_type(struct hdac_chmap *chmap,
599		struct hdac_cea_channel_speaker_allocation *cap, int channels)
600{
601	/* If the speaker allocation matches the channel count, it is OK.*/
602	if (cap->channels != channels)
603		return -1;
604
605	/* all channels are remappable freely */
606	return SNDRV_CTL_TLVT_CHMAP_VAR;
607}
608
609static void hdmi_cea_alloc_to_tlv_chmap(struct hdac_chmap *hchmap,
610		struct hdac_cea_channel_speaker_allocation *cap,
611		unsigned int *chmap, int channels)
612{
613	int count = 0;
614	int c;
615
616	for (c = 7; c >= 0; c--) {
617		int spk = cap->speakers[c];
618
619		if (!spk)
620			continue;
621
622		chmap[count++] = snd_hdac_spk_to_chmap(spk);
623	}
624
625	WARN_ON(count != channels);
626}
627
628static int hdmi_chmap_ctl_tlv(struct snd_kcontrol *kcontrol, int op_flag,
629			      unsigned int size, unsigned int __user *tlv)
630{
631	struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol);
632	struct hdac_chmap *chmap = info->private_data;
633	unsigned int __user *dst;
634	int chs, count = 0;
635
636	if (size < 8)
637		return -ENOMEM;
638	if (put_user(SNDRV_CTL_TLVT_CONTAINER, tlv))
639		return -EFAULT;
640	size -= 8;
641	dst = tlv + 2;
642	for (chs = 2; chs <= chmap->channels_max; chs++) {
643		int i;
644		struct hdac_cea_channel_speaker_allocation *cap;
645
646		cap = channel_allocations;
647		for (i = 0; i < ARRAY_SIZE(channel_allocations); i++, cap++) {
648			int chs_bytes = chs * 4;
649			int type = chmap->ops.chmap_cea_alloc_validate_get_type(
650								chmap, cap, chs);
651			unsigned int tlv_chmap[8];
652
653			if (type < 0)
654				continue;
655			if (size < 8)
656				return -ENOMEM;
657			if (put_user(type, dst) ||
658			    put_user(chs_bytes, dst + 1))
659				return -EFAULT;
660			dst += 2;
661			size -= 8;
662			count += 8;
663			if (size < chs_bytes)
664				return -ENOMEM;
665			size -= chs_bytes;
666			count += chs_bytes;
667			chmap->ops.cea_alloc_to_tlv_chmap(chmap, cap,
668						tlv_chmap, chs);
669			if (copy_to_user(dst, tlv_chmap, chs_bytes))
670				return -EFAULT;
671			dst += chs;
672		}
673	}
674	if (put_user(count, tlv + 1))
675		return -EFAULT;
676	return 0;
677}
678
679static int hdmi_chmap_ctl_get(struct snd_kcontrol *kcontrol,
680			      struct snd_ctl_elem_value *ucontrol)
681{
682	struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol);
683	struct hdac_chmap *chmap = info->private_data;
684	int pcm_idx = kcontrol->private_value;
685	unsigned char pcm_chmap[8];
686	int i;
687
688	memset(pcm_chmap, 0, sizeof(pcm_chmap));
689	chmap->ops.get_chmap(chmap->hdac, pcm_idx, pcm_chmap);
690
691	for (i = 0; i < sizeof(chmap); i++)
692		ucontrol->value.integer.value[i] = pcm_chmap[i];
693
694	return 0;
695}
696
697static int hdmi_chmap_ctl_put(struct snd_kcontrol *kcontrol,
698			      struct snd_ctl_elem_value *ucontrol)
699{
700	struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol);
701	struct hdac_chmap *hchmap = info->private_data;
702	int pcm_idx = kcontrol->private_value;
703	unsigned int ctl_idx;
704	struct snd_pcm_substream *substream;
705	unsigned char chmap[8], per_pin_chmap[8];
706	int i, err, ca, prepared = 0;
707
708	/* No monitor is connected in dyn_pcm_assign.
709	 * It's invalid to setup the chmap
710	 */
711	if (!hchmap->ops.is_pcm_attached(hchmap->hdac, pcm_idx))
712		return 0;
713
714	ctl_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
715	substream = snd_pcm_chmap_substream(info, ctl_idx);
716	if (!substream || !substream->runtime)
717		return 0; /* just for avoiding error from alsactl restore */
718	switch (substream->runtime->status->state) {
719	case SNDRV_PCM_STATE_OPEN:
720	case SNDRV_PCM_STATE_SETUP:
721		break;
722	case SNDRV_PCM_STATE_PREPARED:
723		prepared = 1;
724		break;
725	default:
726		return -EBUSY;
727	}
728	memset(chmap, 0, sizeof(chmap));
729	for (i = 0; i < ARRAY_SIZE(chmap); i++)
730		chmap[i] = ucontrol->value.integer.value[i];
731
732	hchmap->ops.get_chmap(hchmap->hdac, pcm_idx, per_pin_chmap);
733	if (!memcmp(chmap, per_pin_chmap, sizeof(chmap)))
734		return 0;
735	ca = hdmi_manual_channel_allocation(ARRAY_SIZE(chmap), chmap);
736	if (ca < 0)
737		return -EINVAL;
738	if (hchmap->ops.chmap_validate) {
739		err = hchmap->ops.chmap_validate(hchmap, ca,
740				ARRAY_SIZE(chmap), chmap);
741		if (err)
742			return err;
743	}
744
745	hchmap->ops.set_chmap(hchmap->hdac, pcm_idx, chmap, prepared);
746
747	return 0;
748}
749
750static const struct hdac_chmap_ops chmap_ops = {
751	.chmap_cea_alloc_validate_get_type	= hdmi_chmap_cea_alloc_validate_get_type,
752	.cea_alloc_to_tlv_chmap			= hdmi_cea_alloc_to_tlv_chmap,
753	.pin_get_slot_channel			= hdmi_pin_get_slot_channel,
754	.pin_set_slot_channel			= hdmi_pin_set_slot_channel,
755	.set_channel_count			= hdmi_set_channel_count,
756};
757
758void snd_hdac_register_chmap_ops(struct hdac_device *hdac,
759				struct hdac_chmap *chmap)
760{
761	chmap->ops = chmap_ops;
762	chmap->hdac = hdac;
763	init_channel_allocations();
764}
765EXPORT_SYMBOL_GPL(snd_hdac_register_chmap_ops);
766
767int snd_hdac_add_chmap_ctls(struct snd_pcm *pcm, int pcm_idx,
768				struct hdac_chmap *hchmap)
769{
770	struct snd_pcm_chmap *chmap;
771	struct snd_kcontrol *kctl;
772	int err, i;
773
774	err = snd_pcm_add_chmap_ctls(pcm,
775				     SNDRV_PCM_STREAM_PLAYBACK,
776				     NULL, 0, pcm_idx, &chmap);
777	if (err < 0)
778		return err;
779	/* override handlers */
780	chmap->private_data = hchmap;
781	kctl = chmap->kctl;
782	for (i = 0; i < kctl->count; i++)
783		kctl->vd[i].access |= SNDRV_CTL_ELEM_ACCESS_WRITE;
784	kctl->info = hdmi_chmap_ctl_info;
785	kctl->get = hdmi_chmap_ctl_get;
786	kctl->put = hdmi_chmap_ctl_put;
787	kctl->tlv.c = hdmi_chmap_ctl_tlv;
788
789	return 0;
790}
791EXPORT_SYMBOL_GPL(snd_hdac_add_chmap_ctls);