]> Pileus Git - ~andy/linux/blob - drivers/staging/intel_sst/intelmid_ctrl.c
Merge Qualcom Hexagon architecture
[~andy/linux] / drivers / staging / intel_sst / intelmid_ctrl.c
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
45 static char *router_dmics[] = { "DMIC1",
46                                 "DMIC2",
47                                 "DMIC3",
48                                 "DMIC4",
49                                 "DMIC5",
50                                 "DMIC6"
51                                 };
52
53 static char *out_names_mrst[] = {"Headphones",
54                                 "Internal speakers"};
55 static char *in_names_mrst[] = {"AMIC",
56                                 "DMIC",
57                                 "HS_MIC"};
58 static char *line_out_names_mfld[] = {"Headset",
59                                 "IHF    ",
60                                 "Vibra1 ",
61                                 "Vibra2 ",
62                                 "NONE   "};
63 static char *out_names_mfld[] = {"Headset ",
64                                 "EarPiece  "};
65 static char *in_names_mfld[] = {"AMIC",
66                                 "DMIC"};
67
68 struct 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
93 static 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 */
114 static 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 */
137 static 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 */
155 static 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
164 static 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 */
182 static 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
210 static 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 */
265 static 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 */
327 static 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 */
387 static 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 */
450 static 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 */
520 static 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 */
577 static 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
635 static 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
660 void msic_set_bit(u8 index, unsigned int *available_dmics)
661 {
662         *available_dmics |= (1 << index);
663 }
664
665 void msic_clear_bit(u8 index, unsigned int *available_dmics)
666 {
667         *available_dmics &= ~(1 << index);
668 }
669
670 int 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
678 static 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
745 static 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
780 struct 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
855 struct snd_kcontrol_new
856 snd_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