diff --git a/debian/changelog b/debian/changelog index 98f69f812..dad0f6897 100644 --- a/debian/changelog +++ b/debian/changelog @@ -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 diff --git a/debian/patches/features/all/sound-pci-cs46xx-request_firmware.patch b/debian/patches/features/all/sound-pci-cs46xx-request_firmware.patch new file mode 100644 index 000000000..445a9a80f --- /dev/null +++ b/debian/patches/features/all/sound-pci-cs46xx-request_firmware.patch @@ -0,0 +1,169 @@ +From: Ben Hutchings + +Tested by Antonio Ospite . +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 + #include + #include ++#include + + + #include +@@ -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); diff --git a/debian/patches/series/base b/debian/patches/series/base index 06158f3e6..97fdea8f3 100644 --- a/debian/patches/series/base +++ b/debian/patches/series/base @@ -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