linux/sound/pci/ctxfi/ctmixer.c
<<
>>
Prefs
   1/**
   2 * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
   3 *
   4 * This source file is released under GPL v2 license (no other versions).
   5 * See the COPYING file included in the main directory of this source
   6 * distribution for the license terms and conditions.
   7 *
   8 * @File        ctmixer.c
   9 *
  10 * @Brief
  11 * This file contains the implementation of alsa mixer device functions.
  12 *
  13 * @Author      Liu Chun
  14 * @Date        May 28 2008
  15 *
  16 */
  17
  18
  19#include "ctmixer.h"
  20#include "ctamixer.h"
  21#include <linux/slab.h>
  22#include <sound/core.h>
  23#include <sound/control.h>
  24#include <sound/asoundef.h>
  25#include <sound/pcm.h>
  26#include <sound/tlv.h>
  27
  28enum CT_SUM_CTL {
  29        SUM_IN_F,
  30        SUM_IN_R,
  31        SUM_IN_C,
  32        SUM_IN_S,
  33        SUM_IN_F_C,
  34
  35        NUM_CT_SUMS
  36};
  37
  38enum CT_AMIXER_CTL {
  39        /* volume control mixers */
  40        AMIXER_MASTER_F,
  41        AMIXER_MASTER_R,
  42        AMIXER_MASTER_C,
  43        AMIXER_MASTER_S,
  44        AMIXER_PCM_F,
  45        AMIXER_PCM_R,
  46        AMIXER_PCM_C,
  47        AMIXER_PCM_S,
  48        AMIXER_SPDIFI,
  49        AMIXER_LINEIN,
  50        AMIXER_MIC,
  51        AMIXER_SPDIFO,
  52        AMIXER_WAVE_F,
  53        AMIXER_WAVE_R,
  54        AMIXER_WAVE_C,
  55        AMIXER_WAVE_S,
  56        AMIXER_MASTER_F_C,
  57        AMIXER_PCM_F_C,
  58        AMIXER_SPDIFI_C,
  59        AMIXER_LINEIN_C,
  60        AMIXER_MIC_C,
  61
  62        /* this should always be the last one */
  63        NUM_CT_AMIXERS
  64};
  65
  66enum CTALSA_MIXER_CTL {
  67        /* volume control mixers */
  68        MIXER_MASTER_P,
  69        MIXER_PCM_P,
  70        MIXER_LINEIN_P,
  71        MIXER_MIC_P,
  72        MIXER_SPDIFI_P,
  73        MIXER_SPDIFO_P,
  74        MIXER_WAVEF_P,
  75        MIXER_WAVER_P,
  76        MIXER_WAVEC_P,
  77        MIXER_WAVES_P,
  78        MIXER_MASTER_C,
  79        MIXER_PCM_C,
  80        MIXER_LINEIN_C,
  81        MIXER_MIC_C,
  82        MIXER_SPDIFI_C,
  83
  84        /* switch control mixers */
  85        MIXER_PCM_C_S,
  86        MIXER_LINEIN_C_S,
  87        MIXER_MIC_C_S,
  88        MIXER_SPDIFI_C_S,
  89        MIXER_LINEIN_P_S,
  90        MIXER_SPDIFO_P_S,
  91        MIXER_SPDIFI_P_S,
  92        MIXER_WAVEF_P_S,
  93        MIXER_WAVER_P_S,
  94        MIXER_WAVEC_P_S,
  95        MIXER_WAVES_P_S,
  96        MIXER_DIGITAL_IO_S,
  97        MIXER_IEC958_MASK,
  98        MIXER_IEC958_DEFAULT,
  99        MIXER_IEC958_STREAM,
 100
 101        /* this should always be the last one */
 102        NUM_CTALSA_MIXERS
 103};
 104
 105#define VOL_MIXER_START         MIXER_MASTER_P
 106#define VOL_MIXER_END           MIXER_SPDIFI_C
 107#define VOL_MIXER_NUM           (VOL_MIXER_END - VOL_MIXER_START + 1)
 108#define SWH_MIXER_START         MIXER_PCM_C_S
 109#define SWH_MIXER_END           MIXER_DIGITAL_IO_S
 110#define SWH_CAPTURE_START       MIXER_PCM_C_S
 111#define SWH_CAPTURE_END         MIXER_SPDIFI_C_S
 112
 113#define CHN_NUM         2
 114
 115struct ct_kcontrol_init {
 116        unsigned char ctl;
 117        char *name;
 118};
 119
 120static struct ct_kcontrol_init
 121ct_kcontrol_init_table[NUM_CTALSA_MIXERS] = {
 122        [MIXER_MASTER_P] = {
 123                .ctl = 1,
 124                .name = "Master Playback Volume",
 125        },
 126        [MIXER_MASTER_C] = {
 127                .ctl = 1,
 128                .name = "Master Capture Volume",
 129        },
 130        [MIXER_PCM_P] = {
 131                .ctl = 1,
 132                .name = "PCM Playback Volume",
 133        },
 134        [MIXER_PCM_C] = {
 135                .ctl = 1,
 136                .name = "PCM Capture Volume",
 137        },
 138        [MIXER_LINEIN_P] = {
 139                .ctl = 1,
 140                .name = "Line-in Playback Volume",
 141        },
 142        [MIXER_LINEIN_C] = {
 143                .ctl = 1,
 144                .name = "Line-in Capture Volume",
 145        },
 146        [MIXER_MIC_P] = {
 147                .ctl = 1,
 148                .name = "Mic Playback Volume",
 149        },
 150        [MIXER_MIC_C] = {
 151                .ctl = 1,
 152                .name = "Mic Capture Volume",
 153        },
 154        [MIXER_SPDIFI_P] = {
 155                .ctl = 1,
 156                .name = "S/PDIF-in Playback Volume",
 157        },
 158        [MIXER_SPDIFI_C] = {
 159                .ctl = 1,
 160                .name = "S/PDIF-in Capture Volume",
 161        },
 162        [MIXER_SPDIFO_P] = {
 163                .ctl = 1,
 164                .name = "S/PDIF-out Playback Volume",
 165        },
 166        [MIXER_WAVEF_P] = {
 167                .ctl = 1,
 168                .name = "Front Playback Volume",
 169        },
 170        [MIXER_WAVES_P] = {
 171                .ctl = 1,
 172                .name = "Side Playback Volume",
 173        },
 174        [MIXER_WAVEC_P] = {
 175                .ctl = 1,
 176                .name = "Center/LFE Playback Volume",
 177        },
 178        [MIXER_WAVER_P] = {
 179                .ctl = 1,
 180                .name = "Surround Playback Volume",
 181        },
 182
 183        [MIXER_PCM_C_S] = {
 184                .ctl = 1,
 185                .name = "PCM Capture Switch",
 186        },
 187        [MIXER_LINEIN_C_S] = {
 188                .ctl = 1,
 189                .name = "Line-in Capture Switch",
 190        },
 191        [MIXER_MIC_C_S] = {
 192                .ctl = 1,
 193                .name = "Mic Capture Switch",
 194        },
 195        [MIXER_SPDIFI_C_S] = {
 196                .ctl = 1,
 197                .name = "S/PDIF-in Capture Switch",
 198        },
 199        [MIXER_LINEIN_P_S] = {
 200                .ctl = 1,
 201                .name = "Line-in Playback Switch",
 202        },
 203        [MIXER_SPDIFO_P_S] = {
 204                .ctl = 1,
 205                .name = "S/PDIF-out Playback Switch",
 206        },
 207        [MIXER_SPDIFI_P_S] = {
 208                .ctl = 1,
 209                .name = "S/PDIF-in Playback Switch",
 210        },
 211        [MIXER_WAVEF_P_S] = {
 212                .ctl = 1,
 213                .name = "Front Playback Switch",
 214        },
 215        [MIXER_WAVES_P_S] = {
 216                .ctl = 1,
 217                .name = "Side Playback Switch",
 218        },
 219        [MIXER_WAVEC_P_S] = {
 220                .ctl = 1,
 221                .name = "Center/LFE Playback Switch",
 222        },
 223        [MIXER_WAVER_P_S] = {
 224                .ctl = 1,
 225                .name = "Surround Playback Switch",
 226        },
 227        [MIXER_DIGITAL_IO_S] = {
 228                .ctl = 0,
 229                .name = "Digit-IO Playback Switch",
 230        },
 231};
 232
 233static void
 234ct_mixer_recording_select(struct ct_mixer *mixer, enum CT_AMIXER_CTL type);
 235
 236static void
 237ct_mixer_recording_unselect(struct ct_mixer *mixer, enum CT_AMIXER_CTL type);
 238
 239static struct snd_kcontrol *kctls[2] = {NULL};
 240
 241static enum CT_AMIXER_CTL get_amixer_index(enum CTALSA_MIXER_CTL alsa_index)
 242{
 243        switch (alsa_index) {
 244        case MIXER_MASTER_P:    return AMIXER_MASTER_F;
 245        case MIXER_MASTER_C:    return AMIXER_MASTER_F_C;
 246        case MIXER_PCM_P:       return AMIXER_PCM_F;
 247        case MIXER_PCM_C:
 248        case MIXER_PCM_C_S:     return AMIXER_PCM_F_C;
 249        case MIXER_LINEIN_P:    return AMIXER_LINEIN;
 250        case MIXER_LINEIN_C:
 251        case MIXER_LINEIN_C_S:  return AMIXER_LINEIN_C;
 252        case MIXER_MIC_P:       return AMIXER_MIC;
 253        case MIXER_MIC_C:
 254        case MIXER_MIC_C_S:     return AMIXER_MIC_C;
 255        case MIXER_SPDIFI_P:    return AMIXER_SPDIFI;
 256        case MIXER_SPDIFI_C:
 257        case MIXER_SPDIFI_C_S:  return AMIXER_SPDIFI_C;
 258        case MIXER_SPDIFO_P:    return AMIXER_SPDIFO;
 259        case MIXER_WAVEF_P:     return AMIXER_WAVE_F;
 260        case MIXER_WAVES_P:     return AMIXER_WAVE_S;
 261        case MIXER_WAVEC_P:     return AMIXER_WAVE_C;
 262        case MIXER_WAVER_P:     return AMIXER_WAVE_R;
 263        default:                return NUM_CT_AMIXERS;
 264        }
 265}
 266
 267static enum CT_AMIXER_CTL get_recording_amixer(enum CT_AMIXER_CTL index)
 268{
 269        switch (index) {
 270        case AMIXER_MASTER_F:   return AMIXER_MASTER_F_C;
 271        case AMIXER_PCM_F:      return AMIXER_PCM_F_C;
 272        case AMIXER_SPDIFI:     return AMIXER_SPDIFI_C;
 273        case AMIXER_LINEIN:     return AMIXER_LINEIN_C;
 274        case AMIXER_MIC:        return AMIXER_MIC_C;
 275        default:                return NUM_CT_AMIXERS;
 276        }
 277}
 278
 279static unsigned char
 280get_switch_state(struct ct_mixer *mixer, enum CTALSA_MIXER_CTL type)
 281{
 282        return (mixer->switch_state & (0x1 << (type - SWH_MIXER_START)))
 283                ? 1 : 0;
 284}
 285
 286static void
 287set_switch_state(struct ct_mixer *mixer,
 288                 enum CTALSA_MIXER_CTL type, unsigned char state)
 289{
 290        if (state)
 291                mixer->switch_state |= (0x1 << (type - SWH_MIXER_START));
 292        else
 293                mixer->switch_state &= ~(0x1 << (type - SWH_MIXER_START));
 294}
 295
 296#if 0 /* not used */
 297/* Map integer value ranging from 0 to 65535 to 14-bit float value ranging
 298 * from 2^-6 to (1+1023/1024) */
 299static unsigned int uint16_to_float14(unsigned int x)
 300{
 301        unsigned int i;
 302
 303        if (x < 17)
 304                return 0;
 305
 306        x *= 2031;
 307        x /= 65535;
 308        x += 16;
 309
 310        /* i <= 6 */
 311        for (i = 0; !(x & 0x400); i++)
 312                x <<= 1;
 313
 314        x = (((7 - i) & 0x7) << 10) | (x & 0x3ff);
 315
 316        return x;
 317}
 318
 319static unsigned int float14_to_uint16(unsigned int x)
 320{
 321        unsigned int e;
 322
 323        if (!x)
 324                return x;
 325
 326        e = (x >> 10) & 0x7;
 327        x &= 0x3ff;
 328        x += 1024;
 329        x >>= (7 - e);
 330        x -= 16;
 331        x *= 65535;
 332        x /= 2031;
 333
 334        return x;
 335}
 336#endif /* not used */
 337
 338#define VOL_SCALE       0x1c
 339#define VOL_MAX         0x100
 340
 341static const DECLARE_TLV_DB_SCALE(ct_vol_db_scale, -6400, 25, 1);
 342
 343static int ct_alsa_mix_volume_info(struct snd_kcontrol *kcontrol,
 344                                   struct snd_ctl_elem_info *uinfo)
 345{
 346        uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
 347        uinfo->count = 2;
 348        uinfo->value.integer.min = 0;
 349        uinfo->value.integer.max = VOL_MAX;
 350
 351        return 0;
 352}
 353
 354static int ct_alsa_mix_volume_get(struct snd_kcontrol *kcontrol,
 355                                  struct snd_ctl_elem_value *ucontrol)
 356{
 357        struct ct_atc *atc = snd_kcontrol_chip(kcontrol);
 358        enum CT_AMIXER_CTL type = get_amixer_index(kcontrol->private_value);
 359        struct amixer *amixer;
 360        int i, val;
 361
 362        for (i = 0; i < 2; i++) {
 363                amixer = ((struct ct_mixer *)atc->mixer)->
 364                                                amixers[type*CHN_NUM+i];
 365                val = amixer->ops->get_scale(amixer) / VOL_SCALE;
 366                if (val < 0)
 367                        val = 0;
 368                else if (val > VOL_MAX)
 369                        val = VOL_MAX;
 370                ucontrol->value.integer.value[i] = val;
 371        }
 372
 373        return 0;
 374}
 375
 376static int ct_alsa_mix_volume_put(struct snd_kcontrol *kcontrol,
 377                                  struct snd_ctl_elem_value *ucontrol)
 378{
 379        struct ct_atc *atc = snd_kcontrol_chip(kcontrol);
 380        struct ct_mixer *mixer = atc->mixer;
 381        enum CT_AMIXER_CTL type = get_amixer_index(kcontrol->private_value);
 382        struct amixer *amixer;
 383        int i, j, val, oval, change = 0;
 384
 385        for (i = 0; i < 2; i++) {
 386                val = ucontrol->value.integer.value[i];
 387                if (val < 0)
 388                        val = 0;
 389                else if (val > VOL_MAX)
 390                        val = VOL_MAX;
 391                val *= VOL_SCALE;
 392                amixer = mixer->amixers[type*CHN_NUM+i];
 393                oval = amixer->ops->get_scale(amixer);
 394                if (val != oval) {
 395                        amixer->ops->set_scale(amixer, val);
 396                        amixer->ops->commit_write(amixer);
 397                        change = 1;
 398                        /* Synchronize Master/PCM playback AMIXERs. */
 399                        if (AMIXER_MASTER_F == type || AMIXER_PCM_F == type) {
 400                                for (j = 1; j < 4; j++) {
 401                                        amixer = mixer->
 402                                                amixers[(type+j)*CHN_NUM+i];
 403                                        amixer->ops->set_scale(amixer, val);
 404                                        amixer->ops->commit_write(amixer);
 405                                }
 406                        }
 407                }
 408        }
 409
 410        return change;
 411}
 412
 413static struct snd_kcontrol_new vol_ctl = {
 414        .access         = SNDRV_CTL_ELEM_ACCESS_READWRITE |
 415                          SNDRV_CTL_ELEM_ACCESS_TLV_READ,
 416        .iface          = SNDRV_CTL_ELEM_IFACE_MIXER,
 417        .info           = ct_alsa_mix_volume_info,
 418        .get            = ct_alsa_mix_volume_get,
 419        .put            = ct_alsa_mix_volume_put,
 420        .tlv            = { .p =  ct_vol_db_scale },
 421};
 422
 423static void
 424do_line_mic_switch(struct ct_atc *atc, enum CTALSA_MIXER_CTL type)
 425{
 426
 427        if (MIXER_LINEIN_C_S == type) {
 428                atc->select_line_in(atc);
 429                set_switch_state(atc->mixer, MIXER_MIC_C_S, 0);
 430                snd_ctl_notify(atc->card, SNDRV_CTL_EVENT_MASK_VALUE,
 431                                                        &kctls[1]->id);
 432        } else if (MIXER_MIC_C_S == type) {
 433                atc->select_mic_in(atc);
 434                set_switch_state(atc->mixer, MIXER_LINEIN_C_S, 0);
 435                snd_ctl_notify(atc->card, SNDRV_CTL_EVENT_MASK_VALUE,
 436                                                        &kctls[0]->id);
 437        }
 438}
 439
 440static void
 441do_digit_io_switch(struct ct_atc *atc, int state)
 442{
 443        struct ct_mixer *mixer = atc->mixer;
 444
 445        if (state) {
 446                atc->select_digit_io(atc);
 447                atc->spdif_out_unmute(atc,
 448                                get_switch_state(mixer, MIXER_SPDIFO_P_S));
 449                atc->spdif_in_unmute(atc, 1);
 450                atc->line_in_unmute(atc, 0);
 451                return;
 452        }
 453
 454        if (get_switch_state(mixer, MIXER_LINEIN_C_S))
 455                atc->select_line_in(atc);
 456        else if (get_switch_state(mixer, MIXER_MIC_C_S))
 457                atc->select_mic_in(atc);
 458
 459        atc->spdif_out_unmute(atc, 0);
 460        atc->spdif_in_unmute(atc, 0);
 461        atc->line_in_unmute(atc, 1);
 462        return;
 463}
 464
 465static void do_switch(struct ct_atc *atc, enum CTALSA_MIXER_CTL type, int state)
 466{
 467        struct ct_mixer *mixer = atc->mixer;
 468
 469        /* Do changes in mixer. */
 470        if ((SWH_CAPTURE_START <= type) && (SWH_CAPTURE_END >= type)) {
 471                if (state) {
 472                        ct_mixer_recording_select(mixer,
 473                                                  get_amixer_index(type));
 474                } else {
 475                        ct_mixer_recording_unselect(mixer,
 476                                                    get_amixer_index(type));
 477                }
 478        }
 479        /* Do changes out of mixer. */
 480        if (state && (MIXER_LINEIN_C_S == type || MIXER_MIC_C_S == type))
 481                do_line_mic_switch(atc, type);
 482        else if (MIXER_WAVEF_P_S == type)
 483                atc->line_front_unmute(atc, state);
 484        else if (MIXER_WAVES_P_S == type)
 485                atc->line_surround_unmute(atc, state);
 486        else if (MIXER_WAVEC_P_S == type)
 487                atc->line_clfe_unmute(atc, state);
 488        else if (MIXER_WAVER_P_S == type)
 489                atc->line_rear_unmute(atc, state);
 490        else if (MIXER_LINEIN_P_S == type)
 491                atc->line_in_unmute(atc, state);
 492        else if (MIXER_SPDIFO_P_S == type)
 493                atc->spdif_out_unmute(atc, state);
 494        else if (MIXER_SPDIFI_P_S == type)
 495                atc->spdif_in_unmute(atc, state);
 496        else if (MIXER_DIGITAL_IO_S == type)
 497                do_digit_io_switch(atc, state);
 498
 499        return;
 500}
 501
 502static int ct_alsa_mix_switch_info(struct snd_kcontrol *kcontrol,
 503                                   struct snd_ctl_elem_info *uinfo)
 504{
 505        uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
 506        uinfo->count = 1;
 507        uinfo->value.integer.min = 0;
 508        uinfo->value.integer.max = 1;
 509        uinfo->value.integer.step = 1;
 510
 511        return 0;
 512}
 513
 514static int ct_alsa_mix_switch_get(struct snd_kcontrol *kcontrol,
 515                                  struct snd_ctl_elem_value *ucontrol)
 516{
 517        struct ct_mixer *mixer =
 518                ((struct ct_atc *)snd_kcontrol_chip(kcontrol))->mixer;
 519        enum CTALSA_MIXER_CTL type = kcontrol->private_value;
 520
 521        ucontrol->value.integer.value[0] = get_switch_state(mixer, type);
 522        return 0;
 523}
 524
 525static int ct_alsa_mix_switch_put(struct snd_kcontrol *kcontrol,
 526                                  struct snd_ctl_elem_value *ucontrol)
 527{
 528        struct ct_atc *atc = snd_kcontrol_chip(kcontrol);
 529        struct ct_mixer *mixer = atc->mixer;
 530        enum CTALSA_MIXER_CTL type = kcontrol->private_value;
 531        int state;
 532
 533        state = ucontrol->value.integer.value[0];
 534        if (get_switch_state(mixer, type) == state)
 535                return 0;
 536
 537        set_switch_state(mixer, type, state);
 538        do_switch(atc, type, state);
 539
 540        return 1;
 541}
 542
 543static struct snd_kcontrol_new swh_ctl = {
 544        .access         = SNDRV_CTL_ELEM_ACCESS_READWRITE,
 545        .iface          = SNDRV_CTL_ELEM_IFACE_MIXER,
 546        .info           = ct_alsa_mix_switch_info,
 547        .get            = ct_alsa_mix_switch_get,
 548        .put            = ct_alsa_mix_switch_put
 549};
 550
 551static int ct_spdif_info(struct snd_kcontrol *kcontrol,
 552                         struct snd_ctl_elem_info *uinfo)
 553{
 554        uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
 555        uinfo->count = 1;
 556        return 0;
 557}
 558
 559static int ct_spdif_get_mask(struct snd_kcontrol *kcontrol,
 560                             struct snd_ctl_elem_value *ucontrol)
 561{
 562        ucontrol->value.iec958.status[0] = 0xff;
 563        ucontrol->value.iec958.status[1] = 0xff;
 564        ucontrol->value.iec958.status[2] = 0xff;
 565        ucontrol->value.iec958.status[3] = 0xff;
 566        return 0;
 567}
 568
 569static int ct_spdif_get(struct snd_kcontrol *kcontrol,
 570                        struct snd_ctl_elem_value *ucontrol)
 571{
 572        struct ct_atc *atc = snd_kcontrol_chip(kcontrol);
 573        unsigned int status;
 574
 575        atc->spdif_out_get_status(atc, &status);
 576
 577        if (status == 0)
 578                status = SNDRV_PCM_DEFAULT_CON_SPDIF;
 579
 580        ucontrol->value.iec958.status[0] = (status >> 0) & 0xff;
 581        ucontrol->value.iec958.status[1] = (status >> 8) & 0xff;
 582        ucontrol->value.iec958.status[2] = (status >> 16) & 0xff;
 583        ucontrol->value.iec958.status[3] = (status >> 24) & 0xff;
 584
 585        return 0;
 586}
 587
 588static int ct_spdif_put(struct snd_kcontrol *kcontrol,
 589                        struct snd_ctl_elem_value *ucontrol)
 590{
 591        struct ct_atc *atc = snd_kcontrol_chip(kcontrol);
 592        int change;
 593        unsigned int status, old_status;
 594
 595        status = (ucontrol->value.iec958.status[0] << 0) |
 596                 (ucontrol->value.iec958.status[1] << 8) |
 597                 (ucontrol->value.iec958.status[2] << 16) |
 598                 (ucontrol->value.iec958.status[3] << 24);
 599
 600        atc->spdif_out_get_status(atc, &old_status);
 601        change = (old_status != status);
 602        if (change)
 603                atc->spdif_out_set_status(atc, status);
 604
 605        return change;
 606}
 607
 608static struct snd_kcontrol_new iec958_mask_ctl = {
 609        .access         = SNDRV_CTL_ELEM_ACCESS_READ,
 610        .iface          = SNDRV_CTL_ELEM_IFACE_PCM,
 611        .name           = SNDRV_CTL_NAME_IEC958("", PLAYBACK, MASK),
 612        .count          = 1,
 613        .info           = ct_spdif_info,
 614        .get            = ct_spdif_get_mask,
 615        .private_value  = MIXER_IEC958_MASK
 616};
 617
 618static struct snd_kcontrol_new iec958_default_ctl = {
 619        .iface          = SNDRV_CTL_ELEM_IFACE_PCM,
 620        .name           = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT),
 621        .count          = 1,
 622        .info           = ct_spdif_info,
 623        .get            = ct_spdif_get,
 624        .put            = ct_spdif_put,
 625        .private_value  = MIXER_IEC958_DEFAULT
 626};
 627
 628static struct snd_kcontrol_new iec958_ctl = {
 629        .access         = SNDRV_CTL_ELEM_ACCESS_READWRITE,
 630        .iface          = SNDRV_CTL_ELEM_IFACE_PCM,
 631        .name           = SNDRV_CTL_NAME_IEC958("", PLAYBACK, PCM_STREAM),
 632        .count          = 1,
 633        .info           = ct_spdif_info,
 634        .get            = ct_spdif_get,
 635        .put            = ct_spdif_put,
 636        .private_value  = MIXER_IEC958_STREAM
 637};
 638
 639#define NUM_IEC958_CTL 3
 640
 641static int
 642ct_mixer_kcontrol_new(struct ct_mixer *mixer, struct snd_kcontrol_new *new)
 643{
 644        struct snd_kcontrol *kctl;
 645        int err;
 646
 647        kctl = snd_ctl_new1(new, mixer->atc);
 648        if (!kctl)
 649                return -ENOMEM;
 650
 651        if (SNDRV_CTL_ELEM_IFACE_PCM == kctl->id.iface)
 652                kctl->id.device = IEC958;
 653
 654        err = snd_ctl_add(mixer->atc->card, kctl);
 655        if (err)
 656                return err;
 657
 658        switch (new->private_value) {
 659        case MIXER_LINEIN_C_S:
 660                kctls[0] = kctl; break;
 661        case MIXER_MIC_C_S:
 662                kctls[1] = kctl; break;
 663        default:
 664                break;
 665        }
 666
 667        return 0;
 668}
 669
 670static int ct_mixer_kcontrols_create(struct ct_mixer *mixer)
 671{
 672        enum CTALSA_MIXER_CTL type;
 673        struct ct_atc *atc = mixer->atc;
 674        int err;
 675
 676        /* Create snd kcontrol instances on demand */
 677        for (type = VOL_MIXER_START; type <= VOL_MIXER_END; type++) {
 678                if (ct_kcontrol_init_table[type].ctl) {
 679                        vol_ctl.name = ct_kcontrol_init_table[type].name;
 680                        vol_ctl.private_value = (unsigned long)type;
 681                        err = ct_mixer_kcontrol_new(mixer, &vol_ctl);
 682                        if (err)
 683                                return err;
 684                }
 685        }
 686
 687        ct_kcontrol_init_table[MIXER_DIGITAL_IO_S].ctl =
 688                                        atc->have_digit_io_switch(atc);
 689        for (type = SWH_MIXER_START; type <= SWH_MIXER_END; type++) {
 690                if (ct_kcontrol_init_table[type].ctl) {
 691                        swh_ctl.name = ct_kcontrol_init_table[type].name;
 692                        swh_ctl.private_value = (unsigned long)type;
 693                        err = ct_mixer_kcontrol_new(mixer, &swh_ctl);
 694                        if (err)
 695                                return err;
 696                }
 697        }
 698
 699        err = ct_mixer_kcontrol_new(mixer, &iec958_mask_ctl);
 700        if (err)
 701                return err;
 702
 703        err = ct_mixer_kcontrol_new(mixer, &iec958_default_ctl);
 704        if (err)
 705                return err;
 706
 707        err = ct_mixer_kcontrol_new(mixer, &iec958_ctl);
 708        if (err)
 709                return err;
 710
 711        atc->line_front_unmute(atc, 1);
 712        set_switch_state(mixer, MIXER_WAVEF_P_S, 1);
 713        atc->line_surround_unmute(atc, 0);
 714        set_switch_state(mixer, MIXER_WAVES_P_S, 0);
 715        atc->line_clfe_unmute(atc, 0);
 716        set_switch_state(mixer, MIXER_WAVEC_P_S, 0);
 717        atc->line_rear_unmute(atc, 0);
 718        set_switch_state(mixer, MIXER_WAVER_P_S, 0);
 719        atc->spdif_out_unmute(atc, 0);
 720        set_switch_state(mixer, MIXER_SPDIFO_P_S, 0);
 721        atc->line_in_unmute(atc, 0);
 722        set_switch_state(mixer, MIXER_LINEIN_P_S, 0);
 723        atc->spdif_in_unmute(atc, 0);
 724        set_switch_state(mixer, MIXER_SPDIFI_P_S, 0);
 725
 726        set_switch_state(mixer, MIXER_PCM_C_S, 1);
 727        set_switch_state(mixer, MIXER_LINEIN_C_S, 1);
 728        set_switch_state(mixer, MIXER_SPDIFI_C_S, 1);
 729
 730        return 0;
 731}
 732
 733static void
 734ct_mixer_recording_select(struct ct_mixer *mixer, enum CT_AMIXER_CTL type)
 735{
 736        struct amixer *amix_d;
 737        struct sum *sum_c;
 738        int i;
 739
 740        for (i = 0; i < 2; i++) {
 741                amix_d = mixer->amixers[type*CHN_NUM+i];
 742                sum_c = mixer->sums[SUM_IN_F_C*CHN_NUM+i];
 743                amix_d->ops->set_sum(amix_d, sum_c);
 744                amix_d->ops->commit_write(amix_d);
 745        }
 746}
 747
 748static void
 749ct_mixer_recording_unselect(struct ct_mixer *mixer, enum CT_AMIXER_CTL type)
 750{
 751        struct amixer *amix_d;
 752        int i;
 753
 754        for (i = 0; i < 2; i++) {
 755                amix_d = mixer->amixers[type*CHN_NUM+i];
 756                amix_d->ops->set_sum(amix_d, NULL);
 757                amix_d->ops->commit_write(amix_d);
 758        }
 759}
 760
 761static int ct_mixer_get_resources(struct ct_mixer *mixer)
 762{
 763        struct sum_mgr *sum_mgr;
 764        struct sum *sum;
 765        struct sum_desc sum_desc = {0};
 766        struct amixer_mgr *amixer_mgr;
 767        struct amixer *amixer;
 768        struct amixer_desc am_desc = {0};
 769        int err;
 770        int i;
 771
 772        /* Allocate sum resources for mixer obj */
 773        sum_mgr = (struct sum_mgr *)mixer->atc->rsc_mgrs[SUM];
 774        sum_desc.msr = mixer->atc->msr;
 775        for (i = 0; i < (NUM_CT_SUMS * CHN_NUM); i++) {
 776                err = sum_mgr->get_sum(sum_mgr, &sum_desc, &sum);
 777                if (err) {
 778                        printk(KERN_ERR "ctxfi:Failed to get sum resources for "
 779                                          "front output!\n");
 780                        break;
 781                }
 782                mixer->sums[i] = sum;
 783        }
 784        if (err)
 785                goto error1;
 786
 787        /* Allocate amixer resources for mixer obj */
 788        amixer_mgr = (struct amixer_mgr *)mixer->atc->rsc_mgrs[AMIXER];
 789        am_desc.msr = mixer->atc->msr;
 790        for (i = 0; i < (NUM_CT_AMIXERS * CHN_NUM); i++) {
 791                err = amixer_mgr->get_amixer(amixer_mgr, &am_desc, &amixer);
 792                if (err) {
 793                        printk(KERN_ERR "ctxfi:Failed to get amixer resources "
 794                               "for mixer obj!\n");
 795                        break;
 796                }
 797                mixer->amixers[i] = amixer;
 798        }
 799        if (err)
 800                goto error2;
 801
 802        return 0;
 803
 804error2:
 805        for (i = 0; i < (NUM_CT_AMIXERS * CHN_NUM); i++) {
 806                if (NULL != mixer->amixers[i]) {
 807                        amixer = mixer->amixers[i];
 808                        amixer_mgr->put_amixer(amixer_mgr, amixer);
 809                        mixer->amixers[i] = NULL;
 810                }
 811        }
 812error1:
 813        for (i = 0; i < (NUM_CT_SUMS * CHN_NUM); i++) {
 814                if (NULL != mixer->sums[i]) {
 815                        sum_mgr->put_sum(sum_mgr, (struct sum *)mixer->sums[i]);
 816                        mixer->sums[i] = NULL;
 817                }
 818        }
 819
 820        return err;
 821}
 822
 823static int ct_mixer_get_mem(struct ct_mixer **rmixer)
 824{
 825        struct ct_mixer *mixer;
 826        int err;
 827
 828        *rmixer = NULL;
 829        /* Allocate mem for mixer obj */
 830        mixer = kzalloc(sizeof(*mixer), GFP_KERNEL);
 831        if (!mixer)
 832                return -ENOMEM;
 833
 834        mixer->amixers = kzalloc(sizeof(void *)*(NUM_CT_AMIXERS*CHN_NUM),
 835                                 GFP_KERNEL);
 836        if (!mixer->amixers) {
 837                err = -ENOMEM;
 838                goto error1;
 839        }
 840        mixer->sums = kzalloc(sizeof(void *)*(NUM_CT_SUMS*CHN_NUM), GFP_KERNEL);
 841        if (!mixer->sums) {
 842                err = -ENOMEM;
 843                goto error2;
 844        }
 845
 846        *rmixer = mixer;
 847        return 0;
 848
 849error2:
 850        kfree(mixer->amixers);
 851error1:
 852        kfree(mixer);
 853        return err;
 854}
 855
 856static int ct_mixer_topology_build(struct ct_mixer *mixer)
 857{
 858        struct sum *sum;
 859        struct amixer *amix_d, *amix_s;
 860        enum CT_AMIXER_CTL i, j;
 861
 862        /* Build topology from destination to source */
 863
 864        /* Set up Master mixer */
 865        for (i = AMIXER_MASTER_F, j = SUM_IN_F;
 866                                        i <= AMIXER_MASTER_S; i++, j++) {
 867                amix_d = mixer->amixers[i*CHN_NUM];
 868                sum = mixer->sums[j*CHN_NUM];
 869                amix_d->ops->setup(amix_d, &sum->rsc, INIT_VOL, NULL);
 870                amix_d = mixer->amixers[i*CHN_NUM+1];
 871                sum = mixer->sums[j*CHN_NUM+1];
 872                amix_d->ops->setup(amix_d, &sum->rsc, INIT_VOL, NULL);
 873        }
 874
 875        /* Set up Wave-out mixer */
 876        for (i = AMIXER_WAVE_F, j = AMIXER_MASTER_F;
 877                                        i <= AMIXER_WAVE_S; i++, j++) {
 878                amix_d = mixer->amixers[i*CHN_NUM];
 879                amix_s = mixer->amixers[j*CHN_NUM];
 880                amix_d->ops->setup(amix_d, &amix_s->rsc, INIT_VOL, NULL);
 881                amix_d = mixer->amixers[i*CHN_NUM+1];
 882                amix_s = mixer->amixers[j*CHN_NUM+1];
 883                amix_d->ops->setup(amix_d, &amix_s->rsc, INIT_VOL, NULL);
 884        }
 885
 886        /* Set up S/PDIF-out mixer */
 887        amix_d = mixer->amixers[AMIXER_SPDIFO*CHN_NUM];
 888        amix_s = mixer->amixers[AMIXER_MASTER_F*CHN_NUM];
 889        amix_d->ops->setup(amix_d, &amix_s->rsc, INIT_VOL, NULL);
 890        amix_d = mixer->amixers[AMIXER_SPDIFO*CHN_NUM+1];
 891        amix_s = mixer->amixers[AMIXER_MASTER_F*CHN_NUM+1];
 892        amix_d->ops->setup(amix_d, &amix_s->rsc, INIT_VOL, NULL);
 893
 894        /* Set up PCM-in mixer */
 895        for (i = AMIXER_PCM_F, j = SUM_IN_F; i <= AMIXER_PCM_S; i++, j++) {
 896                amix_d = mixer->amixers[i*CHN_NUM];
 897                sum = mixer->sums[j*CHN_NUM];
 898                amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
 899                amix_d = mixer->amixers[i*CHN_NUM+1];
 900                sum = mixer->sums[j*CHN_NUM+1];
 901                amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
 902        }
 903
 904        /* Set up Line-in mixer */
 905        amix_d = mixer->amixers[AMIXER_LINEIN*CHN_NUM];
 906        sum = mixer->sums[SUM_IN_F*CHN_NUM];
 907        amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
 908        amix_d = mixer->amixers[AMIXER_LINEIN*CHN_NUM+1];
 909        sum = mixer->sums[SUM_IN_F*CHN_NUM+1];
 910        amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
 911
 912        /* Set up Mic-in mixer */
 913        amix_d = mixer->amixers[AMIXER_MIC*CHN_NUM];
 914        sum = mixer->sums[SUM_IN_F*CHN_NUM];
 915        amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
 916        amix_d = mixer->amixers[AMIXER_MIC*CHN_NUM+1];
 917        sum = mixer->sums[SUM_IN_F*CHN_NUM+1];
 918        amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
 919
 920        /* Set up S/PDIF-in mixer */
 921        amix_d = mixer->amixers[AMIXER_SPDIFI*CHN_NUM];
 922        sum = mixer->sums[SUM_IN_F*CHN_NUM];
 923        amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
 924        amix_d = mixer->amixers[AMIXER_SPDIFI*CHN_NUM+1];
 925        sum = mixer->sums[SUM_IN_F*CHN_NUM+1];
 926        amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
 927
 928        /* Set up Master recording mixer */
 929        amix_d = mixer->amixers[AMIXER_MASTER_F_C*CHN_NUM];
 930        sum = mixer->sums[SUM_IN_F_C*CHN_NUM];
 931        amix_d->ops->setup(amix_d, &sum->rsc, INIT_VOL, NULL);
 932        amix_d = mixer->amixers[AMIXER_MASTER_F_C*CHN_NUM+1];
 933        sum = mixer->sums[SUM_IN_F_C*CHN_NUM+1];
 934        amix_d->ops->setup(amix_d, &sum->rsc, INIT_VOL, NULL);
 935
 936        /* Set up PCM-in recording mixer */
 937        amix_d = mixer->amixers[AMIXER_PCM_F_C*CHN_NUM];
 938        sum = mixer->sums[SUM_IN_F_C*CHN_NUM];
 939        amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
 940        amix_d = mixer->amixers[AMIXER_PCM_F_C*CHN_NUM+1];
 941        sum = mixer->sums[SUM_IN_F_C*CHN_NUM+1];
 942        amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
 943
 944        /* Set up Line-in recording mixer */
 945        amix_d = mixer->amixers[AMIXER_LINEIN_C*CHN_NUM];
 946        sum = mixer->sums[SUM_IN_F_C*CHN_NUM];
 947        amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
 948        amix_d = mixer->amixers[AMIXER_LINEIN_C*CHN_NUM+1];
 949        sum = mixer->sums[SUM_IN_F_C*CHN_NUM+1];
 950        amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
 951
 952        /* Set up Mic-in recording mixer */
 953        amix_d = mixer->amixers[AMIXER_MIC_C*CHN_NUM];
 954        sum = mixer->sums[SUM_IN_F_C*CHN_NUM];
 955        amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
 956        amix_d = mixer->amixers[AMIXER_MIC_C*CHN_NUM+1];
 957        sum = mixer->sums[SUM_IN_F_C*CHN_NUM+1];
 958        amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
 959
 960        /* Set up S/PDIF-in recording mixer */
 961        amix_d = mixer->amixers[AMIXER_SPDIFI_C*CHN_NUM];
 962        sum = mixer->sums[SUM_IN_F_C*CHN_NUM];
 963        amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
 964        amix_d = mixer->amixers[AMIXER_SPDIFI_C*CHN_NUM+1];
 965        sum = mixer->sums[SUM_IN_F_C*CHN_NUM+1];
 966        amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
 967
 968        return 0;
 969}
 970
 971static int mixer_set_input_port(struct amixer *amixer, struct rsc *rsc)
 972{
 973        amixer->ops->set_input(amixer, rsc);
 974        amixer->ops->commit_write(amixer);
 975
 976        return 0;
 977}
 978
 979static enum CT_AMIXER_CTL port_to_amixer(enum MIXER_PORT_T type)
 980{
 981        switch (type) {
 982        case MIX_WAVE_FRONT:    return AMIXER_WAVE_F;
 983        case MIX_WAVE_SURROUND: return AMIXER_WAVE_S;
 984        case MIX_WAVE_CENTLFE:  return AMIXER_WAVE_C;
 985        case MIX_WAVE_REAR:     return AMIXER_WAVE_R;
 986        case MIX_PCMO_FRONT:    return AMIXER_MASTER_F_C;
 987        case MIX_SPDIF_OUT:     return AMIXER_SPDIFO;
 988        case MIX_LINE_IN:       return AMIXER_LINEIN;
 989        case MIX_MIC_IN:        return AMIXER_MIC;
 990        case MIX_SPDIF_IN:      return AMIXER_SPDIFI;
 991        case MIX_PCMI_FRONT:    return AMIXER_PCM_F;
 992        case MIX_PCMI_SURROUND: return AMIXER_PCM_S;
 993        case MIX_PCMI_CENTLFE:  return AMIXER_PCM_C;
 994        case MIX_PCMI_REAR:     return AMIXER_PCM_R;
 995        default:                return 0;
 996        }
 997}
 998
 999static int mixer_get_output_ports(struct ct_mixer *mixer,
1000                                  enum MIXER_PORT_T type,
1001                                  struct rsc **rleft, struct rsc **rright)
1002{
1003        enum CT_AMIXER_CTL amix = port_to_amixer(type);
1004
1005        if (NULL != rleft)
1006                *rleft = &((struct amixer *)mixer->amixers[amix*CHN_NUM])->rsc;
1007
1008        if (NULL != rright)
1009                *rright =
1010                        &((struct amixer *)mixer->amixers[amix*CHN_NUM+1])->rsc;
1011
1012        return 0;
1013}
1014
1015static int mixer_set_input_left(struct ct_mixer *mixer,
1016                                enum MIXER_PORT_T type, struct rsc *rsc)
1017{
1018        enum CT_AMIXER_CTL amix = port_to_amixer(type);
1019
1020        mixer_set_input_port(mixer->amixers[amix*CHN_NUM], rsc);
1021        amix = get_recording_amixer(amix);
1022        if (amix < NUM_CT_AMIXERS)
1023                mixer_set_input_port(mixer->amixers[amix*CHN_NUM], rsc);
1024
1025        return 0;
1026}
1027
1028static int
1029mixer_set_input_right(struct ct_mixer *mixer,
1030                      enum MIXER_PORT_T type, struct rsc *rsc)
1031{
1032        enum CT_AMIXER_CTL amix = port_to_amixer(type);
1033
1034        mixer_set_input_port(mixer->amixers[amix*CHN_NUM+1], rsc);
1035        amix = get_recording_amixer(amix);
1036        if (amix < NUM_CT_AMIXERS)
1037                mixer_set_input_port(mixer->amixers[amix*CHN_NUM+1], rsc);
1038
1039        return 0;
1040}
1041
1042#ifdef CONFIG_PM
1043static int mixer_resume(struct ct_mixer *mixer)
1044{
1045        int i, state;
1046        struct amixer *amixer;
1047
1048        /* resume topology and volume gain. */
1049        for (i = 0; i < NUM_CT_AMIXERS*CHN_NUM; i++) {
1050                amixer = mixer->amixers[i];
1051                amixer->ops->commit_write(amixer);
1052        }
1053
1054        /* resume switch state. */
1055        for (i = SWH_MIXER_START; i <= SWH_MIXER_END; i++) {
1056                state = get_switch_state(mixer, i);
1057                do_switch(mixer->atc, i, state);
1058        }
1059
1060        return 0;
1061}
1062#endif
1063
1064int ct_mixer_destroy(struct ct_mixer *mixer)
1065{
1066        struct sum_mgr *sum_mgr = (struct sum_mgr *)mixer->atc->rsc_mgrs[SUM];
1067        struct amixer_mgr *amixer_mgr =
1068                        (struct amixer_mgr *)mixer->atc->rsc_mgrs[AMIXER];
1069        struct amixer *amixer;
1070        int i = 0;
1071
1072        /* Release amixer resources */
1073        for (i = 0; i < (NUM_CT_AMIXERS * CHN_NUM); i++) {
1074                if (NULL != mixer->amixers[i]) {
1075                        amixer = mixer->amixers[i];
1076                        amixer_mgr->put_amixer(amixer_mgr, amixer);
1077                }
1078        }
1079
1080        /* Release sum resources */
1081        for (i = 0; i < (NUM_CT_SUMS * CHN_NUM); i++) {
1082                if (NULL != mixer->sums[i])
1083                        sum_mgr->put_sum(sum_mgr, (struct sum *)mixer->sums[i]);
1084        }
1085
1086        /* Release mem assigned to mixer object */
1087        kfree(mixer->sums);
1088        kfree(mixer->amixers);
1089        kfree(mixer);
1090
1091        return 0;
1092}
1093
1094int ct_mixer_create(struct ct_atc *atc, struct ct_mixer **rmixer)
1095{
1096        struct ct_mixer *mixer;
1097        int err;
1098
1099        *rmixer = NULL;
1100
1101        /* Allocate mem for mixer obj */
1102        err = ct_mixer_get_mem(&mixer);
1103        if (err)
1104                return err;
1105
1106        mixer->switch_state = 0;
1107        mixer->atc = atc;
1108        /* Set operations */
1109        mixer->get_output_ports = mixer_get_output_ports;
1110        mixer->set_input_left = mixer_set_input_left;
1111        mixer->set_input_right = mixer_set_input_right;
1112#ifdef CONFIG_PM
1113        mixer->resume = mixer_resume;
1114#endif
1115
1116        /* Allocate chip resources for mixer obj */
1117        err = ct_mixer_get_resources(mixer);
1118        if (err)
1119                goto error;
1120
1121        /* Build internal mixer topology */
1122        ct_mixer_topology_build(mixer);
1123
1124        *rmixer = mixer;
1125
1126        return 0;
1127
1128error:
1129        ct_mixer_destroy(mixer);
1130        return err;
1131}
1132
1133int ct_alsa_mix_create(struct ct_atc *atc,
1134                       enum CTALSADEVS device,
1135                       const char *device_name)
1136{
1137        int err;
1138
1139        /* Create snd kcontrol instances on demand */
1140        /* vol_ctl.device = swh_ctl.device = device; */ /* better w/ device 0 */
1141        err = ct_mixer_kcontrols_create((struct ct_mixer *)atc->mixer);
1142        if (err)
1143                return err;
1144
1145        strcpy(atc->card->mixername, device_name);
1146
1147        return 0;
1148}
1149