static u32 sprd_mcdt_dma_ack_shift(u8 channel)
{ switch (channel) { default: case 0: case 8: return 0; case 1: case 9: return 4; case 2: return 8; case 3: return 12; case 4: return 16; case 5: return 20; case 6: return 24; case 7: return 28;
}
}
for (i = 0; i < MCDT_ADC_CHANNEL_NUM; i++) { if (sprd_mcdt_chan_int_sts(mcdt, i, MCDT_ADC_FIFO_AF_INT)) { struct sprd_mcdt_chan *chan = &mcdt->chan[i];
sprd_mcdt_chan_int_clear(mcdt, i, MCDT_ADC_FIFO_AF_INT); if (chan->cb)
chan->cb->notify(chan->cb->data);
}
}
for (i = 0; i < MCDT_DAC_CHANNEL_NUM; i++) { if (sprd_mcdt_chan_int_sts(mcdt, i, MCDT_DAC_FIFO_AE_INT)) { struct sprd_mcdt_chan *chan =
&mcdt->chan[i + MCDT_ADC_CHANNEL_NUM];
sprd_mcdt_chan_int_clear(mcdt, i, MCDT_DAC_FIFO_AE_INT); if (chan->cb)
chan->cb->notify(chan->cb->data);
}
}
spin_unlock(&mcdt->lock);
return IRQ_HANDLED;
}
/** * sprd_mcdt_chan_write - write data to the MCDT channel's fifo * @chan: the MCDT channel * @tx_buf: send buffer * @size: data size * * Note: We can not write data to the channel fifo when enabling the DMA mode, * otherwise the channel fifo data will be invalid. * * If there are not enough space of the channel fifo, it will return errors * to users. * * Returns 0 on success, or an appropriate error code on failure.
*/ int sprd_mcdt_chan_write(struct sprd_mcdt_chan *chan, char *tx_buf, u32 size)
{ struct sprd_mcdt_dev *mcdt = chan->mcdt; unsignedlong flags; int avail, i = 0, words = size / 4;
u32 *buf = (u32 *)tx_buf;
spin_lock_irqsave(&mcdt->lock, flags);
if (chan->dma_enable) {
dev_err(mcdt->dev, "Can not write data when DMA mode enabled\n");
spin_unlock_irqrestore(&mcdt->lock, flags); return -EINVAL;
}
if (sprd_mcdt_chan_fifo_sts(mcdt, chan->id, MCDT_DAC_FIFO_REAL_FULL)) {
dev_err(mcdt->dev, "Channel fifo is full now\n");
spin_unlock_irqrestore(&mcdt->lock, flags); return -EBUSY;
}
avail = sprd_mcdt_dac_fifo_avail(mcdt, chan->id); if (size > avail) {
dev_err(mcdt->dev, "Data size is larger than the available fifo size\n");
spin_unlock_irqrestore(&mcdt->lock, flags); return -EBUSY;
}
while (i++ < words)
sprd_mcdt_dac_write_fifo(mcdt, chan->id, *buf++);
/** * sprd_mcdt_chan_read - read data from the MCDT channel's fifo * @chan: the MCDT channel * @rx_buf: receive buffer * @size: data size * * Note: We can not read data from the channel fifo when enabling the DMA mode, * otherwise the reading data will be invalid. * * Usually user need start to read data once receiving the fifo full interrupt. * * Returns data size of reading successfully, or an error code on failure.
*/ int sprd_mcdt_chan_read(struct sprd_mcdt_chan *chan, char *rx_buf, u32 size)
{ struct sprd_mcdt_dev *mcdt = chan->mcdt; unsignedlong flags; int i = 0, avail, words = size / 4;
u32 *buf = (u32 *)rx_buf;
spin_lock_irqsave(&mcdt->lock, flags);
if (chan->dma_enable) {
dev_err(mcdt->dev, "Can not read data when DMA mode enabled\n");
spin_unlock_irqrestore(&mcdt->lock, flags); return -EINVAL;
}
if (sprd_mcdt_chan_fifo_sts(mcdt, chan->id, MCDT_ADC_FIFO_REAL_EMPTY)) {
dev_err(mcdt->dev, "Channel fifo is empty\n");
spin_unlock_irqrestore(&mcdt->lock, flags); return -EBUSY;
}
avail = sprd_mcdt_adc_fifo_avail(mcdt, chan->id); if (size > avail)
words = avail / 4;
while (i++ < words)
sprd_mcdt_adc_read_fifo(mcdt, chan->id, buf++);
spin_unlock_irqrestore(&mcdt->lock, flags); return words * 4;
}
EXPORT_SYMBOL_GPL(sprd_mcdt_chan_read);
/** * sprd_mcdt_chan_int_enable - enable the interrupt mode for the MCDT channel * @chan: the MCDT channel * @water_mark: water mark to trigger a interrupt * @cb: callback when a interrupt happened * * Now it only can enable fifo almost full interrupt for ADC channel and fifo * almost empty interrupt for DAC channel. Morevoer for interrupt mode, user * should use sprd_mcdt_chan_read() or sprd_mcdt_chan_write() to read or write * data manually. * * For ADC channel, user can start to read data once receiving one fifo full * interrupt. For DAC channel, user can start to write data once receiving one * fifo empty interrupt or just call sprd_mcdt_chan_write() to write data * directly. * * Returns 0 on success, or an error code on failure.
*/ int sprd_mcdt_chan_int_enable(struct sprd_mcdt_chan *chan, u32 water_mark, struct sprd_mcdt_chan_callback *cb)
{ struct sprd_mcdt_dev *mcdt = chan->mcdt; unsignedlong flags; int ret = 0;
spin_lock_irqsave(&mcdt->lock, flags);
if (chan->dma_enable || chan->int_enable) {
dev_err(mcdt->dev, "Failed to set interrupt mode.\n");
spin_unlock_irqrestore(&mcdt->lock, flags); return -EINVAL;
}
/** * sprd_mcdt_chan_dma_enable - enable the DMA mode for the MCDT channel * @chan: the MCDT channel * @dma_chan: specify which DMA channel will be used for this MCDT channel * @water_mark: water mark to trigger a DMA request * * Enable the DMA mode for the MCDT channel, that means we can use DMA to * transfer data to the channel fifo and do not need reading/writing data * manually. * * Returns 0 on success, or an error code on failure.
*/ int sprd_mcdt_chan_dma_enable(struct sprd_mcdt_chan *chan, enum sprd_mcdt_dma_chan dma_chan,
u32 water_mark)
{ struct sprd_mcdt_dev *mcdt = chan->mcdt; unsignedlong flags; int ret = 0;
spin_lock_irqsave(&mcdt->lock, flags);
if (chan->dma_enable || chan->int_enable ||
dma_chan > SPRD_MCDT_DMA_CH4) {
dev_err(mcdt->dev, "Failed to set DMA mode\n");
spin_unlock_irqrestore(&mcdt->lock, flags); return -EINVAL;
}
/** * sprd_mcdt_request_chan - request one MCDT channel * @channel: channel id * @type: channel type, it can be one ADC channel or DAC channel * * Rreturn NULL if no available channel.
*/ struct sprd_mcdt_chan *sprd_mcdt_request_chan(u8 channel, enum sprd_mcdt_channel_type type)
{ struct sprd_mcdt_chan *temp;
mutex_lock(&sprd_mcdt_list_mutex);
list_for_each_entry(temp, &sprd_mcdt_chan_list, list) { if (temp->type == type && temp->id == channel) {
list_del_init(&temp->list); break;
}
}
if (list_entry_is_head(temp, &sprd_mcdt_chan_list, list))
temp = NULL;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.