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 int pcm_set_fmt(unsigned long *format,int mode) { int ret = 0; int data_width = 0; struct dsp_pipe *dp_in = NULL; struct dsp_pipe *dp_out = NULL; dp_in = pcm_priv->endpoint->in_endpoint; dp_out = pcm_priv->endpoint->out_endpoint; switch (*format) { case AFMT_U8: case AFMT_S8: *format = AFMT_U8; data_width = 8; if (mode & CODEC_WMODE) { __pcm_set_oss_sample_size(0); dp_out->dma_config.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; dp_out->dma_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; } if (mode & CODEC_RMODE) { __pcm_set_iss_sample_size(0); dp_in->dma_config.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; dp_in->dma_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; } break; case AFMT_S16_LE: case AFMT_S16_BE: data_width = 16; *format = AFMT_S16_LE; if (mode & CODEC_WMODE) { __pcm_set_oss_sample_size(1); /*__pcm_set_oss_sample_size(0);*/ dp_out->dma_config.src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; dp_out->dma_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; } if (mode & CODEC_RMODE) { __pcm_set_iss_sample_size(1); dp_in->dma_config.src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; dp_in->dma_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; } break; default : printk("PCM: there is unknown format 0x%x.\n",(unsigned int)*format); return -EINVAL; } if (mode & CODEC_WMODE) { dp_out->dma_config.dst_maxburst = 16 * data_width/8/2; dump_dma_config(dp_out); if (pcm_priv->replay_format != *format) { pcm_priv->replay_format = *format; ret |= NEED_RECONF_TRIGGER | NEED_RECONF_FILTER; ret |= NEED_RECONF_DMA; } } if (mode & CODEC_RMODE) { dp_in->dma_config.src_maxburst = 16 * data_width/8/2; dump_dma_config(dp_in); if (pcm_priv->record_format != *format) { pcm_priv->record_format = *format; ret |= NEED_RECONF_TRIGGER | NEED_RECONF_FILTER; ret |= NEED_RECONF_DMA; } } return ret; }