diff options
author | Teru KAMOGASHIRA <teru@sodan.ecc.u-tokyo.ac.jp> | 2006-12-04 12:03:53 -0500 |
---|---|---|
committer | Jaroslav Kysela <perex@suse.cz> | 2007-02-09 03:02:16 -0500 |
commit | 9ed1261e3e617d99b0eb74041d0337ff664e4f5b (patch) | |
tree | df8006d93195edb21bb38f51ff94457e30cfc48f | |
parent | c577b8a16fd19a33a8865ca6451287d284a0faf6 (diff) |
[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: Teru KAMOGASHIRA <teru@sodan.ecc.u-tokyo.ac.jp>
Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Signed-off-by: Jaroslav Kysela <perex@suse.cz>
-rw-r--r-- | include/sound/ymfpci.h | 4 | ||||
-rw-r--r-- | sound/pci/ymfpci/ymfpci_main.c | 44 |
2 files changed, 43 insertions, 5 deletions
diff --git a/include/sound/ymfpci.h b/include/sound/ymfpci.h index eef46faaee30..203d2b45b788 100644 --- a/include/sound/ymfpci.h +++ b/include/sound/ymfpci.h | |||
@@ -270,6 +270,7 @@ struct snd_ymfpci_pcm { | |||
270 | struct snd_pcm_substream *substream; | 270 | struct snd_pcm_substream *substream; |
271 | struct snd_ymfpci_voice *voices[2]; /* playback only */ | 271 | struct snd_ymfpci_voice *voices[2]; /* playback only */ |
272 | unsigned int running: 1, | 272 | unsigned int running: 1, |
273 | use_441_slot: 1, | ||
273 | output_front: 1, | 274 | output_front: 1, |
274 | output_rear: 1, | 275 | output_rear: 1, |
275 | swap_rear: 1; | 276 | swap_rear: 1; |
@@ -324,6 +325,7 @@ struct snd_ymfpci { | |||
324 | 325 | ||
325 | u32 active_bank; | 326 | u32 active_bank; |
326 | struct snd_ymfpci_voice voices[64]; | 327 | struct snd_ymfpci_voice voices[64]; |
328 | int src441_used; | ||
327 | 329 | ||
328 | struct snd_ac97_bus *ac97_bus; | 330 | struct snd_ac97_bus *ac97_bus; |
329 | struct snd_ac97 *ac97; | 331 | struct snd_ac97 *ac97; |
@@ -346,7 +348,7 @@ struct snd_ymfpci { | |||
346 | int mode_dup4ch; | 348 | int mode_dup4ch; |
347 | int rear_opened; | 349 | int rear_opened; |
348 | int spdif_opened; | 350 | int spdif_opened; |
349 | struct { | 351 | struct snd_ymfpci_pcm_mixer { |
350 | u16 left; | 352 | u16 left; |
351 | u16 right; | 353 | u16 right; |
352 | struct snd_kcontrol *ctl; | 354 | struct snd_kcontrol *ctl; |
diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c index 5bde816cd5c4..8b076932f4f5 100644 --- a/sound/pci/ymfpci/ymfpci_main.c +++ b/sound/pci/ymfpci/ymfpci_main.c | |||
@@ -171,6 +171,17 @@ static u32 snd_ymfpci_calc_lpfQ(u32 rate) | |||
171 | return val[0]; | 171 | return val[0]; |
172 | } | 172 | } |
173 | 173 | ||
174 | static void snd_ymfpci_pcm_441_volume_set(struct snd_ymfpci_pcm *ypcm) | ||
175 | { | ||
176 | unsigned int value; | ||
177 | struct snd_ymfpci_pcm_mixer *mixer; | ||
178 | |||
179 | mixer = &ypcm->chip->pcm_mixer[ypcm->substream->number]; | ||
180 | value = min_t(unsigned int, mixer->left, 0x7fff) >> 1; | ||
181 | value |= (min_t(unsigned int, mixer->right, 0x7fff) >> 1) << 16; | ||
182 | snd_ymfpci_writel(ypcm->chip, YDSXGR_BUF441OUTVOL, value); | ||
183 | } | ||
184 | |||
174 | /* | 185 | /* |
175 | * Hardware start management | 186 | * Hardware start management |
176 | */ | 187 | */ |
@@ -282,6 +293,10 @@ static int snd_ymfpci_voice_free(struct snd_ymfpci *chip, struct snd_ymfpci_voic | |||
282 | snd_assert(pvoice != NULL, return -EINVAL); | 293 | snd_assert(pvoice != NULL, return -EINVAL); |
283 | snd_ymfpci_hw_stop(chip); | 294 | snd_ymfpci_hw_stop(chip); |
284 | spin_lock_irqsave(&chip->voice_lock, flags); | 295 | spin_lock_irqsave(&chip->voice_lock, flags); |
296 | if (pvoice->number == chip->src441_used) { | ||
297 | chip->src441_used = -1; | ||
298 | pvoice->ypcm->use_441_slot = 0; | ||
299 | } | ||
285 | pvoice->use = pvoice->pcm = pvoice->synth = pvoice->midi = 0; | 300 | pvoice->use = pvoice->pcm = pvoice->synth = pvoice->midi = 0; |
286 | pvoice->ypcm = NULL; | 301 | pvoice->ypcm = NULL; |
287 | pvoice->interrupt = NULL; | 302 | pvoice->interrupt = NULL; |
@@ -386,7 +401,7 @@ static int snd_ymfpci_playback_trigger(struct snd_pcm_substream *substream, | |||
386 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | 401 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: |
387 | case SNDRV_PCM_TRIGGER_RESUME: | 402 | case SNDRV_PCM_TRIGGER_RESUME: |
388 | chip->ctrl_playback[ypcm->voices[0]->number + 1] = cpu_to_le32(ypcm->voices[0]->bank_addr); | 403 | chip->ctrl_playback[ypcm->voices[0]->number + 1] = cpu_to_le32(ypcm->voices[0]->bank_addr); |
389 | if (ypcm->voices[1] != NULL) | 404 | if (ypcm->voices[1] != NULL && !ypcm->use_441_slot) |
390 | chip->ctrl_playback[ypcm->voices[1]->number + 1] = cpu_to_le32(ypcm->voices[1]->bank_addr); | 405 | chip->ctrl_playback[ypcm->voices[1]->number + 1] = cpu_to_le32(ypcm->voices[1]->bank_addr); |
391 | ypcm->running = 1; | 406 | ypcm->running = 1; |
392 | break; | 407 | break; |
@@ -394,7 +409,7 @@ static int snd_ymfpci_playback_trigger(struct snd_pcm_substream *substream, | |||
394 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | 409 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: |
395 | case SNDRV_PCM_TRIGGER_SUSPEND: | 410 | case SNDRV_PCM_TRIGGER_SUSPEND: |
396 | chip->ctrl_playback[ypcm->voices[0]->number + 1] = 0; | 411 | chip->ctrl_playback[ypcm->voices[0]->number + 1] = 0; |
397 | if (ypcm->voices[1] != NULL) | 412 | if (ypcm->voices[1] != NULL && !ypcm->use_441_slot) |
398 | chip->ctrl_playback[ypcm->voices[1]->number + 1] = 0; | 413 | chip->ctrl_playback[ypcm->voices[1]->number + 1] = 0; |
399 | ypcm->running = 0; | 414 | ypcm->running = 0; |
400 | break; | 415 | break; |
@@ -481,6 +496,7 @@ static void snd_ymfpci_pcm_init_voice(struct snd_ymfpci_pcm *ypcm, unsigned int | |||
481 | unsigned int nbank; | 496 | unsigned int nbank; |
482 | u32 vol_left, vol_right; | 497 | u32 vol_left, vol_right; |
483 | u8 use_left, use_right; | 498 | u8 use_left, use_right; |
499 | unsigned long flags; | ||
484 | 500 | ||
485 | snd_assert(voice != NULL, return); | 501 | snd_assert(voice != NULL, return); |
486 | if (runtime->channels == 1) { | 502 | if (runtime->channels == 1) { |
@@ -499,11 +515,27 @@ static void snd_ymfpci_pcm_init_voice(struct snd_ymfpci_pcm *ypcm, unsigned int | |||
499 | vol_left = cpu_to_le32(0x40000000); | 515 | vol_left = cpu_to_le32(0x40000000); |
500 | vol_right = cpu_to_le32(0x40000000); | 516 | vol_right = cpu_to_le32(0x40000000); |
501 | } | 517 | } |
518 | spin_lock_irqsave(&ypcm->chip->voice_lock, flags); | ||
502 | format = runtime->channels == 2 ? 0x00010000 : 0; | 519 | format = runtime->channels == 2 ? 0x00010000 : 0; |
503 | if (snd_pcm_format_width(runtime->format) == 8) | 520 | if (snd_pcm_format_width(runtime->format) == 8) |
504 | format |= 0x80000000; | 521 | format |= 0x80000000; |
522 | else if (ypcm->chip->device_id == PCI_DEVICE_ID_YAMAHA_754 && | ||
523 | runtime->rate == 44100 && runtime->channels == 2 && | ||
524 | voiceidx == 0 && (ypcm->chip->src441_used == -1 || | ||
525 | ypcm->chip->src441_used == voice->number)) { | ||
526 | ypcm->chip->src441_used = voice->number; | ||
527 | ypcm->use_441_slot = 1; | ||
528 | format |= 0x10000000; | ||
529 | snd_ymfpci_pcm_441_volume_set(ypcm); | ||
530 | } | ||
531 | if (ypcm->chip->src441_used == voice->number && | ||
532 | (format & 0x10000000) == 0) { | ||
533 | ypcm->chip->src441_used = -1; | ||
534 | ypcm->use_441_slot = 0; | ||
535 | } | ||
505 | if (runtime->channels == 2 && (voiceidx & 1) != 0) | 536 | if (runtime->channels == 2 && (voiceidx & 1) != 0) |
506 | format |= 1; | 537 | format |= 1; |
538 | spin_unlock_irqrestore(&ypcm->chip->voice_lock, flags); | ||
507 | for (nbank = 0; nbank < 2; nbank++) { | 539 | for (nbank = 0; nbank < 2; nbank++) { |
508 | bank = &voice->bank[nbank]; | 540 | bank = &voice->bank[nbank]; |
509 | memset(bank, 0, sizeof(*bank)); | 541 | memset(bank, 0, sizeof(*bank)); |
@@ -1714,7 +1746,10 @@ static int snd_ymfpci_pcm_vol_put(struct snd_kcontrol *kcontrol, | |||
1714 | spin_lock_irqsave(&chip->voice_lock, flags); | 1746 | spin_lock_irqsave(&chip->voice_lock, flags); |
1715 | if (substream->runtime && substream->runtime->private_data) { | 1747 | if (substream->runtime && substream->runtime->private_data) { |
1716 | struct snd_ymfpci_pcm *ypcm = substream->runtime->private_data; | 1748 | struct snd_ymfpci_pcm *ypcm = substream->runtime->private_data; |
1717 | ypcm->update_pcm_vol = 2; | 1749 | if (!ypcm->use_441_slot) |
1750 | ypcm->update_pcm_vol = 2; | ||
1751 | else | ||
1752 | snd_ymfpci_pcm_441_volume_set(ypcm); | ||
1718 | } | 1753 | } |
1719 | spin_unlock_irqrestore(&chip->voice_lock, flags); | 1754 | spin_unlock_irqrestore(&chip->voice_lock, flags); |
1720 | return 1; | 1755 | return 1; |
@@ -2253,7 +2288,7 @@ static int saved_regs_index[] = { | |||
2253 | YDSXGR_PRIADCLOOPVOL, | 2288 | YDSXGR_PRIADCLOOPVOL, |
2254 | YDSXGR_NATIVEDACINVOL, | 2289 | YDSXGR_NATIVEDACINVOL, |
2255 | YDSXGR_NATIVEDACOUTVOL, | 2290 | YDSXGR_NATIVEDACOUTVOL, |
2256 | // YDSXGR_BUF441OUTVOL, | 2291 | YDSXGR_BUF441OUTVOL, |
2257 | YDSXGR_NATIVEADCINVOL, | 2292 | YDSXGR_NATIVEADCINVOL, |
2258 | YDSXGR_SPDIFLOOPVOL, | 2293 | YDSXGR_SPDIFLOOPVOL, |
2259 | YDSXGR_SPDIFOUTVOL, | 2294 | YDSXGR_SPDIFOUTVOL, |
@@ -2368,6 +2403,7 @@ int __devinit snd_ymfpci_create(struct snd_card *card, | |||
2368 | chip->reg_area_phys = pci_resource_start(pci, 0); | 2403 | chip->reg_area_phys = pci_resource_start(pci, 0); |
2369 | chip->reg_area_virt = ioremap_nocache(chip->reg_area_phys, 0x8000); | 2404 | chip->reg_area_virt = ioremap_nocache(chip->reg_area_phys, 0x8000); |
2370 | pci_set_master(pci); | 2405 | pci_set_master(pci); |
2406 | chip->src441_used = -1; | ||
2371 | 2407 | ||
2372 | if ((chip->res_reg_area = request_mem_region(chip->reg_area_phys, 0x8000, "YMFPCI")) == NULL) { | 2408 | if ((chip->res_reg_area = request_mem_region(chip->reg_area_phys, 0x8000, "YMFPCI")) == NULL) { |
2373 | snd_printk(KERN_ERR "unable to grab memory region 0x%lx-0x%lx\n", chip->reg_area_phys, chip->reg_area_phys + 0x8000 - 1); | 2409 | snd_printk(KERN_ERR "unable to grab memory region 0x%lx-0x%lx\n", chip->reg_area_phys, chip->reg_area_phys + 0x8000 - 1); |