[ALSA] Remove sound/driver.h
[pandora-kernel.git] / sound / pci / cs46xx / dsp_spos.c
index 89c4027..ccc8bed 100644 (file)
  */
 
 
-#include <sound/driver.h>
 #include <asm/io.h>
 #include <linux/delay.h>
-#include <linux/pci.h>
 #include <linux/pm.h>
 #include <linux/init.h>
 #include <linux/slab.h>
@@ -307,13 +305,59 @@ void  cs46xx_dsp_spos_destroy (struct snd_cs46xx * chip)
        mutex_unlock(&chip->spos_mutex);
 }
 
+static int dsp_load_parameter(struct snd_cs46xx *chip,
+                             struct dsp_segment_desc *parameter)
+{
+       u32 doffset, dsize;
+
+       if (!parameter) {
+               snd_printdd("dsp_spos: module got no parameter segment\n");
+               return 0;
+       }
+
+       doffset = (parameter->offset * 4 + DSP_PARAMETER_BYTE_OFFSET);
+       dsize   = parameter->size * 4;
+
+       snd_printdd("dsp_spos: "
+                   "downloading parameter data to chip (%08x-%08x)\n",
+                   doffset,doffset + dsize);
+       if (snd_cs46xx_download (chip, parameter->data, doffset, dsize)) {
+               snd_printk(KERN_ERR "dsp_spos: "
+                          "failed to download parameter data to DSP\n");
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static int dsp_load_sample(struct snd_cs46xx *chip,
+                          struct dsp_segment_desc *sample)
+{
+       u32 doffset, dsize;
+
+       if (!sample) {
+               snd_printdd("dsp_spos: module got no sample segment\n");
+               return 0;
+       }
+
+       doffset = (sample->offset * 4  + DSP_SAMPLE_BYTE_OFFSET);
+       dsize   =  sample->size * 4;
+
+       snd_printdd("dsp_spos: downloading sample data to chip (%08x-%08x)\n",
+                   doffset,doffset + dsize);
+
+       if (snd_cs46xx_download (chip,sample->data,doffset,dsize)) {
+               snd_printk(KERN_ERR "dsp_spos: failed to sample data to DSP\n");
+               return -EINVAL;
+       }
+       return 0;
+}
+
 int cs46xx_dsp_load_module (struct snd_cs46xx * chip, struct dsp_module_desc * module)
 {
        struct dsp_spos_instance * ins = chip->dsp_spos_instance;
        struct dsp_segment_desc * code = get_segment_desc (module,SEGTYPE_SP_PROGRAM);
-       struct dsp_segment_desc * parameter = get_segment_desc (module,SEGTYPE_SP_PARAMETER);
-       struct dsp_segment_desc * sample = get_segment_desc (module,SEGTYPE_SP_SAMPLE);
        u32 doffset, dsize;
+       int err;
 
        if (ins->nmodules == DSP_MAX_MODULES - 1) {
                snd_printk(KERN_ERR "dsp_spos: to many modules loaded into DSP\n");
@@ -327,49 +371,20 @@ int cs46xx_dsp_load_module (struct snd_cs46xx * chip, struct dsp_module_desc * m
                snd_cs46xx_clear_BA1(chip, DSP_PARAMETER_BYTE_OFFSET, DSP_PARAMETER_BYTE_SIZE);
        }
   
-       if (parameter == NULL) {
-               snd_printdd("dsp_spos: module got no parameter segment\n");
-       } else {
-               if (ins->nmodules > 0) {
-                       snd_printk(KERN_WARNING "dsp_spos: WARNING current parameter data may be overwriten!\n");
-               }
-
-               doffset = (parameter->offset * 4 + DSP_PARAMETER_BYTE_OFFSET);
-               dsize   = parameter->size * 4;
-
-               snd_printdd("dsp_spos: downloading parameter data to chip (%08x-%08x)\n",
-                           doffset,doffset + dsize);
-
-               if (snd_cs46xx_download (chip, parameter->data, doffset, dsize)) {
-                       snd_printk(KERN_ERR "dsp_spos: failed to download parameter data to DSP\n");
-                       return -EINVAL;
-               }
-       }
+       err = dsp_load_parameter(chip, get_segment_desc(module,
+                                                       SEGTYPE_SP_PARAMETER));
+       if (err < 0)
+               return err;
 
        if (ins->nmodules == 0) {
                snd_printdd("dsp_spos: clearing sample area\n");
                snd_cs46xx_clear_BA1(chip, DSP_SAMPLE_BYTE_OFFSET, DSP_SAMPLE_BYTE_SIZE);
        }
 
-       if (sample == NULL) {
-               snd_printdd("dsp_spos: module got no sample segment\n");
-       } else {
-               if (ins->nmodules > 0) {
-                       snd_printk(KERN_WARNING "dsp_spos: WARNING current sample data may be overwriten\n");
-               }
-
-               doffset = (sample->offset * 4  + DSP_SAMPLE_BYTE_OFFSET);
-               dsize   =  sample->size * 4;
-
-               snd_printdd("dsp_spos: downloading sample data to chip (%08x-%08x)\n",
-                           doffset,doffset + dsize);
-
-               if (snd_cs46xx_download (chip,sample->data,doffset,dsize)) {
-                       snd_printk(KERN_ERR "dsp_spos: failed to sample data to DSP\n");
-                       return -EINVAL;
-               }
-       }
-
+       err = dsp_load_sample(chip, get_segment_desc(module,
+                                                    SEGTYPE_SP_SAMPLE));
+       if (err < 0)
+               return err;
 
        if (ins->nmodules == 0) {
                snd_printdd("dsp_spos: clearing code area\n");
@@ -987,7 +1002,10 @@ _map_task_tree (struct snd_cs46xx *chip, char * name, u32 dest, u32 size)
                return NULL;
        }
 
-       strcpy(ins->tasks[ins->ntask].task_name,name);
+       if (name)
+               strcpy(ins->tasks[ins->ntask].task_name, name);
+       else
+               strcpy(ins->tasks[ins->ntask].task_name, "(NULL)");
        ins->tasks[ins->ntask].address = dest;
        ins->tasks[ins->ntask].size = size;
 
@@ -996,7 +1014,8 @@ _map_task_tree (struct snd_cs46xx *chip, char * name, u32 dest, u32 size)
        desc = (ins->tasks + ins->ntask);
        ins->ntask++;
 
-       add_symbol (chip,name,dest,SYMBOL_PARAMETER);
+       if (name)
+               add_symbol (chip,name,dest,SYMBOL_PARAMETER);
        return desc;
 }
 
@@ -1007,6 +1026,7 @@ cs46xx_dsp_create_scb (struct snd_cs46xx *chip, char * name, u32 * scb_data, u32
 
        desc = _map_scb (chip,name,dest);
        if (desc) {
+               desc->data = scb_data;
                _dsp_create_scb(chip,scb_data,dest);
        } else {
                snd_printk(KERN_ERR "dsp_spos: failed to map SCB\n");
@@ -1024,6 +1044,7 @@ cs46xx_dsp_create_task_tree (struct snd_cs46xx *chip, char * name, u32 * task_da
 
        desc = _map_task_tree (chip,name,dest,size);
        if (desc) {
+               desc->data = task_data;
                _dsp_create_task_tree(chip,task_data,dest,size);
        } else {
                snd_printk(KERN_ERR "dsp_spos: failed to map TASK\n");
@@ -1321,8 +1342,10 @@ int cs46xx_dsp_scb_and_task_init (struct snd_cs46xx *chip)
                        0x0000ffff
                };
     
-               /* dirty hack ... */
-               _dsp_create_task_tree (chip,(u32 *)&mix2_ostream_spb,WRITE_BACK_SPB,2);
+               if (!cs46xx_dsp_create_task_tree(chip, NULL,
+                                                (u32 *)&mix2_ostream_spb,
+                                                WRITE_BACK_SPB, 2))
+                       goto _fail_end;
        }
 
        /* input sample converter */
@@ -1623,7 +1646,6 @@ static int cs46xx_dsp_async_init (struct snd_cs46xx *chip,
        return 0;
 }
 
-
 static void cs46xx_dsp_disable_spdif_hw (struct snd_cs46xx *chip)
 {
        struct dsp_spos_instance * ins = chip->dsp_spos_instance;
@@ -1895,3 +1917,61 @@ int cs46xx_dsp_set_iec958_volume (struct snd_cs46xx * chip, u16 left, u16 right)
 
        return 0;
 }
+
+#ifdef CONFIG_PM
+int cs46xx_dsp_resume(struct snd_cs46xx * chip)
+{
+       struct dsp_spos_instance * ins = chip->dsp_spos_instance;
+       int i, err;
+
+       /* clear parameter, sample and code areas */
+       snd_cs46xx_clear_BA1(chip, DSP_PARAMETER_BYTE_OFFSET,
+                            DSP_PARAMETER_BYTE_SIZE);
+       snd_cs46xx_clear_BA1(chip, DSP_SAMPLE_BYTE_OFFSET,
+                            DSP_SAMPLE_BYTE_SIZE);
+       snd_cs46xx_clear_BA1(chip, DSP_CODE_BYTE_OFFSET, DSP_CODE_BYTE_SIZE);
+
+       for (i = 0; i < ins->nmodules; i++) {
+               struct dsp_module_desc *module = &ins->modules[i];
+               struct dsp_segment_desc *seg;
+               u32 doffset, dsize;
+
+               seg = get_segment_desc(module, SEGTYPE_SP_PARAMETER);
+               err = dsp_load_parameter(chip, seg);
+               if (err < 0)
+                       return err;
+
+               seg = get_segment_desc(module, SEGTYPE_SP_SAMPLE);
+               err = dsp_load_sample(chip, seg);
+               if (err < 0)
+                       return err;
+
+               seg = get_segment_desc(module, SEGTYPE_SP_PROGRAM);
+               if (!seg)
+                       continue;
+
+               doffset = seg->offset * 4 + module->load_address * 4
+                       + DSP_CODE_BYTE_OFFSET;
+               dsize   = seg->size * 4;
+               err = snd_cs46xx_download(chip,
+                                         ins->code.data + module->load_address,
+                                         doffset, dsize);
+               if (err < 0)
+                       return err;
+       }
+
+       for (i = 0; i < ins->ntask; i++) {
+               struct dsp_task_descriptor *t = &ins->tasks[i];
+               _dsp_create_task_tree(chip, t->data, t->address, t->size);
+       }
+
+       for (i = 0; i < ins->nscb; i++) {
+               struct dsp_scb_descriptor *s = &ins->scbs[i];
+               if (s->deleted)
+                       continue;
+               _dsp_create_scb(chip, s->data, s->address);
+       }
+
+       return 0;
+}
+#endif