linux/sound/hda/hdmi_chmap.c
<<
>>
Prefs
   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 (!WARN_ON(hdmi_slot >= 8) &&
 357                               !ch_alloc->speakers[7 - hdmi_slot])
 358                                hdmi_slot++; /* skip zero slots */
 359
 360                        hdmi_channel_mapping[ca][i] = (i << 4) | hdmi_slot++;
 361                }
 362                /* fill the rest of the slots with ALSA channel 0xf */
 363                for (hdmi_slot = 0; hdmi_slot < 8; hdmi_slot++)
 364                        if (!ch_alloc->speakers[7 - hdmi_slot])
 365                                hdmi_channel_mapping[ca][i++] = (0xf << 4) | hdmi_slot;
 366        }
 367
 368        if (non_pcm) {
 369                for (i = 0; i < ch_alloc->channels; i++)
 370                        non_pcm_mapping[i] = (i << 4) | i;
 371                for (; i < 8; i++)
 372                        non_pcm_mapping[i] = (0xf << 4) | i;
 373        }
 374
 375        for (i = 0; i < 8; i++) {
 376                int slotsetup = non_pcm ? non_pcm_mapping[i] : hdmi_channel_mapping[ca][i];
 377                int hdmi_slot = slotsetup & 0x0f;
 378                int channel = (slotsetup & 0xf0) >> 4;
 379
 380                err = chmap->ops.pin_set_slot_channel(chmap->hdac,
 381                                pin_nid, hdmi_slot, channel);
 382                if (err) {
 383                        dev_dbg(&chmap->hdac->dev, "HDMI: channel mapping failed\n");
 384                        break;
 385                }
 386        }
 387}
 388
 389struct channel_map_table {
 390        unsigned char map;              /* ALSA API channel map position */
 391        int spk_mask;                   /* speaker position bit mask */
 392};
 393
 394static struct channel_map_table map_tables[] = {
 395        { SNDRV_CHMAP_FL,       FL },
 396        { SNDRV_CHMAP_FR,       FR },
 397        { SNDRV_CHMAP_RL,       RL },
 398        { SNDRV_CHMAP_RR,       RR },
 399        { SNDRV_CHMAP_LFE,      LFE },
 400        { SNDRV_CHMAP_FC,       FC },
 401        { SNDRV_CHMAP_RLC,      RLC },
 402        { SNDRV_CHMAP_RRC,      RRC },
 403        { SNDRV_CHMAP_RC,       RC },
 404        { SNDRV_CHMAP_FLC,      FLC },
 405        { SNDRV_CHMAP_FRC,      FRC },
 406        { SNDRV_CHMAP_TFL,      FLH },
 407        { SNDRV_CHMAP_TFR,      FRH },
 408        { SNDRV_CHMAP_FLW,      FLW },
 409        { SNDRV_CHMAP_FRW,      FRW },
 410        { SNDRV_CHMAP_TC,       TC },
 411        { SNDRV_CHMAP_TFC,      FCH },
 412        {} /* terminator */
 413};
 414
 415/* from ALSA API channel position to speaker bit mask */
 416int snd_hdac_chmap_to_spk_mask(unsigned char c)
 417{
 418        struct channel_map_table *t = map_tables;
 419
 420        for (; t->map; t++) {
 421                if (t->map == c)
 422                        return t->spk_mask;
 423        }
 424        return 0;
 425}
 426EXPORT_SYMBOL_GPL(snd_hdac_chmap_to_spk_mask);
 427
 428/* from ALSA API channel position to CEA slot */
 429static int to_cea_slot(int ordered_ca, unsigned char pos)
 430{
 431        int mask = snd_hdac_chmap_to_spk_mask(pos);
 432        int i;
 433
 434        /* Add sanity check to pass klockwork check.
 435         * This should never happen.
 436         */
 437        if (ordered_ca >= ARRAY_SIZE(channel_allocations))
 438                return -1;
 439
 440        if (mask) {
 441                for (i = 0; i < 8; i++) {
 442                        if (channel_allocations[ordered_ca].speakers[7 - i] == mask)
 443                                return i;
 444                }
 445        }
 446
 447        return -1;
 448}
 449
 450/* from speaker bit mask to ALSA API channel position */
 451int snd_hdac_spk_to_chmap(int spk)
 452{
 453        struct channel_map_table *t = map_tables;
 454
 455        for (; t->map; t++) {
 456                if (t->spk_mask == spk)
 457                        return t->map;
 458        }
 459        return 0;
 460}
 461EXPORT_SYMBOL_GPL(snd_hdac_spk_to_chmap);
 462
 463/* from CEA slot to ALSA API channel position */
 464static int from_cea_slot(int ordered_ca, unsigned char slot)
 465{
 466        int mask;
 467
 468        /* Add sanity check to pass klockwork check.
 469         * This should never happen.
 470         */
 471        if (slot >= 8)
 472                return 0;
 473
 474        mask = channel_allocations[ordered_ca].speakers[7 - slot];
 475
 476        return snd_hdac_spk_to_chmap(mask);
 477}
 478
 479/* get the CA index corresponding to the given ALSA API channel map */
 480static int hdmi_manual_channel_allocation(int chs, unsigned char *map)
 481{
 482        int i, spks = 0, spk_mask = 0;
 483
 484        for (i = 0; i < chs; i++) {
 485                int mask = snd_hdac_chmap_to_spk_mask(map[i]);
 486
 487                if (mask) {
 488                        spk_mask |= mask;
 489                        spks++;
 490                }
 491        }
 492
 493        for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
 494                if ((chs == channel_allocations[i].channels ||
 495                     spks == channel_allocations[i].channels) &&
 496                    (spk_mask & channel_allocations[i].spk_mask) ==
 497                                channel_allocations[i].spk_mask)
 498                        return channel_allocations[i].ca_index;
 499        }
 500        return -1;
 501}
 502
 503/* set up the channel slots for the given ALSA API channel map */
 504static int hdmi_manual_setup_channel_mapping(struct hdac_chmap *chmap,
 505                                             hda_nid_t pin_nid,
 506                                             int chs, unsigned char *map,
 507                                             int ca)
 508{
 509        int ordered_ca = get_channel_allocation_order(ca);
 510        int alsa_pos, hdmi_slot;
 511        int assignments[8] = {[0 ... 7] = 0xf};
 512
 513        for (alsa_pos = 0; alsa_pos < chs; alsa_pos++) {
 514
 515                hdmi_slot = to_cea_slot(ordered_ca, map[alsa_pos]);
 516
 517                if (hdmi_slot < 0)
 518                        continue; /* unassigned channel */
 519
 520                assignments[hdmi_slot] = alsa_pos;
 521        }
 522
 523        for (hdmi_slot = 0; hdmi_slot < 8; hdmi_slot++) {
 524                int err;
 525
 526                err = chmap->ops.pin_set_slot_channel(chmap->hdac,
 527                                pin_nid, hdmi_slot, assignments[hdmi_slot]);
 528                if (err)
 529                        return -EINVAL;
 530        }
 531        return 0;
 532}
 533
 534/* store ALSA API channel map from the current default map */
 535static void hdmi_setup_fake_chmap(unsigned char *map, int ca)
 536{
 537        int i;
 538        int ordered_ca = get_channel_allocation_order(ca);
 539
 540        for (i = 0; i < 8; i++) {
 541                if (ordered_ca < ARRAY_SIZE(channel_allocations) &&
 542                    i < channel_allocations[ordered_ca].channels)
 543                        map[i] = from_cea_slot(ordered_ca, hdmi_channel_mapping[ca][i] & 0x0f);
 544                else
 545                        map[i] = 0;
 546        }
 547}
 548
 549void snd_hdac_setup_channel_mapping(struct hdac_chmap *chmap,
 550                                       hda_nid_t pin_nid, bool non_pcm, int ca,
 551                                       int channels, unsigned char *map,
 552                                       bool chmap_set)
 553{
 554        if (!non_pcm && chmap_set) {
 555                hdmi_manual_setup_channel_mapping(chmap, pin_nid,
 556                                                  channels, map, ca);
 557        } else {
 558                hdmi_std_setup_channel_mapping(chmap, pin_nid, non_pcm, ca);
 559                hdmi_setup_fake_chmap(map, ca);
 560        }
 561
 562        hdmi_debug_channel_mapping(chmap, pin_nid);
 563}
 564EXPORT_SYMBOL_GPL(snd_hdac_setup_channel_mapping);
 565
 566int snd_hdac_get_active_channels(int ca)
 567{
 568        int ordered_ca = get_channel_allocation_order(ca);
 569
 570        /* Add sanity check to pass klockwork check.
 571         * This should never happen.
 572         */
 573        if (ordered_ca >= ARRAY_SIZE(channel_allocations))
 574                ordered_ca = 0;
 575
 576        return channel_allocations[ordered_ca].channels;
 577}
 578EXPORT_SYMBOL_GPL(snd_hdac_get_active_channels);
 579
 580struct hdac_cea_channel_speaker_allocation *snd_hdac_get_ch_alloc_from_ca(int ca)
 581{
 582        return &channel_allocations[get_channel_allocation_order(ca)];
 583}
 584EXPORT_SYMBOL_GPL(snd_hdac_get_ch_alloc_from_ca);
 585
 586int snd_hdac_channel_allocation(struct hdac_device *hdac, int spk_alloc,
 587                int channels, bool chmap_set, bool non_pcm, unsigned char *map)
 588{
 589        int ca;
 590
 591        if (!non_pcm && chmap_set)
 592                ca = hdmi_manual_channel_allocation(channels, map);
 593        else
 594                ca = hdmi_channel_allocation_spk_alloc_blk(hdac,
 595                                        spk_alloc, channels);
 596
 597        if (ca < 0)
 598                ca = 0;
 599
 600        return ca;
 601}
 602EXPORT_SYMBOL_GPL(snd_hdac_channel_allocation);
 603
 604/*
 605 * ALSA API channel-map control callbacks
 606 */
 607static int hdmi_chmap_ctl_info(struct snd_kcontrol *kcontrol,
 608                               struct snd_ctl_elem_info *uinfo)
 609{
 610        struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol);
 611        struct hdac_chmap *chmap = info->private_data;
 612
 613        uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
 614        uinfo->count = chmap->channels_max;
 615        uinfo->value.integer.min = 0;
 616        uinfo->value.integer.max = SNDRV_CHMAP_LAST;
 617        return 0;
 618}
 619
 620static int hdmi_chmap_cea_alloc_validate_get_type(struct hdac_chmap *chmap,
 621                struct hdac_cea_channel_speaker_allocation *cap, int channels)
 622{
 623        /* If the speaker allocation matches the channel count, it is OK.*/
 624        if (cap->channels != channels)
 625                return -1;
 626
 627        /* all channels are remappable freely */
 628        return SNDRV_CTL_TLVT_CHMAP_VAR;
 629}
 630
 631static void hdmi_cea_alloc_to_tlv_chmap(struct hdac_chmap *hchmap,
 632                struct hdac_cea_channel_speaker_allocation *cap,
 633                unsigned int *chmap, int channels)
 634{
 635        int count = 0;
 636        int c;
 637
 638        for (c = 7; c >= 0; c--) {
 639                int spk = cap->speakers[c];
 640
 641                if (!spk)
 642                        continue;
 643
 644                chmap[count++] = snd_hdac_spk_to_chmap(spk);
 645        }
 646
 647        WARN_ON(count != channels);
 648}
 649
 650static int spk_mask_from_spk_alloc(int spk_alloc)
 651{
 652        int i;
 653        int spk_mask = eld_speaker_allocation_bits[0];
 654
 655        for (i = 0; i < ARRAY_SIZE(eld_speaker_allocation_bits); i++) {
 656                if (spk_alloc & (1 << i))
 657                        spk_mask |= eld_speaker_allocation_bits[i];
 658        }
 659
 660        return spk_mask;
 661}
 662
 663static int hdmi_chmap_ctl_tlv(struct snd_kcontrol *kcontrol, int op_flag,
 664                              unsigned int size, unsigned int __user *tlv)
 665{
 666        struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol);
 667        struct hdac_chmap *chmap = info->private_data;
 668        int pcm_idx = kcontrol->private_value;
 669        unsigned int __user *dst;
 670        int chs, count = 0;
 671        unsigned long max_chs;
 672        int type;
 673        int spk_alloc, spk_mask;
 674
 675        if (size < 8)
 676                return -ENOMEM;
 677        if (put_user(SNDRV_CTL_TLVT_CONTAINER, tlv))
 678                return -EFAULT;
 679        size -= 8;
 680        dst = tlv + 2;
 681
 682        spk_alloc = chmap->ops.get_spk_alloc(chmap->hdac, pcm_idx);
 683        spk_mask = spk_mask_from_spk_alloc(spk_alloc);
 684
 685        max_chs = hweight_long(spk_mask);
 686
 687        for (chs = 2; chs <= max_chs; chs++) {
 688                int i;
 689                struct hdac_cea_channel_speaker_allocation *cap;
 690
 691                cap = channel_allocations;
 692                for (i = 0; i < ARRAY_SIZE(channel_allocations); i++, cap++) {
 693                        int chs_bytes = chs * 4;
 694                        unsigned int tlv_chmap[8];
 695
 696                        if (cap->channels != chs)
 697                                continue;
 698
 699                        if (!(cap->spk_mask == (spk_mask & cap->spk_mask)))
 700                                continue;
 701
 702                        type = chmap->ops.chmap_cea_alloc_validate_get_type(
 703                                                        chmap, cap, chs);
 704                        if (type < 0)
 705                                return -ENODEV;
 706                        if (size < 8)
 707                                return -ENOMEM;
 708
 709                        if (put_user(type, dst) ||
 710                            put_user(chs_bytes, dst + 1))
 711                                return -EFAULT;
 712
 713                        dst += 2;
 714                        size -= 8;
 715                        count += 8;
 716
 717                        if (size < chs_bytes)
 718                                return -ENOMEM;
 719
 720                        size -= chs_bytes;
 721                        count += chs_bytes;
 722                        chmap->ops.cea_alloc_to_tlv_chmap(chmap, cap,
 723                                                tlv_chmap, chs);
 724
 725                        if (copy_to_user(dst, tlv_chmap, chs_bytes))
 726                                return -EFAULT;
 727                        dst += chs;
 728                }
 729        }
 730
 731        if (put_user(count, tlv + 1))
 732                return -EFAULT;
 733
 734        return 0;
 735}
 736
 737static int hdmi_chmap_ctl_get(struct snd_kcontrol *kcontrol,
 738                              struct snd_ctl_elem_value *ucontrol)
 739{
 740        struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol);
 741        struct hdac_chmap *chmap = info->private_data;
 742        int pcm_idx = kcontrol->private_value;
 743        unsigned char pcm_chmap[8];
 744        int i;
 745
 746        memset(pcm_chmap, 0, sizeof(pcm_chmap));
 747        chmap->ops.get_chmap(chmap->hdac, pcm_idx, pcm_chmap);
 748
 749        for (i = 0; i < sizeof(chmap); i++)
 750                ucontrol->value.integer.value[i] = pcm_chmap[i];
 751
 752        return 0;
 753}
 754
 755static int hdmi_chmap_ctl_put(struct snd_kcontrol *kcontrol,
 756                              struct snd_ctl_elem_value *ucontrol)
 757{
 758        struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol);
 759        struct hdac_chmap *hchmap = info->private_data;
 760        int pcm_idx = kcontrol->private_value;
 761        unsigned int ctl_idx;
 762        struct snd_pcm_substream *substream;
 763        unsigned char chmap[8], per_pin_chmap[8];
 764        int i, err, ca, prepared = 0;
 765
 766        /* No monitor is connected in dyn_pcm_assign.
 767         * It's invalid to setup the chmap
 768         */
 769        if (!hchmap->ops.is_pcm_attached(hchmap->hdac, pcm_idx))
 770                return 0;
 771
 772        ctl_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
 773        substream = snd_pcm_chmap_substream(info, ctl_idx);
 774        if (!substream || !substream->runtime)
 775                return 0; /* just for avoiding error from alsactl restore */
 776        switch (substream->runtime->status->state) {
 777        case SNDRV_PCM_STATE_OPEN:
 778        case SNDRV_PCM_STATE_SETUP:
 779                break;
 780        case SNDRV_PCM_STATE_PREPARED:
 781                prepared = 1;
 782                break;
 783        default:
 784                return -EBUSY;
 785        }
 786        memset(chmap, 0, sizeof(chmap));
 787        for (i = 0; i < ARRAY_SIZE(chmap); i++)
 788                chmap[i] = ucontrol->value.integer.value[i];
 789
 790        hchmap->ops.get_chmap(hchmap->hdac, pcm_idx, per_pin_chmap);
 791        if (!memcmp(chmap, per_pin_chmap, sizeof(chmap)))
 792                return 0;
 793        ca = hdmi_manual_channel_allocation(ARRAY_SIZE(chmap), chmap);
 794        if (ca < 0)
 795                return -EINVAL;
 796        if (hchmap->ops.chmap_validate) {
 797                err = hchmap->ops.chmap_validate(hchmap, ca,
 798                                ARRAY_SIZE(chmap), chmap);
 799                if (err)
 800                        return err;
 801        }
 802
 803        hchmap->ops.set_chmap(hchmap->hdac, pcm_idx, chmap, prepared);
 804
 805        return 0;
 806}
 807
 808static const struct hdac_chmap_ops chmap_ops = {
 809        .chmap_cea_alloc_validate_get_type      = hdmi_chmap_cea_alloc_validate_get_type,
 810        .cea_alloc_to_tlv_chmap                 = hdmi_cea_alloc_to_tlv_chmap,
 811        .pin_get_slot_channel                   = hdmi_pin_get_slot_channel,
 812        .pin_set_slot_channel                   = hdmi_pin_set_slot_channel,
 813        .set_channel_count                      = hdmi_set_channel_count,
 814};
 815
 816void snd_hdac_register_chmap_ops(struct hdac_device *hdac,
 817                                struct hdac_chmap *chmap)
 818{
 819        chmap->ops = chmap_ops;
 820        chmap->hdac = hdac;
 821        init_channel_allocations();
 822}
 823EXPORT_SYMBOL_GPL(snd_hdac_register_chmap_ops);
 824
 825int snd_hdac_add_chmap_ctls(struct snd_pcm *pcm, int pcm_idx,
 826                                struct hdac_chmap *hchmap)
 827{
 828        struct snd_pcm_chmap *chmap;
 829        struct snd_kcontrol *kctl;
 830        int err, i;
 831
 832        err = snd_pcm_add_chmap_ctls(pcm,
 833                                     SNDRV_PCM_STREAM_PLAYBACK,
 834                                     NULL, 0, pcm_idx, &chmap);
 835        if (err < 0)
 836                return err;
 837        /* override handlers */
 838        chmap->private_data = hchmap;
 839        kctl = chmap->kctl;
 840        for (i = 0; i < kctl->count; i++)
 841                kctl->vd[i].access |= SNDRV_CTL_ELEM_ACCESS_WRITE;
 842        kctl->info = hdmi_chmap_ctl_info;
 843        kctl->get = hdmi_chmap_ctl_get;
 844        kctl->put = hdmi_chmap_ctl_put;
 845        kctl->tlv.c = hdmi_chmap_ctl_tlv;
 846
 847        return 0;
 848}
 849EXPORT_SYMBOL_GPL(snd_hdac_add_chmap_ctls);
 850