|
@@ -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);
|