28 #include <linux/slab.h>
57 if (symbol_index < ins->
symbol_table.highest_frag_index) {
81 ins = chip->dsp_spos_instance;
86 for (col = 0,j = 0;j < 0x10; j++,col++) {
88 snd_iprintf(buffer,
"\n");
91 snd_iprintf(buffer,
"%08x ",
readl(dst + (scb->
address + j) *
sizeof(
u32)));
94 snd_iprintf(buffer,
"\n");
97 snd_iprintf(buffer,
"parent [%s:%04x] ",
100 }
else snd_iprintf(buffer,
"parent [none] ");
102 snd_iprintf(buffer,
"sub_list_ptr [%s:%04x]\nnext_scb_ptr [%s:%04x] task_entry [%s:%04x]\n",
110 snd_iprintf(buffer,
"index [%d] ref_count [%d]\n",scb->
index,scb->
ref_count);
159 cs46xx_dsp_spos_update_scb(chip,scb);
165 static void _dsp_clear_sample_buffer (
struct snd_cs46xx *chip,
u32 sample_buffer_addr,
171 for (i = 0; i < dword_count ; ++
i ) {
197 _dsp_unlink_scb (chip,scb);
198 spin_unlock_irqrestore(&chip->
reg_lock, flags);
206 #ifdef CONFIG_PM_SLEEP
224 for(i = scb->
index + 1;i < ins->
nscb; ++i) {
225 ins->
scbs[i - 1].index = i - 1;
231 #ifdef CONFIG_PROC_FS
261 snd_info_free_entry(entry);
273 entry->
c.
text.read = cs46xx_dsp_proc_scb_info_read;
275 if (snd_info_register(entry) < 0) {
276 snd_info_free_entry(entry);
302 scb_data[SCBsubListPtr] =
305 scb_data[SCBfuncEntryPtr] &= 0xFFFF0000;
306 scb_data[SCBfuncEntryPtr] |= task_entry->
address;
324 printk (
"scb->parent_scb_ptr->next_scb_ptr = %s\n",scb->
parent_scb_ptr->next_scb_ptr->scb_name);
325 printk (
"scb->parent_scb_ptr->sub_list_ptr = %s\n",scb->
parent_scb_ptr->sub_list_ptr->scb_name);
350 spin_unlock_irqrestore(&chip->
reg_lock, flags);
360 cs46xx_dsp_create_generic_scb (
struct snd_cs46xx *chip,
char * name,
u32 * scb_data,
361 u32 dest,
char * task_entry_name,
370 if (task_entry ==
NULL) {
375 return _dsp_create_generic_scb (chip,name,scb_data,dest,task_entry,
376 parent_scb,scb_child_type);
405 scb = cs46xx_dsp_create_generic_scb(chip,
"TimingMasterSCBInst",(
u32 *)&timing_master_scb,
406 TIMINGMASTER_SCB_ADDR,
415 u16 channel_disp,
u16 fifo_addr,
u16 child_scb_addr,
438 channel_disp,fifo_addr,
444 scb = cs46xx_dsp_create_generic_scb(chip,codec_name,(
u32 *)&codec_out_scb,
445 dest,
"S16_CODECOUTPUTTASK",parent_scb,
453 u16 channel_disp,
u16 fifo_addr,
u16 sample_buffer_addr,
474 SyncIOSCB,NULL_SCB_ADDR
480 RSCONFIG_SAMPLE_16STEREO + RSCONFIG_MODULO_64,
481 sample_buffer_addr << 0x10,
482 channel_disp,fifo_addr,
489 scb = cs46xx_dsp_create_generic_scb(chip,codec_name,(
u32 *)&codec_input_scb,
490 dest,
"S16_CODECINPUTTASK",parent_scb,
498 u16 sample_buffer_addr,
u32 dest,
499 int virtual_channel,
u32 playback_hw_addr,
557 NULL_SCB_ADDR,NULL_SCB_ADDR,
562 RSCONFIG_DMA_ENABLE +
563 (19 << RSCONFIG_MAX_DMA_SIZE_SHIFT) +
565 ((dest >> 4) << RSCONFIG_STREAM_NUM_SHIFT) +
566 RSCONFIG_SAMPLE_16STEREO +
569 (sample_buffer_addr << 0x10),
590 scb = _dsp_create_generic_scb(chip,scb_name,(
u32 *)&pcm_reader_scb,
597 #define GOF_PER_SEC 200
603 u16 src_delay_buffer_addr,
u32 dest,
611 unsigned int tmp1, tmp2;
612 unsigned int phiIncr;
613 unsigned int correctionPerGOF, correctionPerSec;
615 snd_printdd(
"dsp_spos: setting %s rate to %u\n",scb_name,rate);
635 phiIncr = tmp1 / 48000;
636 tmp1 -= phiIncr * 48000;
641 tmp1 -= tmp2 * 48000;
644 correctionPerSec =
tmp1;
652 correctionPerGOF,correctionPerSec,
653 RSCONFIG_SAMPLE_16STEREO + RSCONFIG_MODULO_32,
654 0x0000,src_delay_buffer_addr,
656 0x080,(src_delay_buffer_addr + (24 * 4)),
659 RSCONFIG_SAMPLE_16STEREO + RSCONFIG_MODULO_8,
660 src_buffer_addr << 0x10,
679 _dsp_clear_sample_buffer (chip,src_buffer_addr,8);
680 _dsp_clear_sample_buffer (chip,src_delay_buffer_addr,32);
687 scb = cs46xx_dsp_create_generic_scb(chip,scb_name,(
u32 *)&src_task_scb,
688 dest,
"DMAREADER",parent_scb,
691 scb = _dsp_create_generic_scb(chip,scb_name,(
u32 *)&src_task_scb,
692 dest,ins->
s16_up,parent_scb,
704 cs46xx_dsp_create_filter_scb(
struct snd_cs46xx * chip,
char * scb_name,
707 int scb_child_type) {
718 .filter_unused3 = 0x0000,
719 .filter_unused2 = 0x0000,
724 .prev_sample_output1 = 0x00000000,
725 .prev_sample_output2 = 0x00000000,
727 .prev_sample_input1 = 0x00000000,
728 .prev_sample_input2 = 0x00000000,
730 .next_scb_ptr = 0x0000,
731 .sub_list_ptr = 0x0000,
733 .entry_point = 0x0000,
745 scb = cs46xx_dsp_create_generic_scb(chip,scb_name,(
u32 *)&filter_scb,
746 dest,
"FILTERTASK",parent_scb,
755 u16 mix_buffer_addr,
u32 dest,
776 RSCONFIG_SAMPLE_16STEREO + RSCONFIG_MODULO_32,
777 (mix_buffer_addr + (16 * 4)) << 0x10,
786 scb = cs46xx_dsp_create_generic_scb(chip,scb_name,(
u32 *)&master_mix_scb,
787 dest,
"S16_MIX",parent_scb,
795 u16 mix_buffer_addr,
u16 writeback_spb,
u32 dest,
824 RSCONFIG_DMA_ENABLE +
825 (19 << RSCONFIG_MAX_DMA_SIZE_SHIFT) +
827 ((dest >> 4) << RSCONFIG_STREAM_NUM_SHIFT) +
828 RSCONFIG_DMA_TO_HOST +
829 RSCONFIG_SAMPLE_16STEREO +
831 (mix_buffer_addr + (32 * 4)) << 0x10,
838 scb = cs46xx_dsp_create_generic_scb(chip,scb_name,(
u32 *)&mix2_ostream_scb,
840 dest,
"S16_MIX_TO_OSTREAM",parent_scb,
849 u16 vari_buffer_addr0,
850 u16 vari_buffer_addr1,
862 vari_buffer_addr0,vari_buffer_addr1,
865 RSCONFIG_SAMPLE_16STEREO + RSCONFIG_MODULO_256,
869 0x0080,vari_buffer_addr1 + (25 * 4),
874 RSCONFIG_SAMPLE_16STEREO + RSCONFIG_MODULO_8,
875 vari_buffer_addr0 << 0x10,
883 scb = cs46xx_dsp_create_generic_scb(chip,scb_name,(
u32 *)&vari_decimate_scb,
884 dest,
"VARIDECIMATE",parent_scb,
892 cs46xx_dsp_create_pcm_serial_input_scb(
struct snd_cs46xx * chip,
char * scb_name,
u32 dest,
918 RSCONFIG_SAMPLE_16STEREO + RSCONFIG_MODULO_16,
927 scb = cs46xx_dsp_create_generic_scb(chip,scb_name,(
u32 *)&pcm_serial_input_scb,
928 dest,
"PCMSERIALINPUTTASK",parent_scb,
935 cs46xx_dsp_create_asynch_fg_tx_scb(
struct snd_cs46xx * chip,
char * scb_name,
u32 dest,
937 u16 asynch_buffer_address,
960 0,dest + AFGTxAccumPhi,
962 RSCONFIG_SAMPLE_16STEREO + RSCONFIG_MODULO_256,
963 (asynch_buffer_address) << 0x10,
973 scb = cs46xx_dsp_create_generic_scb(chip,scb_name,(
u32 *)&asynch_fg_tx_scb,
974 dest,
"ASYNCHFGTXCODE",parent_scb,
984 u16 asynch_buffer_address,
1008 RSCONFIG_MODULO_128 |
1009 RSCONFIG_SAMPLE_16STEREO,
1010 ( (asynch_buffer_address + (16 * 4)) << 0x10),
1022 scb = cs46xx_dsp_create_generic_scb(chip,scb_name,(
u32 *)&asynch_fg_rx_scb,
1023 dest,
"ASYNCHFGRXCODE",parent_scb,
1032 cs46xx_dsp_create_output_snoop_scb(
struct snd_cs46xx * chip,
char * scb_name,
u32 dest,
1033 u16 snoop_buffer_address,
1058 RSCONFIG_SAMPLE_16STEREO + RSCONFIG_MODULO_64,
1059 snoop_buffer_address << 0x10,
1065 scb = cs46xx_dsp_create_generic_scb(chip,scb_name,(
u32 *)&output_snoop_scb,
1066 dest,
"OUTPUTSNOOP",parent_scb,
1102 scb = cs46xx_dsp_create_generic_scb(chip,scb_name,(
u32 *)&spio_write_scb,
1103 dest,
"SPIOWRITE",parent_scb,
1111 u16 snoop_buffer_address,
1121 snoop_buffer_address << 0x10,
1130 RSCONFIG_SAMPLE_16STEREO + RSCONFIG_MODULO_64,
1131 snoop_buffer_address << 0x10,
1138 scb = cs46xx_dsp_create_generic_scb(chip,scb_name,(
u32 *)&magic_snoop_scb,
1139 dest,
"MAGICSNOOPTASK",parent_scb,
1242 int i, pcm_index = -1, insert_point, src_index = -1,
pass_through = 0;
1243 unsigned long flags;
1245 switch (pcm_channel_id) {
1267 if (sample_rate == 48000) {
1278 if (!sample_rate) sample_rate = 44100;
1282 (pcm_index == -1 || src_scb ==
NULL); ++
i) {
1296 }
else if (pcm_index == -1) {
1301 if (pcm_index == -1) {
1306 if (src_scb ==
NULL) {
1325 src_parent_scb = mixer_scb;
1328 src_parent_scb = find_next_free_scb(chip,mixer_scb->sub_list_ptr);
1334 snd_printdd(
"dsp_spos: creating SRC \"%s\"\n",scb_name);
1337 src_output_buffer_addr[src_index],
1338 src_delay_buffer_addr[src_index],
1340 0x400 + (src_index * 0x10) ,
1358 snd_printdd(
"dsp_spos: creating PCM \"%s\" (%d)\n",scb_name,
1361 pcm_scb = cs46xx_dsp_create_pcm_reader_scb(chip,scb_name,
1362 pcm_reader_buffer_addr[pcm_index],
1364 (pcm_index * 0x10) + 0x200,
1377 ins->
pcm_channels[pcm_index].sample_rate = sample_rate;
1387 spin_unlock_irqrestore(&chip->
reg_lock, flags);
1399 switch (period_size) {
1422 snd_printdd (
"period size (%d) not supported by HW\n", period_size);
1426 snd_cs46xx_poke (chip,pcm_channel->
pcm_reader_scb->address << 2,temp);
1434 u32 temp = snd_cs46xx_peek (chip,WRITEBACK_SCB_ADDR << 2);
1437 switch (period_size) {
1460 snd_printdd (
"period size (%d) not supported by HW\n", period_size);
1464 snd_cs46xx_poke (chip,WRITEBACK_SCB_ADDR << 2,temp);
1473 unsigned long flags;
1477 pcm_channel->
src_scb->ref_count <= 0))
1484 pcm_channel->
src_scb->ref_count --;
1486 spin_unlock_irqrestore(&chip->
reg_lock, flags);
1490 if (!pcm_channel->
src_scb->ref_count) {
1505 unsigned long flags;
1508 chip->dsp_spos_instance->npcm_channels <= 0))
1513 spin_unlock_irqrestore(&chip->
reg_lock, flags);
1520 spin_unlock_irqrestore(&chip->
reg_lock, flags);
1531 unsigned long flags;
1536 spin_unlock_irqrestore(&chip->
reg_lock, flags);
1540 parent_scb = src_scb;
1556 cs46xx_dsp_spos_update_scb(chip,parent_scb);
1559 spin_unlock_irqrestore(&chip->
reg_lock, flags);
1583 pcm_input = cs46xx_dsp_create_pcm_serial_input_scb(chip,scb_name,addr,
1592 unsigned long flags;
1598 cs46xx_dsp_scb_set_volume (chip,src,0,0);
1601 _dsp_unlink_scb (chip,src);
1602 spin_unlock_irqrestore(&chip->
reg_lock, flags);
1618 parent_scb = find_next_free_scb (chip,ins->
master_mix_scb->sub_list_ptr);
1628 cs46xx_dsp_spos_update_scb(chip,parent_scb);
1658 snd_cs46xx_poke (chip, (ins->
ref_snoop_scb->address + 2) << 2,
1659 (OUTPUT_SNOOP_BUFFER + 0x10) << 0x10 );
1662 ins->
asynch_tx_scb = cs46xx_dsp_create_asynch_fg_tx_scb(chip,
"AsynchFGTxSCB",ASYNCTX_SCB_ADDR,
1664 SPDIFO_IP_OUTPUT_BUFFER1,
1669 ins->
spdif_pcm_input_scb = cs46xx_dsp_create_pcm_serial_input_scb(chip,
"PCMSerialInput_II",
1670 PCMSERIALINII_SCB_ADDR,
1712 _dsp_clear_sample_buffer(chip,SPDIFO_IP_OUTPUT_BUFFER1,256);
1739 ins->
asynch_tx_scb = cs46xx_dsp_create_asynch_fg_tx_scb(chip,
"AsynchFGTxSCB",ASYNCTX_SCB_ADDR,
1741 SPDIFO_IP_OUTPUT_BUFFER1,
1776 _dsp_clear_sample_buffer(chip,SPDIFO_IP_OUTPUT_BUFFER1,256);