[Audio: PWMDAC] enable pwmdac driver on 7110 evb board
authorcurry.zhang <curry.zhang@starfivetech.com>
Wed, 18 May 2022 12:56:11 +0000 (05:56 -0700)
committercurry.zhang <curry.zhang@starfivetech.com>
Wed, 18 May 2022 12:56:11 +0000 (05:56 -0700)
Signed-off-by: curry.zhang <curry.zhang@starfivetech.com>
drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
sound/soc/starfive/starfive_pwmdac.c

index 4029bb5..d3c2433 100755 (executable)
@@ -797,6 +797,11 @@ dw_axi_dma_chan_prep_cyclic(struct dma_chan *dchan, dma_addr_t dma_addr,
 
        num_segments = DIV_ROUND_UP(period_len, axi_block_len);
        segment_len = DIV_ROUND_UP(period_len, num_segments);
+       if (!IS_ALIGNED(segment_len, 4))
+       {
+               segment_len = ALIGN(segment_len, 4);
+               period_len = segment_len * num_segments;
+       }
 
        total_segments = num_periods * num_segments;
 
index dcc897a..e5ecb8f 100755 (executable)
@@ -562,10 +562,43 @@ static int sf_pwmdac_trigger(struct snd_pcm_substream *substream,
 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;
@@ -578,7 +611,23 @@ static int sf_pwmdac_hw_params(struct snd_pcm_substream *substream,
                                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;
        
@@ -586,6 +635,10 @@ static int sf_pwmdac_hw_params(struct snd_pcm_substream *substream,
        snd_soc_dai_set_drvdata(dai, dev);
 
        return 0;
+
+err_clk_pwmdac:
+       return ret;
+
 }
 
 static int sf_pwmdac_clks_get(struct platform_device *pdev,
@@ -640,6 +693,12 @@ static int sf_pwmdac_clk_init(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));
@@ -711,7 +770,7 @@ static struct snd_soc_dai_driver pwmdac_dai = {
        .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,