aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/au88x0/au88x0_pcm.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/pci/au88x0/au88x0_pcm.c')
-rw-r--r--sound/pci/au88x0/au88x0_pcm.c127
1 files changed, 123 insertions, 4 deletions
diff --git a/sound/pci/au88x0/au88x0_pcm.c b/sound/pci/au88x0/au88x0_pcm.c
index 0ef2f9712208..e59f120742a4 100644
--- a/sound/pci/au88x0/au88x0_pcm.c
+++ b/sound/pci/au88x0/au88x0_pcm.c
@@ -122,6 +122,18 @@ static struct snd_pcm_hw_constraint_list hw_constraints_au8830_channels = {
122 .mask = 0, 122 .mask = 0,
123}; 123};
124#endif 124#endif
125
126static void vortex_notify_pcm_vol_change(struct snd_card *card,
127 struct snd_kcontrol *kctl, int activate)
128{
129 if (activate)
130 kctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
131 else
132 kctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
133 snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE |
134 SNDRV_CTL_EVENT_MASK_INFO, &(kctl->id));
135}
136
125/* open callback */ 137/* open callback */
126static int snd_vortex_pcm_open(struct snd_pcm_substream *substream) 138static int snd_vortex_pcm_open(struct snd_pcm_substream *substream)
127{ 139{
@@ -230,12 +242,14 @@ snd_vortex_pcm_hw_params(struct snd_pcm_substream *substream,
230 if (stream != NULL) 242 if (stream != NULL)
231 vortex_adb_allocroute(chip, stream->dma, 243 vortex_adb_allocroute(chip, stream->dma,
232 stream->nr_ch, stream->dir, 244 stream->nr_ch, stream->dir,
233 stream->type); 245 stream->type,
246 substream->number);
234 /* Alloc routes. */ 247 /* Alloc routes. */
235 dma = 248 dma =
236 vortex_adb_allocroute(chip, -1, 249 vortex_adb_allocroute(chip, -1,
237 params_channels(hw_params), 250 params_channels(hw_params),
238 substream->stream, type); 251 substream->stream, type,
252 substream->number);
239 if (dma < 0) { 253 if (dma < 0) {
240 spin_unlock_irq(&chip->lock); 254 spin_unlock_irq(&chip->lock);
241 return dma; 255 return dma;
@@ -246,6 +260,11 @@ snd_vortex_pcm_hw_params(struct snd_pcm_substream *substream,
246 vortex_adbdma_setbuffers(chip, dma, 260 vortex_adbdma_setbuffers(chip, dma,
247 params_period_bytes(hw_params), 261 params_period_bytes(hw_params),
248 params_periods(hw_params)); 262 params_periods(hw_params));
263 if (VORTEX_PCM_TYPE(substream->pcm) == VORTEX_PCM_ADB) {
264 chip->pcm_vol[substream->number].active = 1;
265 vortex_notify_pcm_vol_change(chip->card,
266 chip->pcm_vol[substream->number].kctl, 1);
267 }
249 } 268 }
250#ifndef CHIP_AU8810 269#ifndef CHIP_AU8810
251 else { 270 else {
@@ -275,10 +294,18 @@ static int snd_vortex_pcm_hw_free(struct snd_pcm_substream *substream)
275 spin_lock_irq(&chip->lock); 294 spin_lock_irq(&chip->lock);
276 // Delete audio routes. 295 // Delete audio routes.
277 if (VORTEX_PCM_TYPE(substream->pcm) != VORTEX_PCM_WT) { 296 if (VORTEX_PCM_TYPE(substream->pcm) != VORTEX_PCM_WT) {
278 if (stream != NULL) 297 if (stream != NULL) {
298 if (VORTEX_PCM_TYPE(substream->pcm) == VORTEX_PCM_ADB) {
299 chip->pcm_vol[substream->number].active = 0;
300 vortex_notify_pcm_vol_change(chip->card,
301 chip->pcm_vol[substream->number].kctl,
302 0);
303 }
279 vortex_adb_allocroute(chip, stream->dma, 304 vortex_adb_allocroute(chip, stream->dma,
280 stream->nr_ch, stream->dir, 305 stream->nr_ch, stream->dir,
281 stream->type); 306 stream->type,
307 substream->number);
308 }
282 } 309 }
283#ifndef CHIP_AU8810 310#ifndef CHIP_AU8810
284 else { 311 else {
@@ -506,6 +533,83 @@ static struct snd_kcontrol_new snd_vortex_mixer_spdif[] __devinitdata = {
506 }, 533 },
507}; 534};
508 535
536/* subdevice PCM Volume control */
537
538static int snd_vortex_pcm_vol_info(struct snd_kcontrol *kcontrol,
539 struct snd_ctl_elem_info *uinfo)
540{
541 vortex_t *vortex = snd_kcontrol_chip(kcontrol);
542 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
543 uinfo->count = (VORTEX_IS_QUAD(vortex) ? 4 : 2);
544 uinfo->value.integer.min = -128;
545 uinfo->value.integer.max = 32;
546 return 0;
547}
548
549static int snd_vortex_pcm_vol_get(struct snd_kcontrol *kcontrol,
550 struct snd_ctl_elem_value *ucontrol)
551{
552 int i;
553 vortex_t *vortex = snd_kcontrol_chip(kcontrol);
554 int subdev = kcontrol->id.subdevice;
555 struct pcm_vol *p = &vortex->pcm_vol[subdev];
556 int max_chn = (VORTEX_IS_QUAD(vortex) ? 4 : 2);
557 for (i = 0; i < max_chn; i++)
558 ucontrol->value.integer.value[i] = p->vol[i];
559 return 0;
560}
561
562static int snd_vortex_pcm_vol_put(struct snd_kcontrol *kcontrol,
563 struct snd_ctl_elem_value *ucontrol)
564{
565 int i;
566 int changed = 0;
567 int mixin;
568 unsigned char vol;
569 vortex_t *vortex = snd_kcontrol_chip(kcontrol);
570 int subdev = kcontrol->id.subdevice;
571 struct pcm_vol *p = &vortex->pcm_vol[subdev];
572 int max_chn = (VORTEX_IS_QUAD(vortex) ? 4 : 2);
573 for (i = 0; i < max_chn; i++) {
574 if (p->vol[i] != ucontrol->value.integer.value[i]) {
575 p->vol[i] = ucontrol->value.integer.value[i];
576 if (p->active) {
577 switch (vortex->dma_adb[p->dma].nr_ch) {
578 case 1:
579 mixin = p->mixin[0];
580 break;
581 case 2:
582 default:
583 mixin = p->mixin[(i < 2) ? i : (i - 2)];
584 break;
585 case 4:
586 mixin = p->mixin[i];
587 break;
588 };
589 vol = p->vol[i];
590 vortex_mix_setinputvolumebyte(vortex,
591 vortex->mixplayb[i], mixin, vol);
592 }
593 changed = 1;
594 }
595 }
596 return changed;
597}
598
599static const DECLARE_TLV_DB_MINMAX(vortex_pcm_vol_db_scale, -9600, 2400);
600
601static struct snd_kcontrol_new snd_vortex_pcm_vol __devinitdata = {
602 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
603 .name = "PCM Playback Volume",
604 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
605 SNDRV_CTL_ELEM_ACCESS_TLV_READ |
606 SNDRV_CTL_ELEM_ACCESS_INACTIVE,
607 .info = snd_vortex_pcm_vol_info,
608 .get = snd_vortex_pcm_vol_get,
609 .put = snd_vortex_pcm_vol_put,
610 .tlv = { .p = vortex_pcm_vol_db_scale },
611};
612
509/* create a pcm device */ 613/* create a pcm device */
510static int __devinit snd_vortex_new_pcm(vortex_t *chip, int idx, int nr) 614static int __devinit snd_vortex_new_pcm(vortex_t *chip, int idx, int nr)
511{ 615{
@@ -555,5 +659,20 @@ static int __devinit snd_vortex_new_pcm(vortex_t *chip, int idx, int nr)
555 return err; 659 return err;
556 } 660 }
557 } 661 }
662 if (VORTEX_PCM_TYPE(pcm) == VORTEX_PCM_ADB) {
663 for (i = 0; i < NR_PCM; i++) {
664 chip->pcm_vol[i].active = 0;
665 chip->pcm_vol[i].dma = -1;
666 kctl = snd_ctl_new1(&snd_vortex_pcm_vol, chip);
667 if (!kctl)
668 return -ENOMEM;
669 chip->pcm_vol[i].kctl = kctl;
670 kctl->id.device = 0;
671 kctl->id.subdevice = i;
672 err = snd_ctl_add(chip->card, kctl);
673 if (err < 0)
674 return err;
675 }
676 }
558 return 0; 677 return 0;
559} 678}