From: Mark Brown Date: Mon, 9 Feb 2015 07:10:17 +0000 (+0800) Subject: Merge remote-tracking branches 'asoc/topic/doc', 'asoc/topic/dwc', 'asoc/topic/fsi... X-Git-Url: http://git.cdn.openwrt.org/?a=commitdiff_plain;h=97edc4164f73ba916ae2bdece14b83f854fb3837;p=openwrt%2Fstaging%2Fblogic.git Merge remote-tracking branches 'asoc/topic/doc', 'asoc/topic/dwc', 'asoc/topic/fsi', 'asoc/topic/fsl' and 'asoc/topic/fsl-asrc' into asoc-next --- 97edc4164f73ba916ae2bdece14b83f854fb3837 diff --cc sound/soc/dwc/designware_i2s.c index 06d3a34ac90a,b93168d4f648,8fbf0381ee53,b93168d4f648,b93168d4f648,b93168d4f648..a3e97b46b64e --- a/sound/soc/dwc/designware_i2s.c +++ b/sound/soc/dwc/designware_i2s.c @@@@@@@ -335,54 -324,20 -363,162 -324,20 -324,20 -324,20 +374,162 @@@@@@@ static int dw_i2s_resume(struct snd_soc #define dw_i2s_resume NULL #endif - static void dw_configure_dai_by_pd(struct dw_i2s_dev *dev, ++ +++/* ++ +++ * The following tables allow a direct lookup of various parameters ++ +++ * defined in the I2S block's configuration in terms of sound system ++ +++ * parameters. Each table is sized to the number of entries possible ++ +++ * according to the number of configuration bits describing an I2S ++ +++ * block parameter. ++ +++ */ ++ +++ ++ +++/* Maximum bit resolution of a channel - not uniformly spaced */ ++ +++static const u32 fifo_width[COMP_MAX_WORDSIZE] = { ++ +++ 12, 16, 20, 24, 32, 0, 0, 0 ++ +++}; ++ +++ ++ +++/* Width of (DMA) bus */ ++ +++static const u32 bus_widths[COMP_MAX_DATA_WIDTH] = { ++ +++ DMA_SLAVE_BUSWIDTH_1_BYTE, ++ +++ DMA_SLAVE_BUSWIDTH_2_BYTES, ++ +++ DMA_SLAVE_BUSWIDTH_4_BYTES, ++ +++ DMA_SLAVE_BUSWIDTH_UNDEFINED ++ +++}; ++ +++ ++ +++/* PCM format to support channel resolution */ ++ +++static const u32 formats[COMP_MAX_WORDSIZE] = { ++ +++ SNDRV_PCM_FMTBIT_S16_LE, ++ +++ SNDRV_PCM_FMTBIT_S16_LE, ++ +++ SNDRV_PCM_FMTBIT_S24_LE, ++ +++ SNDRV_PCM_FMTBIT_S24_LE, ++ +++ SNDRV_PCM_FMTBIT_S32_LE, ++ +++ 0, ++ +++ 0, ++ +++ 0 ++ +++}; ++ +++ ++ +++static int dw_configure_dai(struct dw_i2s_dev *dev, + +++ struct snd_soc_dai_driver *dw_i2s_dai, - struct resource *res, - const struct i2s_platform_data *pdata) ++ +++ unsigned int rates) + +++{ - /* Set DMA slaves info */ - - dev->play_dma_data.data = pdata->play_dma_data; - dev->capture_dma_data.data = pdata->capture_dma_data; - dev->play_dma_data.addr = res->start + I2S_TXDMA; - dev->capture_dma_data.addr = res->start + I2S_RXDMA; - dev->play_dma_data.max_burst = 16; - dev->capture_dma_data.max_burst = 16; - dev->play_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; - dev->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; - dev->play_dma_data.filter = pdata->filter; - dev->capture_dma_data.filter = pdata->filter; - - if (pdata->cap & DWC_I2S_PLAY) { ++ +++ /* ++ +++ * Read component parameter registers to extract ++ +++ * the I2S block's configuration. ++ +++ */ ++ +++ u32 comp1 = i2s_read_reg(dev->i2s_base, I2S_COMP_PARAM_1); ++ +++ u32 comp2 = i2s_read_reg(dev->i2s_base, I2S_COMP_PARAM_2); ++ +++ u32 idx; ++ +++ ++ +++ if (COMP1_TX_ENABLED(comp1)) { + +++ dev_dbg(dev->dev, " designware: play supported\n"); ++ +++ idx = COMP1_TX_WORDSIZE_0(comp1); ++ +++ if (WARN_ON(idx >= ARRAY_SIZE(formats))) ++ +++ return -EINVAL; + +++ dw_i2s_dai->playback.channels_min = MIN_CHANNEL_NUM; - dw_i2s_dai->playback.channels_max = pdata->channel; - dw_i2s_dai->playback.formats = pdata->snd_fmts; - dw_i2s_dai->playback.rates = pdata->snd_rates; ++ +++ dw_i2s_dai->playback.channels_max = ++ +++ 1 << (COMP1_TX_CHANNELS(comp1) + 1); ++ +++ dw_i2s_dai->playback.formats = formats[idx]; ++ +++ dw_i2s_dai->playback.rates = rates; + +++ } + +++ - if (pdata->cap & DWC_I2S_RECORD) { ++ +++ if (COMP1_RX_ENABLED(comp1)) { + +++ dev_dbg(dev->dev, "designware: record supported\n"); ++ +++ idx = COMP2_RX_WORDSIZE_0(comp2); ++ +++ if (WARN_ON(idx >= ARRAY_SIZE(formats))) ++ +++ return -EINVAL; + +++ dw_i2s_dai->capture.channels_min = MIN_CHANNEL_NUM; - dw_i2s_dai->capture.channels_max = pdata->channel; - dw_i2s_dai->capture.formats = pdata->snd_fmts; - dw_i2s_dai->capture.rates = pdata->snd_rates; ++ +++ dw_i2s_dai->capture.channels_max = ++ +++ 1 << (COMP1_RX_CHANNELS(comp1) + 1); ++ +++ dw_i2s_dai->capture.formats = formats[idx]; ++ +++ dw_i2s_dai->capture.rates = rates; + +++ } ++ +++ ++ +++ return 0; ++ +++} ++ +++ ++ +++static int dw_configure_dai_by_pd(struct dw_i2s_dev *dev, ++ +++ struct snd_soc_dai_driver *dw_i2s_dai, ++ +++ struct resource *res, ++ +++ const struct i2s_platform_data *pdata) ++ +++{ ++ +++ u32 comp1 = i2s_read_reg(dev->i2s_base, I2S_COMP_PARAM_1); ++ +++ u32 idx = COMP1_APB_DATA_WIDTH(comp1); ++ +++ int ret; ++ +++ ++ +++ if (WARN_ON(idx >= ARRAY_SIZE(bus_widths))) ++ +++ return -EINVAL; ++ +++ ++ +++ ret = dw_configure_dai(dev, dw_i2s_dai, pdata->snd_rates); ++ +++ if (ret < 0) ++ +++ return ret; ++ +++ ++ +++ /* Set DMA slaves info */ ++ +++ dev->play_dma_data.pd.data = pdata->play_dma_data; ++ +++ dev->capture_dma_data.pd.data = pdata->capture_dma_data; ++ +++ dev->play_dma_data.pd.addr = res->start + I2S_TXDMA; ++ +++ dev->capture_dma_data.pd.addr = res->start + I2S_RXDMA; ++ +++ dev->play_dma_data.pd.max_burst = 16; ++ +++ dev->capture_dma_data.pd.max_burst = 16; ++ +++ dev->play_dma_data.pd.addr_width = bus_widths[idx]; ++ +++ dev->capture_dma_data.pd.addr_width = bus_widths[idx]; ++ +++ dev->play_dma_data.pd.filter = pdata->filter; ++ +++ dev->capture_dma_data.pd.filter = pdata->filter; ++ +++ ++ +++ return 0; ++ +++} ++ +++ ++ +++static int dw_configure_dai_by_dt(struct dw_i2s_dev *dev, ++ +++ struct snd_soc_dai_driver *dw_i2s_dai, ++ +++ struct resource *res) ++ +++{ ++ +++ u32 comp1 = i2s_read_reg(dev->i2s_base, I2S_COMP_PARAM_1); ++ +++ u32 comp2 = i2s_read_reg(dev->i2s_base, I2S_COMP_PARAM_2); ++ +++ u32 fifo_depth = 1 << (1 + COMP1_FIFO_DEPTH_GLOBAL(comp1)); ++ +++ u32 idx = COMP1_APB_DATA_WIDTH(comp1); ++ +++ u32 idx2; ++ +++ int ret; ++ +++ ++ +++ if (WARN_ON(idx >= ARRAY_SIZE(bus_widths))) ++ +++ return -EINVAL; ++ +++ ++ +++ ret = dw_configure_dai(dev, dw_i2s_dai, SNDRV_PCM_RATE_8000_192000); ++ +++ if (ret < 0) ++ +++ return ret; ++ +++ ++ +++ if (COMP1_TX_ENABLED(comp1)) { ++ +++ idx2 = COMP1_TX_WORDSIZE_0(comp1); ++ +++ ++ +++ dev->capability |= DWC_I2S_PLAY; ++ +++ dev->play_dma_data.dt.addr = res->start + I2S_TXDMA; ++ +++ dev->play_dma_data.dt.addr_width = bus_widths[idx]; ++ +++ dev->play_dma_data.dt.chan_name = "TX"; ++ +++ dev->play_dma_data.dt.fifo_size = fifo_depth * ++ +++ (fifo_width[idx2]) >> 8; ++ +++ dev->play_dma_data.dt.maxburst = 16; ++ +++ } ++ +++ if (COMP1_RX_ENABLED(comp1)) { ++ +++ idx2 = COMP2_RX_WORDSIZE_0(comp2); ++ +++ ++ +++ dev->capability |= DWC_I2S_RECORD; ++ +++ dev->capture_dma_data.dt.addr = res->start + I2S_RXDMA; ++ +++ dev->capture_dma_data.dt.addr_width = bus_widths[idx]; ++ +++ dev->capture_dma_data.dt.chan_name = "RX"; ++ +++ dev->capture_dma_data.dt.fifo_size = fifo_depth * ++ +++ (fifo_width[idx2] >> 8); ++ +++ dev->capture_dma_data.dt.maxburst = 16; ++ +++ } ++ +++ ++ +++ return 0; ++ +++ + +++} + +++ static int dw_i2s_probe(struct platform_device *pdev) { const struct i2s_platform_data *pdata = pdev->dev.platform_data; struct dw_i2s_dev *dev; struct resource *res; int ret; - --- unsigned int cap; struct snd_soc_dai_driver *dw_i2s_dai; -- --- if (!pdata) { -- --- dev_err(&pdev->dev, "Invalid platform data\n"); -- --- return -EINVAL; -- --- } -- --- dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL); if (!dev) { dev_warn(&pdev->dev, "kzalloc fail\n"); @@@@@@@ -398,25 -355,61 -534,40 -355,61 -355,61 -355,61 +545,40 @@@@@@@ dw_i2s_dai->resume = dw_i2s_resume; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - --- if (!res) { - --- dev_err(&pdev->dev, "no i2s resource defined\n"); - --- return -ENODEV; - --- } - --- dev->i2s_base = devm_ioremap_resource(&pdev->dev, res); - --- if (IS_ERR(dev->i2s_base)) { - --- dev_err(&pdev->dev, "ioremap fail for i2s_region\n"); + +++ if (IS_ERR(dev->i2s_base)) return PTR_ERR(dev->i2s_base); - --- } - --- cap = pdata->cap; - --- dev->capability = cap; - --- dev->i2s_clk_cfg = pdata->i2s_clk_cfg; + +++ dev->dev = &pdev->dev; - dw_configure_dai_by_pd(dev, dw_i2s_dai, res, pdata); ++ +++ if (pdata) { ++ +++ ret = dw_configure_dai_by_pd(dev, dw_i2s_dai, res, pdata); ++ +++ if (ret < 0) ++ +++ return ret; ++ +++ ++ +++ dev->capability = pdata->cap; ++ +++ dev->i2s_clk_cfg = pdata->i2s_clk_cfg; ++ +++ if (!dev->i2s_clk_cfg) { ++ +++ dev_err(&pdev->dev, "no clock configure method\n"); ++ +++ return -ENODEV; ++ +++ } - dev->capability = pdata->cap; - dev->i2s_clk_cfg = pdata->i2s_clk_cfg; - dev->clk = clk_get(&pdev->dev, NULL); - --- /* Set DMA slaves info */ ++ +++ dev->clk = devm_clk_get(&pdev->dev, NULL); ++ +++ } else { ++ +++ ret = dw_configure_dai_by_dt(dev, dw_i2s_dai, res); ++ +++ if (ret < 0) ++ +++ return ret; + - --- dev->play_dma_data.data = pdata->play_dma_data; - --- dev->capture_dma_data.data = pdata->capture_dma_data; - --- dev->play_dma_data.addr = res->start + I2S_TXDMA; - --- dev->capture_dma_data.addr = res->start + I2S_RXDMA; - --- dev->play_dma_data.max_burst = 16; - --- dev->capture_dma_data.max_burst = 16; - --- dev->play_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; - --- dev->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; - --- dev->play_dma_data.filter = pdata->filter; - --- dev->capture_dma_data.filter = pdata->filter; - --- - --- dev->clk = clk_get(&pdev->dev, NULL); ++ +++ dev->clk = devm_clk_get(&pdev->dev, "i2sclk"); ++ +++ } if (IS_ERR(dev->clk)) -- --- return PTR_ERR(dev->clk); ++ +++ return PTR_ERR(dev->clk); -- --- ret = clk_enable(dev->clk); ++ +++ ret = clk_prepare_enable(dev->clk); if (ret < 0) -- --- goto err_clk_put; - --- - --- if (cap & DWC_I2S_PLAY) { - --- dev_dbg(&pdev->dev, " designware: play supported\n"); - --- dw_i2s_dai->playback.channels_min = MIN_CHANNEL_NUM; - --- dw_i2s_dai->playback.channels_max = pdata->channel; - --- dw_i2s_dai->playback.formats = pdata->snd_fmts; - --- dw_i2s_dai->playback.rates = pdata->snd_rates; - --- } - --- - --- if (cap & DWC_I2S_RECORD) { - --- dev_dbg(&pdev->dev, "designware: record supported\n"); - --- dw_i2s_dai->capture.channels_min = MIN_CHANNEL_NUM; - --- dw_i2s_dai->capture.channels_max = pdata->channel; - --- dw_i2s_dai->capture.formats = pdata->snd_fmts; - --- dw_i2s_dai->capture.rates = pdata->snd_rates; - --- } ++ +++ return ret; - --- dev->dev = &pdev->dev; dev_set_drvdata(&pdev->dev, dev); -- --- ret = snd_soc_register_component(&pdev->dev, &dw_i2s_component, ++ +++ ret = devm_snd_soc_register_component(&pdev->dev, &dw_i2s_component, dw_i2s_dai, 1); if (ret != 0) { dev_err(&pdev->dev, "not able to register dai\n");