aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/sound/ymfpci.h6
-rw-r--r--sound/pci/ymfpci/ymfpci_main.c232
2 files changed, 166 insertions, 72 deletions
diff --git a/include/sound/ymfpci.h b/include/sound/ymfpci.h
index 4b570684a6aa..9a3c1e6c820a 100644
--- a/include/sound/ymfpci.h
+++ b/include/sound/ymfpci.h
@@ -295,6 +295,7 @@ struct _snd_ymfpci_pcm {
295 unsigned int running: 1; 295 unsigned int running: 1;
296 unsigned int output_front: 1; 296 unsigned int output_front: 1;
297 unsigned int output_rear: 1; 297 unsigned int output_rear: 1;
298 unsigned int update_pcm_vol;
298 u32 period_size; /* cached from runtime->period_size */ 299 u32 period_size; /* cached from runtime->period_size */
299 u32 buffer_size; /* cached from runtime->buffer_size */ 300 u32 buffer_size; /* cached from runtime->buffer_size */
300 u32 period_pos; 301 u32 period_pos;
@@ -367,6 +368,11 @@ struct _snd_ymfpci {
367 int mode_dup4ch; 368 int mode_dup4ch;
368 int rear_opened; 369 int rear_opened;
369 int spdif_opened; 370 int spdif_opened;
371 struct {
372 u16 left;
373 u16 right;
374 snd_kcontrol_t *ctl;
375 } pcm_mixer[32];
370 376
371 spinlock_t reg_lock; 377 spinlock_t reg_lock;
372 spinlock_t voice_lock; 378 spinlock_t voice_lock;
diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c
index d54f88a1b525..054836412dc4 100644
--- a/sound/pci/ymfpci/ymfpci_main.c
+++ b/sound/pci/ymfpci/ymfpci_main.c
@@ -321,6 +321,26 @@ static void snd_ymfpci_pcm_interrupt(ymfpci_t *chip, ymfpci_voice_t *voice)
321 snd_pcm_period_elapsed(ypcm->substream); 321 snd_pcm_period_elapsed(ypcm->substream);
322 spin_lock(&chip->reg_lock); 322 spin_lock(&chip->reg_lock);
323 } 323 }
324
325 if (unlikely(ypcm->update_pcm_vol)) {
326 unsigned int subs = ypcm->substream->number;
327 unsigned int next_bank = 1 - chip->active_bank;
328 snd_ymfpci_playback_bank_t *bank;
329 u32 volume;
330
331 bank = &voice->bank[next_bank];
332 volume = cpu_to_le32(chip->pcm_mixer[subs].left << 15);
333 bank->left_gain_end = volume;
334 if (ypcm->output_rear)
335 bank->eff2_gain_end = volume;
336 if (ypcm->voices[1])
337 bank = &ypcm->voices[1]->bank[next_bank];
338 volume = cpu_to_le32(chip->pcm_mixer[subs].right << 15);
339 bank->right_gain_end = volume;
340 if (ypcm->output_rear)
341 bank->eff3_gain_end = volume;
342 ypcm->update_pcm_vol--;
343 }
324 } 344 }
325 spin_unlock(&chip->reg_lock); 345 spin_unlock(&chip->reg_lock);
326} 346}
@@ -451,87 +471,74 @@ static int snd_ymfpci_pcm_voice_alloc(ymfpci_pcm_t *ypcm, int voices)
451 return 0; 471 return 0;
452} 472}
453 473
454static void snd_ymfpci_pcm_init_voice(ymfpci_voice_t *voice, int stereo, 474static void snd_ymfpci_pcm_init_voice(ymfpci_pcm_t *ypcm, unsigned int voiceidx,
455 int rate, int w_16, unsigned long addr, 475 snd_pcm_runtime_t *runtime,
456 unsigned int end, 476 int has_pcm_volume)
457 int output_front, int output_rear)
458{ 477{
478 ymfpci_voice_t *voice = ypcm->voices[voiceidx];
459 u32 format; 479 u32 format;
460 u32 delta = snd_ymfpci_calc_delta(rate); 480 u32 delta = snd_ymfpci_calc_delta(runtime->rate);
461 u32 lpfQ = snd_ymfpci_calc_lpfQ(rate); 481 u32 lpfQ = snd_ymfpci_calc_lpfQ(runtime->rate);
462 u32 lpfK = snd_ymfpci_calc_lpfK(rate); 482 u32 lpfK = snd_ymfpci_calc_lpfK(runtime->rate);
463 snd_ymfpci_playback_bank_t *bank; 483 snd_ymfpci_playback_bank_t *bank;
464 unsigned int nbank; 484 unsigned int nbank;
485 u32 vol_left, vol_right;
486 u8 use_left, use_right;
465 487
466 snd_assert(voice != NULL, return); 488 snd_assert(voice != NULL, return);
467 format = (stereo ? 0x00010000 : 0) | (w_16 ? 0 : 0x80000000); 489 if (runtime->channels == 1) {
490 use_left = 1;
491 use_right = 1;
492 } else {
493 use_left = (voiceidx & 1) == 0;
494 use_right = !use_left;
495 }
496 if (has_pcm_volume) {
497 vol_left = cpu_to_le32(ypcm->chip->pcm_mixer
498 [ypcm->substream->number].left << 15);
499 vol_right = cpu_to_le32(ypcm->chip->pcm_mixer
500 [ypcm->substream->number].right << 15);
501 } else {
502 vol_left = cpu_to_le32(0x40000000);
503 vol_right = cpu_to_le32(0x40000000);
504 }
505 format = runtime->channels == 2 ? 0x00010000 : 0;
506 if (snd_pcm_format_width(runtime->format) == 8)
507 format |= 0x80000000;
508 if (runtime->channels == 2 && (voiceidx & 1) != 0)
509 format |= 1;
468 for (nbank = 0; nbank < 2; nbank++) { 510 for (nbank = 0; nbank < 2; nbank++) {
469 bank = &voice->bank[nbank]; 511 bank = &voice->bank[nbank];
512 memset(bank, 0, sizeof(*bank));
470 bank->format = cpu_to_le32(format); 513 bank->format = cpu_to_le32(format);
471 bank->loop_default = 0; 514 bank->base = cpu_to_le32(runtime->dma_addr);
472 bank->base = cpu_to_le32(addr); 515 bank->loop_end = cpu_to_le32(ypcm->buffer_size);
473 bank->loop_start = 0;
474 bank->loop_end = cpu_to_le32(end);
475 bank->loop_frac = 0;
476 bank->eg_gain_end = cpu_to_le32(0x40000000);
477 bank->lpfQ = cpu_to_le32(lpfQ); 516 bank->lpfQ = cpu_to_le32(lpfQ);
478 bank->status = 0;
479 bank->num_of_frames = 0;
480 bank->loop_count = 0;
481 bank->start = 0;
482 bank->start_frac = 0;
483 bank->delta = 517 bank->delta =
484 bank->delta_end = cpu_to_le32(delta); 518 bank->delta_end = cpu_to_le32(delta);
485 bank->lpfK = 519 bank->lpfK =
486 bank->lpfK_end = cpu_to_le32(lpfK); 520 bank->lpfK_end = cpu_to_le32(lpfK);
487 bank->eg_gain = cpu_to_le32(0x40000000); 521 bank->eg_gain =
488 bank->lpfD1 = 522 bank->eg_gain_end = cpu_to_le32(0x40000000);
489 bank->lpfD2 = 0; 523
490 524 if (ypcm->output_front) {
491 bank->left_gain = 525 if (use_left) {
492 bank->right_gain = 526 bank->left_gain =
493 bank->left_gain_end = 527 bank->left_gain_end = vol_left;
494 bank->right_gain_end = 528 }
495 bank->eff1_gain = 529 if (use_right) {
496 bank->eff2_gain =
497 bank->eff3_gain =
498 bank->eff1_gain_end =
499 bank->eff2_gain_end =
500 bank->eff3_gain_end = 0;
501
502 if (!stereo) {
503 if (output_front) {
504 bank->left_gain =
505 bank->right_gain = 530 bank->right_gain =
506 bank->left_gain_end = 531 bank->right_gain_end = vol_right;
507 bank->right_gain_end = cpu_to_le32(0x40000000);
508 } 532 }
509 if (output_rear) { 533 }
534 if (ypcm->output_rear) {
535 if (use_left) {
510 bank->eff2_gain = 536 bank->eff2_gain =
511 bank->eff2_gain_end = 537 bank->eff2_gain_end = vol_left;
512 bank->eff3_gain =
513 bank->eff3_gain_end = cpu_to_le32(0x40000000);
514 }
515 } else {
516 if (output_front) {
517 if ((voice->number & 1) == 0) {
518 bank->left_gain =
519 bank->left_gain_end = cpu_to_le32(0x40000000);
520 } else {
521 bank->format |= cpu_to_le32(1);
522 bank->right_gain =
523 bank->right_gain_end = cpu_to_le32(0x40000000);
524 }
525 } 538 }
526 if (output_rear) { 539 if (use_right) {
527 if ((voice->number & 1) == 0) { 540 bank->eff3_gain =
528 bank->eff3_gain = 541 bank->eff3_gain_end = vol_right;
529 bank->eff3_gain_end = cpu_to_le32(0x40000000);
530 } else {
531 bank->format |= cpu_to_le32(1);
532 bank->eff2_gain =
533 bank->eff2_gain_end = cpu_to_le32(0x40000000);
534 }
535 } 542 }
536 } 543 }
537 } 544 }
@@ -613,7 +620,7 @@ static int snd_ymfpci_playback_hw_free(snd_pcm_substream_t * substream)
613 620
614static int snd_ymfpci_playback_prepare(snd_pcm_substream_t * substream) 621static int snd_ymfpci_playback_prepare(snd_pcm_substream_t * substream)
615{ 622{
616 // ymfpci_t *chip = snd_pcm_substream_chip(substream); 623 ymfpci_t *chip = snd_pcm_substream_chip(substream);
617 snd_pcm_runtime_t *runtime = substream->runtime; 624 snd_pcm_runtime_t *runtime = substream->runtime;
618 ymfpci_pcm_t *ypcm = runtime->private_data; 625 ymfpci_pcm_t *ypcm = runtime->private_data;
619 unsigned int nvoice; 626 unsigned int nvoice;
@@ -623,14 +630,8 @@ static int snd_ymfpci_playback_prepare(snd_pcm_substream_t * substream)
623 ypcm->period_pos = 0; 630 ypcm->period_pos = 0;
624 ypcm->last_pos = 0; 631 ypcm->last_pos = 0;
625 for (nvoice = 0; nvoice < runtime->channels; nvoice++) 632 for (nvoice = 0; nvoice < runtime->channels; nvoice++)
626 snd_ymfpci_pcm_init_voice(ypcm->voices[nvoice], 633 snd_ymfpci_pcm_init_voice(ypcm, nvoice, runtime,
627 runtime->channels == 2, 634 substream->pcm == chip->pcm);
628 runtime->rate,
629 snd_pcm_format_width(runtime->format) == 16,
630 runtime->dma_addr,
631 ypcm->buffer_size,
632 ypcm->output_front,
633 ypcm->output_rear);
634 return 0; 635 return 0;
635} 636}
636 637
@@ -882,6 +883,7 @@ static int snd_ymfpci_playback_open(snd_pcm_substream_t * substream)
882 ymfpci_t *chip = snd_pcm_substream_chip(substream); 883 ymfpci_t *chip = snd_pcm_substream_chip(substream);
883 snd_pcm_runtime_t *runtime = substream->runtime; 884 snd_pcm_runtime_t *runtime = substream->runtime;
884 ymfpci_pcm_t *ypcm; 885 ymfpci_pcm_t *ypcm;
886 snd_kcontrol_t *kctl;
885 int err; 887 int err;
886 888
887 if ((err = snd_ymfpci_playback_open_1(substream)) < 0) 889 if ((err = snd_ymfpci_playback_open_1(substream)) < 0)
@@ -895,6 +897,10 @@ static int snd_ymfpci_playback_open(snd_pcm_substream_t * substream)
895 chip->rear_opened++; 897 chip->rear_opened++;
896 } 898 }
897 spin_unlock_irq(&chip->reg_lock); 899 spin_unlock_irq(&chip->reg_lock);
900
901 kctl = chip->pcm_mixer[substream->number].ctl;
902 kctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
903 snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_INFO, &kctl->id);
898 return 0; 904 return 0;
899} 905}
900 906
@@ -987,6 +993,7 @@ static int snd_ymfpci_playback_close(snd_pcm_substream_t * substream)
987{ 993{
988 ymfpci_t *chip = snd_pcm_substream_chip(substream); 994 ymfpci_t *chip = snd_pcm_substream_chip(substream);
989 ymfpci_pcm_t *ypcm = substream->runtime->private_data; 995 ymfpci_pcm_t *ypcm = substream->runtime->private_data;
996 snd_kcontrol_t *kctl;
990 997
991 spin_lock_irq(&chip->reg_lock); 998 spin_lock_irq(&chip->reg_lock);
992 if (ypcm->output_rear && chip->rear_opened > 0) { 999 if (ypcm->output_rear && chip->rear_opened > 0) {
@@ -994,6 +1001,9 @@ static int snd_ymfpci_playback_close(snd_pcm_substream_t * substream)
994 ymfpci_close_extension(chip); 1001 ymfpci_close_extension(chip);
995 } 1002 }
996 spin_unlock_irq(&chip->reg_lock); 1003 spin_unlock_irq(&chip->reg_lock);
1004 kctl = chip->pcm_mixer[substream->number].ctl;
1005 kctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
1006 snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_INFO, &kctl->id);
997 return snd_ymfpci_playback_close_1(substream); 1007 return snd_ymfpci_playback_close_1(substream);
998} 1008}
999 1009
@@ -1665,6 +1675,66 @@ static snd_kcontrol_new_t snd_ymfpci_rear_shared __devinitdata = {
1665 .private_value = 2, 1675 .private_value = 2,
1666}; 1676};
1667 1677
1678/*
1679 * PCM voice volume
1680 */
1681
1682static int snd_ymfpci_pcm_vol_info(snd_kcontrol_t *kcontrol,
1683 snd_ctl_elem_info_t *uinfo)
1684{
1685 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1686 uinfo->count = 2;
1687 uinfo->value.integer.min = 0;
1688 uinfo->value.integer.max = 0x8000;
1689 return 0;
1690}
1691
1692static int snd_ymfpci_pcm_vol_get(snd_kcontrol_t *kcontrol,
1693 snd_ctl_elem_value_t *ucontrol)
1694{
1695 ymfpci_t *chip = snd_kcontrol_chip(kcontrol);
1696 unsigned int subs = kcontrol->id.subdevice;
1697
1698 ucontrol->value.integer.value[0] = chip->pcm_mixer[subs].left;
1699 ucontrol->value.integer.value[1] = chip->pcm_mixer[subs].right;
1700 return 0;
1701}
1702
1703static int snd_ymfpci_pcm_vol_put(snd_kcontrol_t *kcontrol,
1704 snd_ctl_elem_value_t *ucontrol)
1705{
1706 ymfpci_t *chip = snd_kcontrol_chip(kcontrol);
1707 unsigned int subs = kcontrol->id.subdevice;
1708 snd_pcm_substream_t *substream;
1709 unsigned long flags;
1710
1711 if (ucontrol->value.integer.value[0] != chip->pcm_mixer[subs].left ||
1712 ucontrol->value.integer.value[1] != chip->pcm_mixer[subs].right) {
1713 chip->pcm_mixer[subs].left = ucontrol->value.integer.value[0];
1714 chip->pcm_mixer[subs].right = ucontrol->value.integer.value[1];
1715
1716 substream = (snd_pcm_substream_t *)kcontrol->private_value;
1717 spin_lock_irqsave(&chip->voice_lock, flags);
1718 if (substream->runtime && substream->runtime->private_data) {
1719 ymfpci_pcm_t *ypcm = substream->runtime->private_data;
1720 ypcm->update_pcm_vol = 2;
1721 }
1722 spin_unlock_irqrestore(&chip->voice_lock, flags);
1723 return 1;
1724 }
1725 return 0;
1726}
1727
1728static snd_kcontrol_new_t snd_ymfpci_pcm_volume __devinitdata = {
1729 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1730 .name = "PCM Playback Volume",
1731 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
1732 SNDRV_CTL_ELEM_ACCESS_INACTIVE,
1733 .info = snd_ymfpci_pcm_vol_info,
1734 .get = snd_ymfpci_pcm_vol_get,
1735 .put = snd_ymfpci_pcm_vol_put,
1736};
1737
1668 1738
1669/* 1739/*
1670 * Mixer routines 1740 * Mixer routines
@@ -1686,6 +1756,7 @@ int __devinit snd_ymfpci_mixer(ymfpci_t *chip, int rear_switch)
1686{ 1756{
1687 ac97_template_t ac97; 1757 ac97_template_t ac97;
1688 snd_kcontrol_t *kctl; 1758 snd_kcontrol_t *kctl;
1759 snd_pcm_substream_t *substream;
1689 unsigned int idx; 1760 unsigned int idx;
1690 int err; 1761 int err;
1691 static ac97_bus_ops_t ops = { 1762 static ac97_bus_ops_t ops = {
@@ -1739,6 +1810,23 @@ int __devinit snd_ymfpci_mixer(ymfpci_t *chip, int rear_switch)
1739 return err; 1810 return err;
1740 } 1811 }
1741 1812
1813 /* per-voice volume */
1814 substream = chip->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
1815 for (idx = 0; idx < 32; ++idx) {
1816 kctl = snd_ctl_new1(&snd_ymfpci_pcm_volume, chip);
1817 if (!kctl)
1818 return -ENOMEM;
1819 kctl->id.device = chip->pcm->device;
1820 kctl->id.subdevice = idx;
1821 kctl->private_value = (unsigned long)substream;
1822 if ((err = snd_ctl_add(chip->card, kctl)) < 0)
1823 return err;
1824 chip->pcm_mixer[idx].left = 0x8000;
1825 chip->pcm_mixer[idx].right = 0x8000;
1826 chip->pcm_mixer[idx].ctl = kctl;
1827 substream = substream->next;
1828 }
1829
1742 return 0; 1830 return 0;
1743} 1831}
1744 1832