aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/cs46xx/dsp_spos.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/pci/cs46xx/dsp_spos.c')
-rw-r--r--sound/pci/cs46xx/dsp_spos.c42
1 files changed, 38 insertions, 4 deletions
diff --git a/sound/pci/cs46xx/dsp_spos.c b/sound/pci/cs46xx/dsp_spos.c
index f4f0c8f5dad7..3e5ca8fb519f 100644
--- a/sound/pci/cs46xx/dsp_spos.c
+++ b/sound/pci/cs46xx/dsp_spos.c
@@ -298,6 +298,9 @@ void cs46xx_dsp_spos_destroy (struct snd_cs46xx * chip)
298 if (ins->scbs[i].deleted) continue; 298 if (ins->scbs[i].deleted) continue;
299 299
300 cs46xx_dsp_proc_free_scb_desc ( (ins->scbs + i) ); 300 cs46xx_dsp_proc_free_scb_desc ( (ins->scbs + i) );
301#ifdef CONFIG_PM
302 kfree(ins->scbs[i].data);
303#endif
301 } 304 }
302 305
303 kfree(ins->code.data); 306 kfree(ins->code.data);
@@ -974,13 +977,11 @@ static struct dsp_scb_descriptor * _map_scb (struct snd_cs46xx *chip, char * nam
974 977
975 index = find_free_scb_index (ins); 978 index = find_free_scb_index (ins);
976 979
980 memset(&ins->scbs[index], 0, sizeof(ins->scbs[index]));
977 strcpy(ins->scbs[index].scb_name, name); 981 strcpy(ins->scbs[index].scb_name, name);
978 ins->scbs[index].address = dest; 982 ins->scbs[index].address = dest;
979 ins->scbs[index].index = index; 983 ins->scbs[index].index = index;
980 ins->scbs[index].proc_info = NULL;
981 ins->scbs[index].ref_count = 1; 984 ins->scbs[index].ref_count = 1;
982 ins->scbs[index].deleted = 0;
983 spin_lock_init(&ins->scbs[index].lock);
984 985
985 desc = (ins->scbs + index); 986 desc = (ins->scbs + index);
986 ins->scbs[index].scb_symbol = add_symbol (chip, name, dest, SYMBOL_PARAMETER); 987 ins->scbs[index].scb_symbol = add_symbol (chip, name, dest, SYMBOL_PARAMETER);
@@ -1022,17 +1023,29 @@ _map_task_tree (struct snd_cs46xx *chip, char * name, u32 dest, u32 size)
1022 return desc; 1023 return desc;
1023} 1024}
1024 1025
1026#define SCB_BYTES (0x10 * 4)
1027
1025struct dsp_scb_descriptor * 1028struct dsp_scb_descriptor *
1026cs46xx_dsp_create_scb (struct snd_cs46xx *chip, char * name, u32 * scb_data, u32 dest) 1029cs46xx_dsp_create_scb (struct snd_cs46xx *chip, char * name, u32 * scb_data, u32 dest)
1027{ 1030{
1028 struct dsp_scb_descriptor * desc; 1031 struct dsp_scb_descriptor * desc;
1029 1032
1033#ifdef CONFIG_PM
1034 /* copy the data for resume */
1035 scb_data = kmemdup(scb_data, SCB_BYTES, GFP_KERNEL);
1036 if (!scb_data)
1037 return NULL;
1038#endif
1039
1030 desc = _map_scb (chip,name,dest); 1040 desc = _map_scb (chip,name,dest);
1031 if (desc) { 1041 if (desc) {
1032 desc->data = scb_data; 1042 desc->data = scb_data;
1033 _dsp_create_scb(chip,scb_data,dest); 1043 _dsp_create_scb(chip,scb_data,dest);
1034 } else { 1044 } else {
1035 snd_printk(KERN_ERR "dsp_spos: failed to map SCB\n"); 1045 snd_printk(KERN_ERR "dsp_spos: failed to map SCB\n");
1046#ifdef CONFIG_PM
1047 kfree(scb_data);
1048#endif
1036 } 1049 }
1037 1050
1038 return desc; 1051 return desc;
@@ -1988,7 +2001,28 @@ int cs46xx_dsp_resume(struct snd_cs46xx * chip)
1988 continue; 2001 continue;
1989 _dsp_create_scb(chip, s->data, s->address); 2002 _dsp_create_scb(chip, s->data, s->address);
1990 } 2003 }
1991 2004 for (i = 0; i < ins->nscb; i++) {
2005 struct dsp_scb_descriptor *s = &ins->scbs[i];
2006 if (s->deleted)
2007 continue;
2008 if (s->updated)
2009 cs46xx_dsp_spos_update_scb(chip, s);
2010 if (s->volume_set)
2011 cs46xx_dsp_scb_set_volume(chip, s,
2012 s->volume[0], s->volume[1]);
2013 }
2014 if (ins->spdif_status_out & DSP_SPDIF_STATUS_HW_ENABLED) {
2015 cs46xx_dsp_enable_spdif_hw(chip);
2016 snd_cs46xx_poke(chip, (ins->ref_snoop_scb->address + 2) << 2,
2017 (OUTPUT_SNOOP_BUFFER + 0x10) << 0x10);
2018 if (ins->spdif_status_out & DSP_SPDIF_STATUS_PLAYBACK_OPEN)
2019 cs46xx_poke_via_dsp(chip, SP_SPDOUT_CSUV,
2020 ins->spdif_csuv_stream);
2021 }
2022 if (chip->dsp_spos_instance->spdif_status_in) {
2023 cs46xx_poke_via_dsp(chip, SP_ASER_COUNTDOWN, 0x80000005);
2024 cs46xx_poke_via_dsp(chip, SP_SPDIN_CONTROL, 0x800003ff);
2025 }
1992 return 0; 2026 return 0;
1993} 2027}
1994#endif 2028#endif