diff options
Diffstat (limited to 'sound/pci/cs46xx/cs46xx_lib.c')
| -rw-r--r-- | sound/pci/cs46xx/cs46xx_lib.c | 471 |
1 files changed, 341 insertions, 130 deletions
diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c index aad37082cb6..32b44f25b5c 100644 --- a/sound/pci/cs46xx/cs46xx_lib.c +++ b/sound/pci/cs46xx/cs46xx_lib.c @@ -53,14 +53,17 @@ #include <linux/slab.h> #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> #include <sound/info.h> #include <sound/pcm.h> #include <sound/pcm_params.h> -#include <sound/cs46xx.h> +#include "cs46xx.h" #include <asm/io.h> @@ -93,7 +96,7 @@ static unsigned short snd_cs46xx_codec_read(struct snd_cs46xx *chip, if (snd_BUG_ON(codec_index != CS46XX_PRIMARY_CODEC_INDEX && codec_index != CS46XX_SECONDARY_CODEC_INDEX)) - return -EINVAL; + return 0xffff; chip->active_ctrl(chip, 1); @@ -113,7 +116,7 @@ static unsigned short snd_cs46xx_codec_read(struct snd_cs46xx *chip, tmp = snd_cs46xx_peekBA0(chip, BA0_ACCTL); if ((tmp & ACCTL_VFRM) == 0) { - snd_printk(KERN_WARNING "cs46xx: ACCTL_VFRM not set 0x%x\n",tmp); + dev_warn(chip->card->dev, "ACCTL_VFRM not set 0x%x\n", tmp); snd_cs46xx_pokeBA0(chip, BA0_ACCTL, (tmp & (~ACCTL_ESYN)) | ACCTL_VFRM ); msleep(50); tmp = snd_cs46xx_peekBA0(chip, BA0_ACCTL + offset); @@ -165,7 +168,8 @@ static unsigned short snd_cs46xx_codec_read(struct snd_cs46xx *chip, goto ok1; } - snd_printk(KERN_ERR "AC'97 read problem (ACCTL_DCV), reg = 0x%x\n", reg); + dev_err(chip->card->dev, + "AC'97 read problem (ACCTL_DCV), reg = 0x%x\n", reg); result = 0xffff; goto end; @@ -184,7 +188,9 @@ static unsigned short snd_cs46xx_codec_read(struct snd_cs46xx *chip, udelay(10); } - snd_printk(KERN_ERR "AC'97 read problem (ACSTS_VSTS), codec_index %d, reg = 0x%x\n", codec_index, reg); + dev_err(chip->card->dev, + "AC'97 read problem (ACSTS_VSTS), codec_index %d, reg = 0x%x\n", + codec_index, reg); result = 0xffff; goto end; @@ -194,7 +200,8 @@ static unsigned short snd_cs46xx_codec_read(struct snd_cs46xx *chip, * ACSDA = Status Data Register = 474h */ #if 0 - printk(KERN_DEBUG "e) reg = 0x%x, val = 0x%x, BA0_ACCAD = 0x%x\n", reg, + dev_dbg(chip->card->dev, + "e) reg = 0x%x, val = 0x%x, BA0_ACCAD = 0x%x\n", reg, snd_cs46xx_peekBA0(chip, BA0_ACSDA), snd_cs46xx_peekBA0(chip, BA0_ACCAD)); #endif @@ -283,7 +290,9 @@ static void snd_cs46xx_codec_write(struct snd_cs46xx *chip, goto end; } } - snd_printk(KERN_ERR "AC'97 write problem, codec_index = %d, reg = 0x%x, val = 0x%x\n", codec_index, reg, val); + dev_err(chip->card->dev, + "AC'97 write problem, codec_index = %d, reg = 0x%x, val = 0x%x\n", + codec_index, reg, val); end: chip->active_ctrl(chip, -1); } @@ -329,13 +338,147 @@ 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); + } + kfree(module); +} + +/* 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, @@ -360,20 +503,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; } @@ -428,8 +614,8 @@ static int cs46xx_wait_for_fifo(struct snd_cs46xx * chip,int retry_timeout) } if(status & SERBST_WBSY) { - snd_printk(KERN_ERR "cs46xx: failure waiting for " - "FIFO command to complete\n"); + dev_err(chip->card->dev, + "failure waiting for FIFO command to complete\n"); return -EINVAL; } @@ -466,7 +652,9 @@ static void snd_cs46xx_clear_serial_FIFOs(struct snd_cs46xx *chip) * Make sure the previous FIFO write operation has completed. */ if (cs46xx_wait_for_fifo(chip,1)) { - snd_printdd ("failed waiting for FIFO at addr (%02X)\n",idx); + dev_dbg(chip->card->dev, + "failed waiting for FIFO at addr (%02X)\n", + idx); if (powerdown) snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, tmp); @@ -514,7 +702,7 @@ static void snd_cs46xx_proc_start(struct snd_cs46xx *chip) } if (snd_cs46xx_peek(chip, BA1_SPCR) & SPCR_RUNFR) - snd_printk(KERN_ERR "SPCR_RUNFR never reset\n"); + dev_err(chip->card->dev, "SPCR_RUNFR never reset\n"); } static void snd_cs46xx_proc_stop(struct snd_cs46xx *chip) @@ -874,7 +1062,8 @@ static int _cs46xx_adjust_sample_rate (struct snd_cs46xx *chip, struct snd_cs46x cpcm->pcm_channel = cs46xx_dsp_create_pcm_channel (chip, sample_rate, cpcm, cpcm->hw_buf.addr,cpcm->pcm_channel_id); if (cpcm->pcm_channel == NULL) { - snd_printk(KERN_ERR "cs46xx: failed to create virtual PCM channel\n"); + dev_err(chip->card->dev, + "failed to create virtual PCM channel\n"); return -ENOMEM; } cpcm->pcm_channel->sample_rate = sample_rate; @@ -887,7 +1076,8 @@ static int _cs46xx_adjust_sample_rate (struct snd_cs46xx *chip, struct snd_cs46x if ( (cpcm->pcm_channel = cs46xx_dsp_create_pcm_channel (chip, sample_rate, cpcm, cpcm->hw_buf.addr, cpcm->pcm_channel_id)) == NULL) { - snd_printk(KERN_ERR "cs46xx: failed to re-create virtual PCM channel\n"); + dev_err(chip->card->dev, + "failed to re-create virtual PCM channel\n"); return -ENOMEM; } @@ -936,7 +1126,8 @@ static int snd_cs46xx_playback_hw_params(struct snd_pcm_substream *substream, return -EINVAL; } - snd_printdd ("period_size (%d), periods (%d) buffer_size(%d)\n", + dev_dbg(chip->card->dev, + "period_size (%d), periods (%d) buffer_size(%d)\n", period_size, params_periods(hw_params), params_buffer_bytes(hw_params)); #endif @@ -1351,22 +1542,20 @@ static int _cs46xx_playback_open_channel (struct snd_pcm_substream *substream,in static int snd_cs46xx_playback_open(struct snd_pcm_substream *substream) { - snd_printdd("open front channel\n"); + dev_dbg(substream->pcm->card->dev, "open front channel\n"); return _cs46xx_playback_open_channel(substream,DSP_PCM_MAIN_CHANNEL); } #ifdef CONFIG_SND_CS46XX_NEW_DSP static int snd_cs46xx_playback_open_rear(struct snd_pcm_substream *substream) { - snd_printdd("open rear channel\n"); - + dev_dbg(substream->pcm->card->dev, "open rear channel\n"); return _cs46xx_playback_open_channel(substream,DSP_PCM_REAR_CHANNEL); } static int snd_cs46xx_playback_open_clfe(struct snd_pcm_substream *substream) { - snd_printdd("open center - LFE channel\n"); - + dev_dbg(substream->pcm->card->dev, "open center - LFE channel\n"); return _cs46xx_playback_open_channel(substream,DSP_PCM_CENTER_LFE_CHANNEL); } @@ -1374,7 +1563,7 @@ static int snd_cs46xx_playback_open_iec958(struct snd_pcm_substream *substream) { struct snd_cs46xx *chip = snd_pcm_substream_chip(substream); - snd_printdd("open raw iec958 channel\n"); + dev_dbg(chip->card->dev, "open raw iec958 channel\n"); mutex_lock(&chip->spos_mutex); cs46xx_iec958_pre_open (chip); @@ -1390,7 +1579,7 @@ static int snd_cs46xx_playback_close_iec958(struct snd_pcm_substream *substream) int err; struct snd_cs46xx *chip = snd_pcm_substream_chip(substream); - snd_printdd("close raw iec958 channel\n"); + dev_dbg(chip->card->dev, "close raw iec958 channel\n"); err = snd_cs46xx_playback_close(substream); @@ -1589,7 +1778,7 @@ static struct snd_pcm_ops snd_cs46xx_capture_indirect_ops = { #define MAX_PLAYBACK_CHANNELS 1 #endif -int __devinit snd_cs46xx_pcm(struct snd_cs46xx *chip, int device, struct snd_pcm ** rpcm) +int snd_cs46xx_pcm(struct snd_cs46xx *chip, int device, struct snd_pcm **rpcm) { struct snd_pcm *pcm; int err; @@ -1620,7 +1809,8 @@ int __devinit snd_cs46xx_pcm(struct snd_cs46xx *chip, int device, struct snd_pcm #ifdef CONFIG_SND_CS46XX_NEW_DSP -int __devinit snd_cs46xx_pcm_rear(struct snd_cs46xx *chip, int device, struct snd_pcm ** rpcm) +int snd_cs46xx_pcm_rear(struct snd_cs46xx *chip, int device, + struct snd_pcm **rpcm) { struct snd_pcm *pcm; int err; @@ -1649,7 +1839,8 @@ int __devinit snd_cs46xx_pcm_rear(struct snd_cs46xx *chip, int device, struct sn return 0; } -int __devinit snd_cs46xx_pcm_center_lfe(struct snd_cs46xx *chip, int device, struct snd_pcm ** rpcm) +int snd_cs46xx_pcm_center_lfe(struct snd_cs46xx *chip, int device, + struct snd_pcm **rpcm) { struct snd_pcm *pcm; int err; @@ -1678,7 +1869,8 @@ int __devinit snd_cs46xx_pcm_center_lfe(struct snd_cs46xx *chip, int device, str return 0; } -int __devinit snd_cs46xx_pcm_iec958(struct snd_cs46xx *chip, int device, struct snd_pcm ** rpcm) +int snd_cs46xx_pcm_iec958(struct snd_cs46xx *chip, int device, + struct snd_pcm **rpcm) { struct snd_pcm *pcm; int err; @@ -2091,7 +2283,7 @@ static int snd_cs46xx_spdif_stream_put(struct snd_kcontrol *kcontrol, #endif /* CONFIG_SND_CS46XX_NEW_DSP */ -static struct snd_kcontrol_new snd_cs46xx_controls[] __devinitdata = { +static struct snd_kcontrol_new snd_cs46xx_controls[] = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "DAC Volume", @@ -2238,10 +2430,10 @@ static void snd_cs46xx_codec_reset (struct snd_ac97 * ac97) /* set the desired CODEC mode */ if (ac97->num == CS46XX_PRIMARY_CODEC_INDEX) { - snd_printdd("cs46xx: CODEC1 mode %04x\n", 0x0); + dev_dbg(ac97->bus->card->dev, "CODEC1 mode %04x\n", 0x0); snd_cs46xx_ac97_write(ac97, AC97_CSR_ACMODE, 0x0); } else if (ac97->num == CS46XX_SECONDARY_CODEC_INDEX) { - snd_printdd("cs46xx: CODEC2 mode %04x\n", 0x3); + dev_dbg(ac97->bus->card->dev, "CODEC2 mode %04x\n", 0x3); snd_cs46xx_ac97_write(ac97, AC97_CSR_ACMODE, 0x3); } else { snd_BUG(); /* should never happen ... */ @@ -2273,11 +2465,12 @@ static void snd_cs46xx_codec_reset (struct snd_ac97 * ac97) msleep(10); } while (time_after_eq(end_time, jiffies)); - snd_printk(KERN_ERR "CS46xx secondary codec doesn't respond!\n"); + dev_err(ac97->bus->card->dev, + "CS46xx secondary codec doesn't respond!\n"); } #endif -static int __devinit cs46xx_detect_codec(struct snd_cs46xx *chip, int codec) +static int cs46xx_detect_codec(struct snd_cs46xx *chip, int codec) { int idx, err; struct snd_ac97_template ac97; @@ -2293,7 +2486,8 @@ static int __devinit cs46xx_detect_codec(struct snd_cs46xx *chip, int codec) snd_cs46xx_codec_write(chip, AC97_RESET, 0, codec); udelay(10); if (snd_cs46xx_codec_read(chip, AC97_RESET, codec) & 0x8000) { - snd_printdd("snd_cs46xx: seconadry codec not present\n"); + dev_dbg(chip->card->dev, + "seconadry codec not present\n"); return -ENXIO; } } @@ -2306,11 +2500,11 @@ static int __devinit cs46xx_detect_codec(struct snd_cs46xx *chip, int codec) } msleep(10); } - snd_printdd("snd_cs46xx: codec %d detection timeout\n", codec); + dev_dbg(chip->card->dev, "codec %d detection timeout\n", codec); return -ENXIO; } -int __devinit snd_cs46xx_mixer(struct snd_cs46xx *chip, int spdif_device) +int snd_cs46xx_mixer(struct snd_cs46xx *chip, int spdif_device) { struct snd_card *card = chip->card; struct snd_ctl_elem_id id; @@ -2326,7 +2520,7 @@ int __devinit snd_cs46xx_mixer(struct snd_cs46xx *chip, int spdif_device) /* detect primary codec */ chip->nr_ac97_codecs = 0; - snd_printdd("snd_cs46xx: detecting primary codec\n"); + dev_dbg(chip->card->dev, "detecting primary codec\n"); if ((err = snd_ac97_bus(card, 0, &ops, chip, &chip->ac97_bus)) < 0) return err; chip->ac97_bus->private_free = snd_cs46xx_mixer_free_ac97_bus; @@ -2336,7 +2530,7 @@ int __devinit snd_cs46xx_mixer(struct snd_cs46xx *chip, int spdif_device) chip->nr_ac97_codecs = 1; #ifdef CONFIG_SND_CS46XX_NEW_DSP - snd_printdd("snd_cs46xx: detecting seconadry codec\n"); + dev_dbg(chip->card->dev, "detecting seconadry codec\n"); /* try detect a secondary codec */ if (! cs46xx_detect_codec(chip, CS46XX_SECONDARY_CODEC_INDEX)) chip->nr_ac97_codecs = 2; @@ -2371,7 +2565,7 @@ int __devinit snd_cs46xx_mixer(struct snd_cs46xx *chip, int spdif_device) } /* do soundcard specific mixer setup */ if (chip->mixer_init) { - snd_printdd ("calling chip->mixer_init(chip);\n"); + dev_dbg(chip->card->dev, "calling chip->mixer_init(chip);\n"); chip->mixer_init(chip); } #endif @@ -2530,7 +2724,7 @@ static struct snd_rawmidi_ops snd_cs46xx_midi_input = .trigger = snd_cs46xx_midi_input_trigger, }; -int __devinit snd_cs46xx_midi(struct snd_cs46xx *chip, int device, struct snd_rawmidi **rrawmidi) +int snd_cs46xx_midi(struct snd_cs46xx *chip, int device, struct snd_rawmidi **rrawmidi) { struct snd_rawmidi *rmidi; int err; @@ -2612,13 +2806,14 @@ static int snd_cs46xx_gameport_open(struct gameport *gameport, int mode) return 0; } -int __devinit snd_cs46xx_gameport(struct snd_cs46xx *chip) +int snd_cs46xx_gameport(struct snd_cs46xx *chip) { struct gameport *gp; chip->gameport = gp = gameport_allocate_port(); if (!gp) { - printk(KERN_ERR "cs46xx: cannot allocate memory for gameport\n"); + dev_err(chip->card->dev, + "cannot allocate memory for gameport\n"); return -ENOMEM; } @@ -2648,7 +2843,7 @@ static inline void snd_cs46xx_remove_gameport(struct snd_cs46xx *chip) } } #else -int __devinit snd_cs46xx_gameport(struct snd_cs46xx *chip) { return -ENOSYS; } +int snd_cs46xx_gameport(struct snd_cs46xx *chip) { return -ENOSYS; } static inline void snd_cs46xx_remove_gameport(struct snd_cs46xx *chip) { } #endif /* CONFIG_GAMEPORT */ @@ -2673,7 +2868,7 @@ static struct snd_info_entry_ops snd_cs46xx_proc_io_ops = { .read = snd_cs46xx_io_read, }; -static int __devinit snd_cs46xx_proc_init(struct snd_card *card, struct snd_cs46xx *chip) +static int snd_cs46xx_proc_init(struct snd_card *card, struct snd_cs46xx *chip) { struct snd_info_entry *entry; int idx; @@ -2794,9 +2989,13 @@ 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 +#ifdef CONFIG_PM_SLEEP kfree(chip->saved_regs); #endif @@ -2951,8 +3150,10 @@ static int snd_cs46xx_chip_init(struct snd_cs46xx *chip) } - snd_printk(KERN_ERR "create - never read codec ready from AC'97\n"); - snd_printk(KERN_ERR "it is not probably bug, try to use CS4236 driver\n"); + dev_err(chip->card->dev, + "create - never read codec ready from AC'97\n"); + dev_err(chip->card->dev, + "it is not probably bug, try to use CS4236 driver\n"); return -EIO; ok1: #ifdef CONFIG_SND_CS46XX_NEW_DSP @@ -2970,7 +3171,8 @@ static int snd_cs46xx_chip_init(struct snd_cs46xx *chip) * Make sure CODEC is READY. */ if (!(snd_cs46xx_peekBA0(chip, BA0_ACSTS2) & ACSTS_CRDY)) - snd_printdd("cs46xx: never read card ready from secondary AC'97\n"); + dev_dbg(chip->card->dev, + "never read card ready from secondary AC'97\n"); } #endif @@ -3000,17 +3202,21 @@ static int snd_cs46xx_chip_init(struct snd_cs46xx *chip) } #ifndef CONFIG_SND_CS46XX_NEW_DSP - snd_printk(KERN_ERR "create - never read ISV3 & ISV4 from AC'97\n"); + dev_err(chip->card->dev, + "create - never read ISV3 & ISV4 from AC'97\n"); return -EIO; #else /* This may happen on a cold boot with a Terratec SiXPack 5.1. Reloading the driver may help, if there's other soundcards with the same problem I would like to know. (Benny) */ - snd_printk(KERN_ERR "ERROR: snd-cs46xx: never read ISV3 & ISV4 from AC'97\n"); - snd_printk(KERN_ERR " Try reloading the ALSA driver, if you find something\n"); - snd_printk(KERN_ERR " broken or not working on your soundcard upon\n"); - snd_printk(KERN_ERR " this message please report to alsa-devel@alsa-project.org\n"); + dev_err(chip->card->dev, "never read ISV3 & ISV4 from AC'97\n"); + dev_err(chip->card->dev, + "Try reloading the ALSA driver, if you find something\n"); + dev_err(chip->card->dev, + "broken or not working on your soundcard upon\n"); + dev_err(chip->card->dev, + "this message please report to alsa-devel@alsa-project.org\n"); return -EIO; #endif @@ -3060,9 +3266,14 @@ static void cs46xx_enable_stream_irqs(struct snd_cs46xx *chip) snd_cs46xx_poke(chip, BA1_CIE, tmp); /* capture interrupt enable */ } -int __devinit snd_cs46xx_start_dsp(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. */ @@ -3071,45 +3282,33 @@ int __devinit 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; - } - - if (cs46xx_dsp_load_module(chip, &cwcbinhack_module) < 0) { - snd_printk(KERN_ERR "image download error [cwcbinhack]\n"); - return -EIO; - } - - if (cs46xx_dsp_load_module(chip, &cwcdma_module) < 0) { - snd_printk(KERN_ERR "image download error [cwcdma]\n"); - return -EIO; + for (i = 0; i < CS46XX_DSP_MODULES; i++) { + err = load_firmware(chip, &chip->modules[i], module_names[i]); + if (err < 0) { + dev_err(chip->card->dev, "firmware load error [%s]\n", + module_names[i]); + return err; + } + err = cs46xx_dsp_load_module(chip, chip->modules[i]); + if (err < 0) { + dev_err(chip->card->dev, "image download error [%s]\n", + module_names[i]); + return err; + } } 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) { - snd_printk(KERN_ERR "image download error\n"); - return -EIO; + err = snd_cs46xx_download_image(chip); + if (err < 0) { + dev_err(chip->card->dev, "image download error\n"); + return err; } /* @@ -3161,7 +3360,7 @@ static int voyetra_setup_eapd_slot(struct snd_cs46xx *chip) u32 idx, valid_slots,tmp,powerdown = 0; u16 modem_power,pin_config,logic_type; - snd_printdd ("cs46xx: cs46xx_setup_eapd_slot()+\n"); + dev_dbg(chip->card->dev, "cs46xx_setup_eapd_slot()+\n"); /* * See if the devices are powered down. If so, we must power them up first @@ -3179,7 +3378,8 @@ static int voyetra_setup_eapd_slot(struct snd_cs46xx *chip) * stuff. */ if(chip->nr_ac97_codecs != 2) { - snd_printk (KERN_ERR "cs46xx: cs46xx_setup_eapd_slot() - no secondary codec configured\n"); + dev_err(chip->card->dev, + "cs46xx_setup_eapd_slot() - no secondary codec configured\n"); return -EINVAL; } @@ -3220,7 +3420,7 @@ static int voyetra_setup_eapd_slot(struct snd_cs46xx *chip) snd_cs46xx_pokeBA0(chip, BA0_ACOSV, valid_slots); if ( cs46xx_wait_for_fifo(chip,1) ) { - snd_printdd("FIFO is busy\n"); + dev_dbg(chip->card->dev, "FIFO is busy\n"); return -EINVAL; } @@ -3241,7 +3441,9 @@ static int voyetra_setup_eapd_slot(struct snd_cs46xx *chip) * Wait for command to complete */ if ( cs46xx_wait_for_fifo(chip,200) ) { - snd_printdd("failed waiting for FIFO at addr (%02X)\n",idx); + dev_dbg(chip->card->dev, + "failed waiting for FIFO at addr (%02X)\n", + idx); return -EINVAL; } @@ -3330,14 +3532,14 @@ static void amp_hercules(struct snd_cs46xx *chip, int change) chip->amplifier += change; if (chip->amplifier && !old) { - snd_printdd ("Hercules amplifier ON\n"); + dev_dbg(chip->card->dev, "Hercules amplifier ON\n"); snd_cs46xx_pokeBA0(chip, BA0_EGPIODR, EGPIODR_GPOE2 | val1); /* enable EGPIO2 output */ snd_cs46xx_pokeBA0(chip, BA0_EGPIOPTR, EGPIOPTR_GPPT2 | val2); /* open-drain on output */ } else if (old && !chip->amplifier) { - snd_printdd ("Hercules amplifier OFF\n"); + dev_dbg(chip->card->dev, "Hercules amplifier OFF\n"); snd_cs46xx_pokeBA0(chip, BA0_EGPIODR, val1 & ~EGPIODR_GPOE2); /* disable */ snd_cs46xx_pokeBA0(chip, BA0_EGPIOPTR, val2 & ~EGPIOPTR_GPPT2); /* disable */ } @@ -3345,7 +3547,7 @@ static void amp_hercules(struct snd_cs46xx *chip, int change) static void voyetra_mixer_init (struct snd_cs46xx *chip) { - snd_printdd ("initializing Voyetra mixer\n"); + dev_dbg(chip->card->dev, "initializing Voyetra mixer\n"); /* Enable SPDIF out */ snd_cs46xx_pokeBA0(chip, BA0_EGPIODR, EGPIODR_GPOE0); @@ -3363,7 +3565,7 @@ static void hercules_mixer_init (struct snd_cs46xx *chip) /* set EGPIO to default */ hercules_init(chip); - snd_printdd ("initializing Hercules mixer\n"); + dev_dbg(chip->card->dev, "initializing Hercules mixer\n"); #ifdef CONFIG_SND_CS46XX_NEW_DSP if (chip->in_suspend) @@ -3374,7 +3576,9 @@ static void hercules_mixer_init (struct snd_cs46xx *chip) kctl = snd_ctl_new1(&snd_hercules_controls[idx], chip); if ((err = snd_ctl_add(card, kctl)) < 0) { - printk (KERN_ERR "cs46xx: failed to initialize Hercules mixer (%d)\n",err); + dev_err(card->dev, + "failed to initialize Hercules mixer (%d)\n", + err); break; } } @@ -3476,7 +3680,7 @@ struct cs_card_type void (*mixer_init)(struct snd_cs46xx *); }; -static struct cs_card_type __devinitdata cards[] = { +static struct cs_card_type cards[] = { { .vendor = 0x1489, .id = 0x7001, @@ -3589,7 +3793,7 @@ static struct cs_card_type __devinitdata cards[] = { /* * APM support */ -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP static unsigned int saved_regs[] = { BA0_ACOSV, /*BA0_ASER_FADDR,*/ @@ -3598,9 +3802,10 @@ static unsigned int saved_regs[] = { BA1_CVOL, }; -int snd_cs46xx_suspend(struct pci_dev *pci, pm_message_t state) +static int snd_cs46xx_suspend(struct device *dev) { - struct snd_card *card = pci_get_drvdata(pci); + struct pci_dev *pci = to_pci_dev(dev); + struct snd_card *card = dev_get_drvdata(dev); struct snd_cs46xx *chip = card->private_data; int i, amp_saved; @@ -3627,13 +3832,14 @@ int snd_cs46xx_suspend(struct pci_dev *pci, pm_message_t state) pci_disable_device(pci); pci_save_state(pci); - pci_set_power_state(pci, pci_choose_state(pci, state)); + pci_set_power_state(pci, PCI_D3hot); return 0; } -int snd_cs46xx_resume(struct pci_dev *pci) +static int snd_cs46xx_resume(struct device *dev) { - struct snd_card *card = pci_get_drvdata(pci); + struct pci_dev *pci = to_pci_dev(dev); + struct snd_card *card = dev_get_drvdata(dev); struct snd_cs46xx *chip = card->private_data; int amp_saved; #ifdef CONFIG_SND_CS46XX_NEW_DSP @@ -3644,8 +3850,7 @@ int snd_cs46xx_resume(struct pci_dev *pci) pci_set_power_state(pci, PCI_D0); pci_restore_state(pci); if (pci_enable_device(pci) < 0) { - printk(KERN_ERR "cs46xx: pci_enable_device failed, " - "disabling device\n"); + dev_err(dev, "pci_enable_device failed, disabling device\n"); snd_card_disconnect(card); return -EIO; } @@ -3706,16 +3911,18 @@ int snd_cs46xx_resume(struct pci_dev *pci) snd_power_change_state(card, SNDRV_CTL_POWER_D0); return 0; } -#endif /* CONFIG_PM */ + +SIMPLE_DEV_PM_OPS(snd_cs46xx_pm, snd_cs46xx_suspend, snd_cs46xx_resume); +#endif /* CONFIG_PM_SLEEP */ /* */ -int __devinit snd_cs46xx_create(struct snd_card *card, - struct pci_dev * pci, +int snd_cs46xx_create(struct snd_card *card, + struct pci_dev *pci, int external_amp, int thinkpad, - struct snd_cs46xx ** rchip) + struct snd_cs46xx **rchip) { struct snd_cs46xx *chip; int err, idx; @@ -3748,7 +3955,8 @@ int __devinit snd_cs46xx_create(struct snd_card *card, chip->ba1_addr = pci_resource_start(pci, 1); if (chip->ba0_addr == 0 || chip->ba0_addr == (unsigned long)~0 || chip->ba1_addr == 0 || chip->ba1_addr == (unsigned long)~0) { - snd_printk(KERN_ERR "wrong address(es) - ba0 = 0x%lx, ba1 = 0x%lx\n", + dev_err(chip->card->dev, + "wrong address(es) - ba0 = 0x%lx, ba1 = 0x%lx\n", chip->ba0_addr, chip->ba1_addr); snd_cs46xx_free(chip); return -ENOMEM; @@ -3785,7 +3993,8 @@ int __devinit snd_cs46xx_create(struct snd_card *card, for (cp = &cards[0]; cp->name; cp++) { if (cp->vendor == ss_vendor && cp->id == ss_card) { - snd_printdd ("hack for %s enabled\n", cp->name); + dev_dbg(chip->card->dev, "hack for %s enabled\n", + cp->name); chip->amplifier_ctrl = cp->amp; chip->active_ctrl = cp->active; @@ -3798,12 +4007,14 @@ int __devinit snd_cs46xx_create(struct snd_card *card, } if (external_amp) { - snd_printk(KERN_INFO "Crystal EAPD support forced on.\n"); + dev_info(chip->card->dev, + "Crystal EAPD support forced on.\n"); chip->amplifier_ctrl = amp_voyetra; } if (thinkpad) { - snd_printk(KERN_INFO "Activating CLKRUN hack for Thinkpad.\n"); + dev_info(chip->card->dev, + "Activating CLKRUN hack for Thinkpad.\n"); chip->active_ctrl = clkrun_hack; clkrun_init(chip); } @@ -3821,22 +4032,24 @@ int __devinit snd_cs46xx_create(struct snd_card *card, region = &chip->region.idx[idx]; if ((region->resource = request_mem_region(region->base, region->size, region->name)) == NULL) { - snd_printk(KERN_ERR "unable to request memory region 0x%lx-0x%lx\n", + dev_err(chip->card->dev, + "unable to request memory region 0x%lx-0x%lx\n", region->base, region->base + region->size - 1); snd_cs46xx_free(chip); return -EBUSY; } region->remap_addr = ioremap_nocache(region->base, region->size); if (region->remap_addr == NULL) { - snd_printk(KERN_ERR "%s ioremap problem\n", region->name); + dev_err(chip->card->dev, + "%s ioremap problem\n", region->name); snd_cs46xx_free(chip); return -ENOMEM; } } if (request_irq(pci->irq, snd_cs46xx_interrupt, IRQF_SHARED, - "CS46XX", chip)) { - snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); + KBUILD_MODNAME, chip)) { + dev_err(chip->card->dev, "unable to grab IRQ %d\n", pci->irq); snd_cs46xx_free(chip); return -EBUSY; } @@ -3863,7 +4076,7 @@ int __devinit snd_cs46xx_create(struct snd_card *card, snd_cs46xx_proc_init(card, chip); -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP chip->saved_regs = kmalloc(sizeof(*chip->saved_regs) * ARRAY_SIZE(saved_regs), GFP_KERNEL); if (!chip->saved_regs) { @@ -3874,8 +4087,6 @@ int __devinit snd_cs46xx_create(struct snd_card *card, chip->active_ctrl(chip, -1); /* disable CLKRUN */ - snd_card_set_dev(card, &pci->dev); - *rchip = chip; return 0; } |
