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.c170
1 files changed, 126 insertions, 44 deletions
diff --git a/sound/pci/cs46xx/dsp_spos.c b/sound/pci/cs46xx/dsp_spos.c
index 336e77e2600c..590b35d91df2 100644
--- a/sound/pci/cs46xx/dsp_spos.c
+++ b/sound/pci/cs46xx/dsp_spos.c
@@ -306,13 +306,59 @@ void cs46xx_dsp_spos_destroy (struct snd_cs46xx * chip)
306 mutex_unlock(&chip->spos_mutex); 306 mutex_unlock(&chip->spos_mutex);
307} 307}
308 308
309static int dsp_load_parameter(struct snd_cs46xx *chip,
310 struct dsp_segment_desc *parameter)
311{
312 u32 doffset, dsize;
313
314 if (!parameter) {
315 snd_printdd("dsp_spos: module got no parameter segment\n");
316 return 0;
317 }
318
319 doffset = (parameter->offset * 4 + DSP_PARAMETER_BYTE_OFFSET);
320 dsize = parameter->size * 4;
321
322 snd_printdd("dsp_spos: "
323 "downloading parameter data to chip (%08x-%08x)\n",
324 doffset,doffset + dsize);
325 if (snd_cs46xx_download (chip, parameter->data, doffset, dsize)) {
326 snd_printk(KERN_ERR "dsp_spos: "
327 "failed to download parameter data to DSP\n");
328 return -EINVAL;
329 }
330 return 0;
331}
332
333static int dsp_load_sample(struct snd_cs46xx *chip,
334 struct dsp_segment_desc *sample)
335{
336 u32 doffset, dsize;
337
338 if (!sample) {
339 snd_printdd("dsp_spos: module got no sample segment\n");
340 return 0;
341 }
342
343 doffset = (sample->offset * 4 + DSP_SAMPLE_BYTE_OFFSET);
344 dsize = sample->size * 4;
345
346 snd_printdd("dsp_spos: downloading sample data to chip (%08x-%08x)\n",
347 doffset,doffset + dsize);
348
349 if (snd_cs46xx_download (chip,sample->data,doffset,dsize)) {
350 snd_printk(KERN_ERR "dsp_spos: failed to sample data to DSP\n");
351 return -EINVAL;
352 }
353 return 0;
354}
355
309int cs46xx_dsp_load_module (struct snd_cs46xx * chip, struct dsp_module_desc * module) 356int cs46xx_dsp_load_module (struct snd_cs46xx * chip, struct dsp_module_desc * module)
310{ 357{
311 struct dsp_spos_instance * ins = chip->dsp_spos_instance; 358 struct dsp_spos_instance * ins = chip->dsp_spos_instance;
312 struct dsp_segment_desc * code = get_segment_desc (module,SEGTYPE_SP_PROGRAM); 359 struct dsp_segment_desc * code = get_segment_desc (module,SEGTYPE_SP_PROGRAM);
313 struct dsp_segment_desc * parameter = get_segment_desc (module,SEGTYPE_SP_PARAMETER);
314 struct dsp_segment_desc * sample = get_segment_desc (module,SEGTYPE_SP_SAMPLE);
315 u32 doffset, dsize; 360 u32 doffset, dsize;
361 int err;
316 362
317 if (ins->nmodules == DSP_MAX_MODULES - 1) { 363 if (ins->nmodules == DSP_MAX_MODULES - 1) {
318 snd_printk(KERN_ERR "dsp_spos: to many modules loaded into DSP\n"); 364 snd_printk(KERN_ERR "dsp_spos: to many modules loaded into DSP\n");
@@ -326,49 +372,20 @@ int cs46xx_dsp_load_module (struct snd_cs46xx * chip, struct dsp_module_desc * m
326 snd_cs46xx_clear_BA1(chip, DSP_PARAMETER_BYTE_OFFSET, DSP_PARAMETER_BYTE_SIZE); 372 snd_cs46xx_clear_BA1(chip, DSP_PARAMETER_BYTE_OFFSET, DSP_PARAMETER_BYTE_SIZE);
327 } 373 }
328 374
329 if (parameter == NULL) { 375 err = dsp_load_parameter(chip, get_segment_desc(module,
330 snd_printdd("dsp_spos: module got no parameter segment\n"); 376 SEGTYPE_SP_PARAMETER));
331 } else { 377 if (err < 0)
332 if (ins->nmodules > 0) { 378 return err;
333 snd_printk(KERN_WARNING "dsp_spos: WARNING current parameter data may be overwriten!\n");
334 }
335
336 doffset = (parameter->offset * 4 + DSP_PARAMETER_BYTE_OFFSET);
337 dsize = parameter->size * 4;
338
339 snd_printdd("dsp_spos: downloading parameter data to chip (%08x-%08x)\n",
340 doffset,doffset + dsize);
341
342 if (snd_cs46xx_download (chip, parameter->data, doffset, dsize)) {
343 snd_printk(KERN_ERR "dsp_spos: failed to download parameter data to DSP\n");
344 return -EINVAL;
345 }
346 }
347 379
348 if (ins->nmodules == 0) { 380 if (ins->nmodules == 0) {
349 snd_printdd("dsp_spos: clearing sample area\n"); 381 snd_printdd("dsp_spos: clearing sample area\n");
350 snd_cs46xx_clear_BA1(chip, DSP_SAMPLE_BYTE_OFFSET, DSP_SAMPLE_BYTE_SIZE); 382 snd_cs46xx_clear_BA1(chip, DSP_SAMPLE_BYTE_OFFSET, DSP_SAMPLE_BYTE_SIZE);
351 } 383 }
352 384
353 if (sample == NULL) { 385 err = dsp_load_sample(chip, get_segment_desc(module,
354 snd_printdd("dsp_spos: module got no sample segment\n"); 386 SEGTYPE_SP_SAMPLE));
355 } else { 387 if (err < 0)
356 if (ins->nmodules > 0) { 388 return err;
357 snd_printk(KERN_WARNING "dsp_spos: WARNING current sample data may be overwriten\n");
358 }
359
360 doffset = (sample->offset * 4 + DSP_SAMPLE_BYTE_OFFSET);
361 dsize = sample->size * 4;
362
363 snd_printdd("dsp_spos: downloading sample data to chip (%08x-%08x)\n",
364 doffset,doffset + dsize);
365
366 if (snd_cs46xx_download (chip,sample->data,doffset,dsize)) {
367 snd_printk(KERN_ERR "dsp_spos: failed to sample data to DSP\n");
368 return -EINVAL;
369 }
370 }
371
372 389
373 if (ins->nmodules == 0) { 390 if (ins->nmodules == 0) {
374 snd_printdd("dsp_spos: clearing code area\n"); 391 snd_printdd("dsp_spos: clearing code area\n");
@@ -986,7 +1003,10 @@ _map_task_tree (struct snd_cs46xx *chip, char * name, u32 dest, u32 size)
986 return NULL; 1003 return NULL;
987 } 1004 }
988 1005
989 strcpy(ins->tasks[ins->ntask].task_name,name); 1006 if (name)
1007 strcpy(ins->tasks[ins->ntask].task_name, name);
1008 else
1009 strcpy(ins->tasks[ins->ntask].task_name, "(NULL)");
990 ins->tasks[ins->ntask].address = dest; 1010 ins->tasks[ins->ntask].address = dest;
991 ins->tasks[ins->ntask].size = size; 1011 ins->tasks[ins->ntask].size = size;
992 1012
@@ -995,7 +1015,8 @@ _map_task_tree (struct snd_cs46xx *chip, char * name, u32 dest, u32 size)
995 desc = (ins->tasks + ins->ntask); 1015 desc = (ins->tasks + ins->ntask);
996 ins->ntask++; 1016 ins->ntask++;
997 1017
998 add_symbol (chip,name,dest,SYMBOL_PARAMETER); 1018 if (name)
1019 add_symbol (chip,name,dest,SYMBOL_PARAMETER);
999 return desc; 1020 return desc;
1000} 1021}
1001 1022
@@ -1006,6 +1027,7 @@ cs46xx_dsp_create_scb (struct snd_cs46xx *chip, char * name, u32 * scb_data, u32
1006 1027
1007 desc = _map_scb (chip,name,dest); 1028 desc = _map_scb (chip,name,dest);
1008 if (desc) { 1029 if (desc) {
1030 desc->data = scb_data;
1009 _dsp_create_scb(chip,scb_data,dest); 1031 _dsp_create_scb(chip,scb_data,dest);
1010 } else { 1032 } else {
1011 snd_printk(KERN_ERR "dsp_spos: failed to map SCB\n"); 1033 snd_printk(KERN_ERR "dsp_spos: failed to map SCB\n");
@@ -1023,6 +1045,7 @@ cs46xx_dsp_create_task_tree (struct snd_cs46xx *chip, char * name, u32 * task_da
1023 1045
1024 desc = _map_task_tree (chip,name,dest,size); 1046 desc = _map_task_tree (chip,name,dest,size);
1025 if (desc) { 1047 if (desc) {
1048 desc->data = task_data;
1026 _dsp_create_task_tree(chip,task_data,dest,size); 1049 _dsp_create_task_tree(chip,task_data,dest,size);
1027 } else { 1050 } else {
1028 snd_printk(KERN_ERR "dsp_spos: failed to map TASK\n"); 1051 snd_printk(KERN_ERR "dsp_spos: failed to map TASK\n");
@@ -1320,8 +1343,10 @@ int cs46xx_dsp_scb_and_task_init (struct snd_cs46xx *chip)
1320 0x0000ffff 1343 0x0000ffff
1321 }; 1344 };
1322 1345
1323 /* dirty hack ... */ 1346 if (!cs46xx_dsp_create_task_tree(chip, NULL,
1324 _dsp_create_task_tree (chip,(u32 *)&mix2_ostream_spb,WRITE_BACK_SPB,2); 1347 (u32 *)&mix2_ostream_spb,
1348 WRITE_BACK_SPB, 2))
1349 goto _fail_end;
1325 } 1350 }
1326 1351
1327 /* input sample converter */ 1352 /* input sample converter */
@@ -1622,7 +1647,6 @@ static int cs46xx_dsp_async_init (struct snd_cs46xx *chip,
1622 return 0; 1647 return 0;
1623} 1648}
1624 1649
1625
1626static void cs46xx_dsp_disable_spdif_hw (struct snd_cs46xx *chip) 1650static void cs46xx_dsp_disable_spdif_hw (struct snd_cs46xx *chip)
1627{ 1651{
1628 struct dsp_spos_instance * ins = chip->dsp_spos_instance; 1652 struct dsp_spos_instance * ins = chip->dsp_spos_instance;
@@ -1894,3 +1918,61 @@ int cs46xx_dsp_set_iec958_volume (struct snd_cs46xx * chip, u16 left, u16 right)
1894 1918
1895 return 0; 1919 return 0;
1896} 1920}
1921
1922#ifdef CONFIG_PM
1923int cs46xx_dsp_resume(struct snd_cs46xx * chip)
1924{
1925 struct dsp_spos_instance * ins = chip->dsp_spos_instance;
1926 int i, err;
1927
1928 /* clear parameter, sample and code areas */
1929 snd_cs46xx_clear_BA1(chip, DSP_PARAMETER_BYTE_OFFSET,
1930 DSP_PARAMETER_BYTE_SIZE);
1931 snd_cs46xx_clear_BA1(chip, DSP_SAMPLE_BYTE_OFFSET,
1932 DSP_SAMPLE_BYTE_SIZE);
1933 snd_cs46xx_clear_BA1(chip, DSP_CODE_BYTE_OFFSET, DSP_CODE_BYTE_SIZE);
1934
1935 for (i = 0; i < ins->nmodules; i++) {
1936 struct dsp_module_desc *module = &ins->modules[i];
1937 struct dsp_segment_desc *seg;
1938 u32 doffset, dsize;
1939
1940 seg = get_segment_desc(module, SEGTYPE_SP_PARAMETER);
1941 err = dsp_load_parameter(chip, seg);
1942 if (err < 0)
1943 return err;
1944
1945 seg = get_segment_desc(module, SEGTYPE_SP_SAMPLE);
1946 err = dsp_load_sample(chip, seg);
1947 if (err < 0)
1948 return err;
1949
1950 seg = get_segment_desc(module, SEGTYPE_SP_PROGRAM);
1951 if (!seg)
1952 continue;
1953
1954 doffset = seg->offset * 4 + module->load_address * 4
1955 + DSP_CODE_BYTE_OFFSET;
1956 dsize = seg->size * 4;
1957 err = snd_cs46xx_download(chip,
1958 ins->code.data + module->load_address,
1959 doffset, dsize);
1960 if (err < 0)
1961 return err;
1962 }
1963
1964 for (i = 0; i < ins->ntask; i++) {
1965 struct dsp_task_descriptor *t = &ins->tasks[i];
1966 _dsp_create_task_tree(chip, t->data, t->address, t->size);
1967 }
1968
1969 for (i = 0; i < ins->nscb; i++) {
1970 struct dsp_scb_descriptor *s = &ins->scbs[i];
1971 if (s->deleted)
1972 continue;
1973 _dsp_create_scb(chip, s->data, s->address);
1974 }
1975
1976 return 0;
1977}
1978#endif