mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-03-15 11:44:11 +00:00
1.[alsa]Resolve the failure of pwmdac to play mono 8K audio
2.[dma] Modify the DMA error interrupt handling process Signed-off-by: jenny.zhang <jenny.zhang@starfivetech.com>
This commit is contained in:
parent
7d3709aaf0
commit
f51ce46905
4 changed files with 95 additions and 199 deletions
210
drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
Normal file → Executable file
210
drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
Normal file → Executable file
|
@ -309,13 +309,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;
|
||||
}
|
||||
|
||||
|
@ -329,64 +328,29 @@ 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)
|
||||
{
|
||||
struct axi_dma_hw_desc *hw_desc = NULL;
|
||||
u32 priority = chan->chip->dw->hdata->priority[chan->id];
|
||||
u32 reg, irq_mask;
|
||||
s32 descs_flush, descs_count;
|
||||
u8 lms = 0; /* Select AXI0 master for LLI fetching */
|
||||
|
||||
#ifdef CONFIG_DW_AXI_DMAC_STARFIVE
|
||||
s32 descs_flush, descs_count;
|
||||
struct axi_dma_hw_desc *hw_desc = NULL;
|
||||
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;
|
||||
//return;
|
||||
}
|
||||
#else
|
||||
if (unlikely(axi_chan_is_hw_enable(chan))) {
|
||||
dev_err(chan2dev(chan), "%s is non-idle!\n",
|
||||
axi_chan_name(chan));
|
||||
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
axi_dma_enable(chan->chip);
|
||||
|
||||
reg = (DWAXIDMAC_MBLK_TYPE_LL << CH_CFG_L_DST_MULTBLK_TYPE_POS |
|
||||
DWAXIDMAC_MBLK_TYPE_LL << CH_CFG_L_SRC_MULTBLK_TYPE_POS);
|
||||
|
||||
#ifdef CONFIG_DW_AXI_DMAC_STARFIVE
|
||||
if (chan->hw_handshake_num) {
|
||||
switch (chan->direction) {
|
||||
case DMA_MEM_TO_DEV:
|
||||
|
@ -399,7 +363,6 @@ static void axi_chan_block_xfer_start(struct axi_dma_chan *chan,
|
|||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
axi_chan_iowrite32(chan, CH_CFG_L, reg);
|
||||
|
||||
|
@ -409,7 +372,6 @@ static void axi_chan_block_xfer_start(struct axi_dma_chan *chan,
|
|||
DWAXIDMAC_HS_SEL_HW << CH_CFG_H_HS_SEL_SRC_POS);
|
||||
switch (chan->direction) {
|
||||
case DMA_MEM_TO_DEV:
|
||||
dw_axi_dma_set_byte_halfword(chan, true);
|
||||
reg |= (chan->config.device_fc ?
|
||||
DWAXIDMAC_TT_FC_MEM_TO_PER_DST :
|
||||
DWAXIDMAC_TT_FC_MEM_TO_PER_DMAC)
|
||||
|
@ -435,23 +397,13 @@ static void axi_chan_block_xfer_start(struct axi_dma_chan *chan,
|
|||
irq_mask |= DWAXIDMAC_IRQ_SUSPENDED;
|
||||
axi_chan_irq_set(chan, irq_mask);
|
||||
|
||||
/* flush all the desc */
|
||||
#ifdef CONFIG_DW_AXI_DMAC_STARFIVE
|
||||
/*flush all the desc */
|
||||
#ifdef CONFIG_SOC_STARFIVE_VIC7100
|
||||
if(chan->chip->flag->need_flush) {
|
||||
int count = atomic_read(&chan->descs_allocated);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
starfive_flush_dcache(first->hw_desc[i].llp,
|
||||
sizeof(*first->hw_desc[i].lli));
|
||||
|
||||
dev_dbg(chan->chip->dev,
|
||||
"sar:%#llx dar:%#llx llp:%#llx ctl:0x%x:%08x\n",
|
||||
first->hw_desc[i].lli->sar,
|
||||
first->hw_desc[i].lli->dar,
|
||||
first->hw_desc[i].lli->llp,
|
||||
first->hw_desc[i].lli->ctl_hi,
|
||||
first->hw_desc[i].lli->ctl_lo);
|
||||
descs_count = atomic_read(&chan->descs_allocated);
|
||||
for (descs_flush = 0; descs_flush < descs_count; descs_flush++) {
|
||||
hw_desc = &first->hw_desc[descs_flush];
|
||||
starfive_flush_dcache(hw_desc->llp, sizeof(*hw_desc->lli));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -542,48 +494,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_chip *chip,
|
||||
u32 handshake_num, bool set)
|
||||
{
|
||||
unsigned long start = 0;
|
||||
unsigned long reg_value;
|
||||
unsigned long reg_mask;
|
||||
unsigned long reg_set;
|
||||
unsigned long mask;
|
||||
unsigned long val;
|
||||
|
||||
if (!chip->apb_regs) {
|
||||
dev_dbg(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) {
|
||||
reg_set = UNUSED_CHANNEL;
|
||||
val = handshake_num;
|
||||
} else {
|
||||
reg_set = handshake_num;
|
||||
val = UNUSED_CHANNEL;
|
||||
}
|
||||
|
||||
reg_value = lo_hi_readq(chip->apb_regs + DMAC_APB_HW_HS_SEL_0);
|
||||
|
||||
for_each_set_clump8(start, reg_mask, ®_value, 64) {
|
||||
if (reg_mask == reg_set) {
|
||||
mask = GENMASK_ULL(start + 7, start);
|
||||
reg_value &= ~mask;
|
||||
reg_value |= rol64(val, start);
|
||||
lo_hi_writeq(reg_value,
|
||||
chip->apb_regs + DMAC_APB_HW_HS_SEL_0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 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
|
||||
|
@ -709,7 +619,7 @@ static int dw_axi_dma_set_hw_desc(struct axi_dma_chan *chan,
|
|||
|
||||
hw_desc->lli->block_ts_lo = cpu_to_le32(block_ts - 1);
|
||||
|
||||
#ifdef CONFIG_DW_AXI_DMAC_STARFIVE
|
||||
#ifdef CONFIG_SOC_STARFIVE_VIC7100
|
||||
ctllo |= DWAXIDMAC_BURST_TRANS_LEN_16 << CH_CTL_L_DST_MSIZE_POS |
|
||||
DWAXIDMAC_BURST_TRANS_LEN_16 << CH_CTL_L_SRC_MSIZE_POS;
|
||||
#else
|
||||
|
@ -819,8 +729,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->chip, chan->hw_handshake_num, true);
|
||||
|
||||
return vchan_tx_prep(&chan->vc, &desc->vd, flags);
|
||||
|
||||
err_desc_get:
|
||||
|
@ -899,8 +807,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->chip, chan->hw_handshake_num, true);
|
||||
|
||||
return vchan_tx_prep(&chan->vc, &desc->vd, flags);
|
||||
|
||||
err_desc_get:
|
||||
|
@ -996,6 +902,10 @@ dma_chan_prep_dma_memcpy(struct dma_chan *dchan, dma_addr_t dst_adr,
|
|||
num++;
|
||||
}
|
||||
|
||||
/* Total len of src/dest sg == 0, so no descriptor were allocated */
|
||||
if (unlikely(!desc))
|
||||
return NULL;
|
||||
|
||||
/* Set end-of-link to the last link descriptor of list */
|
||||
set_desc_last(&desc->hw_desc[num - 1]);
|
||||
/* Managed transfer list */
|
||||
|
@ -1046,16 +956,23 @@ 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)
|
||||
{
|
||||
struct virt_dma_desc *vd;
|
||||
unsigned long flags;
|
||||
#ifdef CONFIG_DW_AXI_DMAC_STARFIVE
|
||||
struct axi_dma_desc *desc;
|
||||
#endif
|
||||
spin_lock_irqsave(&chan->vc.lock, flags);
|
||||
|
||||
axi_chan_disable(chan);
|
||||
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;
|
||||
|
||||
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));
|
||||
|
||||
spin_lock_irqsave(&chan->vc.lock, flags);
|
||||
|
||||
/* The bad descriptor currently is in the head of vc list */
|
||||
vd = vchan_next_desc(&chan->vc);
|
||||
|
@ -1065,33 +982,43 @@ static noinline void axi_chan_handle_err(struct axi_dma_chan *chan, u32 status)
|
|||
spin_unlock_irqrestore(&chan->vc.lock, flags);
|
||||
return;
|
||||
}
|
||||
#ifdef CONFIG_DW_AXI_DMAC_STARFIVE
|
||||
if (chan->is_err) {
|
||||
desc = vd_to_axi_desc(vd);
|
||||
axi_chan_block_xfer_start(chan, desc);
|
||||
chan->is_err = false;
|
||||
|
||||
if (chan->cyclic) {
|
||||
vchan_cyclic_callback(vd);
|
||||
axi_chan_enable(chan);
|
||||
} else {
|
||||
#endif
|
||||
/* 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, irq: 0x%08x\n",
|
||||
axi_chan_name(chan), vd->tx.cookie, status);
|
||||
"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);
|
||||
#ifdef CONFIG_DW_AXI_DMAC_STARFIVE
|
||||
}
|
||||
#endif
|
||||
|
||||
spin_unlock_irqrestore(&chan->vc.lock, flags);
|
||||
}
|
||||
|
||||
|
||||
static noinline void axi_chan_handle_err(struct axi_dma_chan *chan, u32 status)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
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)
|
||||
{
|
||||
int count = atomic_read(&chan->descs_allocated);
|
||||
|
@ -1127,6 +1054,9 @@ static void axi_chan_block_xfer_complete(struct axi_dma_chan *chan)
|
|||
if (hw_desc->llp == llp) {
|
||||
axi_chan_irq_clear(chan, hw_desc->lli->status_lo);
|
||||
hw_desc->lli->ctl_hi |= CH_CTL_H_LLI_VALID;
|
||||
#ifdef CONFIG_SOC_STARFIVE_VIC7100
|
||||
starfive_flush_dcache(hw_desc->llp, sizeof(*hw_desc->lli));
|
||||
#endif
|
||||
desc->completed_blocks = i;
|
||||
|
||||
if (((hw_desc->len * (i + 1)) % desc->period_len) == 0)
|
||||
|
@ -1169,11 +1099,11 @@ static irqreturn_t dw_axi_dma_interrupt(int irq, void *dev_id)
|
|||
dev_vdbg(chip->dev, "%s %u IRQ status: 0x%08x\n",
|
||||
axi_chan_name(chan), i, status);
|
||||
|
||||
if (status & DWAXIDMAC_IRQ_ALL_ERR)
|
||||
if (status & DWAXIDMAC_IRQ_ALL_ERR) {
|
||||
axi_chan_handle_err(chan, status);
|
||||
}
|
||||
else if (status & DWAXIDMAC_IRQ_DMA_TRF) {
|
||||
axi_chan_block_xfer_complete(chan);
|
||||
dev_dbg(chip->dev, "axi_chan_block_xfer_complete.\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1200,13 +1130,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->chip,
|
||||
chan->hw_handshake_num, 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);
|
||||
|
@ -1367,7 +1290,7 @@ static int parse_device_properties(struct axi_dma_chip *chip)
|
|||
|
||||
if(chip->dw->hdata->nr_channels > 8){
|
||||
chip->flag->nr_chan_8 = true;
|
||||
#ifdef CONFIG_DW_AXI_DMAC_STARFIVE
|
||||
#ifdef CONFIG_SOC_STARFIVE_VIC7100
|
||||
chip->flag->need_flush = true;
|
||||
#endif
|
||||
}
|
||||
|
@ -1428,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;
|
||||
|
@ -1467,12 +1389,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);
|
||||
|
@ -1507,6 +1423,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 */
|
||||
|
@ -1544,11 +1462,7 @@ static int dw_probe(struct platform_device *pdev)
|
|||
* Therefore, set constraint to 1024 * 4.
|
||||
*/
|
||||
dw->dma.dev->dma_parms = &dw->dma_parms;
|
||||
#ifdef CONFIG_DW_AXI_DMAC_STARFIVE
|
||||
dma_set_max_seg_size(&pdev->dev, DMAC_MAX_BLK_SIZE);
|
||||
#else
|
||||
dma_set_max_seg_size(&pdev->dev, MAX_BLOCK_SIZE);
|
||||
#endif
|
||||
platform_set_drvdata(pdev, chip);
|
||||
|
||||
pm_runtime_enable(chip->dev);
|
||||
|
@ -1603,6 +1517,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);
|
||||
|
||||
|
@ -1628,7 +1543,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);
|
||||
|
@ -1638,7 +1552,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,
|
||||
},
|
||||
};
|
||||
|
|
1
drivers/dma/dw-axi-dmac/dw-axi-dmac.h
Normal file → Executable file
1
drivers/dma/dw-axi-dmac/dw-axi-dmac.h
Normal file → Executable file
|
@ -59,6 +59,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 {
|
||||
|
|
|
@ -41,7 +41,6 @@
|
|||
* Compatibility
|
||||
*/
|
||||
|
||||
#define CONFIG_SND_STARFIVE
|
||||
struct snd_pcm_hw_params_old {
|
||||
unsigned int flags;
|
||||
unsigned int masks[SNDRV_PCM_HW_PARAM_SUBFORMAT -
|
||||
|
@ -730,11 +729,6 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
|
|||
runtime->subformat = params_subformat(params);
|
||||
runtime->channels = params_channels(params);
|
||||
runtime->rate = params_rate(params);
|
||||
#ifdef CONFIG_SND_STARFIVE
|
||||
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
|
||||
runtime->period_size = params_period_size(params)/2;
|
||||
else
|
||||
#endif
|
||||
runtime->period_size = params_period_size(params);
|
||||
runtime->periods = params_periods(params);
|
||||
runtime->buffer_size = params_buffer_size(params);
|
||||
|
|
77
sound/soc/starfive/starfive_pwmdac.c
Normal file → Executable file
77
sound/soc/starfive/starfive_pwmdac.c
Normal file → Executable file
|
@ -61,9 +61,8 @@ static int pwmdac_shift_bit_info(struct snd_kcontrol *kcontrol,
|
|||
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
|
||||
uinfo->count = 1;
|
||||
uinfo->value.enumerated.items = items;
|
||||
if (uinfo->value.enumerated.item >= items) {
|
||||
if (uinfo->value.enumerated.item >= items)
|
||||
uinfo->value.enumerated.item = items - 1;
|
||||
}
|
||||
strcpy(uinfo->value.enumerated.name,
|
||||
pwmdac_ct_shift_bit[uinfo->value.enumerated.item].name);
|
||||
|
||||
|
@ -150,43 +149,6 @@ static int pwmdac_duty_cycle_put(struct snd_kcontrol *kcontrol,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int pwmdac_datan_info(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_info *uinfo)
|
||||
{
|
||||
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
|
||||
uinfo->count = 1;
|
||||
uinfo->value.integer.min = 1;
|
||||
uinfo->value.integer.max = PWMDAC_SAMPLE_CNT_511;
|
||||
uinfo->value.integer.step = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pwmdac_datan_get(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
|
||||
struct sf_pwmdac_dev *dev = snd_soc_component_get_drvdata(component);
|
||||
|
||||
ucontrol->value.integer.value[0] = dev->datan;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pwmdac_datan_put(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
|
||||
struct sf_pwmdac_dev *dev = snd_soc_component_get_drvdata(component);
|
||||
int sel = ucontrol->value.integer.value[0];
|
||||
|
||||
if (sel > PWMDAC_SAMPLE_CNT_511)
|
||||
return 0;
|
||||
|
||||
dev->datan = sel;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pwmdac_data_mode_info(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_info *uinfo)
|
||||
{
|
||||
|
@ -460,9 +422,7 @@ static void pwmdac_set(struct sf_pwmdac_dev *dev)
|
|||
|
||||
pwmdac_LR_data_change(dev, dev->lr_change);
|
||||
pwmdac_data_mode(dev, dev->data_mode);
|
||||
if (dev->shift) {
|
||||
pwmdac_data_shift(dev, dev->shift);
|
||||
}
|
||||
pwmdac_data_shift(dev, dev->shift);
|
||||
}
|
||||
|
||||
static void pwmdac_stop(struct sf_pwmdac_dev *dev)
|
||||
|
@ -526,8 +486,6 @@ static int pwmdac_config(struct sf_pwmdac_dev *dev)
|
|||
static int sf_pwmdac_prepare(struct snd_pcm_substream *substream,
|
||||
struct snd_soc_dai *dai)
|
||||
{
|
||||
struct sf_pwmdac_dev *dev = snd_soc_dai_get_drvdata(dai);
|
||||
//pwmdac_set(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -592,6 +550,35 @@ static int sf_pwmdac_trigger(struct snd_pcm_substream *substream,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int sf_pwmdac_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
|
||||
{
|
||||
struct sf_pwmdac_dev *dev = dev_get_drvdata(dai->dev);
|
||||
|
||||
dev->play_dma_data.addr = dev->mapbase + PWMDAC_WDATA;
|
||||
|
||||
switch (params_channels(params)) {
|
||||
case 2:
|
||||
dev->play_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
|
||||
break;
|
||||
case 1:
|
||||
dev->play_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
|
||||
break;
|
||||
default:
|
||||
dev_err(dai->dev, "%d channels not supported\n",
|
||||
params_channels(params));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
dev->play_dma_data.fifo_size = 1;
|
||||
dev->play_dma_data.maxburst = 16;
|
||||
|
||||
snd_soc_dai_init_dma_data(dai, &dev->play_dma_data, NULL);
|
||||
snd_soc_dai_set_drvdata(dai, dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sf_pwmdac_dai_probe(struct snd_soc_dai *dai)
|
||||
{
|
||||
struct sf_pwmdac_dev *dev = dev_get_drvdata(dai->dev);
|
||||
|
@ -624,7 +611,6 @@ static const struct snd_kcontrol_new pwmdac_snd_controls[] = {
|
|||
};
|
||||
static int pwmdac_probe(struct snd_soc_component *component)
|
||||
{
|
||||
struct sf_pwmdac_dev *priv = snd_soc_component_get_drvdata(component);
|
||||
snd_soc_add_component_controls(component, pwmdac_snd_controls,
|
||||
ARRAY_SIZE(pwmdac_snd_controls));
|
||||
return 0;
|
||||
|
@ -632,6 +618,7 @@ static int pwmdac_probe(struct snd_soc_component *component)
|
|||
|
||||
|
||||
static const struct snd_soc_dai_ops sf_pwmdac_dai_ops = {
|
||||
.hw_params = sf_pwmdac_hw_params,
|
||||
.prepare = sf_pwmdac_prepare,
|
||||
.trigger = sf_pwmdac_trigger,
|
||||
};
|
||||
|
|
Loading…
Add table
Reference in a new issue