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 "jack.h"
33 #include "intel_sst.h"
34 #include "intel_sst_ioctl.h"
35 #include "intelmid_snd_control.h"
36 #include "intelmid.h"
37 
38 static char *out_names_mrst[] = {"Headphones",
39 				"Internal speakers"};
40 static char *in_names_mrst[] = {"AMIC",
41 				"DMIC",
42 				"HS_MIC"};
43 static char *out_names_mfld[] = {"Headset ",
44 				"EarPiece  "};
45 static char *in_names_mfld[] = {"AMIC",
46 				"DMIC"};
47 
48 struct snd_control_val intelmad_ctrl_val[MAX_VENDORS] = {
49 	{
50 		.playback_vol_max = 63,
51 		.playback_vol_min = 0,
52 		.capture_vol_max = 63,
53 		.capture_vol_min = 0,
54 	},
55 	{
56 		.playback_vol_max = 0,
57 		.playback_vol_min = -31,
58 		.capture_vol_max = 0,
59 		.capture_vol_min = -20,
60 	},
61 	{
62 		.playback_vol_max = 0,
63 		.playback_vol_min = -126,
64 		.capture_vol_max = 0,
65 		.capture_vol_min = -31,
66 	},
67 };
68 
69 /* control path functionalities */
70 
snd_intelmad_volume_info(struct snd_ctl_elem_info * uinfo,int control_type,int max,int min)71 static inline int snd_intelmad_volume_info(struct snd_ctl_elem_info *uinfo,
72 					int control_type, int max, int min)
73 {
74 	WARN_ON(!uinfo);
75 
76 	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
77 	uinfo->count = control_type;
78 	uinfo->value.integer.min = min;
79 	uinfo->value.integer.max = max;
80 	return 0;
81 }
82 
83 /**
84 * snd_intelmad_mute_info - provides information about the mute controls
85 *
86 * @kcontrol:	pointer to the control
87 * @uinfo:	pointer to the structure where the control's info need
88 *		to be filled
89 *
90 * This function is called when a mixer application requests for control's info
91 */
snd_intelmad_mute_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)92 static int snd_intelmad_mute_info(struct snd_kcontrol *kcontrol,
93 					struct snd_ctl_elem_info *uinfo)
94 {
95 	WARN_ON(!uinfo);
96 	WARN_ON(!kcontrol);
97 
98 	/* set up the mute as a boolean mono control with min-max values */
99 	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
100 	uinfo->count = MONO_CNTL;
101 	uinfo->value.integer.min = MIN_MUTE;
102 	uinfo->value.integer.max = MAX_MUTE;
103 	return 0;
104 }
105 
106 /**
107 * snd_intelmad_capture_volume_info - provides info about the volume control
108 *
109 * @kcontrol:	pointer to the control
110 * @uinfo:	pointer to the structure where the control's info need
111 *		to be filled
112 *
113 * This function is called when a mixer application requests for control's info
114 */
snd_intelmad_capture_volume_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)115 static int snd_intelmad_capture_volume_info(struct snd_kcontrol *kcontrol,
116 					struct snd_ctl_elem_info *uinfo)
117 {
118 	snd_intelmad_volume_info(uinfo, MONO_CNTL,
119 		intelmad_ctrl_val[sst_card_vendor_id].capture_vol_max,
120 		intelmad_ctrl_val[sst_card_vendor_id].capture_vol_min);
121 	return 0;
122 }
123 
124 /**
125 * snd_intelmad_playback_volume_info - provides info about the volume control
126 *
127 * @kcontrol:	pointer to the control
128 * @uinfo:	pointer to the structure where the control's info need
129 *		to be filled
130 *
131 * This function is called when a mixer application requests for control's info
132 */
snd_intelmad_playback_volume_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)133 static int snd_intelmad_playback_volume_info(struct snd_kcontrol *kcontrol,
134 					struct snd_ctl_elem_info *uinfo)
135 {
136 	snd_intelmad_volume_info(uinfo, STEREO_CNTL,
137 		intelmad_ctrl_val[sst_card_vendor_id].playback_vol_max,
138 		intelmad_ctrl_val[sst_card_vendor_id].playback_vol_min);
139 	return 0;
140 }
141 
142 /**
143 * snd_intelmad_device_info_mrst - provides information about the devices available
144 *
145 * @kcontrol:	pointer to the control
146 * @uinfo:	pointer to the structure where the devices's info need
147 *		to be filled
148 *
149 * This function is called when a mixer application requests for device's info
150 */
snd_intelmad_device_info_mrst(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)151 static int snd_intelmad_device_info_mrst(struct snd_kcontrol *kcontrol,
152 					struct snd_ctl_elem_info *uinfo)
153 {
154 
155 	WARN_ON(!kcontrol);
156 	WARN_ON(!uinfo);
157 
158 	/* setup device select as drop down controls with different values */
159 	if (kcontrol->id.numid == OUTPUT_SEL)
160 		uinfo->value.enumerated.items = ARRAY_SIZE(out_names_mrst);
161 	else
162 		uinfo->value.enumerated.items = ARRAY_SIZE(in_names_mrst);
163 	uinfo->count = MONO_CNTL;
164 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
165 
166 	if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
167 		uinfo->value.enumerated.item = 1;
168 	if (kcontrol->id.numid == OUTPUT_SEL)
169 		strncpy(uinfo->value.enumerated.name,
170 			out_names_mrst[uinfo->value.enumerated.item],
171 			sizeof(uinfo->value.enumerated.name)-1);
172 	else
173 		strncpy(uinfo->value.enumerated.name,
174 			in_names_mrst[uinfo->value.enumerated.item],
175 			sizeof(uinfo->value.enumerated.name)-1);
176 	return 0;
177 }
178 
snd_intelmad_device_info_mfld(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)179 static int snd_intelmad_device_info_mfld(struct snd_kcontrol *kcontrol,
180 					struct snd_ctl_elem_info *uinfo)
181 {
182 	WARN_ON(!kcontrol);
183 	WARN_ON(!uinfo);
184 	/* setup device select as drop down controls with different values */
185 	if (kcontrol->id.numid == OUTPUT_SEL)
186 		uinfo->value.enumerated.items = ARRAY_SIZE(out_names_mfld);
187 	else
188 		uinfo->value.enumerated.items = ARRAY_SIZE(in_names_mfld);
189 	uinfo->count = MONO_CNTL;
190 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
191 
192 	if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
193 		uinfo->value.enumerated.item = 1;
194 	if (kcontrol->id.numid == OUTPUT_SEL)
195 		strncpy(uinfo->value.enumerated.name,
196 			out_names_mfld[uinfo->value.enumerated.item],
197 			sizeof(uinfo->value.enumerated.name)-1);
198 	else
199 		strncpy(uinfo->value.enumerated.name,
200 			in_names_mfld[uinfo->value.enumerated.item],
201 			sizeof(uinfo->value.enumerated.name)-1);
202 	return 0;
203 }
204 
205 /**
206 * snd_intelmad_volume_get - gets the current volume for the control
207 *
208 * @kcontrol:	pointer to the control
209 * @uval:	pointer to the structure where the control's info need
210 *		to be filled
211 *
212 * This function is called when .get function of a control is invoked from app
213 */
snd_intelmad_volume_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * uval)214 static int snd_intelmad_volume_get(struct snd_kcontrol *kcontrol,
215 				struct snd_ctl_elem_value *uval)
216 {
217 	int ret_val = 0, cntl_list[2] = {0,};
218 	int value = 0;
219 	struct snd_intelmad *intelmaddata;
220 	struct snd_pmic_ops *scard_ops;
221 
222 	pr_debug("snd_intelmad_volume_get called\n");
223 
224 	WARN_ON(!uval);
225 	WARN_ON(!kcontrol);
226 
227 	intelmaddata = kcontrol->private_data;
228 
229 	WARN_ON(!intelmaddata->sstdrv_ops);
230 
231 	scard_ops = intelmaddata->sstdrv_ops->scard_ops;
232 
233 	WARN_ON(!scard_ops);
234 
235 	switch (kcontrol->id.numid) {
236 	case PLAYBACK_VOL:
237 		cntl_list[0] = PMIC_SND_RIGHT_PB_VOL;
238 		cntl_list[1] = PMIC_SND_LEFT_PB_VOL;
239 		break;
240 
241 	case CAPTURE_VOL:
242 		cntl_list[0] = PMIC_SND_CAPTURE_VOL;
243 		break;
244 	default:
245 		return -EINVAL;
246 	}
247 
248 	ret_val = scard_ops->get_vol(cntl_list[0], &value);
249 	uval->value.integer.value[0] = value;
250 
251 	if (ret_val)
252 		return ret_val;
253 
254 	if (kcontrol->id.numid == PLAYBACK_VOL) {
255 		ret_val = scard_ops->get_vol(cntl_list[1], &value);
256 		uval->value.integer.value[1] = value;
257 	}
258 	return ret_val;
259 }
260 
261 /**
262 * snd_intelmad_mute_get - gets the current mute status for the control
263 *
264 * @kcontrol:	pointer to the control
265 * @uval:	pointer to the structure where the control's info need
266 *		to be filled
267 *
268 * This function is called when .get function of a control is invoked from app
269 */
snd_intelmad_mute_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * uval)270 static int snd_intelmad_mute_get(struct snd_kcontrol *kcontrol,
271 					struct snd_ctl_elem_value *uval)
272 {
273 
274 	int cntl_list = 0, ret_val = 0;
275 	u8 value = 0;
276 	struct snd_intelmad *intelmaddata;
277 	struct snd_pmic_ops *scard_ops;
278 
279 	pr_debug("Mute_get called\n");
280 
281 	WARN_ON(!uval);
282 	WARN_ON(!kcontrol);
283 
284 	intelmaddata = kcontrol->private_data;
285 
286 	WARN_ON(!intelmaddata->sstdrv_ops);
287 
288 	scard_ops = intelmaddata->sstdrv_ops->scard_ops;
289 
290 	WARN_ON(!scard_ops);
291 
292 	switch (kcontrol->id.numid) {
293 	case PLAYBACK_MUTE:
294 		if (intelmaddata->output_sel == STEREO_HEADPHONE)
295 			cntl_list = PMIC_SND_LEFT_HP_MUTE;
296 		else if ((intelmaddata->output_sel == INTERNAL_SPKR) ||
297 			(intelmaddata->output_sel == MONO_EARPIECE))
298 			cntl_list = PMIC_SND_LEFT_SPEAKER_MUTE;
299 		break;
300 
301 	case CAPTURE_MUTE:
302 		if (intelmaddata->input_sel == DMIC)
303 			cntl_list = PMIC_SND_DMIC_MUTE;
304 		else if (intelmaddata->input_sel == AMIC)
305 			cntl_list = PMIC_SND_AMIC_MUTE;
306 		else if (intelmaddata->input_sel == HS_MIC)
307 			cntl_list = PMIC_SND_HP_MIC_MUTE;
308 		break;
309 	case MASTER_MUTE:
310 		uval->value.integer.value[0] = intelmaddata->master_mute;
311 		return 0;
312 	default:
313 		return -EINVAL;
314 	}
315 
316 	ret_val = scard_ops->get_mute(cntl_list, &value);
317 	uval->value.integer.value[0] = value;
318 	return ret_val;
319 }
320 
321 /**
322 * snd_intelmad_volume_set - sets the volume control's info
323 *
324 * @kcontrol:	pointer to the control
325 * @uval:	pointer to the structure where the control's info is
326 *		available to be set
327 *
328 * This function is called when .set function of a control is invoked from app
329 */
snd_intelmad_volume_set(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * uval)330 static int snd_intelmad_volume_set(struct snd_kcontrol *kcontrol,
331 					struct snd_ctl_elem_value *uval)
332 {
333 
334 	int ret_val, cntl_list[2] = {0,};
335 	struct snd_intelmad *intelmaddata;
336 	struct snd_pmic_ops *scard_ops;
337 
338 	pr_debug("volume set called:%ld %ld\n",
339 			uval->value.integer.value[0],
340 			uval->value.integer.value[1]);
341 
342 	WARN_ON(!uval);
343 	WARN_ON(!kcontrol);
344 
345 	intelmaddata = kcontrol->private_data;
346 
347 	WARN_ON(!intelmaddata->sstdrv_ops);
348 
349 	scard_ops = intelmaddata->sstdrv_ops->scard_ops;
350 
351 	WARN_ON(!scard_ops);
352 
353 	switch (kcontrol->id.numid) {
354 	case PLAYBACK_VOL:
355 		cntl_list[0] = PMIC_SND_LEFT_PB_VOL;
356 		cntl_list[1] = PMIC_SND_RIGHT_PB_VOL;
357 		break;
358 
359 	case CAPTURE_VOL:
360 		cntl_list[0] = PMIC_SND_CAPTURE_VOL;
361 		break;
362 	default:
363 		return -EINVAL;
364 	}
365 
366 	ret_val = scard_ops->set_vol(cntl_list[0],
367 				uval->value.integer.value[0]);
368 	if (ret_val)
369 		return ret_val;
370 
371 	if (kcontrol->id.numid == PLAYBACK_VOL)
372 		ret_val = scard_ops->set_vol(cntl_list[1],
373 				uval->value.integer.value[1]);
374 	return ret_val;
375 }
376 
377 /**
378 * snd_intelmad_mute_set - sets the mute control's info
379 *
380 * @kcontrol:	pointer to the control
381 * @uval:	pointer to the structure where the control's info is
382 *		available to be set
383 *
384 * This function is called when .set function of a control is invoked from app
385 */
snd_intelmad_mute_set(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * uval)386 static int snd_intelmad_mute_set(struct snd_kcontrol *kcontrol,
387 					struct snd_ctl_elem_value *uval)
388 {
389 	int cntl_list[2] = {0,}, ret_val;
390 	struct snd_intelmad *intelmaddata;
391 	struct snd_pmic_ops *scard_ops;
392 
393 	pr_debug("snd_intelmad_mute_set called\n");
394 
395 	WARN_ON(!uval);
396 	WARN_ON(!kcontrol);
397 
398 	intelmaddata = kcontrol->private_data;
399 
400 	WARN_ON(!intelmaddata->sstdrv_ops);
401 
402 	scard_ops = intelmaddata->sstdrv_ops->scard_ops;
403 
404 	WARN_ON(!scard_ops);
405 
406 	kcontrol->private_value = uval->value.integer.value[0];
407 
408 	switch (kcontrol->id.numid) {
409 	case PLAYBACK_MUTE:
410 		if (intelmaddata->output_sel == STEREO_HEADPHONE) {
411 			cntl_list[0] = PMIC_SND_LEFT_HP_MUTE;
412 			cntl_list[1] = PMIC_SND_RIGHT_HP_MUTE;
413 		} else if ((intelmaddata->output_sel == INTERNAL_SPKR) ||
414 				(intelmaddata->output_sel == MONO_EARPIECE)) {
415 			cntl_list[0] = PMIC_SND_LEFT_SPEAKER_MUTE;
416 			cntl_list[1] = PMIC_SND_RIGHT_SPEAKER_MUTE;
417 		}
418 		break;
419 
420 	case CAPTURE_MUTE:/*based on sel device mute the i/p dev*/
421 		if (intelmaddata->input_sel == DMIC)
422 			cntl_list[0] = PMIC_SND_DMIC_MUTE;
423 		else if (intelmaddata->input_sel == AMIC)
424 			cntl_list[0] = PMIC_SND_AMIC_MUTE;
425 		else if (intelmaddata->input_sel == HS_MIC)
426 			cntl_list[0] = PMIC_SND_HP_MIC_MUTE;
427 		break;
428 	case MASTER_MUTE:
429 		cntl_list[0] = PMIC_SND_MUTE_ALL;
430 		intelmaddata->master_mute = uval->value.integer.value[0];
431 		break;
432 	default:
433 		return -EINVAL;
434 	}
435 
436 	ret_val = scard_ops->set_mute(cntl_list[0],
437 				uval->value.integer.value[0]);
438 	if (ret_val)
439 		return ret_val;
440 
441 	if (kcontrol->id.numid == PLAYBACK_MUTE)
442 		ret_val = scard_ops->set_mute(cntl_list[1],
443 					uval->value.integer.value[0]);
444 	return ret_val;
445 }
446 
447 /**
448 * snd_intelmad_device_get - get the device select control's info
449 *
450 * @kcontrol:	pointer to the control
451 * @uval:	pointer to the structure where the control's info is
452 *		to be filled
453 *
454 * This function is called when .get function of a control is invoked from app
455 */
snd_intelmad_device_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * uval)456 static int snd_intelmad_device_get(struct snd_kcontrol *kcontrol,
457 					struct snd_ctl_elem_value *uval)
458 {
459 	struct snd_intelmad *intelmaddata;
460 	struct snd_pmic_ops *scard_ops;
461 	pr_debug("device_get called\n");
462 
463 	WARN_ON(!uval);
464 	WARN_ON(!kcontrol);
465 
466 	intelmaddata = kcontrol->private_data;
467 	if (intelmaddata->cpu_id == CPU_CHIP_PENWELL) {
468 		scard_ops = intelmaddata->sstdrv_ops->scard_ops;
469 		if (kcontrol->id.numid == OUTPUT_SEL)
470 			uval->value.enumerated.item[0] =
471 					scard_ops->output_dev_id;
472 		else if (kcontrol->id.numid == INPUT_SEL)
473 			uval->value.enumerated.item[0] =
474 					scard_ops->input_dev_id;
475 		else
476 			return -EINVAL;
477 	} else
478 	uval->value.enumerated.item[0] = kcontrol->private_value;
479 	return 0;
480 }
481 
482 /**
483 * snd_intelmad_device_set - set the device select control's info
484 *
485 * @kcontrol:	pointer to the control
486 * @uval:	pointer to the structure where the control's info is
487 *		available to be set
488 *
489 * This function is called when .set function of a control is invoked from app
490 */
snd_intelmad_device_set(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * uval)491 static int snd_intelmad_device_set(struct snd_kcontrol *kcontrol,
492 					struct snd_ctl_elem_value *uval)
493 {
494 	struct snd_intelmad *intelmaddata;
495 	struct snd_pmic_ops *scard_ops;
496 	int ret_val = 0, vendor, status;
497 	struct intel_sst_pcm_control *pcm_control;
498 
499 	pr_debug("snd_intelmad_device_set called\n");
500 
501 	WARN_ON(!uval);
502 	WARN_ON(!kcontrol);
503 	status = -1;
504 
505 	intelmaddata = kcontrol->private_data;
506 
507 	WARN_ON(!intelmaddata->sstdrv_ops);
508 
509 	scard_ops = intelmaddata->sstdrv_ops->scard_ops;
510 
511 	WARN_ON(!scard_ops);
512 
513 	/* store value with driver */
514 	kcontrol->private_value = uval->value.enumerated.item[0];
515 
516 	switch (kcontrol->id.numid) {
517 	case OUTPUT_SEL:
518 		ret_val = scard_ops->set_output_dev(
519 				uval->value.enumerated.item[0]);
520 		intelmaddata->output_sel = uval->value.enumerated.item[0];
521 		break;
522 	case INPUT_SEL:
523 		vendor = intelmaddata->sstdrv_ops->vendor_id;
524 		if ((vendor == SND_MX) || (vendor == SND_FS)) {
525 			pcm_control = intelmaddata->sstdrv_ops->pcm_control;
526 			if (uval->value.enumerated.item[0] == HS_MIC)
527 				status = 1;
528 			else
529 				status = 0;
530 			pcm_control->device_control(
531 					SST_ENABLE_RX_TIME_SLOT, &status);
532 		}
533 		ret_val = scard_ops->set_input_dev(
534 				uval->value.enumerated.item[0]);
535 		intelmaddata->input_sel = uval->value.enumerated.item[0];
536 		break;
537 	default:
538 		return -EINVAL;
539 	}
540 	kcontrol->private_value = uval->value.enumerated.item[0];
541 	return ret_val;
542 }
543 
544 struct snd_kcontrol_new snd_intelmad_controls_mrst[MAX_CTRL] __devinitdata = {
545 {
546 	.iface		=	SNDRV_CTL_ELEM_IFACE_MIXER,
547 	.name		=	"PCM Playback Source",
548 	.access		=	SNDRV_CTL_ELEM_ACCESS_READWRITE,
549 	.info		=	snd_intelmad_device_info_mrst,
550 	.get		=	snd_intelmad_device_get,
551 	.put		=	snd_intelmad_device_set,
552 	.private_value	=	0,
553 },
554 {
555 	.iface		=	SNDRV_CTL_ELEM_IFACE_MIXER,
556 	.name		=	"PCM Capture Source",
557 	.access		=	SNDRV_CTL_ELEM_ACCESS_READWRITE,
558 	.info		=	snd_intelmad_device_info_mrst,
559 	.get		=	snd_intelmad_device_get,
560 	.put		=	snd_intelmad_device_set,
561 	.private_value	=	0,
562 },
563 {
564 	.iface		=	SNDRV_CTL_ELEM_IFACE_MIXER,
565 	.name		=	"PCM Playback Volume",
566 	.access		=	SNDRV_CTL_ELEM_ACCESS_READWRITE,
567 	.info		=	snd_intelmad_playback_volume_info,
568 	.get		=	snd_intelmad_volume_get,
569 	.put		=	snd_intelmad_volume_set,
570 	.private_value	=	0,
571 },
572 {
573 	.iface		=	SNDRV_CTL_ELEM_IFACE_MIXER,
574 	.name		=	"PCM Playback Switch",
575 	.access		=	SNDRV_CTL_ELEM_ACCESS_READWRITE,
576 	.info		=	snd_intelmad_mute_info,
577 	.get		=	snd_intelmad_mute_get,
578 	.put		=	snd_intelmad_mute_set,
579 	.private_value	=	0,
580 },
581 {
582 	.iface		=	SNDRV_CTL_ELEM_IFACE_MIXER,
583 	.name		=	"PCM Capture Volume",
584 	.access		=	SNDRV_CTL_ELEM_ACCESS_READWRITE,
585 	.info		=	snd_intelmad_capture_volume_info,
586 	.get		=	snd_intelmad_volume_get,
587 	.put		=	snd_intelmad_volume_set,
588 	.private_value	=	0,
589 },
590 {
591 	.iface		=	SNDRV_CTL_ELEM_IFACE_MIXER,
592 	.name		=	"PCM Capture Switch",
593 	.access		=	SNDRV_CTL_ELEM_ACCESS_READWRITE,
594 	.info		=	snd_intelmad_mute_info,
595 	.get		=	snd_intelmad_mute_get,
596 	.put		=	snd_intelmad_mute_set,
597 	.private_value	=	0,
598 },
599 {
600 	.iface		=	SNDRV_CTL_ELEM_IFACE_MIXER,
601 	.name		=	"Master Playback Switch",
602 	.access		=	SNDRV_CTL_ELEM_ACCESS_READWRITE,
603 	.info		=	snd_intelmad_mute_info,
604 	.get		=	snd_intelmad_mute_get,
605 	.put		=	snd_intelmad_mute_set,
606 	.private_value	=	0,
607 },
608 };
609 
610 struct snd_kcontrol_new
611 snd_intelmad_controls_mfld[MAX_CTRL_MFLD] __devinitdata = {
612 {
613 	.iface		=	SNDRV_CTL_ELEM_IFACE_MIXER,
614 	.name		=	"PCM Playback Source",
615 	.access		=	SNDRV_CTL_ELEM_ACCESS_READWRITE,
616 	.info		=	snd_intelmad_device_info_mfld,
617 	.get		=	snd_intelmad_device_get,
618 	.put		=	snd_intelmad_device_set,
619 	.private_value	=	0,
620 },
621 {
622 	.iface		=	SNDRV_CTL_ELEM_IFACE_MIXER,
623 	.name		=	"PCM Capture Source",
624 	.access		=	SNDRV_CTL_ELEM_ACCESS_READWRITE,
625 	.info		=	snd_intelmad_device_info_mfld,
626 	.get		=	snd_intelmad_device_get,
627 	.put		=	snd_intelmad_device_set,
628 	.private_value	=	0,
629 },
630 };
631 
632