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