linux/drivers/staging/intel_sst/intelmid_ctrl.c
<<
>>
Prefs
   1/*
   2 *  intelmid_ctrl.c - Intel Sound card driver for MID
   3 *
   4 *  Copyright (C) 2008-10 Intel Corp
   5 *  Authors:    Harsha Priya <priya.harsha@intel.com>
   6 *              Vinod Koul <vinod.koul@intel.com>
   7 *              Dharageswari R <dharageswari.r@intel.com>
   8 *              KP Jeeja <jeeja.kp@intel.com>
   9 *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  10 *
  11 *  This program is free software; you can redistribute it and/or modify
  12 *  it under the terms of the GNU General Public License as published by
  13 *  the Free Software Foundation version 2 of the License.
  14 *
  15 *  This program is distributed in the hope that it will be useful, but
  16 *  WITHOUT ANY WARRANTY; without even the implied warranty of
  17 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  18 *  General Public License for more details.
  19 *
  20 *  You should have received a copy of the GNU General Public License along
  21 *  with this program; if not, write to the Free Software Foundation, Inc.,
  22 *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  23 *
  24 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  25 *  ALSA driver handling mixer controls for Intel MAD chipset
  26 */
  27
  28#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  29
  30#include <sound/core.h>
  31#include <sound/control.h>
  32#include "intel_sst.h"
  33#include "intel_sst_ioctl.h"
  34#include "intelmid_snd_control.h"
  35#include "intelmid.h"
  36
  37#define HW_CH_BASE 4
  38
  39
  40#define HW_CH_0 "Hw1"
  41#define HW_CH_1 "Hw2"
  42#define HW_CH_2 "Hw3"
  43#define HW_CH_3 "Hw4"
  44
  45static char *router_dmics[] = { "DMIC1",
  46                                "DMIC2",
  47                                "DMIC3",
  48                                "DMIC4",
  49                                "DMIC5",
  50                                "DMIC6"
  51                                };
  52
  53static char *out_names_mrst[] = {"Headphones",
  54                                "Internal speakers"};
  55static char *in_names_mrst[] = {"AMIC",
  56                                "DMIC",
  57                                "HS_MIC"};
  58static char *line_out_names_mfld[] = {"Headset",
  59                                "IHF    ",
  60                                "Vibra1 ",
  61                                "Vibra2 ",
  62                                "NONE   "};
  63static char *out_names_mfld[] = {"Headset ",
  64                                "EarPiece  "};
  65static char *in_names_mfld[] = {"AMIC",
  66                                "DMIC"};
  67
  68struct snd_control_val intelmad_ctrl_val[MAX_VENDORS] = {
  69        {
  70                .playback_vol_max = 63,
  71                .playback_vol_min = 0,
  72                .capture_vol_max = 63,
  73                .capture_vol_min = 0,
  74        },
  75        {
  76                .playback_vol_max = 0,
  77                .playback_vol_min = -31,
  78                .capture_vol_max = 0,
  79                .capture_vol_min = -20,
  80        },
  81        {
  82                .playback_vol_max = 0,
  83                .playback_vol_min = -31,
  84                .capture_vol_max = 0,
  85                .capture_vol_min = -31,
  86                .master_vol_max = 0,
  87                .master_vol_min = -126,
  88        },
  89};
  90
  91/* control path functionalities */
  92
  93static inline int snd_intelmad_volume_info(struct snd_ctl_elem_info *uinfo,
  94                                        int control_type, int max, int min)
  95{
  96        WARN_ON(!uinfo);
  97
  98        uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
  99        uinfo->count = control_type;
 100        uinfo->value.integer.min = min;
 101        uinfo->value.integer.max = max;
 102        return 0;
 103}
 104
 105/**
 106* snd_intelmad_mute_info - provides information about the mute controls
 107*
 108* @kcontrol:    pointer to the control
 109* @uinfo:       pointer to the structure where the control's info need
 110*               to be filled
 111*
 112* This function is called when a mixer application requests for control's info
 113*/
 114static int snd_intelmad_mute_info(struct snd_kcontrol *kcontrol,
 115                                        struct snd_ctl_elem_info *uinfo)
 116{
 117        WARN_ON(!uinfo);
 118        WARN_ON(!kcontrol);
 119
 120        /* set up the mute as a boolean mono control with min-max values */
 121        uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
 122        uinfo->count = MONO_CNTL;
 123        uinfo->value.integer.min = MIN_MUTE;
 124        uinfo->value.integer.max = MAX_MUTE;
 125        return 0;
 126}
 127
 128/**
 129* snd_intelmad_capture_volume_info - provides info about the volume control
 130*
 131* @kcontrol:    pointer to the control
 132* @uinfo:       pointer to the structure where the control's info need
 133*               to be filled
 134*
 135* This function is called when a mixer application requests for control's info
 136*/
 137static int snd_intelmad_capture_volume_info(struct snd_kcontrol *kcontrol,
 138                                        struct snd_ctl_elem_info *uinfo)
 139{
 140        snd_intelmad_volume_info(uinfo, MONO_CNTL,
 141                intelmad_ctrl_val[sst_card_vendor_id].capture_vol_max,
 142                intelmad_ctrl_val[sst_card_vendor_id].capture_vol_min);
 143        return 0;
 144}
 145
 146/**
 147* snd_intelmad_playback_volume_info - provides info about the volume control
 148*
 149* @kcontrol:    pointer to the control
 150* @uinfo:       pointer to the structure where the control's info need
 151*               to be filled
 152*
 153* This function is called when a mixer application requests for control's info
 154*/
 155static int snd_intelmad_playback_volume_info(struct snd_kcontrol *kcontrol,
 156                                        struct snd_ctl_elem_info *uinfo)
 157{
 158        snd_intelmad_volume_info(uinfo, STEREO_CNTL,
 159                intelmad_ctrl_val[sst_card_vendor_id].playback_vol_max,
 160                intelmad_ctrl_val[sst_card_vendor_id].playback_vol_min);
 161        return 0;
 162}
 163
 164static int snd_intelmad_master_volume_info(struct snd_kcontrol *kcontrol,
 165                                        struct snd_ctl_elem_info *uinfo)
 166{
 167        snd_intelmad_volume_info(uinfo, STEREO_CNTL,
 168                intelmad_ctrl_val[sst_card_vendor_id].master_vol_max,
 169                intelmad_ctrl_val[sst_card_vendor_id].master_vol_min);
 170        return 0;
 171}
 172
 173/**
 174* snd_intelmad_device_info_mrst - provides information about the devices available
 175*
 176* @kcontrol:    pointer to the control
 177* @uinfo:       pointer to the structure where the devices's info need
 178*               to be filled
 179*
 180* This function is called when a mixer application requests for device's info
 181*/
 182static int snd_intelmad_device_info_mrst(struct snd_kcontrol *kcontrol,
 183                                        struct snd_ctl_elem_info *uinfo)
 184{
 185
 186        WARN_ON(!kcontrol);
 187        WARN_ON(!uinfo);
 188
 189        /* setup device select as drop down controls with different values */
 190        if (kcontrol->id.numid == OUTPUT_SEL)
 191                uinfo->value.enumerated.items = ARRAY_SIZE(out_names_mrst);
 192        else
 193                uinfo->value.enumerated.items = ARRAY_SIZE(in_names_mrst);
 194        uinfo->count = MONO_CNTL;
 195        uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
 196
 197        if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
 198                uinfo->value.enumerated.item = 1;
 199        if (kcontrol->id.numid == OUTPUT_SEL)
 200                strncpy(uinfo->value.enumerated.name,
 201                        out_names_mrst[uinfo->value.enumerated.item],
 202                        sizeof(uinfo->value.enumerated.name)-1);
 203        else
 204                strncpy(uinfo->value.enumerated.name,
 205                        in_names_mrst[uinfo->value.enumerated.item],
 206                        sizeof(uinfo->value.enumerated.name)-1);
 207        return 0;
 208}
 209
 210static int snd_intelmad_device_info_mfld(struct snd_kcontrol *kcontrol,
 211                                        struct snd_ctl_elem_info *uinfo)
 212{
 213        struct snd_pmic_ops *scard_ops;
 214        struct snd_intelmad *intelmaddata;
 215
 216        WARN_ON(!kcontrol);
 217        WARN_ON(!uinfo);
 218
 219        intelmaddata = kcontrol->private_data;
 220
 221        WARN_ON(!intelmaddata->sstdrv_ops);
 222
 223        scard_ops = intelmaddata->sstdrv_ops->scard_ops;
 224        /* setup device select as drop down controls with different values */
 225        if (kcontrol->id.numid == OUTPUT_SEL)
 226                uinfo->value.enumerated.items = ARRAY_SIZE(out_names_mfld);
 227        else if (kcontrol->id.numid == INPUT_SEL)
 228                uinfo->value.enumerated.items = ARRAY_SIZE(in_names_mfld);
 229        else if (kcontrol->id.numid == LINEOUT_SEL_MFLD) {
 230                uinfo->value.enumerated.items = ARRAY_SIZE(line_out_names_mfld);
 231                scard_ops->line_out_names_cnt = uinfo->value.enumerated.items;
 232        } else
 233                return -EINVAL;
 234        uinfo->count = MONO_CNTL;
 235        uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
 236
 237        if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
 238                uinfo->value.enumerated.item = 1;
 239        if (kcontrol->id.numid == OUTPUT_SEL)
 240                strncpy(uinfo->value.enumerated.name,
 241                        out_names_mfld[uinfo->value.enumerated.item],
 242                        sizeof(uinfo->value.enumerated.name)-1);
 243        else if (kcontrol->id.numid == INPUT_SEL)
 244                strncpy(uinfo->value.enumerated.name,
 245                        in_names_mfld[uinfo->value.enumerated.item],
 246                        sizeof(uinfo->value.enumerated.name)-1);
 247        else if (kcontrol->id.numid == LINEOUT_SEL_MFLD)
 248                strncpy(uinfo->value.enumerated.name,
 249                        line_out_names_mfld[uinfo->value.enumerated.item],
 250                        sizeof(uinfo->value.enumerated.name)-1);
 251        else
 252                return -EINVAL;
 253        return 0;
 254}
 255
 256/**
 257* snd_intelmad_volume_get - gets the current volume for the control
 258*
 259* @kcontrol:    pointer to the control
 260* @uval:        pointer to the structure where the control's info need
 261*               to be filled
 262*
 263* This function is called when .get function of a control is invoked from app
 264*/
 265static int snd_intelmad_volume_get(struct snd_kcontrol *kcontrol,
 266                                struct snd_ctl_elem_value *uval)
 267{
 268        int ret_val = 0, cntl_list[2] = {0,};
 269        int value = 0;
 270        struct snd_intelmad *intelmaddata;
 271        struct snd_pmic_ops *scard_ops;
 272
 273        pr_debug("snd_intelmad_volume_get called\n");
 274
 275        WARN_ON(!uval);
 276        WARN_ON(!kcontrol);
 277
 278        intelmaddata = kcontrol->private_data;
 279
 280        WARN_ON(!intelmaddata->sstdrv_ops);
 281
 282        scard_ops = intelmaddata->sstdrv_ops->scard_ops;
 283
 284        WARN_ON(!scard_ops);
 285
 286        switch (kcontrol->id.numid) {
 287        case PLAYBACK_VOL:
 288                cntl_list[0] = PMIC_SND_RIGHT_PB_VOL;
 289                cntl_list[1] = PMIC_SND_LEFT_PB_VOL;
 290                break;
 291
 292        case CAPTURE_VOL:
 293                cntl_list[0] = PMIC_SND_CAPTURE_VOL;
 294                break;
 295
 296        case MASTER_VOL:
 297                cntl_list[0] = PMIC_SND_RIGHT_MASTER_VOL;
 298                cntl_list[1] = PMIC_SND_LEFT_MASTER_VOL;
 299                break;
 300        default:
 301                return -EINVAL;
 302        }
 303
 304        ret_val = scard_ops->get_vol(cntl_list[0], &value);
 305        uval->value.integer.value[0] = value;
 306
 307        if (ret_val)
 308                return ret_val;
 309
 310        if (kcontrol->id.numid == PLAYBACK_VOL ||
 311                kcontrol->id.numid == MASTER_VOL) {
 312                ret_val = scard_ops->get_vol(cntl_list[1], &value);
 313                uval->value.integer.value[1] = value;
 314        }
 315        return ret_val;
 316}
 317
 318/**
 319* snd_intelmad_mute_get - gets the current mute status for the control
 320*
 321* @kcontrol:    pointer to the control
 322* @uval:        pointer to the structure where the control's info need
 323*               to be filled
 324*
 325* This function is called when .get function of a control is invoked from app
 326*/
 327static int snd_intelmad_mute_get(struct snd_kcontrol *kcontrol,
 328                                        struct snd_ctl_elem_value *uval)
 329{
 330
 331        int cntl_list = 0, ret_val = 0;
 332        u8 value = 0;
 333        struct snd_intelmad *intelmaddata;
 334        struct snd_pmic_ops *scard_ops;
 335
 336        pr_debug("Mute_get called\n");
 337
 338        WARN_ON(!uval);
 339        WARN_ON(!kcontrol);
 340
 341        intelmaddata = kcontrol->private_data;
 342
 343        WARN_ON(!intelmaddata->sstdrv_ops);
 344
 345        scard_ops = intelmaddata->sstdrv_ops->scard_ops;
 346
 347        WARN_ON(!scard_ops);
 348
 349        switch (kcontrol->id.numid) {
 350        case PLAYBACK_MUTE:
 351                if (intelmaddata->output_sel == STEREO_HEADPHONE)
 352                        cntl_list = PMIC_SND_LEFT_HP_MUTE;
 353                else if ((intelmaddata->output_sel == INTERNAL_SPKR) ||
 354                        (intelmaddata->output_sel == MONO_EARPIECE))
 355                        cntl_list = PMIC_SND_LEFT_SPEAKER_MUTE;
 356                break;
 357
 358        case CAPTURE_MUTE:
 359                if (intelmaddata->input_sel == DMIC)
 360                        cntl_list = PMIC_SND_DMIC_MUTE;
 361                else if (intelmaddata->input_sel == AMIC)
 362                        cntl_list = PMIC_SND_AMIC_MUTE;
 363                else if (intelmaddata->input_sel == HS_MIC)
 364                        cntl_list = PMIC_SND_HP_MIC_MUTE;
 365                break;
 366        case MASTER_MUTE:
 367                uval->value.integer.value[0] = intelmaddata->master_mute;
 368                return 0;
 369        default:
 370                return -EINVAL;
 371        }
 372
 373        ret_val = scard_ops->get_mute(cntl_list, &value);
 374        uval->value.integer.value[0] = value;
 375        return ret_val;
 376}
 377
 378/**
 379* snd_intelmad_volume_set - sets the volume control's info
 380*
 381* @kcontrol:    pointer to the control
 382* @uval:        pointer to the structure where the control's info is
 383*               available to be set
 384*
 385* This function is called when .set function of a control is invoked from app
 386*/
 387static int snd_intelmad_volume_set(struct snd_kcontrol *kcontrol,
 388                                        struct snd_ctl_elem_value *uval)
 389{
 390
 391        int ret_val, cntl_list[2] = {0,};
 392        struct snd_intelmad *intelmaddata;
 393        struct snd_pmic_ops *scard_ops;
 394
 395        pr_debug("volume set called:%ld %ld\n",
 396                        uval->value.integer.value[0],
 397                        uval->value.integer.value[1]);
 398
 399        WARN_ON(!uval);
 400        WARN_ON(!kcontrol);
 401
 402        intelmaddata = kcontrol->private_data;
 403
 404        WARN_ON(!intelmaddata->sstdrv_ops);
 405
 406        scard_ops = intelmaddata->sstdrv_ops->scard_ops;
 407
 408        WARN_ON(!scard_ops);
 409
 410        switch (kcontrol->id.numid) {
 411        case PLAYBACK_VOL:
 412                cntl_list[0] = PMIC_SND_LEFT_PB_VOL;
 413                cntl_list[1] = PMIC_SND_RIGHT_PB_VOL;
 414                break;
 415
 416        case CAPTURE_VOL:
 417                cntl_list[0] = PMIC_SND_CAPTURE_VOL;
 418                break;
 419
 420        case MASTER_VOL:
 421                cntl_list[0] = PMIC_SND_LEFT_MASTER_VOL;
 422                cntl_list[1] = PMIC_SND_RIGHT_MASTER_VOL;
 423                break;
 424
 425        default:
 426                return -EINVAL;
 427        }
 428
 429        ret_val = scard_ops->set_vol(cntl_list[0],
 430                                uval->value.integer.value[0]);
 431        if (ret_val)
 432                return ret_val;
 433
 434        if (kcontrol->id.numid == PLAYBACK_VOL ||
 435                kcontrol->id.numid == MASTER_VOL)
 436                ret_val = scard_ops->set_vol(cntl_list[1],
 437                                uval->value.integer.value[1]);
 438        return ret_val;
 439}
 440
 441/**
 442* snd_intelmad_mute_set - sets the mute control's info
 443*
 444* @kcontrol:    pointer to the control
 445* @uval:        pointer to the structure where the control's info is
 446*               available to be set
 447*
 448* This function is called when .set function of a control is invoked from app
 449*/
 450static int snd_intelmad_mute_set(struct snd_kcontrol *kcontrol,
 451                                        struct snd_ctl_elem_value *uval)
 452{
 453        int cntl_list[2] = {0,}, ret_val;
 454        struct snd_intelmad *intelmaddata;
 455        struct snd_pmic_ops *scard_ops;
 456
 457        pr_debug("snd_intelmad_mute_set called\n");
 458
 459        WARN_ON(!uval);
 460        WARN_ON(!kcontrol);
 461
 462        intelmaddata = kcontrol->private_data;
 463
 464        WARN_ON(!intelmaddata->sstdrv_ops);
 465
 466        scard_ops = intelmaddata->sstdrv_ops->scard_ops;
 467
 468        WARN_ON(!scard_ops);
 469
 470        kcontrol->private_value = uval->value.integer.value[0];
 471
 472        switch (kcontrol->id.numid) {
 473        case PLAYBACK_MUTE:
 474                if (intelmaddata->output_sel == STEREO_HEADPHONE) {
 475                        cntl_list[0] = PMIC_SND_LEFT_HP_MUTE;
 476                        cntl_list[1] = PMIC_SND_RIGHT_HP_MUTE;
 477                } else if ((intelmaddata->output_sel == INTERNAL_SPKR) ||
 478                                (intelmaddata->output_sel == MONO_EARPIECE)) {
 479                        cntl_list[0] = PMIC_SND_LEFT_SPEAKER_MUTE;
 480                        cntl_list[1] = PMIC_SND_RIGHT_SPEAKER_MUTE;
 481                }
 482                break;
 483
 484        case CAPTURE_MUTE:/*based on sel device mute the i/p dev*/
 485                if (intelmaddata->input_sel == DMIC)
 486                        cntl_list[0] = PMIC_SND_DMIC_MUTE;
 487                else if (intelmaddata->input_sel == AMIC)
 488                        cntl_list[0] = PMIC_SND_AMIC_MUTE;
 489                else if (intelmaddata->input_sel == HS_MIC)
 490                        cntl_list[0] = PMIC_SND_HP_MIC_MUTE;
 491                break;
 492        case MASTER_MUTE:
 493                cntl_list[0] = PMIC_SND_MUTE_ALL;
 494                intelmaddata->master_mute = uval->value.integer.value[0];
 495                break;
 496        default:
 497                return -EINVAL;
 498        }
 499
 500        ret_val = scard_ops->set_mute(cntl_list[0],
 501                                uval->value.integer.value[0]);
 502        if (ret_val)
 503                return ret_val;
 504
 505        if (kcontrol->id.numid == PLAYBACK_MUTE)
 506                ret_val = scard_ops->set_mute(cntl_list[1],
 507                                        uval->value.integer.value[0]);
 508        return ret_val;
 509}
 510
 511/**
 512* snd_intelmad_device_get - get the device select control's info
 513*
 514* @kcontrol:    pointer to the control
 515* @uval:        pointer to the structure where the control's info is
 516*               to be filled
 517*
 518* This function is called when .get function of a control is invoked from app
 519*/
 520static int snd_intelmad_device_get(struct snd_kcontrol *kcontrol,
 521                                        struct snd_ctl_elem_value *uval)
 522{
 523        struct snd_intelmad *intelmaddata;
 524        struct snd_pmic_ops *scard_ops;
 525        pr_debug("device_get called\n");
 526
 527        WARN_ON(!uval);
 528        WARN_ON(!kcontrol);
 529
 530        intelmaddata = kcontrol->private_data;
 531        scard_ops = intelmaddata->sstdrv_ops->scard_ops;
 532        if (intelmaddata->cpu_id == CPU_CHIP_PENWELL) {
 533                if (kcontrol->id.numid == OUTPUT_SEL)
 534                        uval->value.enumerated.item[0] =
 535                                        scard_ops->output_dev_id;
 536                else if (kcontrol->id.numid == INPUT_SEL)
 537                        uval->value.enumerated.item[0] =
 538                                        scard_ops->input_dev_id;
 539                else if (kcontrol->id.numid == LINEOUT_SEL_MFLD)
 540                        uval->value.enumerated.item[0] =
 541                                        scard_ops->lineout_dev_id;
 542                else
 543                        return -EINVAL;
 544        } else if (intelmaddata->cpu_id == CPU_CHIP_LINCROFT) {
 545                if (kcontrol->id.numid == OUTPUT_SEL)
 546                        /* There is a mismatch here.
 547                         * ALSA expects 1 for internal speaker.
 548                         * But internally, we may give 2 for internal speaker.
 549                         */
 550                        if (scard_ops->output_dev_id == MONO_EARPIECE ||
 551                            scard_ops->output_dev_id == INTERNAL_SPKR)
 552                                uval->value.enumerated.item[0] = MONO_EARPIECE;
 553                        else if (scard_ops->output_dev_id == STEREO_HEADPHONE)
 554                                uval->value.enumerated.item[0] =
 555                                        STEREO_HEADPHONE;
 556                        else
 557                                return -EINVAL;
 558                else if (kcontrol->id.numid == INPUT_SEL)
 559                        uval->value.enumerated.item[0] =
 560                                        scard_ops->input_dev_id;
 561                else
 562                        return -EINVAL;
 563        } else
 564        uval->value.enumerated.item[0] = kcontrol->private_value;
 565        return 0;
 566}
 567
 568/**
 569* snd_intelmad_device_set - set the device select control's info
 570*
 571* @kcontrol:    pointer to the control
 572* @uval:        pointer to the structure where the control's info is
 573*               available to be set
 574*
 575* This function is called when .set function of a control is invoked from app
 576*/
 577static int snd_intelmad_device_set(struct snd_kcontrol *kcontrol,
 578                                        struct snd_ctl_elem_value *uval)
 579{
 580        struct snd_intelmad *intelmaddata;
 581        struct snd_pmic_ops *scard_ops;
 582        int ret_val = 0, vendor, status;
 583        struct intel_sst_pcm_control *pcm_control;
 584
 585        pr_debug("snd_intelmad_device_set called\n");
 586
 587        WARN_ON(!uval);
 588        WARN_ON(!kcontrol);
 589        status = -1;
 590
 591        intelmaddata = kcontrol->private_data;
 592
 593        WARN_ON(!intelmaddata->sstdrv_ops);
 594
 595        scard_ops = intelmaddata->sstdrv_ops->scard_ops;
 596
 597        WARN_ON(!scard_ops);
 598
 599        /* store value with driver */
 600        kcontrol->private_value = uval->value.enumerated.item[0];
 601
 602        switch (kcontrol->id.numid) {
 603        case OUTPUT_SEL:
 604                ret_val = scard_ops->set_output_dev(
 605                                uval->value.enumerated.item[0]);
 606                intelmaddata->output_sel = uval->value.enumerated.item[0];
 607                break;
 608        case INPUT_SEL:
 609                vendor = intelmaddata->sstdrv_ops->vendor_id;
 610                if ((vendor == SND_MX) || (vendor == SND_FS)) {
 611                        pcm_control = intelmaddata->sstdrv_ops->pcm_control;
 612                        if (uval->value.enumerated.item[0] == HS_MIC)
 613                                status = 1;
 614                        else
 615                                status = 0;
 616                        pcm_control->device_control(
 617                                        SST_ENABLE_RX_TIME_SLOT, &status);
 618                }
 619                ret_val = scard_ops->set_input_dev(
 620                                uval->value.enumerated.item[0]);
 621                intelmaddata->input_sel = uval->value.enumerated.item[0];
 622                break;
 623        case LINEOUT_SEL_MFLD:
 624                ret_val = scard_ops->set_lineout_dev(
 625                                        uval->value.enumerated.item[0]);
 626                intelmaddata->lineout_sel = uval->value.enumerated.item[0];
 627                break;
 628        default:
 629                return -EINVAL;
 630        }
 631        kcontrol->private_value = uval->value.enumerated.item[0];
 632        return ret_val;
 633}
 634
 635static int snd_intelmad_device_dmic_get(struct snd_kcontrol *kcontrol,
 636                                        struct snd_ctl_elem_value *uval)
 637{
 638        struct snd_intelmad *intelmaddata;
 639        struct snd_pmic_ops *scard_ops;
 640
 641        WARN_ON(!uval);
 642        WARN_ON(!kcontrol);
 643
 644        intelmaddata = kcontrol->private_data;
 645        scard_ops = intelmaddata->sstdrv_ops->scard_ops;
 646
 647        if (scard_ops->input_dev_id != DMIC) {
 648                pr_debug("input dev = 0x%x\n", scard_ops->input_dev_id);
 649                return 0;
 650        }
 651
 652        if (intelmaddata->cpu_id == CPU_CHIP_PENWELL)
 653                uval->value.enumerated.item[0] = kcontrol->private_value;
 654        else
 655                pr_debug(" CPU id = 0x%xis invalid.\n",
 656                        intelmaddata->cpu_id);
 657        return 0;
 658}
 659
 660void msic_set_bit(u8 index, unsigned int *available_dmics)
 661{
 662        *available_dmics |= (1 << index);
 663}
 664
 665void msic_clear_bit(u8 index, unsigned int *available_dmics)
 666{
 667        *available_dmics &= ~(1 << index);
 668}
 669
 670int msic_is_set_bit(u8 index, unsigned int *available_dmics)
 671{
 672        int ret_val;
 673
 674        ret_val = (*available_dmics & (1 << index));
 675        return ret_val;
 676}
 677
 678static int snd_intelmad_device_dmic_set(struct snd_kcontrol *kcontrol,
 679                                        struct snd_ctl_elem_value *uval)
 680{
 681        struct snd_intelmad *intelmaddata;
 682        struct snd_pmic_ops *scard_ops;
 683        int i, dmic_index;
 684        unsigned int available_dmics;
 685        int jump_count;
 686        int max_dmics = ARRAY_SIZE(router_dmics);
 687
 688        WARN_ON(!uval);
 689        WARN_ON(!kcontrol);
 690
 691        intelmaddata = kcontrol->private_data;
 692        WARN_ON(!intelmaddata->sstdrv_ops);
 693
 694        scard_ops = intelmaddata->sstdrv_ops->scard_ops;
 695        WARN_ON(!scard_ops);
 696
 697        if (scard_ops->input_dev_id != DMIC) {
 698                pr_debug("input dev = 0x%x\n", scard_ops->input_dev_id);
 699                return 0;
 700        }
 701
 702        available_dmics = scard_ops->available_dmics;
 703
 704        if (kcontrol->private_value > uval->value.enumerated.item[0]) {
 705                pr_debug("jump count -1.\n");
 706                jump_count = -1;
 707        } else {
 708                pr_debug("jump count 1.\n");
 709                jump_count = 1;
 710        }
 711
 712        dmic_index =  uval->value.enumerated.item[0];
 713        pr_debug("set function. dmic_index = %d, avl_dmic = 0x%x\n",
 714                         dmic_index, available_dmics);
 715        for (i = 0; i < max_dmics; i++) {
 716                pr_debug("set function. loop index = 0x%x.  dmic_index = 0x%x\n",
 717                         i, dmic_index);
 718                if (!msic_is_set_bit(dmic_index, &available_dmics)) {
 719                        msic_clear_bit(kcontrol->private_value,
 720                                                &available_dmics);
 721                        msic_set_bit(dmic_index, &available_dmics);
 722                        kcontrol->private_value = dmic_index;
 723                        scard_ops->available_dmics = available_dmics;
 724                        scard_ops->hw_dmic_map[kcontrol->id.numid-HW_CH_BASE] =
 725                                kcontrol->private_value;
 726                        scard_ops->set_hw_dmic_route
 727                                (kcontrol->id.numid-HW_CH_BASE);
 728                        return 0;
 729                }
 730
 731                dmic_index += jump_count;
 732
 733                if (dmic_index > (max_dmics - 1) && jump_count == 1) {
 734                        pr_debug("Resettingthe dmic index to 0.\n");
 735                        dmic_index = 0;
 736                } else if (dmic_index == -1 && jump_count == -1) {
 737                        pr_debug("Resetting the dmic index to 5.\n");
 738                        dmic_index = max_dmics - 1;
 739                }
 740        }
 741
 742        return -EINVAL;
 743}
 744
 745static int snd_intelmad_device_dmic_info_mfld(struct snd_kcontrol *kcontrol,
 746                                        struct snd_ctl_elem_info *uinfo)
 747{
 748        struct snd_intelmad *intelmaddata;
 749        struct snd_pmic_ops *scard_ops;
 750
 751        uinfo->count                  = MONO_CNTL;
 752        uinfo->type                   = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
 753        uinfo->value.enumerated.items = ARRAY_SIZE(router_dmics);
 754
 755        intelmaddata = kcontrol->private_data;
 756        WARN_ON(!intelmaddata->sstdrv_ops);
 757
 758        scard_ops = intelmaddata->sstdrv_ops->scard_ops;
 759        WARN_ON(!scard_ops);
 760
 761        if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
 762                uinfo->value.enumerated.item =
 763                        uinfo->value.enumerated.items - 1;
 764
 765        strncpy(uinfo->value.enumerated.name,
 766        router_dmics[uinfo->value.enumerated.item],
 767        sizeof(uinfo->value.enumerated.name)-1);
 768
 769
 770        msic_set_bit(kcontrol->private_value, &scard_ops->available_dmics);
 771        pr_debug("info function. avl_dmic = 0x%x",
 772                scard_ops->available_dmics);
 773
 774        scard_ops->hw_dmic_map[kcontrol->id.numid-HW_CH_BASE] =
 775                kcontrol->private_value;
 776
 777        return 0;
 778}
 779
 780struct snd_kcontrol_new snd_intelmad_controls_mrst[MAX_CTRL] __devinitdata = {
 781{
 782        .iface          =       SNDRV_CTL_ELEM_IFACE_MIXER,
 783        .name           =       "PCM Playback Source",
 784        .access         =       SNDRV_CTL_ELEM_ACCESS_READWRITE,
 785        .info           =       snd_intelmad_device_info_mrst,
 786        .get            =       snd_intelmad_device_get,
 787        .put            =       snd_intelmad_device_set,
 788        .private_value  =       0,
 789},
 790{
 791        .iface          =       SNDRV_CTL_ELEM_IFACE_MIXER,
 792        .name           =       "PCM Capture Source",
 793        .access         =       SNDRV_CTL_ELEM_ACCESS_READWRITE,
 794        .info           =       snd_intelmad_device_info_mrst,
 795        .get            =       snd_intelmad_device_get,
 796        .put            =       snd_intelmad_device_set,
 797        .private_value  =       0,
 798},
 799{
 800        .iface          =       SNDRV_CTL_ELEM_IFACE_MIXER,
 801        .name           =       "PCM Playback Volume",
 802        .access         =       SNDRV_CTL_ELEM_ACCESS_READWRITE,
 803        .info           =       snd_intelmad_playback_volume_info,
 804        .get            =       snd_intelmad_volume_get,
 805        .put            =       snd_intelmad_volume_set,
 806        .private_value  =       0,
 807},
 808{
 809        .iface          =       SNDRV_CTL_ELEM_IFACE_MIXER,
 810        .name           =       "PCM Playback Switch",
 811        .access         =       SNDRV_CTL_ELEM_ACCESS_READWRITE,
 812        .info           =       snd_intelmad_mute_info,
 813        .get            =       snd_intelmad_mute_get,
 814        .put            =       snd_intelmad_mute_set,
 815        .private_value  =       0,
 816},
 817{
 818        .iface          =       SNDRV_CTL_ELEM_IFACE_MIXER,
 819        .name           =       "PCM Capture Volume",
 820        .access         =       SNDRV_CTL_ELEM_ACCESS_READWRITE,
 821        .info           =       snd_intelmad_capture_volume_info,
 822        .get            =       snd_intelmad_volume_get,
 823        .put            =       snd_intelmad_volume_set,
 824        .private_value  =       0,
 825},
 826{
 827        .iface          =       SNDRV_CTL_ELEM_IFACE_MIXER,
 828        .name           =       "PCM Capture Switch",
 829        .access         =       SNDRV_CTL_ELEM_ACCESS_READWRITE,
 830        .info           =       snd_intelmad_mute_info,
 831        .get            =       snd_intelmad_mute_get,
 832        .put            =       snd_intelmad_mute_set,
 833        .private_value  =       0,
 834},
 835{
 836        .iface          =       SNDRV_CTL_ELEM_IFACE_MIXER,
 837        .name           =       "Master Playback Volume",
 838        .access         =       SNDRV_CTL_ELEM_ACCESS_READWRITE,
 839        .info           =       snd_intelmad_master_volume_info,
 840        .get            =       snd_intelmad_volume_get,
 841        .put            =       snd_intelmad_volume_set,
 842        .private_value  =       0,
 843},
 844{
 845        .iface          =       SNDRV_CTL_ELEM_IFACE_MIXER,
 846        .name           =       "Master Playback Switch",
 847        .access         =       SNDRV_CTL_ELEM_ACCESS_READWRITE,
 848        .info           =       snd_intelmad_mute_info,
 849        .get            =       snd_intelmad_mute_get,
 850        .put            =       snd_intelmad_mute_set,
 851        .private_value  =       0,
 852},
 853};
 854
 855struct snd_kcontrol_new
 856snd_intelmad_controls_mfld[MAX_CTRL_MFLD] __devinitdata = {
 857{
 858        .iface          =       SNDRV_CTL_ELEM_IFACE_MIXER,
 859        .name           =       "PCM Playback Source",
 860        .access         =       SNDRV_CTL_ELEM_ACCESS_READWRITE,
 861        .info           =       snd_intelmad_device_info_mfld,
 862        .get            =       snd_intelmad_device_get,
 863        .put            =       snd_intelmad_device_set,
 864        .private_value  =       0,
 865},
 866{
 867        .iface          =       SNDRV_CTL_ELEM_IFACE_MIXER,
 868        .name           =       "PCM Capture Source",
 869        .access         =       SNDRV_CTL_ELEM_ACCESS_READWRITE,
 870        .info           =       snd_intelmad_device_info_mfld,
 871        .get            =       snd_intelmad_device_get,
 872        .put            =       snd_intelmad_device_set,
 873        .private_value  =       0,
 874},
 875{
 876        .iface          =       SNDRV_CTL_ELEM_IFACE_MIXER,
 877        .name           =       "Line out",
 878        .access         =       SNDRV_CTL_ELEM_ACCESS_READWRITE,
 879        .info           =       snd_intelmad_device_info_mfld,
 880        .get            =       snd_intelmad_device_get,
 881        .put            =       snd_intelmad_device_set,
 882        .private_value  =       0,
 883},
 884{
 885        .iface          =       SNDRV_CTL_ELEM_IFACE_MIXER,
 886        .name           =       HW_CH_0,
 887        .access         =       SNDRV_CTL_ELEM_ACCESS_READWRITE,
 888        .info           =       snd_intelmad_device_dmic_info_mfld,
 889        .get            =       snd_intelmad_device_dmic_get,
 890        .put            =       snd_intelmad_device_dmic_set,
 891        .private_value  =       0
 892},
 893{
 894        .iface          =       SNDRV_CTL_ELEM_IFACE_MIXER,
 895        .name           =       HW_CH_1,
 896        .access         =       SNDRV_CTL_ELEM_ACCESS_READWRITE,
 897        .info           =       snd_intelmad_device_dmic_info_mfld,
 898        .get            =       snd_intelmad_device_dmic_get,
 899        .put            =       snd_intelmad_device_dmic_set,
 900        .private_value  =       1
 901},
 902{
 903        .iface          =       SNDRV_CTL_ELEM_IFACE_MIXER,
 904        .name           =       HW_CH_2,
 905        .access         =       SNDRV_CTL_ELEM_ACCESS_READWRITE,
 906        .info           =       snd_intelmad_device_dmic_info_mfld,
 907        .get            =       snd_intelmad_device_dmic_get,
 908        .put            =       snd_intelmad_device_dmic_set,
 909        .private_value  =       2
 910},
 911{
 912        .iface          =       SNDRV_CTL_ELEM_IFACE_MIXER,
 913        .name           =       HW_CH_3,
 914        .access         =       SNDRV_CTL_ELEM_ACCESS_READWRITE,
 915        .info           =       snd_intelmad_device_dmic_info_mfld,
 916        .get            =       snd_intelmad_device_dmic_get,
 917        .put            =       snd_intelmad_device_dmic_set,
 918        .private_value  =       3
 919}
 920};
 921
 922