aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/ymfpci
diff options
context:
space:
mode:
authorClemens Ladisch <clemens@ladisch.de>2006-10-11 06:05:59 -0400
committerJaroslav Kysela <perex@suse.cz>2007-02-09 03:00:42 -0500
commit102fa9060e114a53628a6594034b6ecf624dffc6 (patch)
tree13a7fae84cbcea996d61b011bfc99b26b39125e5 /sound/pci/ymfpci
parente40a0b2e9d73c69e6b9e5d55eb56696f81fbf802 (diff)
[ALSA] ymfpci: add request_firmware()
Load the DSP and controller microcode using request_firmware(), if possible, instead of using the built-in firmware. Signed-off-by: Clemens Ladisch <clemens@ladisch.de> Signed-off-by: Jaroslav Kysela <perex@suse.cz>
Diffstat (limited to 'sound/pci/ymfpci')
-rw-r--r--sound/pci/ymfpci/ymfpci_image.h6
-rw-r--r--sound/pci/ymfpci/ymfpci_main.c125
2 files changed, 105 insertions, 26 deletions
diff --git a/sound/pci/ymfpci/ymfpci_image.h b/sound/pci/ymfpci/ymfpci_image.h
index 1b074699166..112f2fff6c8 100644
--- a/sound/pci/ymfpci/ymfpci_image.h
+++ b/sound/pci/ymfpci/ymfpci_image.h
@@ -1,7 +1,7 @@
1#ifndef _HWMCODE_ 1#ifndef _HWMCODE_
2#define _HWMCODE_ 2#define _HWMCODE_
3 3
4static unsigned long DspInst[YDSXG_DSPLENGTH / 4] = { 4static u32 DspInst[YDSXG_DSPLENGTH / 4] = {
5 0x00000081, 0x000001a4, 0x0000000a, 0x0000002f, 5 0x00000081, 0x000001a4, 0x0000000a, 0x0000002f,
6 0x00080253, 0x01800317, 0x0000407b, 0x0000843f, 6 0x00080253, 0x01800317, 0x0000407b, 0x0000843f,
7 0x0001483c, 0x0001943c, 0x0005d83c, 0x00001c3c, 7 0x0001483c, 0x0001943c, 0x0005d83c, 0x00001c3c,
@@ -12,7 +12,7 @@ static unsigned long DspInst[YDSXG_DSPLENGTH / 4] = {
12 0x00000000, 0x00000000, 0x00000000, 0x00000000 12 0x00000000, 0x00000000, 0x00000000, 0x00000000
13}; 13};
14 14
15static unsigned long CntrlInst[YDSXG_CTRLLENGTH / 4] = { 15static u32 CntrlInst[YDSXG_CTRLLENGTH / 4] = {
16 0x000007, 0x240007, 0x0C0007, 0x1C0007, 16 0x000007, 0x240007, 0x0C0007, 0x1C0007,
17 0x060007, 0x700002, 0x000020, 0x030040, 17 0x060007, 0x700002, 0x000020, 0x030040,
18 0x007104, 0x004286, 0x030040, 0x000F0D, 18 0x007104, 0x004286, 0x030040, 0x000F0D,
@@ -791,7 +791,7 @@ static unsigned long CntrlInst[YDSXG_CTRLLENGTH / 4] = {
791// 04/09 creat 791// 04/09 creat
792// 04/12 stop nise fix 792// 04/12 stop nise fix
793// 06/21 WorkingOff timming 793// 06/21 WorkingOff timming
794static unsigned long CntrlInst1E[YDSXG_CTRLLENGTH / 4] = { 794static u32 CntrlInst1E[YDSXG_CTRLLENGTH / 4] = {
795 0x000007, 0x240007, 0x0C0007, 0x1C0007, 795 0x000007, 0x240007, 0x0C0007, 0x1C0007,
796 0x060007, 0x700002, 0x000020, 0x030040, 796 0x060007, 0x700002, 0x000020, 0x030040,
797 0x007104, 0x004286, 0x030040, 0x000F0D, 797 0x007104, 0x004286, 0x030040, 0x000F0D,
diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c
index 7881944a195..5bde816cd5c 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
@@ -1971,13 +1963,94 @@ static void snd_ymfpci_disable_dsp(struct snd_ymfpci *chip)
1971 } 1963 }
1972} 1964}
1973 1965
1966#define FIRMWARE_IN_THE_KERNEL
1967
1968#ifdef FIRMWARE_IN_THE_KERNEL
1969
1974#include "ymfpci_image.h" 1970#include "ymfpci_image.h"
1975 1971
1972static struct firmware snd_ymfpci_dsp_microcode = {
1973 .size = YDSXG_DSPLENGTH,
1974 .data = (u8 *)DspInst,
1975};
1976static struct firmware snd_ymfpci_controller_microcode = {
1977 .size = YDSXG_CTRLLENGTH,
1978 .data = (u8 *)CntrlInst,
1979};
1980static struct firmware snd_ymfpci_controller_1e_microcode = {
1981 .size = YDSXG_CTRLLENGTH,
1982 .data = (u8 *)CntrlInst1E,
1983};
1984#endif
1985
1986#ifdef __LITTLE_ENDIAN
1987static inline void snd_ymfpci_convert_from_le(const struct firmware *fw) { }
1988#else
1989static void snd_ymfpci_convert_from_le(const struct firmware *fw)
1990{
1991 int i;
1992 u32 *data = (u32 *)fw->data;
1993
1994 for (i = 0; i < fw->size / 4; ++i)
1995 le32_to_cpus(&data[i]);
1996}
1997#endif
1998
1999static int snd_ymfpci_request_firmware(struct snd_ymfpci *chip)
2000{
2001 int err, is_1e;
2002 const char *name;
2003
2004 err = request_firmware(&chip->dsp_microcode, "yamaha/ds1_dsp.fw",
2005 &chip->pci->dev);
2006 if (err >= 0) {
2007 if (chip->dsp_microcode->size == YDSXG_DSPLENGTH)
2008 snd_ymfpci_convert_from_le(chip->dsp_microcode);
2009 else {
2010 snd_printk(KERN_ERR "DSP microcode has wrong size\n");
2011 err = -EINVAL;
2012 }
2013 }
2014 if (err < 0) {
2015#ifdef FIRMWARE_IN_THE_KERNEL
2016 chip->dsp_microcode = &snd_ymfpci_dsp_microcode;
2017#else
2018 return err;
2019#endif
2020 }
2021 is_1e = chip->device_id == PCI_DEVICE_ID_YAMAHA_724F ||
2022 chip->device_id == PCI_DEVICE_ID_YAMAHA_740C ||
2023 chip->device_id == PCI_DEVICE_ID_YAMAHA_744 ||
2024 chip->device_id == PCI_DEVICE_ID_YAMAHA_754;
2025 name = is_1e ? "yamaha/ds1e_ctrl.fw" : "yamaha/ds1_ctrl.fw";
2026 err = request_firmware(&chip->controller_microcode, name,
2027 &chip->pci->dev);
2028 if (err >= 0) {
2029 if (chip->controller_microcode->size == YDSXG_CTRLLENGTH)
2030 snd_ymfpci_convert_from_le(chip->controller_microcode);
2031 else {
2032 snd_printk(KERN_ERR "controller microcode"
2033 " has wrong size\n");
2034 err = -EINVAL;
2035 }
2036 }
2037 if (err < 0) {
2038#ifdef FIRMWARE_IN_THE_KERNEL
2039 chip->controller_microcode =
2040 is_1e ? &snd_ymfpci_controller_1e_microcode
2041 : &snd_ymfpci_controller_microcode;
2042#else
2043 return err;
2044#endif
2045 }
2046 return 0;
2047}
2048
1976static void snd_ymfpci_download_image(struct snd_ymfpci *chip) 2049static void snd_ymfpci_download_image(struct snd_ymfpci *chip)
1977{ 2050{
1978 int i; 2051 int i;
1979 u16 ctrl; 2052 u16 ctrl;
1980 unsigned long *inst; 2053 u32 *inst;
1981 2054
1982 snd_ymfpci_writel(chip, YDSXGR_NATIVEDACOUTVOL, 0x00000000); 2055 snd_ymfpci_writel(chip, YDSXGR_NATIVEDACOUTVOL, 0x00000000);
1983 snd_ymfpci_disable_dsp(chip); 2056 snd_ymfpci_disable_dsp(chip);
@@ -1992,21 +2065,12 @@ static void snd_ymfpci_download_image(struct snd_ymfpci *chip)
1992 snd_ymfpci_writew(chip, YDSXGR_GLOBALCTRL, ctrl & ~0x0007); 2065 snd_ymfpci_writew(chip, YDSXGR_GLOBALCTRL, ctrl & ~0x0007);
1993 2066
1994 /* setup DSP instruction code */ 2067 /* setup DSP instruction code */
2068 inst = (u32 *)chip->dsp_microcode->data;
1995 for (i = 0; i < YDSXG_DSPLENGTH / 4; i++) 2069 for (i = 0; i < YDSXG_DSPLENGTH / 4; i++)
1996 snd_ymfpci_writel(chip, YDSXGR_DSPINSTRAM + (i << 2), DspInst[i]); 2070 snd_ymfpci_writel(chip, YDSXGR_DSPINSTRAM + (i << 2), inst[i]);
1997 2071
1998 /* setup control instruction code */ 2072 /* setup control instruction code */
1999 switch (chip->device_id) { 2073 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++) 2074 for (i = 0; i < YDSXG_CTRLLENGTH / 4; i++)
2011 snd_ymfpci_writel(chip, YDSXGR_CTRLINSTRAM + (i << 2), inst[i]); 2075 snd_ymfpci_writel(chip, YDSXGR_CTRLINSTRAM + (i << 2), inst[i]);
2012 2076
@@ -2160,6 +2224,15 @@ static int snd_ymfpci_free(struct snd_ymfpci *chip)
2160 pci_write_config_word(chip->pci, 0x40, chip->old_legacy_ctrl); 2224 pci_write_config_word(chip->pci, 0x40, chip->old_legacy_ctrl);
2161 2225
2162 pci_disable_device(chip->pci); 2226 pci_disable_device(chip->pci);
2227#ifdef FIRMWARE_IN_THE_KERNEL
2228 if (chip->dsp_microcode != &snd_ymfpci_dsp_microcode)
2229#endif
2230 release_firmware(chip->dsp_microcode);
2231#ifdef FIRMWARE_IN_THE_KERNEL
2232 if (chip->controller_microcode != &snd_ymfpci_controller_microcode &&
2233 chip->controller_microcode != &snd_ymfpci_controller_1e_microcode)
2234#endif
2235 release_firmware(chip->controller_microcode);
2163 kfree(chip); 2236 kfree(chip);
2164 return 0; 2237 return 0;
2165} 2238}
@@ -2315,6 +2388,12 @@ int __devinit snd_ymfpci_create(struct snd_card *card,
2315 return -EIO; 2388 return -EIO;
2316 } 2389 }
2317 2390
2391 err = snd_ymfpci_request_firmware(chip);
2392 if (err < 0) {
2393 snd_printk(KERN_ERR "firmware request failed: %d\n", err);
2394 snd_ymfpci_free(chip);
2395 return err;
2396 }
2318 snd_ymfpci_download_image(chip); 2397 snd_ymfpci_download_image(chip);
2319 2398
2320 udelay(100); /* seems we need a delay after downloading image.. */ 2399 udelay(100); /* seems we need a delay after downloading image.. */