Commit 9ed1261e authored by Teru KAMOGASHIRA's avatar Teru KAMOGASHIRA Committed by Jaroslav Kysela

[ALSA] Current driver does not utilize 44.1kHz high quality sampling rate converter.

Following patch will make the driver to use the 44.1kHz SRC automatically
if the pcm source is 44.1kHz signed 16bit stereo.
The SRC is available in YMF754 only.
Signed-off-by: default avatarTeru KAMOGASHIRA <teru@sodan.ecc.u-tokyo.ac.jp>
Signed-off-by: default avatarClemens Ladisch <clemens@ladisch.de>
Signed-off-by: default avatarJaroslav Kysela <perex@suse.cz>
parent c577b8a1
...@@ -270,6 +270,7 @@ struct snd_ymfpci_pcm { ...@@ -270,6 +270,7 @@ struct snd_ymfpci_pcm {
struct snd_pcm_substream *substream; struct snd_pcm_substream *substream;
struct snd_ymfpci_voice *voices[2]; /* playback only */ struct snd_ymfpci_voice *voices[2]; /* playback only */
unsigned int running: 1, unsigned int running: 1,
use_441_slot: 1,
output_front: 1, output_front: 1,
output_rear: 1, output_rear: 1,
swap_rear: 1; swap_rear: 1;
...@@ -324,6 +325,7 @@ struct snd_ymfpci { ...@@ -324,6 +325,7 @@ struct snd_ymfpci {
u32 active_bank; u32 active_bank;
struct snd_ymfpci_voice voices[64]; struct snd_ymfpci_voice voices[64];
int src441_used;
struct snd_ac97_bus *ac97_bus; struct snd_ac97_bus *ac97_bus;
struct snd_ac97 *ac97; struct snd_ac97 *ac97;
...@@ -346,7 +348,7 @@ struct snd_ymfpci { ...@@ -346,7 +348,7 @@ struct snd_ymfpci {
int mode_dup4ch; int mode_dup4ch;
int rear_opened; int rear_opened;
int spdif_opened; int spdif_opened;
struct { struct snd_ymfpci_pcm_mixer {
u16 left; u16 left;
u16 right; u16 right;
struct snd_kcontrol *ctl; struct snd_kcontrol *ctl;
......
...@@ -171,6 +171,17 @@ static u32 snd_ymfpci_calc_lpfQ(u32 rate) ...@@ -171,6 +171,17 @@ static u32 snd_ymfpci_calc_lpfQ(u32 rate)
return val[0]; return val[0];
} }
static void snd_ymfpci_pcm_441_volume_set(struct snd_ymfpci_pcm *ypcm)
{
unsigned int value;
struct snd_ymfpci_pcm_mixer *mixer;
mixer = &ypcm->chip->pcm_mixer[ypcm->substream->number];
value = min_t(unsigned int, mixer->left, 0x7fff) >> 1;
value |= (min_t(unsigned int, mixer->right, 0x7fff) >> 1) << 16;
snd_ymfpci_writel(ypcm->chip, YDSXGR_BUF441OUTVOL, value);
}
/* /*
* Hardware start management * Hardware start management
*/ */
...@@ -282,6 +293,10 @@ static int snd_ymfpci_voice_free(struct snd_ymfpci *chip, struct snd_ymfpci_voic ...@@ -282,6 +293,10 @@ static int snd_ymfpci_voice_free(struct snd_ymfpci *chip, struct snd_ymfpci_voic
snd_assert(pvoice != NULL, return -EINVAL); snd_assert(pvoice != NULL, return -EINVAL);
snd_ymfpci_hw_stop(chip); snd_ymfpci_hw_stop(chip);
spin_lock_irqsave(&chip->voice_lock, flags); spin_lock_irqsave(&chip->voice_lock, flags);
if (pvoice->number == chip->src441_used) {
chip->src441_used = -1;
pvoice->ypcm->use_441_slot = 0;
}
pvoice->use = pvoice->pcm = pvoice->synth = pvoice->midi = 0; pvoice->use = pvoice->pcm = pvoice->synth = pvoice->midi = 0;
pvoice->ypcm = NULL; pvoice->ypcm = NULL;
pvoice->interrupt = NULL; pvoice->interrupt = NULL;
...@@ -386,7 +401,7 @@ static int snd_ymfpci_playback_trigger(struct snd_pcm_substream *substream, ...@@ -386,7 +401,7 @@ static int snd_ymfpci_playback_trigger(struct snd_pcm_substream *substream,
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_RESUME:
chip->ctrl_playback[ypcm->voices[0]->number + 1] = cpu_to_le32(ypcm->voices[0]->bank_addr); chip->ctrl_playback[ypcm->voices[0]->number + 1] = cpu_to_le32(ypcm->voices[0]->bank_addr);
if (ypcm->voices[1] != NULL) if (ypcm->voices[1] != NULL && !ypcm->use_441_slot)
chip->ctrl_playback[ypcm->voices[1]->number + 1] = cpu_to_le32(ypcm->voices[1]->bank_addr); chip->ctrl_playback[ypcm->voices[1]->number + 1] = cpu_to_le32(ypcm->voices[1]->bank_addr);
ypcm->running = 1; ypcm->running = 1;
break; break;
...@@ -394,7 +409,7 @@ static int snd_ymfpci_playback_trigger(struct snd_pcm_substream *substream, ...@@ -394,7 +409,7 @@ static int snd_ymfpci_playback_trigger(struct snd_pcm_substream *substream,
case SNDRV_PCM_TRIGGER_PAUSE_PUSH: case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_SUSPEND:
chip->ctrl_playback[ypcm->voices[0]->number + 1] = 0; chip->ctrl_playback[ypcm->voices[0]->number + 1] = 0;
if (ypcm->voices[1] != NULL) if (ypcm->voices[1] != NULL && !ypcm->use_441_slot)
chip->ctrl_playback[ypcm->voices[1]->number + 1] = 0; chip->ctrl_playback[ypcm->voices[1]->number + 1] = 0;
ypcm->running = 0; ypcm->running = 0;
break; break;
...@@ -481,6 +496,7 @@ static void snd_ymfpci_pcm_init_voice(struct snd_ymfpci_pcm *ypcm, unsigned int ...@@ -481,6 +496,7 @@ static void snd_ymfpci_pcm_init_voice(struct snd_ymfpci_pcm *ypcm, unsigned int
unsigned int nbank; unsigned int nbank;
u32 vol_left, vol_right; u32 vol_left, vol_right;
u8 use_left, use_right; u8 use_left, use_right;
unsigned long flags;
snd_assert(voice != NULL, return); snd_assert(voice != NULL, return);
if (runtime->channels == 1) { if (runtime->channels == 1) {
...@@ -499,11 +515,27 @@ static void snd_ymfpci_pcm_init_voice(struct snd_ymfpci_pcm *ypcm, unsigned int ...@@ -499,11 +515,27 @@ static void snd_ymfpci_pcm_init_voice(struct snd_ymfpci_pcm *ypcm, unsigned int
vol_left = cpu_to_le32(0x40000000); vol_left = cpu_to_le32(0x40000000);
vol_right = cpu_to_le32(0x40000000); vol_right = cpu_to_le32(0x40000000);
} }
spin_lock_irqsave(&ypcm->chip->voice_lock, flags);
format = runtime->channels == 2 ? 0x00010000 : 0; format = runtime->channels == 2 ? 0x00010000 : 0;
if (snd_pcm_format_width(runtime->format) == 8) if (snd_pcm_format_width(runtime->format) == 8)
format |= 0x80000000; format |= 0x80000000;
else if (ypcm->chip->device_id == PCI_DEVICE_ID_YAMAHA_754 &&
runtime->rate == 44100 && runtime->channels == 2 &&
voiceidx == 0 && (ypcm->chip->src441_used == -1 ||
ypcm->chip->src441_used == voice->number)) {
ypcm->chip->src441_used = voice->number;
ypcm->use_441_slot = 1;
format |= 0x10000000;
snd_ymfpci_pcm_441_volume_set(ypcm);
}
if (ypcm->chip->src441_used == voice->number &&
(format & 0x10000000) == 0) {
ypcm->chip->src441_used = -1;
ypcm->use_441_slot = 0;
}
if (runtime->channels == 2 && (voiceidx & 1) != 0) if (runtime->channels == 2 && (voiceidx & 1) != 0)
format |= 1; format |= 1;
spin_unlock_irqrestore(&ypcm->chip->voice_lock, flags);
for (nbank = 0; nbank < 2; nbank++) { for (nbank = 0; nbank < 2; nbank++) {
bank = &voice->bank[nbank]; bank = &voice->bank[nbank];
memset(bank, 0, sizeof(*bank)); memset(bank, 0, sizeof(*bank));
...@@ -1714,7 +1746,10 @@ static int snd_ymfpci_pcm_vol_put(struct snd_kcontrol *kcontrol, ...@@ -1714,7 +1746,10 @@ static int snd_ymfpci_pcm_vol_put(struct snd_kcontrol *kcontrol,
spin_lock_irqsave(&chip->voice_lock, flags); spin_lock_irqsave(&chip->voice_lock, flags);
if (substream->runtime && substream->runtime->private_data) { if (substream->runtime && substream->runtime->private_data) {
struct snd_ymfpci_pcm *ypcm = substream->runtime->private_data; struct snd_ymfpci_pcm *ypcm = substream->runtime->private_data;
ypcm->update_pcm_vol = 2; if (!ypcm->use_441_slot)
ypcm->update_pcm_vol = 2;
else
snd_ymfpci_pcm_441_volume_set(ypcm);
} }
spin_unlock_irqrestore(&chip->voice_lock, flags); spin_unlock_irqrestore(&chip->voice_lock, flags);
return 1; return 1;
...@@ -2253,7 +2288,7 @@ static int saved_regs_index[] = { ...@@ -2253,7 +2288,7 @@ static int saved_regs_index[] = {
YDSXGR_PRIADCLOOPVOL, YDSXGR_PRIADCLOOPVOL,
YDSXGR_NATIVEDACINVOL, YDSXGR_NATIVEDACINVOL,
YDSXGR_NATIVEDACOUTVOL, YDSXGR_NATIVEDACOUTVOL,
// YDSXGR_BUF441OUTVOL, YDSXGR_BUF441OUTVOL,
YDSXGR_NATIVEADCINVOL, YDSXGR_NATIVEADCINVOL,
YDSXGR_SPDIFLOOPVOL, YDSXGR_SPDIFLOOPVOL,
YDSXGR_SPDIFOUTVOL, YDSXGR_SPDIFOUTVOL,
...@@ -2368,6 +2403,7 @@ int __devinit snd_ymfpci_create(struct snd_card *card, ...@@ -2368,6 +2403,7 @@ int __devinit snd_ymfpci_create(struct snd_card *card,
chip->reg_area_phys = pci_resource_start(pci, 0); chip->reg_area_phys = pci_resource_start(pci, 0);
chip->reg_area_virt = ioremap_nocache(chip->reg_area_phys, 0x8000); chip->reg_area_virt = ioremap_nocache(chip->reg_area_phys, 0x8000);
pci_set_master(pci); pci_set_master(pci);
chip->src441_used = -1;
if ((chip->res_reg_area = request_mem_region(chip->reg_area_phys, 0x8000, "YMFPCI")) == NULL) { if ((chip->res_reg_area = request_mem_region(chip->reg_area_phys, 0x8000, "YMFPCI")) == NULL) {
snd_printk(KERN_ERR "unable to grab memory region 0x%lx-0x%lx\n", chip->reg_area_phys, chip->reg_area_phys + 0x8000 - 1); snd_printk(KERN_ERR "unable to grab memory region 0x%lx-0x%lx\n", chip->reg_area_phys, chip->reg_area_phys + 0x8000 - 1);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment