diff --git a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c old mode 100644 new mode 100755 index 4c8416edd4e49..4c34d6594400c --- a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c +++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c @@ -327,13 +327,12 @@ dma_chan_tx_status(struct dma_chan *dchan, dma_cookie_t cookie, len = vd_to_axi_desc(vdesc)->hw_desc[0].len; completed_length = completed_blocks * len; bytes = length - completed_length; + spin_unlock_irqrestore(&chan->vc.lock, flags); + dma_set_residue(txstate, bytes); } else { - bytes = vd_to_axi_desc(vdesc)->length; + spin_unlock_irqrestore(&chan->vc.lock, flags); } - spin_unlock_irqrestore(&chan->vc.lock, flags); - dma_set_residue(txstate, bytes); - return status; } @@ -347,29 +346,6 @@ static void write_chan_llp(struct axi_dma_chan *chan, dma_addr_t adr) axi_chan_iowrite64(chan, CH_LLP, adr); } -static void dw_axi_dma_set_byte_halfword(struct axi_dma_chan *chan, bool set) -{ - u32 offset = DMAC_APB_BYTE_WR_CH_EN; - u32 reg_width, val; - - if (!chan->chip->apb_regs) { - dev_dbg(chan->chip->dev, "apb_regs not initialized\n"); - return; - } - - reg_width = __ffs(chan->config.dst_addr_width); - if (reg_width == DWAXIDMAC_TRANS_WIDTH_16) - offset = DMAC_APB_HALFWORD_WR_CH_EN; - - val = ioread32(chan->chip->apb_regs + offset); - - if (set) - val |= BIT(chan->id); - else - val &= ~BIT(chan->id); - - iowrite32(val, chan->chip->apb_regs + offset); -} /* Called in chan locked context */ static void axi_chan_block_xfer_start(struct axi_dma_chan *chan, struct axi_dma_desc *first) @@ -379,13 +355,11 @@ static void axi_chan_block_xfer_start(struct axi_dma_chan *chan, u32 irq_mask; u8 lms = 0; /* Select AXI0 master for LLI fetching */ - chan->is_err = false; if (unlikely(axi_chan_is_hw_enable(chan))) { dev_err(chan2dev(chan), "%s is non-idle!\n", axi_chan_name(chan)); axi_chan_disable(chan); - chan->is_err = true; } axi_dma_enable(chan->chip); @@ -398,7 +372,6 @@ static void axi_chan_block_xfer_start(struct axi_dma_chan *chan, config.hs_sel_src = DWAXIDMAC_HS_SEL_HW; switch (chan->direction) { case DMA_MEM_TO_DEV: - dw_axi_dma_set_byte_halfword(chan, true); config.tt_fc = chan->config.device_fc ? DWAXIDMAC_TT_FC_MEM_TO_PER_DST : DWAXIDMAC_TT_FC_MEM_TO_PER_DMAC; @@ -535,39 +508,6 @@ static void dma_chan_free_chan_resources(struct dma_chan *dchan) pm_runtime_put(chan->chip->dev); } -static void dw_axi_dma_set_hw_channel(struct axi_dma_chan *chan, bool set) -{ - struct axi_dma_chip *chip = chan->chip; - unsigned long reg_value, val; - - if (!chip->apb_regs) { - dev_err(chip->dev, "apb_regs not initialized\n"); - return; - } - - /* - * An unused DMA channel has a default value of 0x3F. - * Lock the DMA channel by assign a handshake number to the channel. - * Unlock the DMA channel by assign 0x3F to the channel. - */ - if (set) - val = chan->hw_handshake_num; - else - val = UNUSED_CHANNEL; - - reg_value = lo_hi_readq(chip->apb_regs + DMAC_APB_HW_HS_SEL_0); - - /* Channel is already allocated, set handshake as per channel ID */ - /* 64 bit write should handle for 8 channels */ - - reg_value &= ~(DMA_APB_HS_SEL_MASK << - (chan->id * DMA_APB_HS_SEL_BIT_SIZE)); - reg_value |= (val << (chan->id * DMA_APB_HS_SEL_BIT_SIZE)); - lo_hi_writeq(reg_value, chip->apb_regs + DMAC_APB_HW_HS_SEL_0); - - return; -} - /* * If DW_axi_dmac sees CHx_CTL.ShadowReg_Or_LLI_Last bit of the fetched LLI * as 1, it understands that the current block is the final block in the @@ -764,6 +704,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; @@ -803,8 +748,6 @@ dw_axi_dma_chan_prep_cyclic(struct dma_chan *dchan, dma_addr_t dma_addr, llp = hw_desc->llp; } while (total_segments); - dw_axi_dma_set_hw_channel(chan, true); - return vchan_tx_prep(&chan->vc, &desc->vd, flags); err_desc_get: @@ -883,8 +826,6 @@ dw_axi_dma_chan_prep_slave_sg(struct dma_chan *dchan, struct scatterlist *sgl, llp = hw_desc->llp; } while (num_sgs); - dw_axi_dma_set_hw_channel(chan, true); - return vchan_tx_prep(&chan->vc, &desc->vd, flags); err_desc_get: @@ -1030,41 +971,67 @@ static void axi_chan_list_dump_lli(struct axi_dma_chan *chan, axi_chan_dump_lli(chan, &desc_head->hw_desc[i]); } -static noinline void axi_chan_handle_err(struct axi_dma_chan *chan, u32 status) + +static void axi_chan_tasklet(struct tasklet_struct *t) { + struct axi_dma_chan *chan = from_tasklet(chan, t, dma_tasklet); struct virt_dma_desc *vd; + u32 chan_active = BIT(chan->id) << DMAC_CHAN_EN_SHIFT; unsigned long flags; + u32 val; + int ret; - spin_lock_irqsave(&chan->vc.lock, flags); + ret = readl_poll_timeout_atomic(chan->chip->regs + DMAC_CHEN, val, + !(val & chan_active), 10, 2000); + if (ret == -ETIMEDOUT) + dev_warn(chan2dev(chan), + "irq %s failed to stop\n", axi_chan_name(chan)); - axi_chan_disable(chan); + spin_lock_irqsave(&chan->vc.lock, flags); /* The bad descriptor currently is in the head of vc list */ vd = vchan_next_desc(&chan->vc); - if (chan->is_err) { - struct axi_dma_desc *desc = vd_to_axi_desc(vd); - - axi_chan_block_xfer_start(chan, desc); - chan->is_err = false; - goto out; + if (!vd) { + dev_warn(chan2dev(chan), + "%s vd is null\n", axi_chan_name(chan)); + spin_unlock_irqrestore(&chan->vc.lock, flags); + return; } - /* Remove the completed descriptor from issued list */ - list_del(&vd->node); + if (chan->cyclic) { + vchan_cyclic_callback(vd); + axi_chan_enable(chan); + } else { + /* Remove the completed descriptor from issued list */ + list_del(&vd->node); + + /* WARN about bad descriptor */ + dev_err(chan2dev(chan), + "Bad descriptor submitted for %s, cookie: %d\n", + axi_chan_name(chan), vd->tx.cookie); + axi_chan_list_dump_lli(chan, vd_to_axi_desc(vd)); + + vchan_cookie_complete(vd); + + /* Try to restart the controller */ + axi_chan_start_first_queued(chan); + } - /* WARN about bad descriptor */ - dev_err(chan2dev(chan), - "Bad descriptor submitted for %s, cookie: %d, irq: 0x%08x\n", - axi_chan_name(chan), vd->tx.cookie, status); - axi_chan_list_dump_lli(chan, vd_to_axi_desc(vd)); + spin_unlock_irqrestore(&chan->vc.lock, flags); +} - vchan_cookie_complete(vd); - /* Try to restart the controller */ - axi_chan_start_first_queued(chan); +static noinline void axi_chan_handle_err(struct axi_dma_chan *chan, u32 status) +{ + unsigned long flags; -out: + spin_lock_irqsave(&chan->vc.lock, flags); + if (unlikely(axi_chan_is_hw_enable(chan))) { + axi_chan_disable(chan); + } spin_unlock_irqrestore(&chan->vc.lock, flags); + + tasklet_schedule(&chan->dma_tasklet); } static void axi_chan_block_xfer_complete(struct axi_dma_chan *chan) @@ -1167,11 +1134,6 @@ static int dma_chan_terminate_all(struct dma_chan *dchan) dev_warn(dchan2dev(dchan), "%s failed to stop\n", axi_chan_name(chan)); - if (chan->direction != DMA_MEM_TO_MEM) - dw_axi_dma_set_hw_channel(chan, false); - if (chan->direction == DMA_MEM_TO_DEV) - dw_axi_dma_set_byte_halfword(chan, false); - spin_lock_irqsave(&chan->vc.lock, flags); vchan_get_all_descriptors(&chan->vc, &head); @@ -1389,7 +1351,6 @@ static int parse_device_properties(struct axi_dma_chip *chip) static int dw_probe(struct platform_device *pdev) { - struct device_node *node = pdev->dev.of_node; struct axi_dma_chip *chip; struct resource *mem; struct dw_axi_dma *dw; @@ -1422,12 +1383,6 @@ static int dw_probe(struct platform_device *pdev) if (IS_ERR(chip->regs)) return PTR_ERR(chip->regs); - if (of_device_is_compatible(node, "intel,kmb-axi-dma")) { - chip->apb_regs = devm_platform_ioremap_resource(pdev, 1); - if (IS_ERR(chip->apb_regs)) - return PTR_ERR(chip->apb_regs); - } - chip->core_clk = devm_clk_get(chip->dev, "core-clk"); if (IS_ERR(chip->core_clk)) return PTR_ERR(chip->core_clk); @@ -1461,6 +1416,8 @@ static int dw_probe(struct platform_device *pdev) chan->vc.desc_free = vchan_desc_put; vchan_init(&chan->vc, &dw->dma); + + tasklet_setup(&chan->dma_tasklet, axi_chan_tasklet); } /* Set capabilities */ @@ -1558,6 +1515,7 @@ static int dw_remove(struct platform_device *pdev) for (i = 0; i < dw->hdata->nr_channels; i++) { axi_chan_disable(&chip->dw->chan[i]); axi_chan_irq_disable(&chip->dw->chan[i], DWAXIDMAC_IRQ_ALL); + tasklet_kill(&chan->dma_tasklet); } axi_dma_disable(chip); @@ -1583,7 +1541,6 @@ static const struct dev_pm_ops dw_axi_dma_pm_ops = { static const struct of_device_id dw_dma_of_id_table[] = { { .compatible = "snps,axi-dma-1.01a" }, - { .compatible = "intel,kmb-axi-dma" }, {} }; MODULE_DEVICE_TABLE(of, dw_dma_of_id_table); @@ -1593,7 +1550,7 @@ static struct platform_driver dw_driver = { .remove = dw_remove, .driver = { .name = KBUILD_MODNAME, - .of_match_table = dw_dma_of_id_table, + .of_match_table = of_match_ptr(dw_dma_of_id_table), .pm = &dw_axi_dma_pm_ops, }, }; diff --git a/drivers/dma/dw-axi-dmac/dw-axi-dmac.h b/drivers/dma/dw-axi-dmac/dw-axi-dmac.h old mode 100644 new mode 100755 index 8530e3130b764..6933784477f47 --- a/drivers/dma/dw-axi-dmac/dw-axi-dmac.h +++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac.h @@ -52,6 +52,7 @@ struct axi_dma_chan { bool is_err; /* these other elements are all protected by vc.lock */ bool is_paused; + struct tasklet_struct dma_tasklet; }; struct dw_axi_dma { diff --git a/sound/soc/starfive/starfive_pwmdac.c b/sound/soc/starfive/starfive_pwmdac.c old mode 100644 new mode 100755 index 70061cc6ab228..893ea70ea808f --- a/sound/soc/starfive/starfive_pwmdac.c +++ b/sound/soc/starfive/starfive_pwmdac.c @@ -599,10 +599,51 @@ 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; + unsigned long clk_audio_src; 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; + clk_audio_src = 12288000; + /* we want 6144kHz but the clock driver always rounds down so add a little slack */ + mclk_dac_value = 6144000 + 64; + break; + case 16000: + dev->datan = PWMDAC_SAMPLE_CNT_3; + clk_audio_src = 12288000; + mclk_dac_value = 12288000 + 64; + break; + case 22050: + dev->datan = PWMDAC_SAMPLE_CNT_1; + clk_audio_src = 11289600; + mclk_dac_value = 5644800 + 64; + break; + case 32000: + dev->datan = PWMDAC_SAMPLE_CNT_1; + clk_audio_src = 8192000; + mclk_dac_value = 8192000 + 64; + break; + case 44100: + dev->datan = PWMDAC_SAMPLE_CNT_1; + clk_audio_src = 11289600; + mclk_dac_value = 11289600 + 64; + break; + case 48000: + dev->datan = PWMDAC_SAMPLE_CNT_1; + clk_audio_src = 12288000; + mclk_dac_value = 12288000 + 64; + 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; @@ -616,6 +657,27 @@ static int sf_pwmdac_hw_params(struct snd_pcm_substream *substream, return -EINVAL; } + pwmdac_set(dev); + + ret = clk_set_rate(dev->clk_audio_src, clk_audio_src); + if (ret) { + dev_err(dai->dev, "failed to set %lu rate for clk_audio_src\n", clk_audio_src); + goto err_clk_pwmdac; + } + + ret = clk_prepare_enable(dev->clk_dac_mclk); + if (ret) { + dev_err(dai->dev, "failed to prepare enable clk_dac_mclk\n"); + goto err_clk_pwmdac; + } + + /* we want 4096kHz but the clock driver always rounds down so add a little slack */ + ret = clk_set_rate(dev->clk_dac_mclk, mclk_dac_value); + if (ret) { + dev_err(dai->dev, "failed to set rate for clk_dac_mclk %lu\n", mclk_dac_value); + goto err_clk_pwmdac; + } + dev->play_dma_data.fifo_size = 1; dev->play_dma_data.maxburst = 16; @@ -623,6 +685,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, @@ -706,31 +772,12 @@ static int sf_pwmdac_clk_init(struct platform_device *pdev, goto err_clk_pwmdac; } - ret = clk_set_rate(dev->clk_audio_src, 12288000); - if (ret) { - dev_err(&pdev->dev, "failed to set 12.288 MHz rate for clk_audio_src\n"); - goto err_clk_pwmdac; - } - ret = reset_control_assert(dev->rst_apb_pwmdac); if (ret) { printk(KERN_INFO "failed to assert apb_pwmdac\n"); goto err_clk_pwmdac; } - ret = clk_prepare_enable(dev->clk_dac_mclk); - if (ret) { - dev_err(&pdev->dev, "failed to prepare enable clk_dac_mclk\n"); - goto err_clk_pwmdac; - } - - /* we want 4096kHz but the clock driver always rounds down so add a little slack */ - ret = clk_set_rate(dev->clk_dac_mclk, 4096000 + 64); - if (ret) { - dev_err(&pdev->dev, "failed to set 4096kHz rate for clk_dac_mclk\n"); - goto err_clk_pwmdac; - } - ret = clk_prepare_enable(dev->clk_pwmdac_apb); if (ret) { dev_err(&pdev->dev, "failed to prepare enable clk_pwmdac_apb\n"); @@ -805,7 +852,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,