diff options
author | Subhransu S. Prusty <subhransu.s.prusty@intel.com> | 2016-03-04 09:29:51 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2016-03-07 09:45:29 -0500 |
commit | 2f6e8a8518f33b6fac1fb9c79d245e23b6f9b765 (patch) | |
tree | ff54c117e8d756aaab29694c4a24440622be80d2 /sound/pci/hda/patch_hdmi.c | |
parent | 828cb4edd8074d35f814e03bee3e2ad8b7d8f64b (diff) |
ALSA: hda - Move chmap support helpers/ops to core
Chmap helpers, ops, controls are moved to core.
Signed-off-by: Subhransu S. Prusty <subhransu.s.prusty@intel.com>
Signed-off-by: Vinod Koul <vinod.koul@intel.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/hda/patch_hdmi.c')
-rw-r--r-- | sound/pci/hda/patch_hdmi.c | 689 |
1 files changed, 1 insertions, 688 deletions
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 3718b41f4b60..bdfa045f28af 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c | |||
@@ -198,164 +198,6 @@ union audio_infoframe { | |||
198 | }; | 198 | }; |
199 | 199 | ||
200 | /* | 200 | /* |
201 | * CEA speaker placement: | ||
202 | * | ||
203 | * FLH FCH FRH | ||
204 | * FLW FL FLC FC FRC FR FRW | ||
205 | * | ||
206 | * LFE | ||
207 | * TC | ||
208 | * | ||
209 | * RL RLC RC RRC RR | ||
210 | * | ||
211 | * The Left/Right Surround channel _notions_ LS/RS in SMPTE 320M corresponds to | ||
212 | * CEA RL/RR; The SMPTE channel _assignment_ C/LFE is swapped to CEA LFE/FC. | ||
213 | */ | ||
214 | enum cea_speaker_placement { | ||
215 | FL = (1 << 0), /* Front Left */ | ||
216 | FC = (1 << 1), /* Front Center */ | ||
217 | FR = (1 << 2), /* Front Right */ | ||
218 | FLC = (1 << 3), /* Front Left Center */ | ||
219 | FRC = (1 << 4), /* Front Right Center */ | ||
220 | RL = (1 << 5), /* Rear Left */ | ||
221 | RC = (1 << 6), /* Rear Center */ | ||
222 | RR = (1 << 7), /* Rear Right */ | ||
223 | RLC = (1 << 8), /* Rear Left Center */ | ||
224 | RRC = (1 << 9), /* Rear Right Center */ | ||
225 | LFE = (1 << 10), /* Low Frequency Effect */ | ||
226 | FLW = (1 << 11), /* Front Left Wide */ | ||
227 | FRW = (1 << 12), /* Front Right Wide */ | ||
228 | FLH = (1 << 13), /* Front Left High */ | ||
229 | FCH = (1 << 14), /* Front Center High */ | ||
230 | FRH = (1 << 15), /* Front Right High */ | ||
231 | TC = (1 << 16), /* Top Center */ | ||
232 | }; | ||
233 | |||
234 | /* | ||
235 | * ELD SA bits in the CEA Speaker Allocation data block | ||
236 | */ | ||
237 | static int eld_speaker_allocation_bits[] = { | ||
238 | [0] = FL | FR, | ||
239 | [1] = LFE, | ||
240 | [2] = FC, | ||
241 | [3] = RL | RR, | ||
242 | [4] = RC, | ||
243 | [5] = FLC | FRC, | ||
244 | [6] = RLC | RRC, | ||
245 | /* the following are not defined in ELD yet */ | ||
246 | [7] = FLW | FRW, | ||
247 | [8] = FLH | FRH, | ||
248 | [9] = TC, | ||
249 | [10] = FCH, | ||
250 | }; | ||
251 | |||
252 | /* | ||
253 | * ALSA sequence is: | ||
254 | * | ||
255 | * surround40 surround41 surround50 surround51 surround71 | ||
256 | * ch0 front left = = = = | ||
257 | * ch1 front right = = = = | ||
258 | * ch2 rear left = = = = | ||
259 | * ch3 rear right = = = = | ||
260 | * ch4 LFE center center center | ||
261 | * ch5 LFE LFE | ||
262 | * ch6 side left | ||
263 | * ch7 side right | ||
264 | * | ||
265 | * surround71 = {FL, FR, RLC, RRC, FC, LFE, RL, RR} | ||
266 | */ | ||
267 | static int hdmi_channel_mapping[0x32][8] = { | ||
268 | /* stereo */ | ||
269 | [0x00] = { 0x00, 0x11, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 }, | ||
270 | /* 2.1 */ | ||
271 | [0x01] = { 0x00, 0x11, 0x22, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 }, | ||
272 | /* Dolby Surround */ | ||
273 | [0x02] = { 0x00, 0x11, 0x23, 0xf2, 0xf4, 0xf5, 0xf6, 0xf7 }, | ||
274 | /* surround40 */ | ||
275 | [0x08] = { 0x00, 0x11, 0x24, 0x35, 0xf3, 0xf2, 0xf6, 0xf7 }, | ||
276 | /* 4ch */ | ||
277 | [0x03] = { 0x00, 0x11, 0x23, 0x32, 0x44, 0xf5, 0xf6, 0xf7 }, | ||
278 | /* surround41 */ | ||
279 | [0x09] = { 0x00, 0x11, 0x24, 0x35, 0x42, 0xf3, 0xf6, 0xf7 }, | ||
280 | /* surround50 */ | ||
281 | [0x0a] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0xf2, 0xf6, 0xf7 }, | ||
282 | /* surround51 */ | ||
283 | [0x0b] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0x52, 0xf6, 0xf7 }, | ||
284 | /* 7.1 */ | ||
285 | [0x13] = { 0x00, 0x11, 0x26, 0x37, 0x43, 0x52, 0x64, 0x75 }, | ||
286 | }; | ||
287 | |||
288 | /* | ||
289 | * This is an ordered list! | ||
290 | * | ||
291 | * The preceding ones have better chances to be selected by | ||
292 | * hdmi_channel_allocation(). | ||
293 | */ | ||
294 | static struct hdac_cea_channel_speaker_allocation channel_allocations[] = { | ||
295 | /* channel: 7 6 5 4 3 2 1 0 */ | ||
296 | { .ca_index = 0x00, .speakers = { 0, 0, 0, 0, 0, 0, FR, FL } }, | ||
297 | /* 2.1 */ | ||
298 | { .ca_index = 0x01, .speakers = { 0, 0, 0, 0, 0, LFE, FR, FL } }, | ||
299 | /* Dolby Surround */ | ||
300 | { .ca_index = 0x02, .speakers = { 0, 0, 0, 0, FC, 0, FR, FL } }, | ||
301 | /* surround40 */ | ||
302 | { .ca_index = 0x08, .speakers = { 0, 0, RR, RL, 0, 0, FR, FL } }, | ||
303 | /* surround41 */ | ||
304 | { .ca_index = 0x09, .speakers = { 0, 0, RR, RL, 0, LFE, FR, FL } }, | ||
305 | /* surround50 */ | ||
306 | { .ca_index = 0x0a, .speakers = { 0, 0, RR, RL, FC, 0, FR, FL } }, | ||
307 | /* surround51 */ | ||
308 | { .ca_index = 0x0b, .speakers = { 0, 0, RR, RL, FC, LFE, FR, FL } }, | ||
309 | /* 6.1 */ | ||
310 | { .ca_index = 0x0f, .speakers = { 0, RC, RR, RL, FC, LFE, FR, FL } }, | ||
311 | /* surround71 */ | ||
312 | { .ca_index = 0x13, .speakers = { RRC, RLC, RR, RL, FC, LFE, FR, FL } }, | ||
313 | |||
314 | { .ca_index = 0x03, .speakers = { 0, 0, 0, 0, FC, LFE, FR, FL } }, | ||
315 | { .ca_index = 0x04, .speakers = { 0, 0, 0, RC, 0, 0, FR, FL } }, | ||
316 | { .ca_index = 0x05, .speakers = { 0, 0, 0, RC, 0, LFE, FR, FL } }, | ||
317 | { .ca_index = 0x06, .speakers = { 0, 0, 0, RC, FC, 0, FR, FL } }, | ||
318 | { .ca_index = 0x07, .speakers = { 0, 0, 0, RC, FC, LFE, FR, FL } }, | ||
319 | { .ca_index = 0x0c, .speakers = { 0, RC, RR, RL, 0, 0, FR, FL } }, | ||
320 | { .ca_index = 0x0d, .speakers = { 0, RC, RR, RL, 0, LFE, FR, FL } }, | ||
321 | { .ca_index = 0x0e, .speakers = { 0, RC, RR, RL, FC, 0, FR, FL } }, | ||
322 | { .ca_index = 0x10, .speakers = { RRC, RLC, RR, RL, 0, 0, FR, FL } }, | ||
323 | { .ca_index = 0x11, .speakers = { RRC, RLC, RR, RL, 0, LFE, FR, FL } }, | ||
324 | { .ca_index = 0x12, .speakers = { RRC, RLC, RR, RL, FC, 0, FR, FL } }, | ||
325 | { .ca_index = 0x14, .speakers = { FRC, FLC, 0, 0, 0, 0, FR, FL } }, | ||
326 | { .ca_index = 0x15, .speakers = { FRC, FLC, 0, 0, 0, LFE, FR, FL } }, | ||
327 | { .ca_index = 0x16, .speakers = { FRC, FLC, 0, 0, FC, 0, FR, FL } }, | ||
328 | { .ca_index = 0x17, .speakers = { FRC, FLC, 0, 0, FC, LFE, FR, FL } }, | ||
329 | { .ca_index = 0x18, .speakers = { FRC, FLC, 0, RC, 0, 0, FR, FL } }, | ||
330 | { .ca_index = 0x19, .speakers = { FRC, FLC, 0, RC, 0, LFE, FR, FL } }, | ||
331 | { .ca_index = 0x1a, .speakers = { FRC, FLC, 0, RC, FC, 0, FR, FL } }, | ||
332 | { .ca_index = 0x1b, .speakers = { FRC, FLC, 0, RC, FC, LFE, FR, FL } }, | ||
333 | { .ca_index = 0x1c, .speakers = { FRC, FLC, RR, RL, 0, 0, FR, FL } }, | ||
334 | { .ca_index = 0x1d, .speakers = { FRC, FLC, RR, RL, 0, LFE, FR, FL } }, | ||
335 | { .ca_index = 0x1e, .speakers = { FRC, FLC, RR, RL, FC, 0, FR, FL } }, | ||
336 | { .ca_index = 0x1f, .speakers = { FRC, FLC, RR, RL, FC, LFE, FR, FL } }, | ||
337 | { .ca_index = 0x20, .speakers = { 0, FCH, RR, RL, FC, 0, FR, FL } }, | ||
338 | { .ca_index = 0x21, .speakers = { 0, FCH, RR, RL, FC, LFE, FR, FL } }, | ||
339 | { .ca_index = 0x22, .speakers = { TC, 0, RR, RL, FC, 0, FR, FL } }, | ||
340 | { .ca_index = 0x23, .speakers = { TC, 0, RR, RL, FC, LFE, FR, FL } }, | ||
341 | { .ca_index = 0x24, .speakers = { FRH, FLH, RR, RL, 0, 0, FR, FL } }, | ||
342 | { .ca_index = 0x25, .speakers = { FRH, FLH, RR, RL, 0, LFE, FR, FL } }, | ||
343 | { .ca_index = 0x26, .speakers = { FRW, FLW, RR, RL, 0, 0, FR, FL } }, | ||
344 | { .ca_index = 0x27, .speakers = { FRW, FLW, RR, RL, 0, LFE, FR, FL } }, | ||
345 | { .ca_index = 0x28, .speakers = { TC, RC, RR, RL, FC, 0, FR, FL } }, | ||
346 | { .ca_index = 0x29, .speakers = { TC, RC, RR, RL, FC, LFE, FR, FL } }, | ||
347 | { .ca_index = 0x2a, .speakers = { FCH, RC, RR, RL, FC, 0, FR, FL } }, | ||
348 | { .ca_index = 0x2b, .speakers = { FCH, RC, RR, RL, FC, LFE, FR, FL } }, | ||
349 | { .ca_index = 0x2c, .speakers = { TC, FCH, RR, RL, FC, 0, FR, FL } }, | ||
350 | { .ca_index = 0x2d, .speakers = { TC, FCH, RR, RL, FC, LFE, FR, FL } }, | ||
351 | { .ca_index = 0x2e, .speakers = { FRH, FLH, RR, RL, FC, 0, FR, FL } }, | ||
352 | { .ca_index = 0x2f, .speakers = { FRH, FLH, RR, RL, FC, LFE, FR, FL } }, | ||
353 | { .ca_index = 0x30, .speakers = { FRW, FLW, RR, RL, FC, 0, FR, FL } }, | ||
354 | { .ca_index = 0x31, .speakers = { FRW, FLW, RR, RL, FC, LFE, FR, FL } }, | ||
355 | }; | ||
356 | |||
357 | |||
358 | /* | ||
359 | * HDMI routines | 201 | * HDMI routines |
360 | */ | 202 | */ |
361 | 203 | ||
@@ -654,322 +496,6 @@ static inline void eld_proc_free(struct hdmi_spec_per_pin *per_pin) | |||
654 | #endif | 496 | #endif |
655 | 497 | ||
656 | /* | 498 | /* |
657 | * Channel mapping routines | ||
658 | */ | ||
659 | |||
660 | /* | ||
661 | * Compute derived values in channel_allocations[]. | ||
662 | */ | ||
663 | static void init_channel_allocations(void) | ||
664 | { | ||
665 | int i, j; | ||
666 | struct hdac_cea_channel_speaker_allocation *p; | ||
667 | |||
668 | for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) { | ||
669 | p = channel_allocations + i; | ||
670 | p->channels = 0; | ||
671 | p->spk_mask = 0; | ||
672 | for (j = 0; j < ARRAY_SIZE(p->speakers); j++) | ||
673 | if (p->speakers[j]) { | ||
674 | p->channels++; | ||
675 | p->spk_mask |= p->speakers[j]; | ||
676 | } | ||
677 | } | ||
678 | } | ||
679 | |||
680 | static int get_channel_allocation_order(int ca) | ||
681 | { | ||
682 | int i; | ||
683 | |||
684 | for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) { | ||
685 | if (channel_allocations[i].ca_index == ca) | ||
686 | break; | ||
687 | } | ||
688 | return i; | ||
689 | } | ||
690 | |||
691 | /* | ||
692 | * The transformation takes two steps: | ||
693 | * | ||
694 | * eld->spk_alloc => (eld_speaker_allocation_bits[]) => spk_mask | ||
695 | * spk_mask => (channel_allocations[]) => ai->CA | ||
696 | * | ||
697 | * TODO: it could select the wrong CA from multiple candidates. | ||
698 | */ | ||
699 | static int hdmi_channel_allocation_spk_alloc_blk(struct hdac_device *codec, | ||
700 | int spk_alloc, int channels) | ||
701 | { | ||
702 | int i; | ||
703 | int ca = 0; | ||
704 | int spk_mask = 0; | ||
705 | char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE]; | ||
706 | |||
707 | /* | ||
708 | * CA defaults to 0 for basic stereo audio | ||
709 | */ | ||
710 | if (channels <= 2) | ||
711 | return 0; | ||
712 | |||
713 | /* | ||
714 | * expand ELD's speaker allocation mask | ||
715 | * | ||
716 | * ELD tells the speaker mask in a compact(paired) form, | ||
717 | * expand ELD's notions to match the ones used by Audio InfoFrame. | ||
718 | */ | ||
719 | for (i = 0; i < ARRAY_SIZE(eld_speaker_allocation_bits); i++) { | ||
720 | if (spk_alloc & (1 << i)) | ||
721 | spk_mask |= eld_speaker_allocation_bits[i]; | ||
722 | } | ||
723 | |||
724 | /* search for the first working match in the CA table */ | ||
725 | for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) { | ||
726 | if (channels == channel_allocations[i].channels && | ||
727 | (spk_mask & channel_allocations[i].spk_mask) == | ||
728 | channel_allocations[i].spk_mask) { | ||
729 | ca = channel_allocations[i].ca_index; | ||
730 | break; | ||
731 | } | ||
732 | } | ||
733 | |||
734 | if (!ca) { | ||
735 | /* if there was no match, select the regular ALSA channel | ||
736 | * allocation with the matching number of channels */ | ||
737 | for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) { | ||
738 | if (channels == channel_allocations[i].channels) { | ||
739 | ca = channel_allocations[i].ca_index; | ||
740 | break; | ||
741 | } | ||
742 | } | ||
743 | } | ||
744 | |||
745 | snd_print_channel_allocation(spk_alloc, buf, sizeof(buf)); | ||
746 | dev_dbg(&codec->dev, "HDMI: select CA 0x%x for %d-channel allocation: %s\n", | ||
747 | ca, channels, buf); | ||
748 | |||
749 | return ca; | ||
750 | } | ||
751 | |||
752 | static void hdmi_debug_channel_mapping(struct hdac_chmap *chmap, | ||
753 | hda_nid_t pin_nid) | ||
754 | { | ||
755 | #ifdef CONFIG_SND_DEBUG_VERBOSE | ||
756 | int i; | ||
757 | int channel; | ||
758 | |||
759 | for (i = 0; i < 8; i++) { | ||
760 | channel = chmap->ops.pin_get_slot_channel( | ||
761 | chmap->hdac, pin_nid, i); | ||
762 | dev_dbg(&chmap->hdac->dev, "HDMI: ASP channel %d => slot %d\n", | ||
763 | channel, i); | ||
764 | } | ||
765 | #endif | ||
766 | } | ||
767 | |||
768 | static void hdmi_std_setup_channel_mapping(struct hdac_chmap *chmap, | ||
769 | hda_nid_t pin_nid, | ||
770 | bool non_pcm, | ||
771 | int ca) | ||
772 | { | ||
773 | struct hdac_cea_channel_speaker_allocation *ch_alloc; | ||
774 | int i; | ||
775 | int err; | ||
776 | int order; | ||
777 | int non_pcm_mapping[8]; | ||
778 | |||
779 | order = get_channel_allocation_order(ca); | ||
780 | ch_alloc = &channel_allocations[order]; | ||
781 | |||
782 | if (hdmi_channel_mapping[ca][1] == 0) { | ||
783 | int hdmi_slot = 0; | ||
784 | /* fill actual channel mappings in ALSA channel (i) order */ | ||
785 | for (i = 0; i < ch_alloc->channels; i++) { | ||
786 | while (!ch_alloc->speakers[7 - hdmi_slot] && !WARN_ON(hdmi_slot >= 8)) | ||
787 | hdmi_slot++; /* skip zero slots */ | ||
788 | |||
789 | hdmi_channel_mapping[ca][i] = (i << 4) | hdmi_slot++; | ||
790 | } | ||
791 | /* fill the rest of the slots with ALSA channel 0xf */ | ||
792 | for (hdmi_slot = 0; hdmi_slot < 8; hdmi_slot++) | ||
793 | if (!ch_alloc->speakers[7 - hdmi_slot]) | ||
794 | hdmi_channel_mapping[ca][i++] = (0xf << 4) | hdmi_slot; | ||
795 | } | ||
796 | |||
797 | if (non_pcm) { | ||
798 | for (i = 0; i < ch_alloc->channels; i++) | ||
799 | non_pcm_mapping[i] = (i << 4) | i; | ||
800 | for (; i < 8; i++) | ||
801 | non_pcm_mapping[i] = (0xf << 4) | i; | ||
802 | } | ||
803 | |||
804 | for (i = 0; i < 8; i++) { | ||
805 | int slotsetup = non_pcm ? non_pcm_mapping[i] : hdmi_channel_mapping[ca][i]; | ||
806 | int hdmi_slot = slotsetup & 0x0f; | ||
807 | int channel = (slotsetup & 0xf0) >> 4; | ||
808 | err = chmap->ops.pin_set_slot_channel(chmap->hdac, | ||
809 | pin_nid, hdmi_slot, channel); | ||
810 | if (err) { | ||
811 | dev_dbg(&chmap->hdac->dev, "HDMI: channel mapping failed\n"); | ||
812 | break; | ||
813 | } | ||
814 | } | ||
815 | } | ||
816 | |||
817 | struct channel_map_table { | ||
818 | unsigned char map; /* ALSA API channel map position */ | ||
819 | int spk_mask; /* speaker position bit mask */ | ||
820 | }; | ||
821 | |||
822 | static struct channel_map_table map_tables[] = { | ||
823 | { SNDRV_CHMAP_FL, FL }, | ||
824 | { SNDRV_CHMAP_FR, FR }, | ||
825 | { SNDRV_CHMAP_RL, RL }, | ||
826 | { SNDRV_CHMAP_RR, RR }, | ||
827 | { SNDRV_CHMAP_LFE, LFE }, | ||
828 | { SNDRV_CHMAP_FC, FC }, | ||
829 | { SNDRV_CHMAP_RLC, RLC }, | ||
830 | { SNDRV_CHMAP_RRC, RRC }, | ||
831 | { SNDRV_CHMAP_RC, RC }, | ||
832 | { SNDRV_CHMAP_FLC, FLC }, | ||
833 | { SNDRV_CHMAP_FRC, FRC }, | ||
834 | { SNDRV_CHMAP_TFL, FLH }, | ||
835 | { SNDRV_CHMAP_TFR, FRH }, | ||
836 | { SNDRV_CHMAP_FLW, FLW }, | ||
837 | { SNDRV_CHMAP_FRW, FRW }, | ||
838 | { SNDRV_CHMAP_TC, TC }, | ||
839 | { SNDRV_CHMAP_TFC, FCH }, | ||
840 | {} /* terminator */ | ||
841 | }; | ||
842 | |||
843 | /* from ALSA API channel position to speaker bit mask */ | ||
844 | static int to_spk_mask(unsigned char c) | ||
845 | { | ||
846 | struct channel_map_table *t = map_tables; | ||
847 | for (; t->map; t++) { | ||
848 | if (t->map == c) | ||
849 | return t->spk_mask; | ||
850 | } | ||
851 | return 0; | ||
852 | } | ||
853 | |||
854 | /* from ALSA API channel position to CEA slot */ | ||
855 | static int to_cea_slot(int ordered_ca, unsigned char pos) | ||
856 | { | ||
857 | int mask = to_spk_mask(pos); | ||
858 | int i; | ||
859 | |||
860 | if (mask) { | ||
861 | for (i = 0; i < 8; i++) { | ||
862 | if (channel_allocations[ordered_ca].speakers[7 - i] == mask) | ||
863 | return i; | ||
864 | } | ||
865 | } | ||
866 | |||
867 | return -1; | ||
868 | } | ||
869 | |||
870 | /* from speaker bit mask to ALSA API channel position */ | ||
871 | static int spk_to_chmap(int spk) | ||
872 | { | ||
873 | struct channel_map_table *t = map_tables; | ||
874 | for (; t->map; t++) { | ||
875 | if (t->spk_mask == spk) | ||
876 | return t->map; | ||
877 | } | ||
878 | return 0; | ||
879 | } | ||
880 | |||
881 | /* from CEA slot to ALSA API channel position */ | ||
882 | static int from_cea_slot(int ordered_ca, unsigned char slot) | ||
883 | { | ||
884 | int mask = channel_allocations[ordered_ca].speakers[7 - slot]; | ||
885 | |||
886 | return spk_to_chmap(mask); | ||
887 | } | ||
888 | |||
889 | /* get the CA index corresponding to the given ALSA API channel map */ | ||
890 | static int hdmi_manual_channel_allocation(int chs, unsigned char *map) | ||
891 | { | ||
892 | int i, spks = 0, spk_mask = 0; | ||
893 | |||
894 | for (i = 0; i < chs; i++) { | ||
895 | int mask = to_spk_mask(map[i]); | ||
896 | if (mask) { | ||
897 | spk_mask |= mask; | ||
898 | spks++; | ||
899 | } | ||
900 | } | ||
901 | |||
902 | for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) { | ||
903 | if ((chs == channel_allocations[i].channels || | ||
904 | spks == channel_allocations[i].channels) && | ||
905 | (spk_mask & channel_allocations[i].spk_mask) == | ||
906 | channel_allocations[i].spk_mask) | ||
907 | return channel_allocations[i].ca_index; | ||
908 | } | ||
909 | return -1; | ||
910 | } | ||
911 | |||
912 | /* set up the channel slots for the given ALSA API channel map */ | ||
913 | static int hdmi_manual_setup_channel_mapping(struct hdac_chmap *chmap, | ||
914 | hda_nid_t pin_nid, | ||
915 | int chs, unsigned char *map, | ||
916 | int ca) | ||
917 | { | ||
918 | int ordered_ca = get_channel_allocation_order(ca); | ||
919 | int alsa_pos, hdmi_slot; | ||
920 | int assignments[8] = {[0 ... 7] = 0xf}; | ||
921 | |||
922 | for (alsa_pos = 0; alsa_pos < chs; alsa_pos++) { | ||
923 | |||
924 | hdmi_slot = to_cea_slot(ordered_ca, map[alsa_pos]); | ||
925 | |||
926 | if (hdmi_slot < 0) | ||
927 | continue; /* unassigned channel */ | ||
928 | |||
929 | assignments[hdmi_slot] = alsa_pos; | ||
930 | } | ||
931 | |||
932 | for (hdmi_slot = 0; hdmi_slot < 8; hdmi_slot++) { | ||
933 | int err; | ||
934 | |||
935 | err = chmap->ops.pin_set_slot_channel(chmap->hdac, | ||
936 | pin_nid, hdmi_slot, assignments[hdmi_slot]); | ||
937 | if (err) | ||
938 | return -EINVAL; | ||
939 | } | ||
940 | return 0; | ||
941 | } | ||
942 | |||
943 | /* store ALSA API channel map from the current default map */ | ||
944 | static void hdmi_setup_fake_chmap(unsigned char *map, int ca) | ||
945 | { | ||
946 | int i; | ||
947 | int ordered_ca = get_channel_allocation_order(ca); | ||
948 | for (i = 0; i < 8; i++) { | ||
949 | if (i < channel_allocations[ordered_ca].channels) | ||
950 | map[i] = from_cea_slot(ordered_ca, hdmi_channel_mapping[ca][i] & 0x0f); | ||
951 | else | ||
952 | map[i] = 0; | ||
953 | } | ||
954 | } | ||
955 | |||
956 | static void hdmi_setup_channel_mapping(struct hdac_chmap *chmap, | ||
957 | hda_nid_t pin_nid, bool non_pcm, int ca, | ||
958 | int channels, unsigned char *map, | ||
959 | bool chmap_set) | ||
960 | { | ||
961 | if (!non_pcm && chmap_set) { | ||
962 | hdmi_manual_setup_channel_mapping(chmap, pin_nid, | ||
963 | channels, map, ca); | ||
964 | } else { | ||
965 | hdmi_std_setup_channel_mapping(chmap, pin_nid, non_pcm, ca); | ||
966 | hdmi_setup_fake_chmap(map, ca); | ||
967 | } | ||
968 | |||
969 | hdmi_debug_channel_mapping(chmap, pin_nid); | ||
970 | } | ||
971 | |||
972 | /* | ||
973 | * Audio InfoFrame routines | 499 | * Audio InfoFrame routines |
974 | */ | 500 | */ |
975 | 501 | ||
@@ -1139,35 +665,6 @@ static void hdmi_pin_setup_infoframe(struct hda_codec *codec, | |||
1139 | } | 665 | } |
1140 | } | 666 | } |
1141 | 667 | ||
1142 | static int hdmi_get_active_channels(int ca) | ||
1143 | { | ||
1144 | int ordered_ca = get_channel_allocation_order(ca); | ||
1145 | |||
1146 | return channel_allocations[ordered_ca].channels; | ||
1147 | } | ||
1148 | |||
1149 | static struct hdac_cea_channel_speaker_allocation *hdmi_get_ch_alloc_from_ca(int ca) | ||
1150 | { | ||
1151 | return &channel_allocations[get_channel_allocation_order(ca)]; | ||
1152 | } | ||
1153 | |||
1154 | static int hdmi_channel_allocation(struct hdac_device *hdac, int spk_alloc, | ||
1155 | int channels, bool chmap_set, bool non_pcm, unsigned char *map) | ||
1156 | { | ||
1157 | int ca; | ||
1158 | |||
1159 | if (!non_pcm && chmap_set) | ||
1160 | ca = hdmi_manual_channel_allocation(channels, map); | ||
1161 | else | ||
1162 | ca = hdmi_channel_allocation_spk_alloc_blk(hdac, | ||
1163 | spk_alloc, channels); | ||
1164 | |||
1165 | if (ca < 0) | ||
1166 | ca = 0; | ||
1167 | |||
1168 | return ca; | ||
1169 | } | ||
1170 | |||
1171 | static void hdmi_setup_audio_infoframe(struct hda_codec *codec, | 668 | static void hdmi_setup_audio_infoframe(struct hda_codec *codec, |
1172 | struct hdmi_spec_per_pin *per_pin, | 669 | struct hdmi_spec_per_pin *per_pin, |
1173 | bool non_pcm) | 670 | bool non_pcm) |
@@ -2331,51 +1828,6 @@ static const struct hda_pcm_ops generic_ops = { | |||
2331 | .cleanup = generic_hdmi_playback_pcm_cleanup, | 1828 | .cleanup = generic_hdmi_playback_pcm_cleanup, |
2332 | }; | 1829 | }; |
2333 | 1830 | ||
2334 | /* | ||
2335 | * ALSA API channel-map control callbacks | ||
2336 | */ | ||
2337 | static int hdmi_chmap_ctl_info(struct snd_kcontrol *kcontrol, | ||
2338 | struct snd_ctl_elem_info *uinfo) | ||
2339 | { | ||
2340 | struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol); | ||
2341 | struct hdac_chmap *chmap = info->private_data; | ||
2342 | |||
2343 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
2344 | uinfo->count = chmap->channels_max; | ||
2345 | uinfo->value.integer.min = 0; | ||
2346 | uinfo->value.integer.max = SNDRV_CHMAP_LAST; | ||
2347 | return 0; | ||
2348 | } | ||
2349 | |||
2350 | static int hdmi_chmap_cea_alloc_validate_get_type(struct hdac_chmap *chmap, | ||
2351 | struct hdac_cea_channel_speaker_allocation *cap, int channels) | ||
2352 | { | ||
2353 | /* If the speaker allocation matches the channel count, it is OK.*/ | ||
2354 | if (cap->channels != channels) | ||
2355 | return -1; | ||
2356 | |||
2357 | /* all channels are remappable freely */ | ||
2358 | return SNDRV_CTL_TLVT_CHMAP_VAR; | ||
2359 | } | ||
2360 | |||
2361 | static void hdmi_cea_alloc_to_tlv_chmap(struct hdac_chmap *hchmap, | ||
2362 | struct hdac_cea_channel_speaker_allocation *cap, | ||
2363 | unsigned int *chmap, int channels) | ||
2364 | { | ||
2365 | int count = 0; | ||
2366 | int c; | ||
2367 | |||
2368 | for (c = 7; c >= 0; c--) { | ||
2369 | int spk = cap->speakers[c]; | ||
2370 | if (!spk) | ||
2371 | continue; | ||
2372 | |||
2373 | chmap[count++] = spk_to_chmap(spk); | ||
2374 | } | ||
2375 | |||
2376 | WARN_ON(count != channels); | ||
2377 | } | ||
2378 | |||
2379 | static void hdmi_get_chmap(struct hdac_device *hdac, int pcm_idx, | 1831 | static void hdmi_get_chmap(struct hdac_device *hdac, int pcm_idx, |
2380 | unsigned char *chmap) | 1832 | unsigned char *chmap) |
2381 | { | 1833 | { |
@@ -2414,127 +1866,6 @@ static bool is_hdmi_pcm_attached(struct hdac_device *hdac, int pcm_idx) | |||
2414 | return per_pin ? true:false; | 1866 | return per_pin ? true:false; |
2415 | } | 1867 | } |
2416 | 1868 | ||
2417 | static int hdmi_chmap_ctl_tlv(struct snd_kcontrol *kcontrol, int op_flag, | ||
2418 | unsigned int size, unsigned int __user *tlv) | ||
2419 | { | ||
2420 | struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol); | ||
2421 | struct hdac_chmap *chmap = info->private_data; | ||
2422 | unsigned int __user *dst; | ||
2423 | int chs, count = 0; | ||
2424 | |||
2425 | if (size < 8) | ||
2426 | return -ENOMEM; | ||
2427 | if (put_user(SNDRV_CTL_TLVT_CONTAINER, tlv)) | ||
2428 | return -EFAULT; | ||
2429 | size -= 8; | ||
2430 | dst = tlv + 2; | ||
2431 | for (chs = 2; chs <= chmap->channels_max; chs++) { | ||
2432 | int i; | ||
2433 | struct hdac_cea_channel_speaker_allocation *cap; | ||
2434 | cap = channel_allocations; | ||
2435 | for (i = 0; i < ARRAY_SIZE(channel_allocations); i++, cap++) { | ||
2436 | int chs_bytes = chs * 4; | ||
2437 | int type = chmap->ops.chmap_cea_alloc_validate_get_type( | ||
2438 | chmap, cap, chs); | ||
2439 | unsigned int tlv_chmap[8]; | ||
2440 | |||
2441 | if (type < 0) | ||
2442 | continue; | ||
2443 | if (size < 8) | ||
2444 | return -ENOMEM; | ||
2445 | if (put_user(type, dst) || | ||
2446 | put_user(chs_bytes, dst + 1)) | ||
2447 | return -EFAULT; | ||
2448 | dst += 2; | ||
2449 | size -= 8; | ||
2450 | count += 8; | ||
2451 | if (size < chs_bytes) | ||
2452 | return -ENOMEM; | ||
2453 | size -= chs_bytes; | ||
2454 | count += chs_bytes; | ||
2455 | chmap->ops.cea_alloc_to_tlv_chmap(chmap, cap, | ||
2456 | tlv_chmap, chs); | ||
2457 | if (copy_to_user(dst, tlv_chmap, chs_bytes)) | ||
2458 | return -EFAULT; | ||
2459 | dst += chs; | ||
2460 | } | ||
2461 | } | ||
2462 | if (put_user(count, tlv + 1)) | ||
2463 | return -EFAULT; | ||
2464 | return 0; | ||
2465 | } | ||
2466 | |||
2467 | static int hdmi_chmap_ctl_get(struct snd_kcontrol *kcontrol, | ||
2468 | struct snd_ctl_elem_value *ucontrol) | ||
2469 | { | ||
2470 | struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol); | ||
2471 | struct hdac_chmap *chmap = info->private_data; | ||
2472 | int pcm_idx = kcontrol->private_value; | ||
2473 | unsigned char pcm_chmap[8]; | ||
2474 | int i; | ||
2475 | |||
2476 | memset(pcm_chmap, 0, sizeof(pcm_chmap)); | ||
2477 | chmap->ops.get_chmap(chmap->hdac, pcm_idx, pcm_chmap); | ||
2478 | |||
2479 | for (i = 0; i < sizeof(chmap); i++) | ||
2480 | ucontrol->value.integer.value[i] = pcm_chmap[i]; | ||
2481 | |||
2482 | return 0; | ||
2483 | } | ||
2484 | |||
2485 | static int hdmi_chmap_ctl_put(struct snd_kcontrol *kcontrol, | ||
2486 | struct snd_ctl_elem_value *ucontrol) | ||
2487 | { | ||
2488 | struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol); | ||
2489 | struct hdac_chmap *hchmap = info->private_data; | ||
2490 | int pcm_idx = kcontrol->private_value; | ||
2491 | unsigned int ctl_idx; | ||
2492 | struct snd_pcm_substream *substream; | ||
2493 | unsigned char chmap[8], per_pin_chmap[8]; | ||
2494 | int i, err, ca, prepared = 0; | ||
2495 | |||
2496 | /* No monitor is connected in dyn_pcm_assign. | ||
2497 | * It's invalid to setup the chmap | ||
2498 | */ | ||
2499 | if (!hchmap->ops.is_pcm_attached(hchmap->hdac, pcm_idx)) | ||
2500 | return 0; | ||
2501 | |||
2502 | ctl_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); | ||
2503 | substream = snd_pcm_chmap_substream(info, ctl_idx); | ||
2504 | if (!substream || !substream->runtime) | ||
2505 | return 0; /* just for avoiding error from alsactl restore */ | ||
2506 | switch (substream->runtime->status->state) { | ||
2507 | case SNDRV_PCM_STATE_OPEN: | ||
2508 | case SNDRV_PCM_STATE_SETUP: | ||
2509 | break; | ||
2510 | case SNDRV_PCM_STATE_PREPARED: | ||
2511 | prepared = 1; | ||
2512 | break; | ||
2513 | default: | ||
2514 | return -EBUSY; | ||
2515 | } | ||
2516 | memset(chmap, 0, sizeof(chmap)); | ||
2517 | for (i = 0; i < ARRAY_SIZE(chmap); i++) | ||
2518 | chmap[i] = ucontrol->value.integer.value[i]; | ||
2519 | |||
2520 | hchmap->ops.get_chmap(hchmap->hdac, pcm_idx, per_pin_chmap); | ||
2521 | if (!memcmp(chmap, per_pin_chmap, sizeof(chmap))) | ||
2522 | return 0; | ||
2523 | ca = hdmi_manual_channel_allocation(ARRAY_SIZE(chmap), chmap); | ||
2524 | if (ca < 0) | ||
2525 | return -EINVAL; | ||
2526 | if (hchmap->ops.chmap_validate) { | ||
2527 | err = hchmap->ops.chmap_validate(hchmap, ca, | ||
2528 | ARRAY_SIZE(chmap), chmap); | ||
2529 | if (err) | ||
2530 | return err; | ||
2531 | } | ||
2532 | |||
2533 | hchmap->ops.set_chmap(hchmap->hdac, pcm_idx, chmap, prepared); | ||
2534 | |||
2535 | return 0; | ||
2536 | } | ||
2537 | |||
2538 | static int generic_hdmi_build_pcms(struct hda_codec *codec) | 1869 | static int generic_hdmi_build_pcms(struct hda_codec *codec) |
2539 | { | 1870 | { |
2540 | struct hdmi_spec *spec = codec->spec; | 1871 | struct hdmi_spec *spec = codec->spec; |
@@ -2675,27 +2006,13 @@ static int generic_hdmi_build_controls(struct hda_codec *codec) | |||
2675 | /* add channel maps */ | 2006 | /* add channel maps */ |
2676 | for (pcm_idx = 0; pcm_idx < spec->pcm_used; pcm_idx++) { | 2007 | for (pcm_idx = 0; pcm_idx < spec->pcm_used; pcm_idx++) { |
2677 | struct hda_pcm *pcm; | 2008 | struct hda_pcm *pcm; |
2678 | struct snd_pcm_chmap *chmap; | ||
2679 | struct snd_kcontrol *kctl; | ||
2680 | int i; | ||
2681 | 2009 | ||
2682 | pcm = get_pcm_rec(spec, pcm_idx); | 2010 | pcm = get_pcm_rec(spec, pcm_idx); |
2683 | if (!pcm || !pcm->pcm) | 2011 | if (!pcm || !pcm->pcm) |
2684 | break; | 2012 | break; |
2685 | err = snd_pcm_add_chmap_ctls(pcm->pcm, | 2013 | err = snd_hdac_add_chmap_ctls(pcm->pcm, pcm_idx, &spec->chmap); |
2686 | SNDRV_PCM_STREAM_PLAYBACK, | ||
2687 | NULL, 0, pcm_idx, &chmap); | ||
2688 | if (err < 0) | 2014 | if (err < 0) |
2689 | return err; | 2015 | return err; |
2690 | /* override handlers */ | ||
2691 | chmap->private_data = &spec->chmap; | ||
2692 | kctl = chmap->kctl; | ||
2693 | for (i = 0; i < kctl->count; i++) | ||
2694 | kctl->vd[i].access |= SNDRV_CTL_ELEM_ACCESS_WRITE; | ||
2695 | kctl->info = hdmi_chmap_ctl_info; | ||
2696 | kctl->get = hdmi_chmap_ctl_get; | ||
2697 | kctl->put = hdmi_chmap_ctl_put; | ||
2698 | kctl->tlv.c = hdmi_chmap_ctl_tlv; | ||
2699 | } | 2016 | } |
2700 | 2017 | ||
2701 | return 0; | 2018 | return 0; |
@@ -2915,9 +2232,6 @@ static int patch_generic_hdmi(struct hda_codec *codec) | |||
2915 | mutex_init(&spec->pcm_lock); | 2232 | mutex_init(&spec->pcm_lock); |
2916 | snd_hdac_register_chmap_ops(&codec->core, &spec->chmap); | 2233 | snd_hdac_register_chmap_ops(&codec->core, &spec->chmap); |
2917 | 2234 | ||
2918 | spec->chmap.ops.chmap_cea_alloc_validate_get_type = | ||
2919 | hdmi_chmap_cea_alloc_validate_get_type; | ||
2920 | spec->chmap.ops.cea_alloc_to_tlv_chmap = hdmi_cea_alloc_to_tlv_chmap; | ||
2921 | spec->chmap.ops.get_chmap = hdmi_get_chmap; | 2235 | spec->chmap.ops.get_chmap = hdmi_get_chmap; |
2922 | spec->chmap.ops.set_chmap = hdmi_set_chmap; | 2236 | spec->chmap.ops.set_chmap = hdmi_set_chmap; |
2923 | spec->chmap.ops.is_pcm_attached = is_hdmi_pcm_attached; | 2237 | spec->chmap.ops.is_pcm_attached = is_hdmi_pcm_attached; |
@@ -2965,7 +2279,6 @@ static int patch_generic_hdmi(struct hda_codec *codec) | |||
2965 | 2279 | ||
2966 | generic_hdmi_init_per_pins(codec); | 2280 | generic_hdmi_init_per_pins(codec); |
2967 | 2281 | ||
2968 | init_channel_allocations(); | ||
2969 | 2282 | ||
2970 | if (codec_has_acomp(codec)) { | 2283 | if (codec_has_acomp(codec)) { |
2971 | codec->depop_delay = 0; | 2284 | codec->depop_delay = 0; |