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