case THC_TXDMA:
regmap_write_bits(dev->thc_regmap, THC_M_PRT_WRITE_INT_STS_OFFSET,
THC_M_PRT_WRITE_INT_STS_THC_WRDMA_CMPL_STATUS,
THC_M_PRT_WRITE_INT_STS_THC_WRDMA_CMPL_STATUS);
/* Select interrupt or polling method upon Write completion */ if (dev->dma_ctx->use_write_interrupts)
data = THC_M_PRT_WRITE_DMA_CNTRL_THC_WRDMA_IE_IOC_DMACPL; else
data = 0;
/** * thc_dma_set_max_packet_sizes - Set max packet sizes for all DMA engines * * @dev: The pointer of THC private device context * @mps_read1: RxDMA1 max packet size * @mps_read2: RxDMA2 max packet size * @mps_write: TxDMA max packet size * @mps_swdma: Software DMA max packet size * * If mps is not 0, it means the corresponding DMA channel is used, then set * the flag to turn on this channel. * * Return: 0 on success, other error codes on failed.
*/ int thc_dma_set_max_packet_sizes(struct thc_device *dev, size_t mps_read1,
size_t mps_read2, size_t mps_write,
size_t mps_swdma)
{ if (!dev->dma_ctx) {
dev_err_once(dev->dev, "Cannot set max packet sizes because DMA context is NULL!\n"); return -EINVAL;
}
/** * thc_dma_allocate - Allocate DMA buffers for all DMA engines * * @dev: The pointer of THC private device context * * Return: 0 on success, other error codes on failed.
*/ int thc_dma_allocate(struct thc_device *dev)
{ int ret, chan;
for (chan = 0; chan < MAX_THC_DMA_CHANNEL; chan++) {
ret = setup_dma_buffers(dev, &dev->dma_ctx->dma_config[chan],
dev->dma_ctx->dma_config[chan].dir); if (ret < 0) {
dev_err_once(dev->dev, "DMA setup failed for DMA channel %d\n", chan); goto release_bufs;
}
}
return 0;
release_bufs: while (chan--)
release_dma_buffers(dev, &dev->dma_ctx->dma_config[chan]);
for (j = 0; j < PRD_ENTRIES_NUM; j++) {
mes_len += prd_tbl->entries[j].len; if (prd_tbl->entries[j].end_of_prd) break;
}
*nent = j + 1;
return mes_len;
}
/** * thc_dma_configure - Configure DMA settings for all DMA engines * * @dev: The pointer of THC private device context * * Return: 0 on success, other error codes on failed.
*/ int thc_dma_configure(struct thc_device *dev)
{ struct thc_dma_context *dma_ctx = dev->dma_ctx; int chan;
thc_reset_dma_settings(dev);
if (!dma_ctx) {
dev_err_once(dev->dev, "Cannot do DMA configure because DMA context is NULL\n"); return -EINVAL;
}
/* Clear the relevant PRD table */
thc_copy_one_sgl_to_prd(dev, read_config, prd_table_index);
/* Increment the write pointer to let the HW know we have processed this PRD */
update_write_pointer(dev, read_config);
}
/* * This function only reads one frame from PRD table for each call, so we need to * check if all DMAed data is read out and return the flag to the caller. Caller * should repeatedly call thc_dma_read() until all DMAed data is handled.
*/ if (read_finished)
*read_finished = is_dma_buf_empty(dev, read_config, &read_ptr, &write_ptr) ? 1 : 0;
return 0;
}
/** * thc_rxdma_read - Read data from RXDMA buffer * * @dev: The pointer of THC private device context * @dma_channel: The RXDMA engine of read data source * @read_buff: The pointer of the read data buffer * @read_len: The pointer of the read data length * @read_finished: The pointer of the flag indicating if all pending data has been read out * * Return: 0 on success, other error codes on failed.
*/ int thc_rxdma_read(struct thc_device *dev, enum thc_dma_channel dma_channel, void *read_buff, size_t *read_len, int *read_finished)
{ struct thc_dma_configuration *dma_config; int ret;
ret = thc_interrupt_quiesce(dev, true); if (ret) return ret;
if (thc_wait_for_dma_pause(dev, THC_RXDMA1) || thc_wait_for_dma_pause(dev, THC_RXDMA2)) return -EIO;
thc_reset_dma_settings(dev);
/* * Max input size control feature is only available for RxDMA, it must keep disabled * during SWDMA operation, and restore to previous state after SWDMA is done. * Max input size variables in THC device context track hardware state, and keep change * when feature state was changed, so those variables cannot be used to record feature * state after state was changed during SWDMA operation. Here have to use a temp variable * in DMA context to record feature state before SWDMA operation.
*/ if (dev->i2c_max_rx_size_en) {
thc_i2c_rx_max_size_enable(dev, false);
dev->dma_ctx->rx_max_size_en = true;
}
/* * Interrupt delay feature is in the same situation with max input size control feature, * needs record feature state before SWDMA.
*/ if (dev->i2c_int_delay_en) {
thc_i2c_rx_int_delay_enable(dev, false);
dev->dma_ctx->rx_int_delay_en = true;
}
staticint thc_swdma_read_completion(struct thc_device *dev)
{ int ret;
ret = thc_wait_for_dma_pause(dev, THC_SWDMA); if (ret) return ret;
/* * Restore max input size control feature to previous state after SWDMA if it was * enabled before SWDMA, and reset temp rx_max_size_en variable for next time.
*/ if (dev->dma_ctx->rx_max_size_en) {
thc_i2c_rx_max_size_enable(dev, true);
dev->dma_ctx->rx_max_size_en = false;
}
/* * Restore input interrupt delay feature to previous state after SWDMA if it was * enabled before SWDMA, and reset temp rx_int_delay_en variable for next time.
*/ if (dev->dma_ctx->rx_int_delay_en) {
thc_i2c_rx_int_delay_enable(dev, true);
dev->dma_ctx->rx_int_delay_en = false;
}
/** * thc_swdma_read - Use software DMA to read data from touch device * * @dev: The pointer of THC private device context * @write_buff: The pointer of write buffer for SWDMA sequence * @write_len: The write data length for SWDMA sequence * @prd_tbl_len: The prd table length of SWDMA engine, can be set to NULL * @read_buff: The pointer of the read data buffer * @read_len: The pointer of the read data length * * Return: 0 on success, other error codes on failed.
*/ int thc_swdma_read(struct thc_device *dev, void *write_buff, size_t write_len,
u32 *prd_tbl_len, void *read_buff, size_t *read_len)
{ int ret;
if (!(&dev->dma_ctx->dma_config[THC_SWDMA])->is_enabled) {
dev_err_once(dev->dev, "The SWDMA channel is not enabled"); return -EINVAL;
}
staticvoid thc_ensure_performance_limitations(struct thc_device *dev)
{ unsignedlong delay_usec = 0; /* * Minimum amount of delay the THC / QUICKSPI driver must wait * between end of write operation and begin of read operation. * This value shall be in 10us multiples.
*/ if (dev->perf_limit > 0) {
delay_usec = dev->perf_limit * 10;
udelay(delay_usec);
}
}
/** * thc_dma_write - Use TXDMA to write data to touch device * * @dev: The pointer of THC private device context * @buffer: The pointer of write data buffer * @buf_len: The write data length * * Return: 0 on success, other error codes on failed.
*/ int thc_dma_write(struct thc_device *dev, void *buffer, size_t buf_len)
{ bool restore_interrupts = false;
u32 sts, ctrl; int ret;
if (!(&dev->dma_ctx->dma_config[THC_TXDMA])->is_enabled) {
dev_err_once(dev->dev, "The TxDMA channel is not enabled\n"); return -EINVAL;
}
regmap_read(dev->thc_regmap, THC_M_PRT_WRITE_INT_STS_OFFSET, &sts); if (sts & THC_M_PRT_WRITE_INT_STS_THC_WRDMA_ACTIVE) {
dev_err_once(dev->dev, "THC TxDMA is till active and can't start again\n"); return -EBUSY;
}
if (mutex_lock_interruptible(&dev->thc_bus_lock)) return -EINTR;
¤ 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.0.13Bemerkung:
(vorverarbeitet)
¤
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.