static int sf_pwmdac_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
{
+ int ret = 0;
+ unsigned long mclk_dac_value;
struct sf_pwmdac_dev *dev = dev_get_drvdata(dai->dev);
dev->play_dma_data.addr = dev->mapbase + PWMDAC_WDATA;
+ switch (params_rate(params)) {
+ case 8000:
+ dev->datan = PWMDAC_SAMPLE_CNT_3;
+ mclk_dac_value = 6144000;
+ break;
+ case 16000:
+ dev->datan = PWMDAC_SAMPLE_CNT_3;
+ mclk_dac_value = 12288000;
+ break;
+ case 22050:
+ dev->datan = PWMDAC_SAMPLE_CNT_1;
+ mclk_dac_value = 5644800;
+ break;
+ case 32000:
+ dev->datan = PWMDAC_SAMPLE_CNT_1;
+ mclk_dac_value = 8192000;
+ break;
+ case 44100:
+ dev->datan = PWMDAC_SAMPLE_CNT_1;
+ mclk_dac_value = 11289600;
+ break;
+ case 48000:
+ dev->datan = PWMDAC_SAMPLE_CNT_1;
+ mclk_dac_value = 12288000;
+ break;
+ default:
+ dev_err(dai->dev, "%d rate not supported\n",
+ params_rate(params));
+ return -EINVAL;
+ }
+
switch (params_channels(params)) {
case 2:
dev->play_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
params_channels(params));
return -EINVAL;
}
-
+
+ /* The mclock for the clock driver always rounds down so add a little slack */
+ mclk_dac_value = mclk_dac_value + 64;
+ pwmdac_set(dev);
+
+ ret = clk_prepare_enable(dev->clk_pwmdac_core);
+ if (ret) {
+ dev_err(dai->dev, "failed to prepare enable clk_pwmdac_core\n");
+ goto err_clk_pwmdac;
+ }
+
+ ret = clk_set_rate(dev->clk_pwmdac_core, mclk_dac_value);
+ if (ret) {
+ dev_err(dai->dev, "failed to set rate for clk_pwmdac_core %lu\n", mclk_dac_value);
+ goto err_clk_pwmdac;
+ }
+
dev->play_dma_data.fifo_size = 1;
dev->play_dma_data.maxburst = 16;
snd_soc_dai_set_drvdata(dai, dev);
return 0;
+
+err_clk_pwmdac:
+ return ret;
+
}
static int sf_pwmdac_clks_get(struct platform_device *pdev,
dev_err(&pdev->dev, "failed to prepare enable clk_pwmdac_core\n");
goto err_clk_pwmdac;
}
+
+ ret = clk_set_rate(dev->clk_pwmdac_core, 4096000);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to set rate for clk_pwmdac_core \n");
+ goto err_clk_pwmdac;
+ }
dev_info(&pdev->dev, "clk_apb0 = %lu, clk_pwmdac_apb = %lu, clk_pwmdac_core = %lu\n",
clk_get_rate(dev->clk_apb0), clk_get_rate(dev->clk_pwmdac_apb),
clk_get_rate(dev->clk_pwmdac_core));
.playback = {
.channels_min = 1,
.channels_max = 2,
- .rates = SNDRV_PCM_RATE_16000,
+ .rates = SNDRV_PCM_RATE_8000_48000,
.formats = SNDRV_PCM_FMTBIT_S16_LE,
},
.ops = &sf_pwmdac_dai_ops,