diff options
Diffstat (limited to 'sound/pci/ymfpci/ymfpci_main.c')
-rw-r--r-- | sound/pci/ymfpci/ymfpci_main.c | 171 |
1 files changed, 143 insertions, 28 deletions
diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c index 7881944a1957..fd12674d0394 100644 --- a/sound/pci/ymfpci/ymfpci_main.c +++ b/sound/pci/ymfpci/ymfpci_main.c | |||
@@ -2,12 +2,6 @@ | |||
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> |
3 | * Routines for control of YMF724/740/744/754 chips | 3 | * Routines for control of YMF724/740/744/754 chips |
4 | * | 4 | * |
5 | * BUGS: | ||
6 | * -- | ||
7 | * | ||
8 | * TODO: | ||
9 | * -- | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | 5 | * This program is free software; you can redistribute it and/or modify |
12 | * it under the terms of the GNU General Public License as published by | 6 | * it under the terms of the GNU General Public License as published by |
13 | * the Free Software Foundation; either version 2 of the License, or | 7 | * the Free Software Foundation; either version 2 of the License, or |
@@ -26,6 +20,7 @@ | |||
26 | 20 | ||
27 | #include <sound/driver.h> | 21 | #include <sound/driver.h> |
28 | #include <linux/delay.h> | 22 | #include <linux/delay.h> |
23 | #include <linux/firmware.h> | ||
29 | #include <linux/init.h> | 24 | #include <linux/init.h> |
30 | #include <linux/interrupt.h> | 25 | #include <linux/interrupt.h> |
31 | #include <linux/pci.h> | 26 | #include <linux/pci.h> |
@@ -42,10 +37,7 @@ | |||
42 | #include <sound/mpu401.h> | 37 | #include <sound/mpu401.h> |
43 | 38 | ||
44 | #include <asm/io.h> | 39 | #include <asm/io.h> |
45 | 40 | #include <asm/byteorder.h> | |
46 | /* | ||
47 | * constants | ||
48 | */ | ||
49 | 41 | ||
50 | /* | 42 | /* |
51 | * common I/O routines | 43 | * common I/O routines |
@@ -179,6 +171,17 @@ static u32 snd_ymfpci_calc_lpfQ(u32 rate) | |||
179 | return val[0]; | 171 | return val[0]; |
180 | } | 172 | } |
181 | 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 | |||
182 | /* | 185 | /* |
183 | * Hardware start management | 186 | * Hardware start management |
184 | */ | 187 | */ |
@@ -290,6 +293,10 @@ static int snd_ymfpci_voice_free(struct snd_ymfpci *chip, struct snd_ymfpci_voic | |||
290 | snd_assert(pvoice != NULL, return -EINVAL); | 293 | snd_assert(pvoice != NULL, return -EINVAL); |
291 | snd_ymfpci_hw_stop(chip); | 294 | snd_ymfpci_hw_stop(chip); |
292 | 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 | } | ||
293 | pvoice->use = pvoice->pcm = pvoice->synth = pvoice->midi = 0; | 300 | pvoice->use = pvoice->pcm = pvoice->synth = pvoice->midi = 0; |
294 | pvoice->ypcm = NULL; | 301 | pvoice->ypcm = NULL; |
295 | pvoice->interrupt = NULL; | 302 | pvoice->interrupt = NULL; |
@@ -394,7 +401,7 @@ static int snd_ymfpci_playback_trigger(struct snd_pcm_substream *substream, | |||
394 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | 401 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: |
395 | case SNDRV_PCM_TRIGGER_RESUME: | 402 | case SNDRV_PCM_TRIGGER_RESUME: |
396 | 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); |
397 | if (ypcm->voices[1] != NULL) | 404 | if (ypcm->voices[1] != NULL && !ypcm->use_441_slot) |
398 | 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); |
399 | ypcm->running = 1; | 406 | ypcm->running = 1; |
400 | break; | 407 | break; |
@@ -402,7 +409,7 @@ static int snd_ymfpci_playback_trigger(struct snd_pcm_substream *substream, | |||
402 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | 409 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: |
403 | case SNDRV_PCM_TRIGGER_SUSPEND: | 410 | case SNDRV_PCM_TRIGGER_SUSPEND: |
404 | chip->ctrl_playback[ypcm->voices[0]->number + 1] = 0; | 411 | chip->ctrl_playback[ypcm->voices[0]->number + 1] = 0; |
405 | if (ypcm->voices[1] != NULL) | 412 | if (ypcm->voices[1] != NULL && !ypcm->use_441_slot) |
406 | chip->ctrl_playback[ypcm->voices[1]->number + 1] = 0; | 413 | chip->ctrl_playback[ypcm->voices[1]->number + 1] = 0; |
407 | ypcm->running = 0; | 414 | ypcm->running = 0; |
408 | break; | 415 | break; |
@@ -489,6 +496,7 @@ static void snd_ymfpci_pcm_init_voice(struct snd_ymfpci_pcm *ypcm, unsigned int | |||
489 | unsigned int nbank; | 496 | unsigned int nbank; |
490 | u32 vol_left, vol_right; | 497 | u32 vol_left, vol_right; |
491 | u8 use_left, use_right; | 498 | u8 use_left, use_right; |
499 | unsigned long flags; | ||
492 | 500 | ||
493 | snd_assert(voice != NULL, return); | 501 | snd_assert(voice != NULL, return); |
494 | if (runtime->channels == 1) { | 502 | if (runtime->channels == 1) { |
@@ -507,11 +515,27 @@ static void snd_ymfpci_pcm_init_voice(struct snd_ymfpci_pcm *ypcm, unsigned int | |||
507 | vol_left = cpu_to_le32(0x40000000); | 515 | vol_left = cpu_to_le32(0x40000000); |
508 | vol_right = cpu_to_le32(0x40000000); | 516 | vol_right = cpu_to_le32(0x40000000); |
509 | } | 517 | } |
518 | spin_lock_irqsave(&ypcm->chip->voice_lock, flags); | ||
510 | format = runtime->channels == 2 ? 0x00010000 : 0; | 519 | format = runtime->channels == 2 ? 0x00010000 : 0; |
511 | if (snd_pcm_format_width(runtime->format) == 8) | 520 | if (snd_pcm_format_width(runtime->format) == 8) |
512 | 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 | } | ||
513 | if (runtime->channels == 2 && (voiceidx & 1) != 0) | 536 | if (runtime->channels == 2 && (voiceidx & 1) != 0) |
514 | format |= 1; | 537 | format |= 1; |
538 | spin_unlock_irqrestore(&ypcm->chip->voice_lock, flags); | ||
515 | for (nbank = 0; nbank < 2; nbank++) { | 539 | for (nbank = 0; nbank < 2; nbank++) { |
516 | bank = &voice->bank[nbank]; | 540 | bank = &voice->bank[nbank]; |
517 | memset(bank, 0, sizeof(*bank)); | 541 | memset(bank, 0, sizeof(*bank)); |
@@ -1480,7 +1504,7 @@ static int snd_ymfpci_put_single(struct snd_kcontrol *kcontrol, | |||
1480 | return change; | 1504 | return change; |
1481 | } | 1505 | } |
1482 | 1506 | ||
1483 | static DECLARE_TLV_DB_LINEAR(db_scale_native, TLV_DB_GAIN_MUTE, 0); | 1507 | static const DECLARE_TLV_DB_LINEAR(db_scale_native, TLV_DB_GAIN_MUTE, 0); |
1484 | 1508 | ||
1485 | #define YMFPCI_DOUBLE(xname, xindex, reg) \ | 1509 | #define YMFPCI_DOUBLE(xname, xindex, reg) \ |
1486 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ | 1510 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ |
@@ -1722,7 +1746,10 @@ static int snd_ymfpci_pcm_vol_put(struct snd_kcontrol *kcontrol, | |||
1722 | spin_lock_irqsave(&chip->voice_lock, flags); | 1746 | spin_lock_irqsave(&chip->voice_lock, flags); |
1723 | if (substream->runtime && substream->runtime->private_data) { | 1747 | if (substream->runtime && substream->runtime->private_data) { |
1724 | struct snd_ymfpci_pcm *ypcm = substream->runtime->private_data; | 1748 | struct snd_ymfpci_pcm *ypcm = substream->runtime->private_data; |
1725 | 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); | ||
1726 | } | 1753 | } |
1727 | spin_unlock_irqrestore(&chip->voice_lock, flags); | 1754 | spin_unlock_irqrestore(&chip->voice_lock, flags); |
1728 | return 1; | 1755 | return 1; |
@@ -1971,13 +1998,94 @@ static void snd_ymfpci_disable_dsp(struct snd_ymfpci *chip) | |||
1971 | } | 1998 | } |
1972 | } | 1999 | } |
1973 | 2000 | ||
2001 | #define FIRMWARE_IN_THE_KERNEL | ||
2002 | |||
2003 | #ifdef FIRMWARE_IN_THE_KERNEL | ||
2004 | |||
1974 | #include "ymfpci_image.h" | 2005 | #include "ymfpci_image.h" |
1975 | 2006 | ||
2007 | static struct firmware snd_ymfpci_dsp_microcode = { | ||
2008 | .size = YDSXG_DSPLENGTH, | ||
2009 | .data = (u8 *)DspInst, | ||
2010 | }; | ||
2011 | static struct firmware snd_ymfpci_controller_microcode = { | ||
2012 | .size = YDSXG_CTRLLENGTH, | ||
2013 | .data = (u8 *)CntrlInst, | ||
2014 | }; | ||
2015 | static struct firmware snd_ymfpci_controller_1e_microcode = { | ||
2016 | .size = YDSXG_CTRLLENGTH, | ||
2017 | .data = (u8 *)CntrlInst1E, | ||
2018 | }; | ||
2019 | #endif | ||
2020 | |||
2021 | #ifdef __LITTLE_ENDIAN | ||
2022 | static inline void snd_ymfpci_convert_from_le(const struct firmware *fw) { } | ||
2023 | #else | ||
2024 | static void snd_ymfpci_convert_from_le(const struct firmware *fw) | ||
2025 | { | ||
2026 | int i; | ||
2027 | u32 *data = (u32 *)fw->data; | ||
2028 | |||
2029 | for (i = 0; i < fw->size / 4; ++i) | ||
2030 | le32_to_cpus(&data[i]); | ||
2031 | } | ||
2032 | #endif | ||
2033 | |||
2034 | static int snd_ymfpci_request_firmware(struct snd_ymfpci *chip) | ||
2035 | { | ||
2036 | int err, is_1e; | ||
2037 | const char *name; | ||
2038 | |||
2039 | err = request_firmware(&chip->dsp_microcode, "yamaha/ds1_dsp.fw", | ||
2040 | &chip->pci->dev); | ||
2041 | if (err >= 0) { | ||
2042 | if (chip->dsp_microcode->size == YDSXG_DSPLENGTH) | ||
2043 | snd_ymfpci_convert_from_le(chip->dsp_microcode); | ||
2044 | else { | ||
2045 | snd_printk(KERN_ERR "DSP microcode has wrong size\n"); | ||
2046 | err = -EINVAL; | ||
2047 | } | ||
2048 | } | ||
2049 | if (err < 0) { | ||
2050 | #ifdef FIRMWARE_IN_THE_KERNEL | ||
2051 | chip->dsp_microcode = &snd_ymfpci_dsp_microcode; | ||
2052 | #else | ||
2053 | return err; | ||
2054 | #endif | ||
2055 | } | ||
2056 | is_1e = chip->device_id == PCI_DEVICE_ID_YAMAHA_724F || | ||
2057 | chip->device_id == PCI_DEVICE_ID_YAMAHA_740C || | ||
2058 | chip->device_id == PCI_DEVICE_ID_YAMAHA_744 || | ||
2059 | chip->device_id == PCI_DEVICE_ID_YAMAHA_754; | ||
2060 | name = is_1e ? "yamaha/ds1e_ctrl.fw" : "yamaha/ds1_ctrl.fw"; | ||
2061 | err = request_firmware(&chip->controller_microcode, name, | ||
2062 | &chip->pci->dev); | ||
2063 | if (err >= 0) { | ||
2064 | if (chip->controller_microcode->size == YDSXG_CTRLLENGTH) | ||
2065 | snd_ymfpci_convert_from_le(chip->controller_microcode); | ||
2066 | else { | ||
2067 | snd_printk(KERN_ERR "controller microcode" | ||
2068 | " has wrong size\n"); | ||
2069 | err = -EINVAL; | ||
2070 | } | ||
2071 | } | ||
2072 | if (err < 0) { | ||
2073 | #ifdef FIRMWARE_IN_THE_KERNEL | ||
2074 | chip->controller_microcode = | ||
2075 | is_1e ? &snd_ymfpci_controller_1e_microcode | ||
2076 | : &snd_ymfpci_controller_microcode; | ||
2077 | #else | ||
2078 | return err; | ||
2079 | #endif | ||
2080 | } | ||
2081 | return 0; | ||
2082 | } | ||
2083 | |||
1976 | static void snd_ymfpci_download_image(struct snd_ymfpci *chip) | 2084 | static void snd_ymfpci_download_image(struct snd_ymfpci *chip) |
1977 | { | 2085 | { |
1978 | int i; | 2086 | int i; |
1979 | u16 ctrl; | 2087 | u16 ctrl; |
1980 | unsigned long *inst; | 2088 | u32 *inst; |
1981 | 2089 | ||
1982 | snd_ymfpci_writel(chip, YDSXGR_NATIVEDACOUTVOL, 0x00000000); | 2090 | snd_ymfpci_writel(chip, YDSXGR_NATIVEDACOUTVOL, 0x00000000); |
1983 | snd_ymfpci_disable_dsp(chip); | 2091 | snd_ymfpci_disable_dsp(chip); |
@@ -1992,21 +2100,12 @@ static void snd_ymfpci_download_image(struct snd_ymfpci *chip) | |||
1992 | snd_ymfpci_writew(chip, YDSXGR_GLOBALCTRL, ctrl & ~0x0007); | 2100 | snd_ymfpci_writew(chip, YDSXGR_GLOBALCTRL, ctrl & ~0x0007); |
1993 | 2101 | ||
1994 | /* setup DSP instruction code */ | 2102 | /* setup DSP instruction code */ |
2103 | inst = (u32 *)chip->dsp_microcode->data; | ||
1995 | for (i = 0; i < YDSXG_DSPLENGTH / 4; i++) | 2104 | for (i = 0; i < YDSXG_DSPLENGTH / 4; i++) |
1996 | snd_ymfpci_writel(chip, YDSXGR_DSPINSTRAM + (i << 2), DspInst[i]); | 2105 | snd_ymfpci_writel(chip, YDSXGR_DSPINSTRAM + (i << 2), inst[i]); |
1997 | 2106 | ||
1998 | /* setup control instruction code */ | 2107 | /* setup control instruction code */ |
1999 | switch (chip->device_id) { | 2108 | inst = (u32 *)chip->controller_microcode->data; |
2000 | case PCI_DEVICE_ID_YAMAHA_724F: | ||
2001 | case PCI_DEVICE_ID_YAMAHA_740C: | ||
2002 | case PCI_DEVICE_ID_YAMAHA_744: | ||
2003 | case PCI_DEVICE_ID_YAMAHA_754: | ||
2004 | inst = CntrlInst1E; | ||
2005 | break; | ||
2006 | default: | ||
2007 | inst = CntrlInst; | ||
2008 | break; | ||
2009 | } | ||
2010 | for (i = 0; i < YDSXG_CTRLLENGTH / 4; i++) | 2109 | for (i = 0; i < YDSXG_CTRLLENGTH / 4; i++) |
2011 | snd_ymfpci_writel(chip, YDSXGR_CTRLINSTRAM + (i << 2), inst[i]); | 2110 | snd_ymfpci_writel(chip, YDSXGR_CTRLINSTRAM + (i << 2), inst[i]); |
2012 | 2111 | ||
@@ -2160,6 +2259,15 @@ static int snd_ymfpci_free(struct snd_ymfpci *chip) | |||
2160 | pci_write_config_word(chip->pci, 0x40, chip->old_legacy_ctrl); | 2259 | pci_write_config_word(chip->pci, 0x40, chip->old_legacy_ctrl); |
2161 | 2260 | ||
2162 | pci_disable_device(chip->pci); | 2261 | pci_disable_device(chip->pci); |
2262 | #ifdef FIRMWARE_IN_THE_KERNEL | ||
2263 | if (chip->dsp_microcode != &snd_ymfpci_dsp_microcode) | ||
2264 | #endif | ||
2265 | release_firmware(chip->dsp_microcode); | ||
2266 | #ifdef FIRMWARE_IN_THE_KERNEL | ||
2267 | if (chip->controller_microcode != &snd_ymfpci_controller_microcode && | ||
2268 | chip->controller_microcode != &snd_ymfpci_controller_1e_microcode) | ||
2269 | #endif | ||
2270 | release_firmware(chip->controller_microcode); | ||
2163 | kfree(chip); | 2271 | kfree(chip); |
2164 | return 0; | 2272 | return 0; |
2165 | } | 2273 | } |
@@ -2180,7 +2288,7 @@ static int saved_regs_index[] = { | |||
2180 | YDSXGR_PRIADCLOOPVOL, | 2288 | YDSXGR_PRIADCLOOPVOL, |
2181 | YDSXGR_NATIVEDACINVOL, | 2289 | YDSXGR_NATIVEDACINVOL, |
2182 | YDSXGR_NATIVEDACOUTVOL, | 2290 | YDSXGR_NATIVEDACOUTVOL, |
2183 | // YDSXGR_BUF441OUTVOL, | 2291 | YDSXGR_BUF441OUTVOL, |
2184 | YDSXGR_NATIVEADCINVOL, | 2292 | YDSXGR_NATIVEADCINVOL, |
2185 | YDSXGR_SPDIFLOOPVOL, | 2293 | YDSXGR_SPDIFLOOPVOL, |
2186 | YDSXGR_SPDIFOUTVOL, | 2294 | YDSXGR_SPDIFOUTVOL, |
@@ -2295,6 +2403,7 @@ int __devinit snd_ymfpci_create(struct snd_card *card, | |||
2295 | chip->reg_area_phys = pci_resource_start(pci, 0); | 2403 | chip->reg_area_phys = pci_resource_start(pci, 0); |
2296 | chip->reg_area_virt = ioremap_nocache(chip->reg_area_phys, 0x8000); | 2404 | chip->reg_area_virt = ioremap_nocache(chip->reg_area_phys, 0x8000); |
2297 | pci_set_master(pci); | 2405 | pci_set_master(pci); |
2406 | chip->src441_used = -1; | ||
2298 | 2407 | ||
2299 | 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) { |
2300 | 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); |
@@ -2315,6 +2424,12 @@ int __devinit snd_ymfpci_create(struct snd_card *card, | |||
2315 | return -EIO; | 2424 | return -EIO; |
2316 | } | 2425 | } |
2317 | 2426 | ||
2427 | err = snd_ymfpci_request_firmware(chip); | ||
2428 | if (err < 0) { | ||
2429 | snd_printk(KERN_ERR "firmware request failed: %d\n", err); | ||
2430 | snd_ymfpci_free(chip); | ||
2431 | return err; | ||
2432 | } | ||
2318 | snd_ymfpci_download_image(chip); | 2433 | snd_ymfpci_download_image(chip); |
2319 | 2434 | ||
2320 | udelay(100); /* seems we need a delay after downloading image.. */ | 2435 | udelay(100); /* seems we need a delay after downloading image.. */ |