diff --exclude=CVS -Naur alsa-kernel/include/cs46xx.h ../cvs/alsa-kernel/include/cs46xx.h --- alsa-kernel/include/cs46xx.h Mon Nov 4 10:57:10 2002 +++ ../cvs/alsa-kernel/include/cs46xx.h Sun Dec 8 19:03:27 2002 @@ -1663,6 +1663,8 @@ snd_pcm_substream_t *substream; pcm_channel_descriptor_t * pcm_channel; + + int pcm_channel_id; /* Fron Rear, Center Lfe ... */ } cs46xx_pcm_t; typedef struct { diff --exclude=CVS -Naur alsa-kernel/include/cs46xx_dsp_spos.h ../cvs/alsa-kernel/include/cs46xx_dsp_spos.h --- alsa-kernel/include/cs46xx_dsp_spos.h Sun Dec 8 13:21:47 2002 +++ ../cvs/alsa-kernel/include/cs46xx_dsp_spos.h Sun Dec 8 19:04:51 2002 @@ -140,7 +140,6 @@ dsp_scb_descriptor_t * pcm_reader_scb; dsp_scb_descriptor_t * src_scb; dsp_scb_descriptor_t * mixer_scb; - int pcm_channel_id; void * private_data; } pcm_channel_descriptor_t; diff --exclude=CVS -Naur alsa-kernel/pci/cs46xx/cs46xx_lib.c ../cvs/alsa-kernel/pci/cs46xx/cs46xx_lib.c --- alsa-kernel/pci/cs46xx/cs46xx_lib.c Sun Dec 8 13:21:55 2002 +++ ../cvs/alsa-kernel/pci/cs46xx/cs46xx_lib.c Sun Dec 8 20:29:22 2002 @@ -952,7 +952,7 @@ #ifdef CONFIG_SND_CS46XX_NEW_DSP /* magic value to unmute PCM stream playback volume */ snd_cs46xx_poke(chip, (cpcm->pcm_channel->pcm_reader_scb->address + - SCBVolumeCtrl) << 2, 0x80007fff); + SCBVolumeCtrl) << 2, 0x80008000); if (cpcm->pcm_channel->unlinked) cs46xx_dsp_pcm_link(chip,cpcm->pcm_channel); @@ -1032,32 +1032,27 @@ static int _cs46xx_adjust_sample_rate (cs46xx_t *chip, cs46xx_pcm_t *cpcm, int sample_rate) { - /* if this is the only PCMReaderSCB child under current - SrcTask then there no need to re-create pcm-channel */ - if ( cpcm->pcm_channel->src_scb->ref_count == 1 && - cpcm->pcm_channel->sample_rate != sample_rate && - /* never set a 0 khz sample rate */ - sample_rate) { - /* sample rate not set or we can reuse - the same SRC*/ - cs46xx_dsp_set_src_sample_rate (chip,cpcm->pcm_channel->src_scb,sample_rate); - cpcm->pcm_channel->sample_rate = sample_rate; - } - /* if there is more then 1 PCMReaderSCB child's under current - SrcTask then we must recreate channel */ - if (cpcm->pcm_channel->sample_rate != sample_rate && - cpcm->pcm_channel->src_scb->ref_count != 1 && - /* never set a 0 khz sample rate */ - sample_rate) { + /* If PCMReaderSCB and SrcTaskSCB not created yet ... */ + if ( cpcm->pcm_channel == NULL) { + cpcm->pcm_channel = cs46xx_dsp_create_pcm_channel (chip, sample_rate, + cpcm, cpcm->hw_addr,cpcm->pcm_channel_id); + if (cpcm->pcm_channel == NULL) { + snd_printk(KERN_ERR "cs46xx: failed to create virtual PCM channel\n"); + return -ENOMEM; + } + cpcm->pcm_channel->sample_rate = sample_rate; + } else + /* if sample rate is changed */ + if (cpcm->pcm_channel->sample_rate != sample_rate) { int unlinked = cpcm->pcm_channel->unlinked; cs46xx_dsp_destroy_pcm_channel (chip,cpcm->pcm_channel); if ( (cpcm->pcm_channel = cs46xx_dsp_create_pcm_channel (chip, sample_rate, cpcm, cpcm->hw_addr, - cpcm->pcm_channel->pcm_channel_id)) == NULL) { + cpcm->pcm_channel_id)) == NULL) { snd_printk(KERN_ERR "cs46xx: failed to re-create virtual PCM channel\n"); - return -ENXIO; + return -ENOMEM; } if (!unlinked) cs46xx_dsp_pcm_link (chip,cpcm->pcm_channel); @@ -1082,15 +1077,21 @@ cpcm = snd_magic_cast(cs46xx_pcm_t, runtime->private_data, return -ENXIO); #ifdef CONFIG_SND_CS46XX_NEW_DSP + snd_assert (sample_rate != 0, return -ENXIO); + down (&chip->spos_mutex); - snd_assert (cpcm->pcm_channel != NULL); - if (_cs46xx_adjust_sample_rate (chip,cpcm,sample_rate)) { up (&chip->spos_mutex); return -ENXIO; } + snd_assert (cpcm->pcm_channel != NULL); + if (!cpcm->pcm_channel) { + up (&chip->spos_mutex); + return -ENXIO; + } + if (cs46xx_dsp_pcm_channel_set_period (chip,cpcm->pcm_channel,period_size * 4)) { up (&chip->spos_mutex); return -EINVAL; @@ -1108,11 +1109,11 @@ #ifdef CONFIG_SND_CS46XX_NEW_DSP - if (cpcm->pcm_channel->pcm_channel_id == DSP_PCM_MAIN_CHANNEL) { + if (cpcm->pcm_channel_id == DSP_PCM_MAIN_CHANNEL) { substream->ops = &snd_cs46xx_playback_ops; - } else if (cpcm->pcm_channel->pcm_channel_id == DSP_PCM_REAR_CHANNEL) { + } else if (cpcm->pcm_channel_id == DSP_PCM_REAR_CHANNEL) { substream->ops = &snd_cs46xx_playback_rear_ops; - } else if (cpcm->pcm_channel->pcm_channel_id == DSP_IEC958_CHANNEL) { + } else if (cpcm->pcm_channel_id == DSP_IEC958_CHANNEL) { substream->ops = &snd_cs46xx_playback_iec958_ops; } else { snd_assert(0); @@ -1135,11 +1136,11 @@ } #ifdef CONFIG_SND_CS46XX_NEW_DSP - if (cpcm->pcm_channel->pcm_channel_id == DSP_PCM_MAIN_CHANNEL) { + if (cpcm->pcm_channel_id == DSP_PCM_MAIN_CHANNEL) { substream->ops = &snd_cs46xx_playback_indirect_ops; - } else if (cpcm->pcm_channel->pcm_channel_id == DSP_PCM_REAR_CHANNEL) { + } else if (cpcm->pcm_channel_id == DSP_PCM_REAR_CHANNEL) { substream->ops = &snd_cs46xx_playback_indirect_rear_ops; - } else if (cpcm->pcm_channel->pcm_channel_id == DSP_IEC958_CHANNEL) { + } else if (cpcm->pcm_channel_id == DSP_IEC958_CHANNEL) { substream->ops = &snd_cs46xx_playback_indirect_iec958_ops; } else { snd_assert(0); @@ -1165,6 +1166,10 @@ cpcm = snd_magic_cast(cs46xx_pcm_t, runtime->private_data, return -ENXIO); + /* if play_back open fails, then this function + is called and cpcm can actually be NULL here */ + if (!cpcm) return -ENXIO; + if (runtime->dma_area != cpcm->hw_area) snd_pcm_lib_free_pages(substream); @@ -1482,15 +1487,8 @@ cpcm->substream = substream; #ifdef CONFIG_SND_CS46XX_NEW_DSP down (&chip->spos_mutex); - cpcm->pcm_channel = cs46xx_dsp_create_pcm_channel (chip, runtime->rate, cpcm, cpcm->hw_addr,pcm_channel_id); - - if (cpcm->pcm_channel == NULL) { - snd_printk(KERN_ERR "cs46xx: failed to create virtual PCM channel\n"); - snd_free_pci_pages(chip->pci, cpcm->hw_size, cpcm->hw_area, cpcm->hw_addr); - snd_magic_kfree(cpcm); - up (&chip->spos_mutex); - return -ENOMEM; - } + cpcm->pcm_channel = NULL; + cpcm->pcm_channel_id = pcm_channel_id; snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, &hw_constraints_period_sizes); @@ -1583,6 +1581,9 @@ cpcm = snd_magic_cast(cs46xx_pcm_t, runtime->private_data, return -ENXIO); + /* when playback_open fails, then cpcm can be NULL */ + if (!cpcm) return -ENXIO; + #ifdef CONFIG_SND_CS46XX_NEW_DSP down (&chip->spos_mutex); if (cpcm->pcm_channel) { @@ -1887,8 +1888,8 @@ { cs46xx_t *chip = snd_kcontrol_chip(kcontrol); - ucontrol->value.integer.value[0] = chip->dsp_spos_instance->dac_volume_right; - ucontrol->value.integer.value[1] = chip->dsp_spos_instance->dac_volume_left; + ucontrol->value.integer.value[0] = chip->dsp_spos_instance->dac_volume_left; + ucontrol->value.integer.value[1] = chip->dsp_spos_instance->dac_volume_right; return 0; } @@ -3331,8 +3332,8 @@ #ifdef CONFIG_SND_CS46XX_NEW_DSP /* set the attenuation to 0dB */ - snd_cs46xx_poke(chip, (MASTERMIX_SCB_ADDR + 0xE) << 2, 0x80008000); - snd_cs46xx_poke(chip, (VARIDECIMATE_SCB_ADDR + 0xE) << 2, 0x80008000); + /* snd_cs46xx_poke(chip, (MASTERMIX_SCB_ADDR + 0xE) << 2, 0x80008000); + snd_cs46xx_poke(chip, (VARIDECIMATE_SCB_ADDR + 0xE) << 2, 0x80008000); */ /* * Initialize cs46xx SPDIF controller diff --exclude=CVS -Naur alsa-kernel/pci/cs46xx/cs46xx_lib.h ../cvs/alsa-kernel/pci/cs46xx/cs46xx_lib.h --- alsa-kernel/pci/cs46xx/cs46xx_lib.h Sun Dec 8 13:21:55 2002 +++ ../cvs/alsa-kernel/pci/cs46xx/cs46xx_lib.h Sun Dec 8 18:55:22 2002 @@ -152,6 +152,7 @@ dsp_scb_descriptor_t * parent_scb, int scb_child_type); dsp_scb_descriptor_t * cs46xx_dsp_create_src_task_scb(cs46xx_t * chip,char * scb_name, + int sample_rate, u16 src_buffer_addr, u16 src_delay_buffer_addr,u32 dest, dsp_scb_descriptor_t * parent_scb, @@ -202,8 +203,6 @@ int pcm_channel_id); void cs46xx_dsp_destroy_pcm_channel (cs46xx_t * chip, pcm_channel_descriptor_t * pcm_channel); -void cs46xx_dsp_set_src_sample_rate(cs46xx_t * chip,dsp_scb_descriptor_t * src, - u32 rate); int cs46xx_dsp_pcm_unlink (cs46xx_t * chip,pcm_channel_descriptor_t * pcm_channel); int cs46xx_dsp_pcm_link (cs46xx_t * chip,pcm_channel_descriptor_t * pcm_channel); dsp_scb_descriptor_t * cs46xx_add_record_source (cs46xx_t *chip,dsp_scb_descriptor_t * source, diff --exclude=CVS -Naur alsa-kernel/pci/cs46xx/dsp_spos.c ../cvs/alsa-kernel/pci/cs46xx/dsp_spos.c --- alsa-kernel/pci/cs46xx/dsp_spos.c Sun Dec 8 13:21:55 2002 +++ ../cvs/alsa-kernel/pci/cs46xx/dsp_spos.c Sun Dec 8 19:08:46 2002 @@ -615,7 +615,7 @@ snd_iprintf(buffer,"\nMIX_SAMPLE_BUF1:\n"); col = 0; - for (i = MIX_SAMPLE_BUF1;i < MIX_SAMPLE_BUF1 + 0x30; i += sizeof(u32),col ++) { + for (i = MIX_SAMPLE_BUF1;i < MIX_SAMPLE_BUF1 + 0x40; i += sizeof(u32),col ++) { if (col == 4) { snd_iprintf(buffer,"\n"); col = 0; @@ -628,14 +628,14 @@ snd_iprintf(buffer,"%08X ",readl(dst + i)); } - snd_iprintf(buffer,"\n\n"); + snd_iprintf(buffer,"\nSRC_TASK_SCB1:\n"); col = 0; - for (i = SPDIFI_IP_OUTPUT_BUFFER1;i < SPDIFI_IP_OUTPUT_BUFFER1 + 0x40; i += sizeof(u32),col ++) { + for (i = 0x2580 ; i < 0x2580 + 0x40 ; i += sizeof(u32),col ++) { if (col == 4) { snd_iprintf(buffer,"\n"); col = 0; } - + if (col == 0) { snd_iprintf(buffer, "%04X ",i); } @@ -646,7 +646,7 @@ snd_iprintf(buffer,"\nSPDIFO_BUFFER:\n"); col = 0; - for (i = SPDIFO_IP_OUTPUT_BUFFER1;i < SPDIFO_IP_OUTPUT_BUFFER1 + 0x40; i += sizeof(u32),col ++) { + for (i = SPDIFO_IP_OUTPUT_BUFFER1;i < SPDIFO_IP_OUTPUT_BUFFER1 + 0x30; i += sizeof(u32),col ++) { if (col == 4) { snd_iprintf(buffer,"\n"); col = 0; @@ -1356,6 +1356,7 @@ /* SPDIF input sampel rate converter */ src_task_scb = cs46xx_dsp_create_src_task_scb(chip,"SrcTaskSCB_SPDIFI", + 48000, SRC_OUTPUT_BUF1, SRC_DELAY_BUF1,SRCTASK_SCB_ADDR, master_mix_scb, @@ -1601,7 +1602,7 @@ /* set SPDIF input sample rate and unmute NOTE: only 48khz support for SPDIF input this time */ - cs46xx_dsp_set_src_sample_rate(chip,ins->spdif_in_src,48000); + /* cs46xx_dsp_set_src_sample_rate(chip,ins->spdif_in_src,48000); */ /* monitor state */ ins->spdif_status_in = 1; diff --exclude=CVS -Naur alsa-kernel/pci/cs46xx/dsp_spos_scb_lib.c ../cvs/alsa-kernel/pci/cs46xx/dsp_spos_scb_lib.c --- alsa-kernel/pci/cs46xx/dsp_spos_scb_lib.c Sun Dec 8 13:21:55 2002 +++ ../cvs/alsa-kernel/pci/cs46xx/dsp_spos_scb_lib.c Mon Dec 9 00:49:07 2002 @@ -576,8 +576,11 @@ return scb; } +#define GOF_PER_SEC 200 + dsp_scb_descriptor_t * cs46xx_dsp_create_src_task_scb(cs46xx_t * chip,char * scb_name, + int rate, u16 src_buffer_addr, u16 src_delay_buffer_addr,u32 dest, dsp_scb_descriptor_t * parent_scb, @@ -586,45 +589,81 @@ dsp_spos_instance_t * ins = chip->dsp_spos_instance; dsp_scb_descriptor_t * scb; - - src_task_scb_t src_task_scb = { - 0x0028,0x00c8, - 0x5555,0x0000, - 0x0000,0x0000, - src_buffer_addr,1, - 0x0028,0x00c8, - RSCONFIG_SAMPLE_16STEREO + RSCONFIG_MODULO_32, - 0x0000,src_delay_buffer_addr, - 0x0, - 0x80,(src_delay_buffer_addr + (24 * 4)), - 0,0, /* next_scb, sub_list_ptr */ - 0,0, /* entry, this_spb */ - RSCONFIG_SAMPLE_16STEREO + RSCONFIG_MODULO_8, - src_buffer_addr << 0x10, - 0x04000000, - { - 0xffff - ins->dac_volume_right,0xffff - ins->dac_volume_left, - 0xffff - ins->dac_volume_right,0xffff - ins->dac_volume_left - } - }; + unsigned int tmp1, tmp2; + unsigned int phiIncr; + unsigned int correctionPerGOF, correctionPerSec; - if (ins->s16_up == NULL) { - ins->s16_up = cs46xx_dsp_lookup_symbol (chip,"S16_UPSRC", - SYMBOL_CODE); - - if (ins->s16_up == NULL) { - snd_printk (KERN_ERR "dsp_spos: symbol S16_UPSRC not found\n"); - return NULL; - } - } + snd_printdd( "dsp_spos: setting %s rate to %u\n",scb_name,rate); - /* clear buffers */ - _dsp_clear_sample_buffer (chip,src_buffer_addr,8); - _dsp_clear_sample_buffer (chip,src_delay_buffer_addr,32); + /* + * Compute the values used to drive the actual sample rate conversion. + * The following formulas are being computed, using inline assembly + * since we need to use 64 bit arithmetic to compute the values: + * + * phiIncr = floor((Fs,in * 2^26) / Fs,out) + * correctionPerGOF = floor((Fs,in * 2^26 - Fs,out * phiIncr) / + * GOF_PER_SEC) + * ulCorrectionPerSec = Fs,in * 2^26 - Fs,out * phiIncr -M + * GOF_PER_SEC * correctionPerGOF + * + * i.e. + * + * phiIncr:other = dividend:remainder((Fs,in * 2^26) / Fs,out) + * correctionPerGOF:correctionPerSec = + * dividend:remainder(ulOther / GOF_PER_SEC) + */ + tmp1 = rate << 16; + phiIncr = tmp1 / 48000; + tmp1 -= phiIncr * 48000; + tmp1 <<= 10; + phiIncr <<= 10; + tmp2 = tmp1 / 48000; + phiIncr += tmp2; + tmp1 -= tmp2 * 48000; + correctionPerGOF = tmp1 / GOF_PER_SEC; + tmp1 -= correctionPerGOF * GOF_PER_SEC; + correctionPerSec = tmp1; - scb = _dsp_create_generic_scb(chip,scb_name,(u32 *)&src_task_scb, - dest,ins->s16_up,parent_scb, - scb_child_type); + { + src_task_scb_t src_task_scb = { + 0x0028,0x00c8, + 0x5555,0x0000, + 0x0000,0x0000, + src_buffer_addr,1, + correctionPerGOF,correctionPerSec, + RSCONFIG_SAMPLE_16STEREO + RSCONFIG_MODULO_32, + 0x0000,src_delay_buffer_addr, + 0x0, + 0x080,(src_delay_buffer_addr + (24 * 4)), + 0,0, /* next_scb, sub_list_ptr */ + 0,0, /* entry, this_spb */ + RSCONFIG_SAMPLE_16STEREO + RSCONFIG_MODULO_8, + src_buffer_addr << 0x10, + phiIncr, + { + 0xffff - ins->dac_volume_right,0xffff - ins->dac_volume_left, + 0xffff - ins->dac_volume_right,0xffff - ins->dac_volume_left + } + }; + + if (ins->s16_up == NULL) { + ins->s16_up = cs46xx_dsp_lookup_symbol (chip,"S16_UPSRC", + SYMBOL_CODE); + + if (ins->s16_up == NULL) { + snd_printk (KERN_ERR "dsp_spos: symbol S16_UPSRC not found\n"); + return NULL; + } + } + + /* clear buffers */ + _dsp_clear_sample_buffer (chip,src_buffer_addr,8); + _dsp_clear_sample_buffer (chip,src_delay_buffer_addr,32); + + scb = _dsp_create_generic_scb(chip,scb_name,(u32 *)&src_task_scb, + dest,ins->s16_up,parent_scb, + scb_child_type); + } return scb; } @@ -796,7 +835,7 @@ RSCONFIG_SAMPLE_16STEREO + RSCONFIG_MODULO_16, 0, - 0,input_scb->address, + 0,input_scb->address, { 0x8000,0x8000, 0x8000,0x8000 @@ -1007,7 +1046,7 @@ /* C */ snoop_buffer_address << 0x10, /* D */ 0, /* E */ { 0x8000,0x8000, - /* F */ 0xffff,0xffff + /* F */ 0xffff,0xffff } }; @@ -1093,6 +1132,8 @@ { dsp_spos_instance_t * ins = chip->dsp_spos_instance; dsp_scb_descriptor_t * src_scb = NULL,* pcm_scb, * mixer_scb = NULL; + dsp_scb_descriptor_t * src_parent_scb = NULL; + /*dsp_scb_descriptor_t * pcm_parent_scb;*/ char scb_name[DSP_MAX_SCB_NAME]; int i,pcm_index = -1, insert_point, src_index = -1; @@ -1116,13 +1157,14 @@ case DSP_IEC958_CHANNEL: snd_assert (ins->asynch_tx_scb != NULL, return NULL); mixer_scb = ins->asynch_tx_scb; -#if 0 - if (ins->spdif_status_out & DSP_SPDIF_STATUS_AC3_MODE) { - snd_printdd ("IEC958 opened in AC3 mode\n"); - /*src_scb = ins->asynch_tx_scb; - ins->asynch_tx_scb->ref_count ++;*/ + + /* if sample rate is set to 48khz we pass + the Sample Rate Converted (which could + alter the raw data stream ...) */ + if (sample_rate == 48000) { + snd_printdd ("IEC958 pass through\n"); + src_parent_scb = ins->asynch_tx_scb; } -#endif break; default: snd_assert (0); @@ -1158,8 +1200,6 @@ } if (src_scb == NULL) { - dsp_scb_descriptor_t * src_parent_scb; - if (ins->nsrc_scb >= DSP_MAX_SRC_NR) { snd_printk(KERN_ERR "dsp_spos: to many SRC instances\n!"); return NULL; @@ -1176,18 +1216,21 @@ snd_assert (src_index != -1,return NULL); /* we need to create a new SRC SCB */ - if (mixer_scb->sub_list_ptr == ins->the_null_scb) { - src_parent_scb = mixer_scb; - insert_point = SCB_ON_PARENT_SUBLIST_SCB; - } else { - src_parent_scb = find_next_free_scb(chip,mixer_scb->sub_list_ptr); - insert_point = SCB_ON_PARENT_NEXT_SCB; - } + if (src_parent_scb == NULL) { + if (mixer_scb->sub_list_ptr == ins->the_null_scb) { + src_parent_scb = mixer_scb; + insert_point = SCB_ON_PARENT_SUBLIST_SCB; + } else { + src_parent_scb = find_next_free_scb(chip,mixer_scb->sub_list_ptr); + insert_point = SCB_ON_PARENT_NEXT_SCB; + } + } else insert_point = SCB_ON_PARENT_NEXT_SCB; snprintf (scb_name,DSP_MAX_SCB_NAME,"SrcTask_SCB%d",src_index); snd_printdd( "dsp_spos: creating SRC \"%s\"\n",scb_name); src_scb = cs46xx_dsp_create_src_task_scb(chip,scb_name, + sample_rate, src_output_buffer_addr[src_index], src_delay_buffer_addr[src_index], /* 0x400 - 0x600 source SCBs */ @@ -1200,7 +1243,7 @@ return NULL; } - cs46xx_dsp_set_src_sample_rate(chip,src_scb,sample_rate); + /* cs46xx_dsp_set_src_sample_rate(chip,src_scb,sample_rate); */ ins->nsrc_scb ++; } @@ -1226,6 +1269,19 @@ return NULL; } + if (pcm_channel_id == DSP_IEC958_CHANNEL && sample_rate == 48000) { + snd_assert (ins->spdif_pcm_input_scb = NULL); + + /* a hack to make the skip the SRC and pass the stream + directly to the SPDIF task */ + ins->spdif_pcm_input_scb = + cs46xx_dsp_create_pcm_serial_input_scb(chip,"PCMSerialInput_PCM", + PCMSERIALINII_SCB_ADDR, + pcm_scb, + ins->asynch_tx_scb, + SCB_ON_PARENT_SUBLIST_SCB); + } + spin_lock_irqsave(&chip->reg_lock, flags); ins->pcm_channels[pcm_index].sample_rate = sample_rate; ins->pcm_channels[pcm_index].pcm_reader_scb = pcm_scb; @@ -1236,7 +1292,6 @@ ins->pcm_channels[pcm_index].active = 1; ins->pcm_channels[pcm_index].pcm_slot = pcm_index; ins->pcm_channels[pcm_index].mixer_scb = mixer_scb; - ins->pcm_channels[pcm_index].pcm_channel_id = pcm_channel_id; ins->npcm_channels ++; spin_unlock_irqrestore(&chip->reg_lock, flags); @@ -1416,59 +1471,6 @@ return 0; } - -#define GOF_PER_SEC 200 - -void cs46xx_dsp_set_src_sample_rate(cs46xx_t *chip,dsp_scb_descriptor_t * src, u32 rate) -{ - unsigned long flags; - unsigned int tmp1, tmp2; - unsigned int phiIncr; - unsigned int correctionPerGOF, correctionPerSec; - - snd_printdd( "dsp_spos: setting SRC rate to %u\n",rate); - /* - * Compute the values used to drive the actual sample rate conversion. - * The following formulas are being computed, using inline assembly - * since we need to use 64 bit arithmetic to compute the values: - * - * phiIncr = floor((Fs,in * 2^26) / Fs,out) - * correctionPerGOF = floor((Fs,in * 2^26 - Fs,out * phiIncr) / - * GOF_PER_SEC) - * ulCorrectionPerSec = Fs,in * 2^26 - Fs,out * phiIncr -M - * GOF_PER_SEC * correctionPerGOF - * - * i.e. - * - * phiIncr:other = dividend:remainder((Fs,in * 2^26) / Fs,out) - * correctionPerGOF:correctionPerSec = - * dividend:remainder(ulOther / GOF_PER_SEC) - */ - tmp1 = rate << 16; - phiIncr = tmp1 / 48000; - tmp1 -= phiIncr * 48000; - tmp1 <<= 10; - phiIncr <<= 10; - tmp2 = tmp1 / 48000; - phiIncr += tmp2; - tmp1 -= tmp2 * 48000; - correctionPerGOF = tmp1 / GOF_PER_SEC; - tmp1 -= correctionPerGOF * GOF_PER_SEC; - correctionPerSec = tmp1; - - /* - * Fill in the SampleRateConverter control block. - */ - spin_lock_irqsave(&chip->reg_lock, flags); - - snd_cs46xx_poke(chip, (src->address + SRCCorPerGof) << 2, - ((correctionPerSec << 16) & 0xFFFF0000) | (correctionPerGOF & 0xFFFF)); - - snd_cs46xx_poke(chip, (src->address + SRCPhiIncr6Int26Frac) << 2, phiIncr); - - spin_unlock_irqrestore(&chip->reg_lock, flags); -} - dsp_scb_descriptor_t * cs46xx_add_record_source (cs46xx_t *chip,dsp_scb_descriptor_t * source, u16 addr,char * scb_name) { @@ -1655,10 +1657,16 @@ cs46xx_poke_via_dsp (chip,SP_SPDOUT_CSUV, ins->spdif_csuv_default); /* deallocate stuff */ + if (ins->spdif_pcm_input_scb != NULL) { + cs46xx_dsp_remove_scb (chip,ins->spdif_pcm_input_scb); + ins->spdif_pcm_input_scb = NULL; + } + cs46xx_dsp_remove_scb (chip,ins->asynch_tx_scb); ins->asynch_tx_scb = NULL; /* restore state */ + if ( ins->spdif_status_out & DSP_SPDIF_STATUS_OUTPUT_ENABLED ) { cs46xx_dsp_enable_spdif_out (chip); }