diff options
Diffstat (limited to 'sound')
-rw-r--r-- | sound/pci/hda/patch_hdmi.c | 70 |
1 files changed, 41 insertions, 29 deletions
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 8bf526ea8cf..dab2af762d9 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -643,19 +643,27 @@ static void hdmi_std_setup_channel_mapping(struct hda_codec *codec, struct channel_map_table { unsigned char map; /* ALSA API channel map position */ - unsigned char cea_slot; /* CEA slot value */ int spk_mask; /* speaker position bit mask */ }; static struct channel_map_table map_tables[] = { - { SNDRV_CHMAP_FL, 0x00, FL }, - { SNDRV_CHMAP_FR, 0x01, FR }, - { SNDRV_CHMAP_RL, 0x04, RL }, - { SNDRV_CHMAP_RR, 0x05, RR }, - { SNDRV_CHMAP_LFE, 0x02, LFE }, - { SNDRV_CHMAP_FC, 0x03, FC }, - { SNDRV_CHMAP_RLC, 0x06, RLC }, - { SNDRV_CHMAP_RRC, 0x07, RRC }, + { SNDRV_CHMAP_FL, FL }, + { SNDRV_CHMAP_FR, FR }, + { SNDRV_CHMAP_RL, RL }, + { SNDRV_CHMAP_RR, RR }, + { SNDRV_CHMAP_LFE, LFE }, + { SNDRV_CHMAP_FC, FC }, + { SNDRV_CHMAP_RLC, RLC }, + { SNDRV_CHMAP_RRC, RRC }, + { SNDRV_CHMAP_RC, RC }, + { SNDRV_CHMAP_FLC, FLC }, + { SNDRV_CHMAP_FRC, FRC }, + { SNDRV_CHMAP_FLH, FLH }, + { SNDRV_CHMAP_FRH, FRH }, + { SNDRV_CHMAP_FLW, FLW }, + { SNDRV_CHMAP_FRW, FRW }, + { SNDRV_CHMAP_TC, TC }, + { SNDRV_CHMAP_FCH, FCH }, {} /* terminator */ }; @@ -671,25 +679,19 @@ static int to_spk_mask(unsigned char c) } /* from ALSA API channel position to CEA slot */ -static int to_cea_slot(unsigned char c) +static int to_cea_slot(int ordered_ca, unsigned char pos) { - struct channel_map_table *t = map_tables; - for (; t->map; t++) { - if (t->map == c) - return t->cea_slot; - } - return -1; -} + int mask = to_spk_mask(pos); + int i; -/* from CEA slot to ALSA API channel position */ -static int from_cea_slot(unsigned char c) -{ - struct channel_map_table *t = map_tables; - for (; t->map; t++) { - if (t->cea_slot == c) - return t->map; + if (mask) { + for (i = 0; i < 8; i++) { + if (channel_allocations[ordered_ca].speakers[7 - i] == mask) + return i; + } } - return 0; + + return -1; } /* from speaker bit mask to ALSA API channel position */ @@ -703,6 +705,14 @@ static int spk_to_chmap(int spk) return 0; } +/* from CEA slot to ALSA API channel position */ +static int from_cea_slot(int ordered_ca, unsigned char slot) +{ + int mask = channel_allocations[ordered_ca].speakers[7 - slot]; + + return spk_to_chmap(mask); +} + /* get the CA index corresponding to the given ALSA API channel map */ static int hdmi_manual_channel_allocation(int chs, unsigned char *map) { @@ -729,14 +739,16 @@ static int hdmi_manual_channel_allocation(int chs, unsigned char *map) /* set up the channel slots for the given ALSA API channel map */ static int hdmi_manual_setup_channel_mapping(struct hda_codec *codec, hda_nid_t pin_nid, - int chs, unsigned char *map) + int chs, unsigned char *map, + int ca) { + int ordered_ca = get_channel_allocation_order(ca); int alsa_pos, hdmi_slot; int assignments[8] = {[0 ... 7] = 0xf}; for (alsa_pos = 0; alsa_pos < chs; alsa_pos++) { - hdmi_slot = to_cea_slot(map[alsa_pos]); + hdmi_slot = to_cea_slot(ordered_ca, map[alsa_pos]); if (hdmi_slot < 0) continue; /* unassigned channel */ @@ -763,7 +775,7 @@ static void hdmi_setup_fake_chmap(unsigned char *map, int ca) int ordered_ca = get_channel_allocation_order(ca); for (i = 0; i < 8; i++) { if (i < channel_allocations[ordered_ca].channels) - map[i] = from_cea_slot(hdmi_channel_mapping[ca][i] & 0x0f); + map[i] = from_cea_slot(ordered_ca, hdmi_channel_mapping[ca][i] & 0x0f); else map[i] = 0; } @@ -776,7 +788,7 @@ static void hdmi_setup_channel_mapping(struct hda_codec *codec, { if (!non_pcm && chmap_set) { hdmi_manual_setup_channel_mapping(codec, pin_nid, - channels, map); + channels, map, ca); } else { hdmi_std_setup_channel_mapping(codec, pin_nid, non_pcm, ca); hdmi_setup_fake_chmap(map, ca); |