sst: Change the SST driver PCM interface
[deliverable/linux.git] / drivers / staging / intel_sst / intelmid_ctrl.c
CommitLineData
fffa1cca
VK
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 */
d0f40c50
JP
27
28#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
29
fffa1cca
VK
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
38static char *out_names_mrst[] = {"Headphones",
39 "Internal speakers"};
40static char *in_names_mrst[] = {"AMIC",
41 "DMIC",
42 "HS_MIC"};
43static char *out_names_mfld[] = {"Headset ",
44 "EarPiece "};
45static char *in_names_mfld[] = {"AMIC",
46 "DMIC"};
47
48struct 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
71static 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*/
92static 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*/
115static 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*/
133static 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*/
151static 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
179static 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*/
214static 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
d0f40c50 222 pr_debug("snd_intelmad_volume_get called\n");
fffa1cca
VK
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*/
270static 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
d0f40c50 279 pr_debug("Mute_get called\n");
fffa1cca
VK
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*/
330static 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
d0f40c50 338 pr_debug("volume set called:%ld %ld\n",
fffa1cca
VK
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*/
386static 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
d0f40c50 393 pr_debug("snd_intelmad_mute_set called\n");
fffa1cca
VK
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*/
456static 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;
d0f40c50 461 pr_debug("device_get called\n");
fffa1cca
VK
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*/
491static 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;
6f6ffec1 497 struct intel_sst_pcm_control *pcm_control;
fffa1cca 498
d0f40c50 499 pr_debug("snd_intelmad_device_set called\n");
fffa1cca
VK
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)) {
6f6ffec1
VK
525 pcm_control = intelmaddata->sstdrv_ops->pcm_control;
526 if (uval->value.enumerated.item[0] == HS_MIC)
fffa1cca 527 status = 1;
6f6ffec1 528 else
fffa1cca 529 status = 0;
6f6ffec1
VK
530 pcm_control->device_control(
531 SST_ENABLE_RX_TIME_SLOT, &status);
fffa1cca
VK
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
544struct 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
610struct snd_kcontrol_new
611snd_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
This page took 0.06354 seconds and 5 git commands to generate.