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