diff options
-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); |