27 #include <linux/slab.h>
43 static enum wide_opcode wide_opcodes[] = {
48 WIDE_TBEQ_COND_GOTO_ADDR,
49 WIDE_TBEQ_COND_CALL_ADDR,
50 WIDE_TBEQ_NCOND_GOTO_ADDR,
51 WIDE_TBEQ_NCOND_CALL_ADDR,
52 WIDE_TBEQ_COND_GOTO1_ADDR,
53 WIDE_TBEQ_COND_CALL1_ADDR,
54 WIDE_TBEQ_NCOND_GOTOI_ADDR,
55 WIDE_TBEQ_NCOND_CALL1_ADDR
59 u32 overlay_begin_address)
61 unsigned int i = 0,
j, nreallocated = 0;
63 u32 mop_operands,mop_type,wide_op;
73 if (ins->
code.offset > 0) {
74 mop_operands = (hival >> 6) & 0x03fff;
75 mop_type = mop_operands >> 10;
79 (mop_operands & WIDE_LADD_INSTR_MASK) == 0 &&
80 (mop_operands & WIDE_INSTR_MASK) != 0) {
81 wide_op = loval & 0x7f;
83 if (wide_opcodes[
j] == wide_op) {
85 address = (hival & 0x00FFF) << 5;
86 address |= loval >> 15;
88 snd_printdd(
"handle_wideop[1]: %05x:%05x addr %04x\n",hival,loval,address);
90 if ( !(address & 0x8000) ) {
91 address += (ins->
code.offset / 2) - overlay_begin_address;
93 snd_printdd(
"handle_wideop[1]: ROM symbol not reallocated\n");
99 hival |= ( (address >> 5) & 0x00FFF);
100 loval |= ( (address << 15) & 0xF8000);
102 address = (hival & 0x00FFF) << 5;
103 address |= loval >> 15;
105 snd_printdd(
"handle_wideop:[2] %05x:%05x addr %04x\n",hival,loval,address);
112 ins->
code.data[ins->
code.size++] = loval;
113 ins->
code.data[ins->
code.size++] = hival;
116 snd_printdd(
"dsp_spos: %d instructions reallocated\n",nreallocated);
124 if (module->
segments[i].segment_type == seg_type) {
136 for (i = ins->
symbol_table.highest_frag_index; i < ins->symbol_table.nsymbols; ++i) {
159 if (ins->
symbol_table.nsymbols == (DSP_MAX_SYMBOLS - 1)) {
194 if (ins->
symbol_table.nsymbols == (DSP_MAX_SYMBOLS - 1)) {
206 index = find_free_symbol_index (ins);
242 ins->
code.offset = 0;
265 (1 << 13) | (1 << 12);
286 for (i = 0; i < ins->
nscb; ++
i) {
287 if (ins->
scbs[i].deleted)
continue;
290 #ifdef CONFIG_PM_SLEEP
302 static int dsp_load_parameter(
struct snd_cs46xx *chip,
308 snd_printdd(
"dsp_spos: module got no parameter segment\n");
312 doffset = (parameter->
offset * 4 + DSP_PARAMETER_BYTE_OFFSET);
313 dsize = parameter->
size * 4;
316 "downloading parameter data to chip (%08x-%08x)\n",
317 doffset,doffset + dsize);
320 "failed to download parameter data to DSP\n");
326 static int dsp_load_sample(
struct snd_cs46xx *chip,
332 snd_printdd(
"dsp_spos: module got no sample segment\n");
336 doffset = (sample->
offset * 4 + DSP_SAMPLE_BYTE_OFFSET);
337 dsize = sample->
size * 4;
339 snd_printdd(
"dsp_spos: downloading sample data to chip (%08x-%08x)\n",
340 doffset,doffset + dsize);
356 if (ins->
nmodules == DSP_MAX_MODULES - 1) {
364 snd_printdd(
"dsp_spos: clearing parameter area\n");
368 err = dsp_load_parameter(chip, get_segment_desc(module,
378 err = dsp_load_sample(chip, get_segment_desc(module,
389 snd_printdd(
"dsp_spos: module got no code segment\n");
391 if (ins->
code.offset + code->
size > DSP_CODE_BYTE_SIZE) {
403 if (add_symbols(chip,module)) {
408 doffset = (code->
offset * 4 + ins->
code.offset * 4 + DSP_CODE_BYTE_OFFSET);
409 dsize = code->
size * 4;
410 snd_printdd(
"dsp_spos: downloading code to chip (%08x-%08x)\n",
411 doffset,doffset + dsize);
444 ins->
symbol_table.symbols[i].symbol_type == symbol_type) {
450 printk (
"dsp_spos: symbol <%s> type %02x not found\n",
451 symbol_name,symbol_type);
458 #ifdef CONFIG_PROC_FS
471 ins->
symbol_table.symbols[i].symbol_type == symbol_type) {
488 snd_iprintf(buffer,
"SYMBOLS:\n");
490 char *module_str =
"system";
496 module_str = ins->
symbol_table.symbols[
i].module->module_name;
500 snd_iprintf(buffer,
"%04X <%02X> %s [%s]\n",
509 static void cs46xx_dsp_proc_modules_read (
struct snd_info_entry *entry,
517 snd_iprintf(buffer,
"MODULES:\n");
519 snd_iprintf(buffer,
"\n%s:\n", ins->
modules[i].module_name);
520 snd_iprintf(buffer,
" %d symbols\n", ins->
modules[i].symbol_table.nsymbols);
521 snd_iprintf(buffer,
" %d fixups\n", ins->
modules[i].nfixups);
523 for (j = 0; j < ins->
modules[
i].nsegments; ++
j) {
525 snd_iprintf(buffer,
" segment %02x offset %08x size %08x\n",
532 static void cs46xx_dsp_proc_task_tree_read (
struct snd_info_entry *entry,
541 snd_iprintf(buffer,
"TASK TREES:\n");
542 for ( i = 0; i < ins->
ntask; ++
i) {
543 snd_iprintf(buffer,
"\n%04x %s:\n",ins->
tasks[i].address,ins->
tasks[i].task_name);
545 for (col = 0,j = 0;j < ins->
tasks[
i].size; j++,col++) {
548 snd_iprintf(buffer,
"\n");
551 val =
readl(dst + (ins->
tasks[i].address + j) *
sizeof(
u32));
552 snd_iprintf(buffer,
"%08x ",val);
556 snd_iprintf(buffer,
"\n");
560 static void cs46xx_dsp_proc_scb_read (
struct snd_info_entry *entry,
568 snd_iprintf(buffer,
"SCB's:\n");
569 for ( i = 0; i < ins->
nscb; ++
i) {
570 if (ins->
scbs[i].deleted)
572 snd_iprintf(buffer,
"\n%04x %s:\n\n",ins->
scbs[i].address,ins->
scbs[i].scb_name);
574 if (ins->
scbs[i].parent_scb_ptr !=
NULL) {
575 snd_iprintf(buffer,
"parent [%s:%04x] ",
576 ins->
scbs[i].parent_scb_ptr->scb_name,
577 ins->
scbs[i].parent_scb_ptr->address);
578 }
else snd_iprintf(buffer,
"parent [none] ");
580 snd_iprintf(buffer,
"sub_list_ptr [%s:%04x]\nnext_scb_ptr [%s:%04x] task_entry [%s:%04x]\n",
581 ins->
scbs[i].sub_list_ptr->scb_name,
582 ins->
scbs[i].sub_list_ptr->address,
583 ins->
scbs[i].next_scb_ptr->scb_name,
584 ins->
scbs[i].next_scb_ptr->address,
585 ins->
scbs[i].task_entry->symbol_name,
586 ins->
scbs[i].task_entry->address);
589 snd_iprintf(buffer,
"\n");
593 static void cs46xx_dsp_proc_parameter_dump_read (
struct snd_info_entry *entry,
598 unsigned int i, col = 0;
599 void __iomem *dst = chip->
region.
idx[1].remap_addr + DSP_PARAMETER_BYTE_OFFSET;
602 for (i = 0;i < DSP_PARAMETER_BYTE_SIZE; i +=
sizeof(
u32),col ++) {
604 snd_iprintf(buffer,
"\n");
610 snd_iprintf (buffer,
"\n%s:\n",symbol->
symbol_name);
614 snd_iprintf(buffer,
"%04X ", i / (
unsigned int)
sizeof(
u32));
617 snd_iprintf(buffer,
"%08X ",
readl(dst + i));
621 static void cs46xx_dsp_proc_sample_dump_read (
struct snd_info_entry *entry,
628 snd_iprintf(buffer,
"PCMREADER:\n");
629 for (i = PCM_READER_BUF1;i < PCM_READER_BUF1 + 0x30; i +=
sizeof(
u32),col ++) {
631 snd_iprintf(buffer,
"\n");
636 snd_iprintf(buffer,
"%04X ",i);
639 snd_iprintf(buffer,
"%08X ",
readl(dst + i));
642 snd_iprintf(buffer,
"\nMIX_SAMPLE_BUF1:\n");
645 for (i = MIX_SAMPLE_BUF1;i < MIX_SAMPLE_BUF1 + 0x40; i +=
sizeof(
u32),col ++) {
647 snd_iprintf(buffer,
"\n");
652 snd_iprintf(buffer,
"%04X ",i);
655 snd_iprintf(buffer,
"%08X ",
readl(dst + i));
658 snd_iprintf(buffer,
"\nSRC_TASK_SCB1:\n");
660 for (i = 0x2480 ; i < 0x2480 + 0x40 ; i +=
sizeof(
u32),col ++) {
662 snd_iprintf(buffer,
"\n");
667 snd_iprintf(buffer,
"%04X ",i);
670 snd_iprintf(buffer,
"%08X ",
readl(dst + i));
674 snd_iprintf(buffer,
"\nSPDIFO_BUFFER:\n");
676 for (i = SPDIFO_IP_OUTPUT_BUFFER1;i < SPDIFO_IP_OUTPUT_BUFFER1 + 0x30; i +=
sizeof(
u32),col ++) {
678 snd_iprintf(buffer,
"\n");
683 snd_iprintf(buffer,
"%04X ",i);
686 snd_iprintf(buffer,
"%08X ",
readl(dst + i));
689 snd_iprintf(buffer,
"\n...\n");
692 for (i = SPDIFO_IP_OUTPUT_BUFFER1+0xD0;i < SPDIFO_IP_OUTPUT_BUFFER1 + 0x110; i +=
sizeof(
u32),col ++) {
694 snd_iprintf(buffer,
"\n");
699 snd_iprintf(buffer,
"%04X ",i);
702 snd_iprintf(buffer,
"%08X ",
readl(dst + i));
706 snd_iprintf(buffer,
"\nOUTPUT_SNOOP:\n");
708 for (i = OUTPUT_SNOOP_BUFFER;i < OUTPUT_SNOOP_BUFFER + 0x40; i +=
sizeof(
u32),col ++) {
710 snd_iprintf(buffer,
"\n");
715 snd_iprintf(buffer,
"%04X ",i);
718 snd_iprintf(buffer,
"%08X ",
readl(dst + i));
721 snd_iprintf(buffer,
"\nCODEC_INPUT_BUF1: \n");
723 for (i = CODEC_INPUT_BUF1;i < CODEC_INPUT_BUF1 + 0x40; i +=
sizeof(
u32),col ++) {
725 snd_iprintf(buffer,
"\n");
730 snd_iprintf(buffer,
"%04X ",i);
733 snd_iprintf(buffer,
"%08X ",
readl(dst + i));
736 snd_iprintf(buffer,
"\nWRITE_BACK_BUF1: \n");
738 for (i = WRITE_BACK_BUF1;i < WRITE_BACK_BUF1 + 0x40; i +=
sizeof(
u32),col ++) {
740 snd_iprintf(buffer,
"\n");
745 snd_iprintf(buffer,
"%04X ",i);
748 snd_iprintf(buffer,
"%08X ",
readl(dst + i));
752 snd_iprintf(buffer,
"\nSPDIFI_IP_OUTPUT_BUFFER1: \n");
754 for (i = SPDIFI_IP_OUTPUT_BUFFER1;i < SPDIFI_IP_OUTPUT_BUFFER1 + 0x80; i +=
sizeof(
u32),col ++) {
756 snd_iprintf(buffer,
"\n");
761 snd_iprintf(buffer,
"%04X ",i);
764 snd_iprintf(buffer,
"%08X ",
readl(dst + i));
766 snd_iprintf(buffer,
"\n");
777 if ((entry = snd_info_create_card_entry(card,
"dsp", card->
proc_root)) !=
NULL) {
781 if (snd_info_register(entry) < 0) {
782 snd_info_free_entry(entry);
792 if ((entry = snd_info_create_card_entry(card,
"spos_symbols", ins->
proc_dsp_dir)) !=
NULL) {
796 entry->
c.
text.read = cs46xx_dsp_proc_symbol_table_read;
797 if (snd_info_register(entry) < 0) {
798 snd_info_free_entry(entry);
804 if ((entry = snd_info_create_card_entry(card,
"spos_modules", ins->
proc_dsp_dir)) !=
NULL) {
808 entry->
c.
text.read = cs46xx_dsp_proc_modules_read;
809 if (snd_info_register(entry) < 0) {
810 snd_info_free_entry(entry);
816 if ((entry = snd_info_create_card_entry(card,
"parameter", ins->
proc_dsp_dir)) !=
NULL) {
820 entry->
c.
text.read = cs46xx_dsp_proc_parameter_dump_read;
821 if (snd_info_register(entry) < 0) {
822 snd_info_free_entry(entry);
828 if ((entry = snd_info_create_card_entry(card,
"sample", ins->
proc_dsp_dir)) !=
NULL) {
832 entry->
c.
text.read = cs46xx_dsp_proc_sample_dump_read;
833 if (snd_info_register(entry) < 0) {
834 snd_info_free_entry(entry);
840 if ((entry = snd_info_create_card_entry(card,
"task_tree", ins->
proc_dsp_dir)) !=
NULL) {
844 entry->
c.
text.read = cs46xx_dsp_proc_task_tree_read;
845 if (snd_info_register(entry) < 0) {
846 snd_info_free_entry(entry);
852 if ((entry = snd_info_create_card_entry(card,
"scb_info", ins->
proc_dsp_dir)) !=
NULL) {
856 entry->
c.
text.read = cs46xx_dsp_proc_scb_read;
857 if (snd_info_register(entry) < 0) {
858 snd_info_free_entry(entry);
866 for (i = 0; i < ins->
nscb; ++
i) {
867 if (ins->
scbs[i].deleted)
continue;
900 for (i = 0; i < ins->
nscb; ++
i) {
901 if (ins->
scbs[i].deleted)
continue;
913 static int debug_tree;
914 static void _dsp_create_task_tree (
struct snd_cs46xx *chip,
u32 * task_data,
918 DSP_PARAMETER_BYTE_OFFSET + dest *
sizeof(
u32);
921 for (i = 0; i <
size; ++
i) {
922 if (debug_tree)
printk (
"addr %p, val %08x\n",spdst,task_data[i]);
923 writel(task_data[i],spdst);
924 spdst +=
sizeof(
u32);
928 static int debug_scb;
932 DSP_PARAMETER_BYTE_OFFSET + dest *
sizeof(
u32);
935 for (i = 0; i < 0x10; ++
i) {
936 if (debug_scb)
printk (
"addr %p, val %08x\n",spdst,scb_data[i]);
937 writel(scb_data[i],spdst);
938 spdst +=
sizeof(
u32);
944 int index = ins->
nscb,
i;
947 if (ins->
scbs[i].deleted) {
967 index = find_free_scb_index (ins);
981 if (index == ins->
nscb)
1015 #define SCB_BYTES (0x10 * 4)
1022 #ifdef CONFIG_PM_SLEEP
1029 desc = _map_scb (chip,name,dest);
1031 desc->
data = scb_data;
1032 _dsp_create_scb(chip,scb_data,dest);
1035 #ifdef CONFIG_PM_SLEEP
1045 cs46xx_dsp_create_task_tree (
struct snd_cs46xx *chip,
char * name,
u32 * task_data,
1050 desc = _map_task_tree (chip,name,dest,size);
1052 desc->
data = task_data;
1053 _dsp_create_task_tree(chip,task_data,dest,size);
1083 int fifo_addr, fifo_span, valid_slots;
1086 HFG_TREE_SCB,HFG_STACK,
1087 SPOSCB_ADDR,BG_TREE_SCB_ADDR,
1092 FG_TASK_HEADER_ADDR,0,
1104 cs46xx_dsp_create_task_tree(chip,
"sposCB", (
u32 *)&sposcb, SPOSCB_ADDR, 0x10);
1107 if (null_algorithm ==
NULL) {
1113 if (fg_task_tree_header_code ==
NULL) {
1119 if (task_tree_header_code ==
NULL) {
1125 if (task_tree_thread ==
NULL) {
1131 if (magic_snoop_task ==
NULL) {
1141 NULL_SCB_ADDR, NULL_SCB_ADDR,
1149 null_scb.entry_point = null_algorithm->
address;
1172 BG_TREE_SCB_ADDR,TIMINGMASTER_SCB_ADDR,
1174 FG_TASK_HEADER_ADDR + TCBData,
1180 2,SPOSCB_ADDR + HFGFlags,
1182 FG_TASK_HEADER_ADDR + TCBContextBlk,FG_STACK
1228 fg_task_tree_hdr.
links.entry_point = fg_task_tree_header_code->
address;
1230 cs46xx_dsp_create_task_tree(chip,
"FGtaskTreeHdr",(
u32 *)&fg_task_tree_hdr,FG_TASK_HEADER_ADDR,0x35);
1248 NULL_SCB_ADDR,NULL_SCB_ADDR,
1250 BG_TREE_SCB_ADDR + TCBData,
1256 0,SPOSCB_ADDR + HFGFlags,
1258 BG_TREE_SCB_ADDR + TCBContextBlk,BG_STACK
1304 bg_task_tree_hdr.
links.entry_point = task_tree_header_code->
address;
1306 cs46xx_dsp_create_task_tree(chip,
"BGtaskTreeHdr",(
u32 *)&bg_task_tree_hdr,BG_TREE_SCB_ADDR,0x35);
1315 CODECOUT_SCB_ADDR,timing_master_scb,
1318 if (!codec_out_scb)
goto _fail_end;
1321 MIX_SAMPLE_BUF1,MASTERMIX_SCB_ADDR,
1326 if (!master_mix_scb)
goto _fail_end;
1331 CODECIN_SCB_ADDR,codec_out_scb,
1333 if (!codec_in_scb)
goto _fail_end;
1338 WRITE_BACK_BUF1,WRITE_BACK_SPB,
1342 if (!write_back_scb)
goto _fail_end;
1350 if (!cs46xx_dsp_create_task_tree(chip,
NULL,
1351 (
u32 *)&mix2_ostream_spb,
1360 VARIDECIMATE_SCB_ADDR,
1363 if (!vari_decimate_scb)
goto _fail_end;
1368 RECORD_MIXER_SCB_ADDR,
1373 if (!record_mix_scb)
goto _fail_end;
1375 valid_slots = snd_cs46xx_peekBA0(chip,
BA0_ACOSV);
1399 REAR_MIXER_SCB_ADDR,
1400 REAR_CODECOUT_SCB_ADDR,codec_in_scb,
1402 if (!rear_codec_out_scb)
goto _fail_end;
1408 REAR_MIXER_SCB_ADDR,
1412 if (!rear_mix_scb)
goto _fail_end;
1418 CLFE_MIXER_SCB_ADDR,
1419 CLFE_CODEC_SCB_ADDR,
1422 if (!clfe_codec_out_scb)
goto _fail_end;
1428 CLFE_MIXER_SCB_ADDR,
1436 clfe_codec_out_scb = rear_codec_out_scb;
1441 snd_cs46xx_pokeBA0(chip,
BA0_ACOSV, valid_slots);
1445 OUTPUT_SNOOP_BUFFER,
1451 if (!magic_snoop_scb)
goto _fail_end;
1464 SRC_DELAY_BUF1,SRCTASK_SCB_ADDR,
1468 if (!src_task_scb)
goto _fail_end;
1475 cs46xx_dsp_async_init(chip,timing_master_scb);
1483 static int cs46xx_dsp_async_init (
struct snd_cs46xx *chip,
1490 struct dsp_scb_descriptor * spdifi_scb_desc, * spdifo_scb_desc, * async_codec_scb_desc;
1493 if (s16_async_codec_input_task ==
NULL) {
1498 if (spdifo_task ==
NULL) {
1504 if (spdifi_task ==
NULL) {
1523 RSCONFIG_SAMPLE_16MONO + RSCONFIG_MODULO_256,
1524 ( SPDIFO_IP_OUTPUT_BUFFER1 << 0x10 ) | 0xFFFC,
1527 FG_TASK_HEADER_ADDR, NULL_SCB_ADDR,
1529 SPDIFO_SCB_INST + SPDIFOFIFOPointer,
1550 SPDIFO_SCB_INST, NULL_SCB_ADDR,
1552 SPDIFI_SCB_INST + SPDIFIFIFOPointer,
1557 RSCONFIG_SAMPLE_16MONO + RSCONFIG_MODULO_128,
1558 (SPDIFI_IP_OUTPUT_BUFFER1 << 0x10) | 0xFFFC,
1571 RSCONFIG_SAMPLE_16MONO + RSCONFIG_MODULO_64,
1572 (ASYNC_IP_OUTPUT_BUFFER1 << 0x10) | 0xFFFC,
1575 SPDIFI_SCB_INST,NULL_SCB_ADDR,
1576 s16_async_codec_input_task->
address,
1577 HFG_TREE_SCB + AsyncCIOFIFOPointer,
1579 RSCONFIG_SAMPLE_16STEREO + RSCONFIG_MODULO_64,
1580 (ASYNC_IP_OUTPUT_BUFFER1 << 0x10),
1582 #ifdef UseASER1Input
1596 #ifdef UseASER2Input
1623 async_codec_scb_desc =
cs46xx_dsp_create_scb(chip,
"AsynCodecInputSCB",(
u32 *)&async_codec_input_scb, HFG_TREE_SCB);
1630 async_codec_scb_desc->
task_entry = s16_async_codec_input_task;
1658 static void cs46xx_dsp_disable_spdif_hw (
struct snd_cs46xx *chip)
1684 cs46xx_dsp_disable_spdif_hw (chip);
1688 snd_cs46xx_pokeBA0(chip,
BA0_ASER_FADDR, ( 0x8000 | ((SP_SPDOUT_FIFO >> 4) << 4) ));
1734 SPDIFI_IP_OUTPUT_BUFFER1,
1749 cs46xx_dsp_scb_set_volume (chip,ins->
spdif_in_src,0x7fff,0x7fff);
1803 "PCMSerialInput_Wave");
1835 "PCMSerialInput_ADC");
1867 temp = ( address << 16 ) | ( address & 0x0000FFFF);
1869 snd_cs46xx_poke(chip,( SPIOWRITE_SCB_ADDR << 2), temp);
1870 snd_cs46xx_poke(chip,((SPIOWRITE_SCB_ADDR + 1) << 2), data);
1871 snd_cs46xx_poke(chip,((SPIOWRITE_SCB_ADDR + 2) << 2), data);
1874 snd_cs46xx_poke(chip,((SPIOWRITE_SCB_ADDR + 6) << 2), SPIOWRITE_SCB_ADDR << 0x10);
1877 for (i=0; i<25; i++) {
1880 temp = snd_cs46xx_peek(chip,((SPIOWRITE_SCB_ADDR + 6) << 2));
1881 if (temp == 0x00000000)
1903 cs46xx_dsp_scb_set_volume (chip,scb,left,right);
1910 cs46xx_dsp_scb_set_volume (chip,scb,left,right);
1940 #ifdef CONFIG_PM_SLEEP
1941 int cs46xx_dsp_resume(
struct snd_cs46xx * chip)
1948 DSP_PARAMETER_BYTE_SIZE);
1950 DSP_SAMPLE_BYTE_SIZE);
1953 for (i = 0; i < ins->
nmodules; i++) {
1959 err = dsp_load_parameter(chip, seg);
1964 err = dsp_load_sample(chip, seg);
1973 + DSP_CODE_BYTE_OFFSET;
1974 dsize = seg->
size * 4;
1982 for (i = 0; i < ins->
ntask; i++) {
1987 for (i = 0; i < ins->
nscb; i++) {
1993 for (i = 0; i < ins->
nscb; i++) {
1998 cs46xx_dsp_spos_update_scb(chip, s);
2000 cs46xx_dsp_scb_set_volume(chip, s,
2005 snd_cs46xx_poke(chip, (ins->
ref_snoop_scb->address + 2) << 2,
2006 (OUTPUT_SNOOP_BUFFER + 0x10) << 0x10);
2011 if (chip->dsp_spos_instance->spdif_status_in) {