📄 i2s.patch
字号:
++ if (!supported_mixer(i))+ return -EINVAL;++ val = s->i2s->get_mixer(s->i2s, i);+ break;+ }+ return put_user(val, (int *)arg);+ }++ if (_SIOC_DIR(cmd) == (_SIOC_WRITE|_SIOC_READ)) {+ if (get_user(val, (int *)arg))+ return -EFAULT;+ switch (_IOC_NR(cmd)) {+ case SOUND_MIXER_RECSRC: + /* Arg contains a bit for each recording source */+ if (!s->i2s->input_mask)+ return -EINVAL;+ if (!val)+ return 0;++ if (!(val &= s->i2s->input_mask))+ return -EINVAL;+ else + s->i2s->set_recsrc(s->i2s, val);++ return 0;+ default: /* write a specific mixer */+ i = _IOC_NR(cmd);++ if (!supported_mixer(i))+ return -EINVAL;++ s->i2s->set_mixer(s->i2s, i, val);++ return 0;+ }+}+ return -EINVAL;+}++static loff_t+au1550_llseek(struct file *file, loff_t offset, int origin)+{+ return -ESPIPE;+}++static /*const */ struct file_operations au1550_mixer_fops = {+ owner:THIS_MODULE,+ llseek:au1550_llseek,+ ioctl:au1550_ioctl_mixdev,+ open:au1550_open_mixdev,+ release:au1550_release_mixdev,+};+++ /* stop the ADC before calling */ static void set_adc_rate(struct au1550_state *s, unsigned rate) {+ struct dmabuf *dac = &s->dma_dac; struct dmabuf *adc = &s->dma_adc;+ unsigned adcr=rate, dacr=dac->sample_rate; - /* calc SRC factor */- adc->src_factor = (((SAMP_RATE*2) / rate) + 1) >> 1;- adc->sample_rate = SAMP_RATE / adc->src_factor;- return; +#ifndef try_srcfacor+ adcr = dacr = rate;+#endif+ s->i2s->set_rates(s->i2s, &adcr, &dacr);+ +#ifdef try_srcfacor+ if ( adcr != rate ) {+ /* calc SRC factor+ */+ adc->src_factor = ((96000 / rate) + 1) >> 1;+ adc->sample_rate = adcr / adc->src_factor;+ } else { adc->src_factor = 1;+ adc->sample_rate = adcr;+ }++ /* Check to see if changing ADC rate had effect on DAC rate */+ if ( dacr != dac->sample_rate ) {+ /* calc SRC factor+ */+ dac->src_factor = ((96000 / dac->sample_rate) + 1) >> 1;+ dac->sample_rate = dacr / dac->src_factor;+ }+ printk("-----------------------------------------\n");+ printk("dacr %d Hz adcr %d Hz\n", dacr, adcr);+ printk("dac_srcfactor %d adc_srcfactor %d\n", dac->src_factor, adc->src_factor );+ printk("-----------------------------------------\n");++#endif+ adc->sample_rate = adcr;+ dac->sample_rate = dacr;+ dac->src_factor = adc->src_factor = 1; } /* stop the DAC before calling */@@ -372,13 +437,44 @@ static void set_dac_rate(struct au1550_state *s, unsigned rate) { struct dmabuf *dac = &s->dma_dac;+ struct dmabuf *adc = &s->dma_adc;+ unsigned adcr=adc->sample_rate, dacr=rate; - /* calc SRC factor */- dac->src_factor = (((SAMP_RATE*2) / rate) + 1) >> 1;- dac->sample_rate = SAMP_RATE / dac->src_factor;- return;+#ifndef try_srcfacor+ adcr = dacr = rate;+#endif+ s->i2s->set_rates(s->i2s, &adcr, &dacr); +#ifdef try_srcfacor+ if ( dacr != rate ) {+ /* calc SRC factor+ */+ dac->src_factor = ((96000 / rate) + 1) >> 1;+ dac->sample_rate = dacr / dac->src_factor;+ } else { dac->src_factor = 1;+ dac->sample_rate = dacr;+ }++ /* Check to see if changing DAC rate had effect on ADC rate */+ if ( adcr != adc->sample_rate ) {+ /* calc SRC factor+ */+ adc->src_factor = ((96000 / adc->sample_rate) + 1) >> 1;+ adc->sample_rate = adcr / adc->src_factor;+ }++ printk("-----------------------------------------\n");+ printk("dacr %d Hz adcr %d Hz\n", dacr, adcr);+ printk("dac_srcfactor %d adc_srcfactor %d\n", dac->src_factor, adc->src_factor );+ printk("-----------------------------------------\n");++#endif++ adc->sample_rate = adcr;+ dac->sample_rate = dacr;+ dac->src_factor = adc->src_factor = 1;+ } static void@@ -386,29 +482,37 @@ stop_dac(struct au1550_state *s) { struct dmabuf *db = &s->dma_dac; unsigned long flags;- uint stat;- volatile psc_i2s_t *ip; if (db->stopped)+ {+ au1xxx_dbdma_reset(db->dmanr); return;+ } - ip = s->psc_addr; spin_lock_irqsave(&s->lock, flags); - ip->psc_i2spcr = PSC_I2SPCR_TP;- au_sync();-- /* Wait for Transmit Busy to show disabled.- */- do {- stat = ip->psc_i2sstat;- au_sync();- } while ((stat & PSC_I2SSTAT_TB) != 0);-+ i2s_stop_xmit(s->i2s); au1xxx_dbdma_reset(db->dmanr); db->stopped = 1;+ spin_unlock_irqrestore(&s->lock, flags);+}++static void+pause_dac(struct au1550_state *s)+{+ struct dmabuf *db = &s->dma_dac;+ unsigned long flags; + if (db->stopped)+ return;++ spin_lock_irqsave(&s->lock, flags);++ i2s_stop_xmit(s->i2s);+ au1xxx_dbdma_stop(db->dmanr);++ db->stopped = 1; spin_unlock_irqrestore(&s->lock, flags); } @@ -417,32 +521,20 @@ stop_adc(struct au1550_state *s) { struct dmabuf *db = &s->dma_adc; unsigned long flags;- uint stat;- volatile psc_i2s_t *ip; if (db->stopped) return; - ip = s->psc_addr; spin_lock_irqsave(&s->lock, flags); - ip->psc_i2spcr = PSC_I2SPCR_RP;- au_sync();-- /* Wait for Receive Busy to show disabled.- */- do {- stat = ip->psc_i2sstat;- au_sync();- } while ((stat & PSC_I2SSTAT_RB) != 0);-+ i2s_stop_recv(s->i2s); au1xxx_dbdma_reset(db->dmanr); db->stopped = 1;- spin_unlock_irqrestore(&s->lock, flags); } + static void set_xmit_slots(int num_channels) {@@ -464,19 +556,14 @@ start_dac(struct au1550_state *s) { struct dmabuf *db = &s->dma_dac; unsigned long flags;- volatile psc_i2s_t *ip; if (!db->stopped) return; spin_lock_irqsave(&s->lock, flags); - ip = s->psc_addr; set_xmit_slots(db->num_channels);- ip->psc_i2spcr = PSC_I2SPCR_TC;- au_sync();- ip->psc_i2spcr = PSC_I2SPCR_TS;- au_sync();+ i2s_start_xmit(s->i2s); au1xxx_dbdma_start(db->dmanr); @@ -490,7 +577,6 @@ start_adc(struct au1550_state *s) { struct dmabuf *db = &s->dma_adc; int i;- volatile psc_i2s_t *ip; if (!db->stopped) return;@@ -505,14 +591,9 @@ start_adc(struct au1550_state *s) db->nextIn -= db->dmasize; } - ip = s->psc_addr; set_recv_slots(db->num_channels); au1xxx_dbdma_start(db->dmanr);- ip->psc_i2spcr = PSC_I2SPCR_RC;- au_sync();- ip->psc_i2spcr = PSC_I2SPCR_RS;- au_sync();-+ i2s_start_recv(s->i2s); db->stopped = 0; } @@ -537,7 +618,6 @@ prog_dmabuf(struct au1550_state *s, stru if (db->num_channels == 1) db->cnt_factor *= 2; db->cnt_factor *= db->src_factor;- db->count = 0; db->dma_qcount = 0; db->nextIn = db->nextOut = db->rawbuf;@@ -576,15 +656,6 @@ prog_dmabuf(struct au1550_state *s, stru db->dmasize = db->dma_fragsize * db->numfrag; memset(db->rawbuf, 0, bufs);--#ifdef AU1000_VERBOSE_DEBUG- dbg("rate=%d, samplesize=%d, channels=%d",- rate, db->sample_size, db->num_channels);- dbg("fragsize=%d, cnt_factor=%d, dma_fragsize=%d",- db->fragsize, db->cnt_factor, db->dma_fragsize);- dbg("numfrag=%d, dmasize=%d", db->numfrag, db->dmasize);-#endif- db->ready = 1; return 0; }@@ -611,21 +682,14 @@ dac_dma_interrupt(int irq, void *dev_id, { struct au1550_state *s = (struct au1550_state *) dev_id; struct dmabuf *db = &s->dma_dac;- u32 i2s_stat;- volatile psc_i2s_t *ip; - ip = s->psc_addr;- i2s_stat = ip->psc_i2sstat;-#ifdef AU1000_VERBOSE_DEBUG- if (i2s_stat & (PSC_I2SSTAT_TF | PSC_I2SSTAT_TR | PSC_I2SSTAT_TF))- dbg("I2S status = 0x%08x", i2s_stat);-#endif+// i2s_status(s->i2s); db->dma_qcount--; if (db->count >= db->fragsize) {- if (au1xxx_dbdma_put_source(db->dmanr, db->nextOut,- db->fragsize) == 0) {- pr_error("qcount < 2 and no ring room!");+ if (au1xxx_dbdma_put_source(db->dmanr, db->nextOut, db->fragsize) == 0)+ {+ err("qcount < MIN_Q_COUNT and no ring room!"); } db->nextOut += db->fragsize; if (db->nextOut >= db->rawbuf + db->dmasize)@@ -658,7 +722,7 @@ adc_dma_interrupt(int irq, void *dev_id, */ stop_adc(s); dp->error++;- pr_error("adc overrun");+ err("adc overrun"); return; } @@ -680,130 +744,6 @@ adc_dma_interrupt(int irq, void *dev_id, } -static loff_t-au1550_llseek(struct file *file, loff_t offset, int origin)-{- return -ESPIPE;-}--static int-au1550_open_mixdev(struct inode *inode, struct file *file)-{- file->private_data = &au1550_state;- return 0;-}--static int-au1550_release_mixdev(struct inode *inode, struct file *file)-{- return 0;-}--#define I2S_CODEC "Wolfson WM8731"--static int-au1550_ioctl_mixdev(struct inode *inode, struct file *file,- unsigned int cmd, unsigned long arg)-{- struct au1550_state *s = (struct au1550_state *)file->private_data;- struct i2s_codec *codec = s->codec;- int i, val = 0;-- if (cmd == SOUND_MIXER_INFO) {- mixer_info info;- memset(&info, 0, sizeof(info));- strlcpy(info.id, I2S_CODEC, sizeof(info.id));- strlcpy(info.name, I2S_CODEC, sizeof(info.name));- info.modify_counter = codec->modcnt;- if (copy_to_user((void __user *)arg, &info, sizeof(info)))- return -EFAULT;- return 0;- }- if (cmd == SOUND_OLD_MIXER_INFO) {- _old_mixer_info info;- memset(&info, 0, sizeof(info));- strlcpy(info.id, I2S_CODEC, sizeof(info.id));- strlcpy(info.name, I2S_CODEC, sizeof(info.name));- if (copy_to_user((void __user *)arg, &info, sizeof(info)))- return -EFAULT;- return 0;- }-- if (_IOC_TYPE(cmd) != 'M' || _SIOC_SIZE(cmd) != sizeof(int))- return -EINVAL;-- if (cmd == OSS_GETVERSION)- return put_user(SOUND_VERSION, (int __user *)arg);-- if (_SIOC_DIR(cmd) == _SIOC_READ) {- switch (_IOC_NR(cmd)) {- case SOUND_MIXER_RECSRC: /* give them the current record source */- val = codec->mixer_state[SOUND_MIXER_RECSRC];- break;-- case SOUND_MIXER_DEVMASK: /* give them the supported mixers */- val = codec->supported_mixers;- break;-- case SOUND_MIXER_RECMASK: /* Arg contains a bit for each supported recording source */- val = codec->record_sources;- break;-- case SOUND_MIXER_STEREODEVS: /* Mixer channels supporting stereo */- val = codec->stereo_mixers;- break;-- case SOUND_MIXER_CAPS:- val = SOUND_CAP_EXCL_INPUT;- break;-- default: /* read a specific mixer */- i = _IOC_NR(cmd);-- if (!i2s_supported_mixer(codec, i)) - return -EINVAL;-- val = codec->mixer_state[i];- break;- }- return put_user(val, (int __user *)arg);- }-- if (_SIOC_DIR(cmd) == (_SIOC_WRITE|_SIOC_READ)) {- codec->modcnt++;- if (get_user(val, (int __user *)arg))- return -EFAULT;-- switch (_IOC_NR(cmd)) {- case SOUND_MIXER_RECSRC: /* Arg contains a bit for each recording source */- if (!val) return 0;- if (!(val &= codec->record_sources)) return -EINVAL;-- codec->set_mixer(codec, SOUND_MIXER_RECSRC, val);-- return 0;- default: /* write a specific mixer */- i = _IOC_NR(cmd);-- if (!i2s_supported_mixer(codec, i)) - return -EINVAL;-- codec->set_mixer(codec, i, val);-- return 0;- }- }- return -EINVAL;-}--static struct file_operations au1550_mixer_fops = {- owner:THIS_MODULE,- llseek:au1550_llseek,- ioctl:au1550_ioctl_mixdev,- open:au1550_open_mixdev,- release:au1550_release_mixdev,-};- static int drain_dac(struct au1550_state *s, int nonblock) {@@ -817,13 +757,16 @@ drain_dac(struct au1550_state *s, int no spin_lock_irqsave(&s->lock, flags); count = s->dma_dac.count; spin_unlock_irqrestore(&s->lock, flags);- if (count <= 0)+ if (count <= s->dma_dac.fragsize) break; if (signal_pending(current)) break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -