Commit ad233a5f authored by Takashi Iwai's avatar Takashi Iwai

ALSA: cs46xx: Move DSP blob out of kernel tree

... and load from the external firmware files.

The firmware binary blobs in cs46xx driver have been in a gray zone
regarding the license.  It's most likely should be OK, but still
unclear.  And, the size isn't that small, too.

Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=10750Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 5e01dc7b
......@@ -254,6 +254,7 @@ config SND_CS46XX
tristate "Cirrus Logic (Sound Fusion) CS4280/CS461x/CS462x/CS463x"
select SND_RAWMIDI
select SND_AC97_CODEC
select FW_LOADER
help
Say Y here to include support for Cirrus Logic CS4610/CS4612/
CS4614/CS4615/CS4622/CS4624/CS4630/CS4280 chips.
......
......@@ -1716,9 +1716,14 @@ struct snd_cs46xx {
struct snd_pcm *pcm_rear;
struct snd_pcm *pcm_center_lfe;
struct snd_pcm *pcm_iec958;
#define CS46XX_DSP_MODULES 5
struct dsp_module_desc *modules[CS46XX_DSP_MODULES];
#else /* for compatibility */
struct snd_cs46xx_pcm *playback_pcm;
unsigned int play_ctl;
struct ba1_struct *ba1;
#endif
#ifdef CONFIG_PM_SLEEP
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -54,7 +54,9 @@
#include <linux/gameport.h>
#include <linux/mutex.h>
#include <linux/export.h>
#include <linux/module.h>
#include <linux/firmware.h>
#include <linux/vmalloc.h>
#include <sound/core.h>
#include <sound/control.h>
......@@ -330,13 +332,146 @@ int snd_cs46xx_download(struct snd_cs46xx *chip,
return 0;
}
static inline void memcpy_le32(void *dst, const void *src, unsigned int len)
{
#ifdef __LITTLE_ENDIAN
memcpy(dst, src, len);
#else
u32 *_dst = dst;
const __le32 *_src = src;
len /= 4;
while (len-- > 0)
*_dst++ = le32_to_cpu(*_src++);
#endif
}
#ifdef CONFIG_SND_CS46XX_NEW_DSP
#include "imgs/cwc4630.h"
#include "imgs/cwcasync.h"
#include "imgs/cwcsnoop.h"
#include "imgs/cwcbinhack.h"
#include "imgs/cwcdma.h"
static const char *module_names[CS46XX_DSP_MODULES] = {
"cwc4630", "cwcasync", "cwcsnoop", "cwcbinhack", "cwcdma"
};
MODULE_FIRMWARE("cs46xx/cwc4630");
MODULE_FIRMWARE("cs46xx/cwcasync");
MODULE_FIRMWARE("cs46xx/cwcsnoop");
MODULE_FIRMWARE("cs46xx/cwcbinhack");
MODULE_FIRMWARE("cs46xx/cwcdma");
static void free_module_desc(struct dsp_module_desc *module)
{
if (!module)
return;
kfree(module->module_name);
kfree(module->symbol_table.symbols);
if (module->segments) {
int i;
for (i = 0; i < module->nsegments; i++)
kfree(module->segments[i].data);
kfree(module->segments);
}
}
/* firmware binary format:
* le32 nsymbols;
* struct {
* le32 address;
* char symbol_name[DSP_MAX_SYMBOL_NAME];
* le32 symbol_type;
* } symbols[nsymbols];
* le32 nsegments;
* struct {
* le32 segment_type;
* le32 offset;
* le32 size;
* le32 data[size];
* } segments[nsegments];
*/
static int load_firmware(struct snd_cs46xx *chip,
struct dsp_module_desc **module_ret,
const char *fw_name)
{
int i, err;
unsigned int nums, fwlen, fwsize;
const __le32 *fwdat;
struct dsp_module_desc *module = NULL;
const struct firmware *fw;
char fw_path[32];
sprintf(fw_path, "cs46xx/%s", fw_name);
err = request_firmware(&fw, fw_path, &chip->pci->dev);
if (err < 0)
return err;
fwsize = fw->size / 4;
if (fwsize < 2) {
err = -EINVAL;
goto error;
}
err = -ENOMEM;
module = kzalloc(sizeof(*module), GFP_KERNEL);
if (!module)
goto error;
module->module_name = kstrdup(fw_name, GFP_KERNEL);
if (!module->module_name)
goto error;
fwlen = 0;
fwdat = (const __le32 *)fw->data;
nums = module->symbol_table.nsymbols = le32_to_cpu(fwdat[fwlen++]);
if (nums >= 40)
goto error_inval;
module->symbol_table.symbols =
kcalloc(nums, sizeof(struct dsp_symbol_entry), GFP_KERNEL);
if (!module->symbol_table.symbols)
goto error;
for (i = 0; i < nums; i++) {
struct dsp_symbol_entry *entry =
&module->symbol_table.symbols[i];
if (fwlen + 2 + DSP_MAX_SYMBOL_NAME / 4 > fwsize)
goto error_inval;
entry->address = le32_to_cpu(fwdat[fwlen++]);
memcpy(entry->symbol_name, &fwdat[fwlen], DSP_MAX_SYMBOL_NAME - 1);
fwlen += DSP_MAX_SYMBOL_NAME / 4;
entry->symbol_type = le32_to_cpu(fwdat[fwlen++]);
}
if (fwlen >= fwsize)
goto error_inval;
nums = module->nsegments = le32_to_cpu(fwdat[fwlen++]);
if (nums > 10)
goto error_inval;
module->segments =
kcalloc(nums, sizeof(struct dsp_segment_desc), GFP_KERNEL);
if (!module->segments)
goto error;
for (i = 0; i < nums; i++) {
struct dsp_segment_desc *entry = &module->segments[i];
if (fwlen + 3 > fwsize)
goto error_inval;
entry->segment_type = le32_to_cpu(fwdat[fwlen++]);
entry->offset = le32_to_cpu(fwdat[fwlen++]);
entry->size = le32_to_cpu(fwdat[fwlen++]);
if (fwlen + entry->size > fwsize)
goto error_inval;
entry->data = kmalloc(entry->size * 4, GFP_KERNEL);
if (!entry->data)
goto error;
memcpy_le32(entry->data, &fwdat[fwlen], entry->size * 4);
fwlen += entry->size;
}
*module_ret = module;
release_firmware(fw);
return 0;
error_inval:
err = -EINVAL;
error:
free_module_desc(module);
release_firmware(fw);
return err;
}
int snd_cs46xx_clear_BA1(struct snd_cs46xx *chip,
unsigned long offset,
......@@ -361,20 +496,63 @@ int snd_cs46xx_clear_BA1(struct snd_cs46xx *chip,
#else /* old DSP image */
#include "cs46xx_image.h"
struct ba1_struct {
struct {
u32 offset;
u32 size;
} memory[BA1_MEMORY_COUNT];
u32 map[BA1_DWORD_SIZE];
};
MODULE_FIRMWARE("cs46xx/ba1");
static int load_firmware(struct snd_cs46xx *chip)
{
const struct firmware *fw;
int i, size, err;
err = request_firmware(&fw, "cs46xx/ba1", &chip->pci->dev);
if (err < 0)
return err;
if (fw->size != sizeof(*chip->ba1)) {
err = -EINVAL;
goto error;
}
chip->ba1 = vmalloc(sizeof(*chip->ba1));
if (!chip->ba1) {
err = -ENOMEM;
goto error;
}
memcpy_le32(chip->ba1, fw->data, sizeof(*chip->ba1));
/* sanity check */
size = 0;
for (i = 0; i < BA1_MEMORY_COUNT; i++)
size += chip->ba1->memory[i].size;
if (size > BA1_DWORD_SIZE * 4)
err = -EINVAL;
error:
release_firmware(fw);
return err;
}
int snd_cs46xx_download_image(struct snd_cs46xx *chip)
{
int idx, err;
unsigned long offset = 0;
unsigned int offset = 0;
struct ba1_struct *ba1 = chip->ba1;
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)
err = snd_cs46xx_download(chip,
&ba1->map[offset],
ba1->memory[idx].offset,
ba1->memory[idx].size);
if (err < 0)
return err;
offset += BA1Struct.memory[idx].size >> 2;
offset += ba1->memory[idx].size >> 2;
}
return 0;
}
......@@ -2798,6 +2976,10 @@ static int snd_cs46xx_free(struct snd_cs46xx *chip)
cs46xx_dsp_spos_destroy(chip);
chip->dsp_spos_instance = NULL;
}
for (idx = 0; idx < CS46XX_DSP_MODULES; idx++)
free_module_desc(chip->modules[idx]);
#else
vfree(chip->ba1);
#endif
#ifdef CONFIG_PM_SLEEP
......@@ -3067,6 +3249,11 @@ static void cs46xx_enable_stream_irqs(struct snd_cs46xx *chip)
int snd_cs46xx_start_dsp(struct snd_cs46xx *chip)
{
unsigned int tmp;
#ifdef CONFIG_SND_CS46XX_NEW_DSP
int i;
#endif
int err;
/*
* Reset the processor.
*/
......@@ -3075,45 +3262,33 @@ int snd_cs46xx_start_dsp(struct snd_cs46xx *chip)
* Download the image to the processor.
*/
#ifdef CONFIG_SND_CS46XX_NEW_DSP
#if 0
if (cs46xx_dsp_load_module(chip, &cwcemb80_module) < 0) {
snd_printk(KERN_ERR "image download error\n");
return -EIO;
}
#endif
if (cs46xx_dsp_load_module(chip, &cwc4630_module) < 0) {
snd_printk(KERN_ERR "image download error [cwc4630]\n");
return -EIO;
}
if (cs46xx_dsp_load_module(chip, &cwcasync_module) < 0) {
snd_printk(KERN_ERR "image download error [cwcasync]\n");
return -EIO;
}
if (cs46xx_dsp_load_module(chip, &cwcsnoop_module) < 0) {
snd_printk(KERN_ERR "image download error [cwcsnoop]\n");
return -EIO;
for (i = 0; i < CS46XX_DSP_MODULES; i++) {
err = load_firmware(chip, &chip->modules[i], module_names[i]);
if (err < 0) {
snd_printk(KERN_ERR "firmware load error [%s]\n",
module_names[i]);
return err;
}
if (cs46xx_dsp_load_module(chip, &cwcbinhack_module) < 0) {
snd_printk(KERN_ERR "image download error [cwcbinhack]\n");
return -EIO;
err = cs46xx_dsp_load_module(chip, chip->modules[i]);
if (err < 0) {
snd_printk(KERN_ERR "image download error [%s]\n",
module_names[i]);
return err;
}
if (cs46xx_dsp_load_module(chip, &cwcdma_module) < 0) {
snd_printk(KERN_ERR "image download error [cwcdma]\n");
return -EIO;
}
if (cs46xx_dsp_scb_and_task_init(chip) < 0)
return -EIO;
#else
err = load_firmware(chip);
if (err < 0)
return err;
/* old image */
if (snd_cs46xx_download_image(chip) < 0) {
err = snd_cs46xx_download_image(chip);
if (err < 0) {
snd_printk(KERN_ERR "image download error\n");
return -EIO;
return err;
}
/*
......
This diff is collapsed.
/* generated from cwcasync.osp DO NOT MODIFY */
#ifndef __HEADER_cwcasync_H__
#define __HEADER_cwcasync_H__
static struct dsp_symbol_entry cwcasync_symbols[] = {
{ 0x8000, "EXECCHILD",0x03 },
{ 0x8001, "EXECCHILD_98",0x03 },
{ 0x8003, "EXECCHILD_PUSH1IND",0x03 },
{ 0x8008, "EXECSIBLING",0x03 },
{ 0x800a, "EXECSIBLING_298",0x03 },
{ 0x800b, "EXECSIBLING_2IND1",0x03 },
{ 0x8010, "TIMINGMASTER",0x03 },
{ 0x804f, "S16_CODECINPUTTASK",0x03 },
{ 0x805e, "PCMSERIALINPUTTASK",0x03 },
{ 0x806d, "S16_MIX_TO_OSTREAM",0x03 },
{ 0x809a, "S16_MIX",0x03 },
{ 0x80bb, "S16_UPSRC",0x03 },
{ 0x813b, "MIX3_EXP",0x03 },
{ 0x8164, "DECIMATEBYPOW2",0x03 },
{ 0x8197, "VARIDECIMATE",0x03 },
{ 0x81f2, "_3DINPUTTASK",0x03 },
{ 0x820a, "_3DPRLGCINPTASK",0x03 },
{ 0x8227, "_3DSTEREOINPUTTASK",0x03 },
{ 0x8242, "_3DOUTPUTTASK",0x03 },
{ 0x82c4, "HRTF_MORPH_TASK",0x03 },
{ 0x82c6, "WAIT4DATA",0x03 },
{ 0x82fa, "PROLOGIC",0x03 },
{ 0x8496, "DECORRELATOR",0x03 },
{ 0x84a4, "STEREO2MONO",0x03 },
{ 0x0000, "OVERLAYBEGINADDRESS",0x00 },
{ 0x0000, "SPIOWRITE",0x03 },
{ 0x000d, "S16_ASYNCCODECINPUTTASK",0x03 },
{ 0x0043, "SPDIFITASK",0x03 },
{ 0x007b, "SPDIFOTASK",0x03 },
{ 0x0097, "ASYNCHFGTXCODE",0x03 },
{ 0x00be, "ASYNCHFGRXCODE",0x03 },
{ 0x00db, "#CODE_END",0x00 },
}; /* cwcasync symbols */
static u32 cwcasync_code[] = {
/* OVERLAYBEGINADDRESS */
/* 0000 */ 0x00002731,0x00001400,0x00003725,0x000a8440,
/* 0002 */ 0x000000ae,0x00000000,0x00060630,0x00001000,
/* 0004 */ 0x00000000,0x000c7560,0x00075282,0x0002d640,
/* 0006 */ 0x00021705,0x00000000,0x00072ab8,0x0002d6c0,
/* 0008 */ 0x00020630,0x00001000,0x000c74c2,0x000d4b82,
/* 000A */ 0x000475c2,0x00000000,0x0003430a,0x000c0000,
/* 000C */ 0x00042730,0x00001400,
/* S16_ASYNCCODECINPUTTASK */
/* 000D */ 0x0006a108,0x000cf2c4,0x0004f4c0,0x00000000,
/* 000F */ 0x000fa418,0x0000101f,0x0005d402,0x0001c500,
/* 0011 */ 0x000f0630,0x00001000,0x00004418,0x00001380,
/* 0013 */ 0x000e243d,0x000d394a,0x00049705,0x00000000,
/* 0015 */ 0x0007d530,0x000b4240,0x000e00f2,0x00001000,
/* 0017 */ 0x00009134,0x000ca20a,0x00004c90,0x00001000,
/* 0019 */ 0x0005d705,0x00000000,0x00004f25,0x00098240,
/* 001B */ 0x00004725,0x00000000,0x0000e48a,0x00000000,
/* 001D */ 0x00027295,0x0009c2c0,0x0003df25,0x00000000,
/* 001F */ 0x000e8030,0x00001001,0x0005f718,0x000ac600,
/* 0021 */ 0x0007cf30,0x000c2a01,0x00082630,0x00001001,
/* 0023 */ 0x000504a0,0x00001001,0x00029314,0x000bcb80,
/* 0025 */ 0x0003cf25,0x000b0e00,0x0004f5c0,0x00000000,
/* 0027 */ 0x00049118,0x000d888a,0x0007dd02,0x000c6efa,
/* 0029 */ 0x00000000,0x00000000,0x0004f5c0,0x00069c80,
/* 002B */ 0x0000d402,0x00000000,0x000e8630,0x00001001,
/* 002D */ 0x00079130,0x00000000,0x00049118,0x00090e00,
/* 002F */ 0x0006c10a,0x00000000,0x00000000,0x000c0000,
/* 0031 */ 0x0007cf30,0x00030580,0x00005725,0x00000000,
/* 0033 */ 0x000d84a0,0x00001001,0x00029314,0x000b4780,
/* 0035 */ 0x0003cf25,0x000b8600,0x00000000,0x00000000,
/* 0037 */ 0x00000000,0x000c0000,0x00000000,0x00042c80,
/* 0039 */ 0x0001dec1,0x000e488c,0x00031114,0x00000000,
/* 003B */ 0x0004f5c2,0x00000000,0x0003640a,0x00000000,
/* 003D */ 0x00000000,0x000e5084,0x00000000,0x000eb844,
/* 003F */ 0x00007001,0x00000000,0x00000734,0x00001000,
/* 0041 */ 0x00010705,0x000a6880,0x00006a88,0x000c75c4,
/* SPDIFITASK */
/* 0043 */ 0x0006a108,0x000cf2c4,0x0004f4c0,0x000d5384,
/* 0045 */ 0x0007e48a,0x00000000,0x00067718,0x00001000,
/* 0047 */ 0x0007a418,0x00001000,0x0007221a,0x00000000,
/* 0049 */ 0x0005d402,0x00014500,0x000b8630,0x00001002,
/* 004B */ 0x00004418,0x00001780,0x000e243d,0x000d394a,
/* 004D */ 0x00049705,0x00000000,0x0007d530,0x000b4240,
/* 004F */ 0x000ac0f2,0x00001002,0x00014414,0x00000000,
/* 0051 */ 0x00004c90,0x00001000,0x0005d705,0x00000000,
/* 0053 */ 0x00004f25,0x00098240,0x00004725,0x00000000,
/* 0055 */ 0x0000e48a,0x00000000,0x00027295,0x0009c2c0,
/* 0057 */ 0x0007df25,0x00000000,0x000ac030,0x00001003,
/* 0059 */ 0x0005f718,0x000fe798,0x00029314,0x000bcb80,
/* 005B */ 0x00000930,0x000b0e00,0x0004f5c0,0x000de204,
/* 005D */ 0x000884a0,0x00001003,0x0007cf25,0x000e3560,
/* 005F */ 0x00049118,0x00000000,0x00049118,0x000d888a,
/* 0061 */ 0x0007dd02,0x000c6efa,0x0000c434,0x00030040,
/* 0063 */ 0x000fda82,0x000c2312,0x000fdc0e,0x00001001,
/* 0065 */ 0x00083402,0x000c2b92,0x000706b0,0x00001003,
/* 0067 */ 0x00075a82,0x00000000,0x0000d625,0x000b0940,
/* 0069 */ 0x0000840e,0x00001002,0x0000aabc,0x000c511e,
/* 006B */ 0x00078730,0x00001003,0x0000aaf4,0x000e910a,
/* 006D */ 0x0004628a,0x00000000,0x00006aca,0x00000000,
/* 006F */ 0x00000930,0x00000000,0x0004f5c0,0x00069c80,
/* 0071 */ 0x00046ac0,0x00000000,0x0003c40a,0x000fc898,
/* 0073 */ 0x00049118,0x00090e00,0x0006c10a,0x00000000,
/* 0075 */ 0x00000000,0x000e5084,0x00000000,0x000eb844,
/* 0077 */ 0x00007001,0x00000000,0x00000734,0x00001000,
/* 0079 */ 0x00010705,0x000a6880,0x00006a88,0x000c75c4,
/* SPDIFOTASK */
/* 007B */ 0x0006a108,0x000c0000,0x0004f4c0,0x000c3245,
/* 007D */ 0x0000a418,0x00001000,0x0003a20a,0x00000000,
/* 007F */ 0x00004418,0x00001380,0x000e243d,0x000d394a,
/* 0081 */ 0x000c9705,0x000def92,0x0008c030,0x00001004,
/* 0083 */ 0x0005f718,0x000fe798,0x00000000,0x000c0000,
/* 0085 */ 0x00005725,0x00000000,0x000704a0,0x00001004,
/* 0087 */ 0x00029314,0x000b4780,0x0003cf25,0x000b8600,
/* 0089 */ 0x00000000,0x00000000,0x00000000,0x000c0000,
/* 008B */ 0x00000000,0x00042c80,0x0001dec1,0x000e488c,
/* 008D */ 0x00031114,0x00000000,0x0004f5c2,0x00000000,
/* 008F */ 0x0004a918,0x00098600,0x0006c28a,0x00000000,
/* 0091 */ 0x00000000,0x000e5084,0x00000000,0x000eb844,
/* 0093 */ 0x00007001,0x00000000,0x00000734,0x00001000,
/* 0095 */ 0x00010705,0x000a6880,0x00006a88,0x000c75c4,
/* ASYNCHFGTXCODE */
/* 0097 */ 0x0002a880,0x000b4e40,0x00042214,0x000e5548,
/* 0099 */ 0x000542bf,0x00000000,0x00000000,0x000481c0,
/* 009B */ 0x00000000,0x00000000,0x00000000,0x00000030,
/* 009D */ 0x0000072d,0x000fbf8a,0x00077f94,0x000ea7df,
/* 009F */ 0x0002ac95,0x000d3145,0x00002731,0x00001400,
/* 00A1 */ 0x00006288,0x000c71c4,0x00014108,0x000e6044,
/* 00A3 */ 0x00035408,0x00000000,0x00025418,0x000a0ec0,
/* 00A5 */ 0x0001443d,0x000ca21e,0x00046595,0x000d730c,
/* 00A7 */ 0x0006538e,0x00000000,0x00064630,0x00001005,
/* 00A9 */ 0x000e7b0e,0x000df782,0x000746b0,0x00001005,
/* 00AB */ 0x00036f05,0x000c0000,0x00043695,0x000d598c,
/* 00AD */ 0x0005331a,0x000f2185,0x00000000,0x00000000,
/* 00AF */ 0x000007ae,0x000bdb00,0x00040630,0x00001400,
/* 00B1 */ 0x0005e708,0x000c0000,0x0007ef30,0x000b1c00,
/* 00B3 */ 0x000d86a0,0x00001005,0x00066408,0x000c0000,
/* 00B5 */ 0x00000000,0x00000000,0x00021843,0x00000000,
/* 00B7 */ 0x00000cac,0x00062c00,0x00001dac,0x00063400,
/* 00B9 */ 0x00002cac,0x0006cc80,0x000db943,0x000e5ca1,
/* 00BB */ 0x00000000,0x00000000,0x0006680a,0x000f3205,
/* 00BD */ 0x00042730,0x00001400,
/* ASYNCHFGRXCODE */
/* 00BE */ 0x00014108,0x000f2204,0x00025418,0x000a2ec0,
/* 00C0 */ 0x00015dbd,0x00038100,0x00015dbc,0x00000000,
/* 00C2 */ 0x0005e415,0x00034880,0x0001258a,0x000d730c,
/* 00C4 */ 0x0006538e,0x000baa40,0x00060630,0x00001006,
/* 00C6 */ 0x00067b0e,0x000ac380,0x0003ef05,0x00000000,
/* 00C8 */ 0x0000f734,0x0001c300,0x000586b0,0x00001400,
/* 00CA */ 0x000b6f05,0x000c3a00,0x00048f05,0x00000000,
/* 00CC */ 0x0005b695,0x0008c380,0x0002058e,0x00000000,
/* 00CE */ 0x000500b0,0x00001400,0x0002b318,0x000e998d,
/* 00D0 */ 0x0006430a,0x00000000,0x00000000,0x000ef384,
/* 00D2 */ 0x00004725,0x000c0000,0x00000000,0x000f3204,
/* 00D4 */ 0x00004f25,0x000c0000,0x00080000,0x000e5ca1,
/* 00D6 */ 0x000cb943,0x000e5ca1,0x0004b943,0x00000000,
/* 00D8 */ 0x00040730,0x00001400,0x000cb943,0x000e5ca1,
/* 00DA */ 0x0004b943,0x00000000
};
/* #CODE_END */
static struct dsp_segment_desc cwcasync_segments[] = {
{ SEGTYPE_SP_PROGRAM, 0x00000000, 0x000001b6, cwcasync_code },
};
static struct dsp_module_desc cwcasync_module = {
"cwcasync",
{
32,
cwcasync_symbols
},
1,
cwcasync_segments,
};
#endif /* __HEADER_cwcasync_H__ */
/* generated by Benny
MODIFY ON YOUR OWN RISK */
#ifndef __HEADER_cwcbinhack_H__
#define __HEADER_cwcbinhack_H__
static struct dsp_symbol_entry cwcbinhack_symbols[] = {
{ 0x02c8, "OVERLAYBEGINADDRESS",0x00 },
{ 0x02c8, "MAGICSNOOPTASK",0x03 },
{ 0x0308, "#CODE_END",0x00 },
}; /* cwcbinhack symbols */
static u32 cwcbinhack_code[] = {
/* 0x02c8 */
0x0007bfb0,0x000bc240,0x00000c2e,0x000c6084, /* 1 */
0x000b8630,0x00001016,0x00006408,0x000efb84, /* 2 */
0x00016008,0x00000000,0x0001c088,0x000c0000, /* 3 */
0x000fc908,0x000e3392,0x0005f488,0x000efb84, /* 4 */
0x0001d402,0x000b2e00,0x0003d418,0x00001000, /* 5 */
0x0008d574,0x000c4293,0x00065625,0x000ea30e, /* 6 */
0x00096c01,0x000c6f92,0x0001a58a,0x000c6085, /* 7 */
0x00002f43,0x00000000,0x000e03a0,0x00001016, /* 8 */
0x0005e608,0x000c0000,0x00000000,0x00000000, /* 9 */
0x000ca108,0x000dcca1,0x00003bac,0x000c3205, /* 10 */
0x00073843,0x00000000,0x00010730,0x00001017, /* 11 */
0x0001600a,0x000c0000,0x00057488,0x00000000, /* 12 */
0x00000000,0x000e5084,0x00000000,0x000eba44, /* 13 */
0x00087401,0x000e4782,0x00000734,0x00001000, /* 14 */
0x00010705,0x000a6880,0x00006a88,0x000c75c4, /* 15 */
0x00000000,0x00000000,0x00000000,0x00000000, /* 16 */
};
/* #CODE_END */
static struct dsp_segment_desc cwcbinhack_segments[] = {
{ SEGTYPE_SP_PROGRAM, 0x00000000, 64, cwcbinhack_code },
};
static struct dsp_module_desc cwcbinhack_module = {
"cwcbinhack",
{
3,
cwcbinhack_symbols
},
1,
cwcbinhack_segments,
};
#endif /* __HEADER_cwcbinhack_H__ */
//
// Copyright(c) by Benny Sjostrand (benny@hostmobility.com)
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
//
// This code runs inside the DSP (cs4610, cs4612, cs4624, or cs4630),
// to compile it you need a tool named SPASM 3.0 and DSP code owned by
// Cirrus Logic(R). The SPASM program will generate a object file (cwcdma.osp),
// the "ospparser" tool will genereate the cwcdma.h file it's included from
// the cs46xx_lib.c file.
//
//
// The purpose of this code is very simple: make it possible to tranfser
// the samples 'as they are' with no alteration from a PCMreader
// SCB (DMA from host) to any other SCB. This is useful for AC3 through SPDIF.
// SRC (source rate converters) task always alters the samples in somehow,
// however it's from 48khz -> 48khz.
// The alterations are not audible, but AC3 wont work.
//
// ...
// |
// +---------------+
// | AsynchFGTxSCB |
// +---------------+
// |
// subListPtr
// |
// +--------------+
// | DMAReader |
// +--------------+
// |
// subListPtr
// |
// +-------------+
// | PCMReader |
// +-------------+
// (DMA from host)
//
struct dmaSCB
{
long dma_reserved1[3];
short dma_reserved2:dma_outBufPtr;
short dma_unused1:dma_unused2;
long dma_reserved3[4];
short dma_subListPtr:dma_nextSCB;
short dma_SPBptr:dma_entryPoint;
long dma_strmRsConfig;
long dma_strmBufPtr;
long dma_reserved4;
VolumeControl s2m_volume;
};
#export DMAReader
void DMAReader()
{
execChild();
r2 = r0->dma_subListPtr;
r1 = r0->nextSCB;
rsConfig01 = r2->strmRsConfig;
// Load rsConfig for input buffer
rsDMA01 = r2->basicReq.daw, , tb = Z(0 - rf);
// Load rsDMA in case input buffer is a DMA buffer Test to see if there is any data to transfer
if (tb) goto execSibling_2ind1 after {
r5 = rf + (-1);
r6 = r1->dma_entryPoint; // r6 = entry point of sibling task
r1 = r1->dma_SPBptr, // r1 = pointer to sibling task's SPB
, ind = r6; // Load entry point of sibling task
}
rsConfig23 = r0->dma_strmRsConfig;
// Load rsConfig for output buffer (never a DMA buffer)
r4 = r0->dma_outBufPtr;
rsa0 = r2->strmBufPtr;
// rsa0 = input buffer pointer
for (i = r5; i >= 0; --i)
after {
rsa2 = r4;
// rsa2 = output buffer pointer
nop;
nop;
}
//*****************************
// TODO: cycles to this point *
//*****************************
{
acc0 = (rsd0 = *rsa0++1);
// get sample
nop; // Those "nop"'s are really uggly, but there's
nop; // something with DSP's pipelines which I don't
nop; // understand, resulting this code to fail without
// having those "nop"'s (Benny)
rsa0?reqDMA = r2;
// Trigger DMA transfer on input stream,
// if needed to replenish input buffer
nop;
// Yet another magic "nop" to make stuff work
,,r98 = acc0 $+>> 0;
// store sample in ALU
nop;
// latency on load register.
// (this one is understandable)
*rsa2++1 = r98;
// store sample in output buffer
nop; // The same story
nop; // as above again ...
nop;
}
// TODO: cycles per loop iteration
r2->strmBufPtr = rsa0,, ;
// Update the modified buffer pointers
r4 = rsa2;
// Load output pointer position into r4
r2 = r0->nextSCB;
// Sibling task
goto execSibling_2ind1 // takes 6 cycles
after {
r98 = r2->thisSPB:entryPoint;
// Load child routine entry and data address
r1 = r9;
// r9 is r2->thisSPB
r0->dma_outBufPtr = r4,,
// Store updated output buffer pointer
ind = r8;
// r8 is r2->entryPoint
}
}
/* generated from cwcdma.osp DO NOT MODIFY */
#ifndef __HEADER_cwcdma_H__
#define __HEADER_cwcdma_H__
static struct dsp_symbol_entry cwcdma_symbols[] = {
{ 0x8000, "EXECCHILD",0x03 },
{ 0x8001, "EXECCHILD_98",0x03 },
{ 0x8003, "EXECCHILD_PUSH1IND",0x03 },
{ 0x8008, "EXECSIBLING",0x03 },
{ 0x800a, "EXECSIBLING_298",0x03 },
{ 0x800b, "EXECSIBLING_2IND1",0x03 },
{ 0x8010, "TIMINGMASTER",0x03 },
{ 0x804f, "S16_CODECINPUTTASK",0x03 },
{ 0x805e, "PCMSERIALINPUTTASK",0x03 },
{ 0x806d, "S16_MIX_TO_OSTREAM",0x03 },
{ 0x809a, "S16_MIX",0x03 },
{ 0x80bb, "S16_UPSRC",0x03 },
{ 0x813b, "MIX3_EXP",0x03 },
{ 0x8164, "DECIMATEBYPOW2",0x03 },
{ 0x8197, "VARIDECIMATE",0x03 },
{ 0x81f2, "_3DINPUTTASK",0x03 },
{ 0x820a, "_3DPRLGCINPTASK",0x03 },
{ 0x8227, "_3DSTEREOINPUTTASK",0x03 },
{ 0x8242, "_3DOUTPUTTASK",0x03 },
{ 0x82c4, "HRTF_MORPH_TASK",0x03 },
{ 0x82c6, "WAIT4DATA",0x03 },
{ 0x82fa, "PROLOGIC",0x03 },
{ 0x8496, "DECORRELATOR",0x03 },
{ 0x84a4, "STEREO2MONO",0x03 },
{ 0x0000, "OVERLAYBEGINADDRESS",0x00 },
{ 0x0000, "DMAREADER",0x03 },
{ 0x0018, "#CODE_END",0x00 },
}; /* cwcdma symbols */
static u32 cwcdma_code[] = {
/* OVERLAYBEGINADDRESS */
/* 0000 */ 0x00002731,0x00001400,0x0004c108,0x000e5044,
/* 0002 */ 0x0005f608,0x00000000,0x000007ae,0x000be300,
/* 0004 */ 0x00058630,0x00001400,0x0007afb0,0x000e9584,
/* 0006 */ 0x00007301,0x000a9840,0x0005e708,0x000cd104,
/* 0008 */ 0x00067008,0x00000000,0x000902a0,0x00001000,
/* 000A */ 0x00012a01,0x000c0000,0x00000000,0x00000000,
/* 000C */ 0x00021843,0x000c0000,0x00000000,0x000c0000,
/* 000E */ 0x0000e101,0x000c0000,0x00000cac,0x00000000,
/* 0010 */ 0x00080000,0x000e5ca1,0x00000000,0x000c0000,
/* 0012 */ 0x00000000,0x00000000,0x00000000,0x00092c00,
/* 0014 */ 0x000122c1,0x000e5084,0x00058730,0x00001400,
/* 0016 */ 0x000d7488,0x000e4782,0x00007401,0x0001c100
};
/* #CODE_END */
static struct dsp_segment_desc cwcdma_segments[] = {
{ SEGTYPE_SP_PROGRAM, 0x00000000, 0x00000030, cwcdma_code },
};
static struct dsp_module_desc cwcdma_module = {
"cwcdma",
{
27,
cwcdma_symbols
},
1,
cwcdma_segments,
};
#endif /* __HEADER_cwcdma_H__ */
/* generated from cwcsnoop.osp DO NOT MODIFY */
#ifndef __HEADER_cwcsnoop_H__
#define __HEADER_cwcsnoop_H__
static struct dsp_symbol_entry cwcsnoop_symbols[] = {
{ 0x0500, "OVERLAYBEGINADDRESS",0x00 },
{ 0x0500, "OUTPUTSNOOP",0x03 },
{ 0x051f, "#CODE_END",0x00 },
}; /* cwcsnoop symbols */
static u32 cwcsnoop_code[] = {
/* 0000 */ 0x0007bfb0,0x000b4e40,0x0007c088,0x000c0617,
/* 0002 */ 0x00049705,0x00000000,0x00080630,0x00001028,
/* 0004 */ 0x00076408,0x000efb84,0x00066008,0x00000000,
/* 0006 */ 0x0007c908,0x000c0000,0x00046725,0x000efa44,
/* 0008 */ 0x0005f708,0x00000000,0x0001d402,0x000b2e00,
/* 000A */ 0x0003d418,0x00001000,0x0008d574,0x000c4293,
/* 000C */ 0x00065625,0x000ea30e,0x00096c01,0x000c6f92,
/* 000E */ 0x0006a58a,0x000f6085,0x00002f43,0x00000000,
/* 0010 */ 0x000a83a0,0x00001028,0x0005e608,0x000c0000,
/* 0012 */ 0x00000000,0x00000000,0x000ca108,0x000dcca1,
/* 0014 */ 0x00003bac,0x000fb205,0x00073843,0x00000000,
/* 0016 */ 0x000d8730,0x00001028,0x0006600a,0x000c0000,
/* 0018 */ 0x00057488,0x00000000,0x00000000,0x000e5084,
/* 001A */ 0x00000000,0x000eba44,0x00087401,0x000e4782,
/* 001C */ 0x00000734,0x00001000,0x00010705,0x000a6880,
/* 001E */ 0x00006a88,0x000c75c4
};
/* #CODE_END */
static struct dsp_segment_desc cwcsnoop_segments[] = {
{ SEGTYPE_SP_PROGRAM, 0x00000000, 0x0000003e, cwcsnoop_code },
};
static struct dsp_module_desc cwcsnoop_module = {
"cwcsnoop",
{
3,
cwcsnoop_symbols
},
1,
cwcsnoop_segments,
};
#endif /* __HEADER_cwcsnoop_H__ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment