snd-cs46xx: reenable using external firmware (closes: #464197)
svn path=/dists/trunk/linux-2.6/; revision=14124
This commit is contained in:
parent
d3c7acc3e2
commit
10f2508e9d
|
@ -45,6 +45,8 @@ linux-2.6 (2.6.31~rc6-1~experimental.1) UNRELEASED; urgency=low
|
|||
* cxgb3: remove PHY firmware and use request_firmware() to load it
|
||||
* Add firmware-linux-free package containing DFSG-free firmware
|
||||
* av7110: include firmware source and binary
|
||||
* snd-cs46xx: reenable using external firmware (closes: #464197,
|
||||
but note that Debian cannot currently distribute the firmware)
|
||||
|
||||
[ Martin Michlmayr ]
|
||||
* [armel/orion5x, armel/kirkwood] Set GPIO_SYSFS=y since these
|
||||
|
|
|
@ -0,0 +1,169 @@
|
|||
From: Ben Hutchings <ben@decadent.org.uk>
|
||||
|
||||
Tested by Antonio Ospite <ospite@studenti.unina.it>.
|
||||
Unfortunately we cannot currently distribute the firmware.
|
||||
|
||||
diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig
|
||||
index 17e03b9..124b3a0 100644
|
||||
--- a/sound/pci/Kconfig
|
||||
+++ b/sound/pci/Kconfig
|
||||
@@ -229,7 +229,7 @@ config SND_CS4281
|
||||
|
||||
config SND_CS46XX
|
||||
tristate "Cirrus Logic (Sound Fusion) CS4280/CS461x/CS462x/CS463x"
|
||||
- depends on BROKEN
|
||||
+ select FW_LOADER
|
||||
select SND_RAWMIDI
|
||||
select SND_AC97_CODEC
|
||||
help
|
||||
@@ -241,6 +241,7 @@ config SND_CS46XX
|
||||
|
||||
config SND_CS46XX_NEW_DSP
|
||||
bool "Cirrus Logic (Sound Fusion) New DSP support"
|
||||
+ depends on BROKEN
|
||||
depends on SND_CS46XX
|
||||
default y
|
||||
help
|
||||
diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c
|
||||
index 1be96ea..b12b930 100644
|
||||
--- a/sound/pci/cs46xx/cs46xx_lib.c
|
||||
+++ b/sound/pci/cs46xx/cs46xx_lib.c
|
||||
@@ -53,6 +53,7 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/gameport.h>
|
||||
#include <linux/mutex.h>
|
||||
+#include <linux/firmware.h>
|
||||
|
||||
|
||||
#include <sound/core.h>
|
||||
@@ -308,7 +309,7 @@ static void snd_cs46xx_ac97_write(struct snd_ac97 *ac97,
|
||||
*/
|
||||
|
||||
int snd_cs46xx_download(struct snd_cs46xx *chip,
|
||||
- u32 *src,
|
||||
+ const __le32 *src,
|
||||
unsigned long offset,
|
||||
unsigned long len)
|
||||
{
|
||||
@@ -321,9 +322,9 @@ int snd_cs46xx_download(struct snd_cs46xx *chip,
|
||||
dst = chip->region.idx[bank+1].remap_addr + offset;
|
||||
len /= sizeof(u32);
|
||||
|
||||
- /* writel already converts 32-bit value to right endianess */
|
||||
while (len-- > 0) {
|
||||
- writel(*src++, dst);
|
||||
+ __raw_writel((__force u32)*src++, dst);
|
||||
+ mmiowb();
|
||||
dst += sizeof(u32);
|
||||
}
|
||||
return 0;
|
||||
@@ -360,23 +361,77 @@ int snd_cs46xx_clear_BA1(struct snd_cs46xx *chip,
|
||||
|
||||
#else /* old DSP image */
|
||||
|
||||
-#include "cs46xx_image.h"
|
||||
+struct cs46xx_old_image {
|
||||
+ __le32 size[BA1_MEMORY_COUNT];
|
||||
+ __le32 data[0];
|
||||
+};
|
||||
|
||||
-int snd_cs46xx_download_image(struct snd_cs46xx *chip)
|
||||
+static int snd_cs46xx_check_image_size(const struct firmware *firmware)
|
||||
{
|
||||
- int idx, err;
|
||||
- unsigned long offset = 0;
|
||||
+ const struct cs46xx_old_image *image =
|
||||
+ (const struct cs46xx_old_image *)firmware->data;
|
||||
+ size_t offset = sizeof(*image);
|
||||
+ int idx;
|
||||
+
|
||||
+ if (firmware->size < offset) {
|
||||
+ snd_printk(KERN_ERR "cs46xx: firmware too small\n");
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
|
||||
for (idx = 0; idx < BA1_MEMORY_COUNT; idx++) {
|
||||
- if ((err = snd_cs46xx_download(chip,
|
||||
- &BA1Struct.map[offset],
|
||||
- BA1Struct.memory[idx].offset,
|
||||
- BA1Struct.memory[idx].size)) < 0)
|
||||
- return err;
|
||||
- offset += BA1Struct.memory[idx].size >> 2;
|
||||
- }
|
||||
+ size_t size = le32_to_cpu(image->size[idx]);
|
||||
+
|
||||
+ if (size % sizeof(u32)) {
|
||||
+ snd_printk(KERN_ERR "cs46xx: firmware hunk misaligned\n");
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+ if (size > BA1_DWORD_SIZE * sizeof(u32)) {
|
||||
+ snd_printk(KERN_ERR "cs46xx: firmware hunk out of range\n");
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+ offset += size;
|
||||
+ }
|
||||
+
|
||||
+ if (firmware->size != offset) {
|
||||
+ snd_printk(KERN_ERR "cs46xx: firmware size mismatch\n");
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
+
|
||||
+static int snd_cs46xx_download_image(struct snd_cs46xx *chip)
|
||||
+{
|
||||
+ int idx, err;
|
||||
+ const struct firmware *firmware = NULL;
|
||||
+ const struct cs46xx_old_image *image;
|
||||
+ const __le32 *data;
|
||||
+
|
||||
+ err = request_firmware(&firmware, "cs46xx/cs46xx-old.fw",
|
||||
+ &chip->pci->dev);
|
||||
+ if (err < 0) {
|
||||
+ snd_printk(KERN_ERR "cs46xx: no firmware\n");
|
||||
+ return err;
|
||||
+ }
|
||||
+
|
||||
+ err = snd_cs46xx_check_image_size(firmware);
|
||||
+ if (err < 0)
|
||||
+ goto end;
|
||||
+ image = (const struct cs46xx_old_image *)firmware->data;
|
||||
+ data = image->data;
|
||||
+
|
||||
+ for (idx = 0; idx < BA1_MEMORY_COUNT; idx++) {
|
||||
+ size_t size = le32_to_cpu(image->size[idx]);
|
||||
+
|
||||
+ err = snd_cs46xx_download(chip, data, idx << 16, size);
|
||||
+ if (err < 0)
|
||||
+ goto end;
|
||||
+ data += size / sizeof(u32);
|
||||
+ }
|
||||
+end:
|
||||
+ release_firmware(firmware);
|
||||
+ return err;
|
||||
+}
|
||||
#endif /* CONFIG_SND_CS46XX_NEW_DSP */
|
||||
|
||||
/*
|
||||
@@ -3874,3 +3929,5 @@ int __devinit snd_cs46xx_create(struct snd_card *card,
|
||||
*rchip = chip;
|
||||
return 0;
|
||||
}
|
||||
+
|
||||
+MODULE_FIRMWARE("cs46xx/cs46xx-old.fw");
|
||||
diff --git a/sound/pci/cs46xx/cs46xx_lib.h b/sound/pci/cs46xx/cs46xx_lib.h
|
||||
index 4eb55aa..85babb5 100644
|
||||
--- a/sound/pci/cs46xx/cs46xx_lib.h
|
||||
+++ b/sound/pci/cs46xx/cs46xx_lib.h
|
||||
@@ -103,8 +103,8 @@ int cs46xx_dsp_proc_done (struct snd_cs46xx *chip);
|
||||
#define cs46xx_dsp_proc_done(chip)
|
||||
#endif
|
||||
int cs46xx_dsp_scb_and_task_init (struct snd_cs46xx *chip);
|
||||
-int snd_cs46xx_download (struct snd_cs46xx *chip, u32 *src, unsigned long offset,
|
||||
- unsigned long len);
|
||||
+int snd_cs46xx_download(struct snd_cs46xx *chip, const __le32 *src, unsigned long offset,
|
||||
+ unsigned long len);
|
||||
int snd_cs46xx_clear_BA1(struct snd_cs46xx *chip, unsigned long offset, unsigned long len);
|
||||
int cs46xx_dsp_enable_spdif_out (struct snd_cs46xx *chip);
|
||||
int cs46xx_dsp_enable_spdif_hw (struct snd_cs46xx *chip);
|
|
@ -14,6 +14,7 @@
|
|||
+ features/all/lib-crcitut-bit-reversed.patch
|
||||
+ features/all/drivers-staging-rt28x0sta-request_firmware.patch
|
||||
+ features/all/export-unionfs-symbols.patch
|
||||
+ features/all/sound-pci-cs46xx-request_firmware.patch
|
||||
|
||||
+ bugfix/sparc/drivers_net-broken.patch
|
||||
#+ bugfix/ia64/hardcode-arch-script-output.patch
|
||||
|
|
Loading…
Reference in New Issue