static int jz_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { struct device *dev = dai->dev; struct jz_pcm *jz_pcm = dev_get_drvdata(dai->dev); int fmt_width = snd_pcm_format_width(params_format(params)); enum dma_slave_buswidth buswidth; int trigger; PCM_DEBUG_MSG("enter %s, substream = %s\n", __func__, (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? "playback" : "capture"); if (!((1 << params_format(params)) & JZ_PCM_FORMATS) || params_channels(params) != 1 || params_rate(params) != 8000) { dev_err(dai->dev, "hw params not inval channel %d params %x\n", params_channels(params), params_format(params)); return -EINVAL; } /* format 8 bit or 16 bit*/ if (fmt_width == 8) buswidth = DMA_SLAVE_BUSWIDTH_1_BYTE; else buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { jz_pcm->tx_dma_data.buswidth = buswidth; jz_pcm->tx_dma_data.max_burst = (PCM_TFIFO_DEPTH * buswidth)/2; trigger = PCM_TFIFO_DEPTH - (jz_pcm->tx_dma_data.max_burst/(int)buswidth); __pcm_set_oss_sample_size(dev, fmt_width == 8 ? 0 : 1); __pcm_set_transmit_trigger(dev, trigger); snd_soc_dai_set_dma_data(dai, substream, (void *)&jz_pcm->tx_dma_data); } else { jz_pcm->rx_dma_data.buswidth = buswidth; jz_pcm->rx_dma_data.max_burst = (PCM_RFIFO_DEPTH * buswidth)/2; trigger = jz_pcm->rx_dma_data.max_burst/(int)buswidth; __pcm_set_iss_sample_size(dev, fmt_width == 8 ? 0 : 1); __pcm_set_receive_trigger(dev, trigger); snd_soc_dai_set_dma_data(dai, substream, (void *)&jz_pcm->rx_dma_data); } return 0; }
static void pcm_set_trigger(int mode) { int data_width = 0; struct dsp_pipe *dp = NULL; int burst_length = 0; if (!pcm_priv) return; if (mode & CODEC_WMODE) { switch(pcm_priv->replay_format) { case AFMT_U8: data_width = 8; break; case AFMT_S16_LE: data_width = 16; break; } dp = pcm_priv->endpoint->out_endpoint; burst_length = get_burst_length((int)dp->paddr|(int)dp->fragsize|dp->dma_config.dst_maxburst); __pcm_set_transmit_trigger((PCM_FIFO_DEPTH - burst_length/data_width) - 1); printk("PCM_FIFO_DEPTH - burst_length/data_width - 1 = %d\n",(PCM_FIFO_DEPTH - burst_length/data_width) - 1); } if (mode &CODEC_RMODE) { switch(pcm_priv->record_format) { case AFMT_U8: data_width = 8; break; case AFMT_S16_LE: data_width = 16; break; } dp = pcm_priv->endpoint->in_endpoint; burst_length = get_burst_length((int)dp->paddr|(int)dp->fragsize|dp->dma_config.src_maxburst); __pcm_set_receive_trigger((burst_length/data_width) - 1); } return; }
static int pcm_init(struct platform_device *pdev) { int ret = 0; struct resource *pcm_resource = NULL; struct dsp_pipe *pcm_pipe_out = NULL; struct dsp_pipe *pcm_pipe_in = NULL; /* map io address */ pcm_resource = platform_get_resource(pdev,IORESOURCE_MEM,0); if (pcm_resource == NULL) { printk("pcm: platform_get_resource fail.\n"); return -1; } if (!request_mem_region(pcm_resource->start, resource_size(pcm_resource), pdev->name)) { printk("pcm: mem region fail busy .\n"); return -EBUSY; } pcm_iomem = ioremap(pcm_resource->start, resource_size(pcm_resource)); if (!pcm_iomem) { printk ("pcm: ioremap fail.\n"); ret = -ENOMEM; goto __err_ioremap; } /*init pipe*/ ret = pcm_init_pipe(&pcm_pipe_out,DMA_TO_DEVICE,pcm_resource->start); if (ret < 0) goto __err_init_pipeout; ret = pcm_init_pipe(&pcm_pipe_in,DMA_FROM_DEVICE,pcm_resource->start); if (ret < 0) goto __err_init_pipein; pcm_endpoints.out_endpoint = pcm_pipe_out; pcm_endpoints.in_endpoint = pcm_pipe_in; /*spin lock init*/ spin_lock_init(&pcm_irq_lock); /* request irq */ pcm_resource = platform_get_resource(pdev,IORESOURCE_IRQ,0); if (pcm_resource == NULL) { ret = -1; printk("pcm there is not irq resource\n"); goto __err_irq; } pcm_priv->irq = pcm_resource->start; ret = request_irq(pcm_resource->start, pcm_irq_handler, IRQF_DISABLED, "pcm_irq", NULL); if (ret < 0) { printk("pcm:request irq fail\n"); goto __err_irq; } ret = pcm_clk_init(pdev); if (ret < 0) goto __err_clk_init; __pcm_disable_receive_dma(); __pcm_disable_transmit_dma(); __pcm_disable_record(); __pcm_disable_replay(); __pcm_flush_fifo(); __pcm_clear_ror(); __pcm_clear_tur(); __pcm_set_receive_trigger(7); __pcm_set_transmit_trigger(8); __pcm_disable_overrun_intr(); __pcm_disable_underrun_intr(); __pcm_disable_transmit_intr(); __pcm_disable_receive_intr(); /* play zero or last sample when underflow */ __pcm_play_lastsample(); //__pcm_enable(); return 0; __err_clk_init: free_irq(pcm_priv->irq,NULL); __err_irq: vfree(pcm_pipe_in); __err_init_pipein: vfree(pcm_pipe_out); __err_init_pipeout: iounmap(pcm_iomem); __err_ioremap: release_mem_region(pcm_resource->start,resource_size(pcm_resource)); return ret; }