@@ -28,6 +28,9 @@ snd_pcm_substream_to_dma_direction(const struct snd_pcm_substream *substream)
int snd_hwparams_to_dma_slave_config(const struct snd_pcm_substream *substream,
const struct snd_pcm_hw_params *params, struct dma_slave_config *slave_config);
int snd_dmaengine_pcm_trigger(struct snd_pcm_substream *substream, int cmd);
+int snd_dmaengine_pcm_custom_trigger(struct snd_pcm_substream *substream, int cmd,
+ int (*custom_pcm_prepare_and_submit)(struct snd_pcm_substream *substream));
+
snd_pcm_uframes_t snd_dmaengine_pcm_pointer(struct snd_pcm_substream *substream);
snd_pcm_uframes_t snd_dmaengine_pcm_pointer_no_residue(struct snd_pcm_substream *substream);
@@ -113,6 +116,8 @@ int snd_dmaengine_pcm_refine_runtime_hwparams(
* which do not use devicetree.
* @process: Callback used to apply processing on samples transferred from/to
* user space.
+ * @custom_pcm_prepare_and_submit: Callback used to work-around DMA limitations
+ * related to link lists.
* @compat_filter_fn: Will be used as the filter function when requesting a
* channel for platforms which do not use devicetree. The filter parameter
* will be the DAI's DMA data.
@@ -138,6 +143,7 @@ struct snd_dmaengine_pcm_config {
int (*process)(struct snd_pcm_substream *substream,
int channel, unsigned long hwoff,
void *buf, unsigned long bytes);
+ int (*custom_pcm_prepare_and_submit)(struct snd_pcm_substream *substream);
dma_filter_fn compat_filter_fn;
struct device *dma_dev;
const char *chan_names[SNDRV_PCM_STREAM_LAST + 1];
@@ -170,16 +170,20 @@ static int dmaengine_pcm_prepare_and_submit(struct snd_pcm_substream *substream)
}
/**
- * snd_dmaengine_pcm_trigger - dmaengine based PCM trigger implementation
+ * snd_dmaengine_pcm_custom_trigger - customized PCM trigger implementation to
+ * work-around DMA limitations related to link lists.
* @substream: PCM substream
* @cmd: Trigger command
+ * @custom_pcm_prepare_and_submit: custom function to deal with DMA limitations
*
* Returns 0 on success, a negative error code otherwise.
*
- * This function can be used as the PCM trigger callback for dmaengine based PCM
- * driver implementations.
+ * This function can be used as the PCM trigger callback for customized dmaengine
+ * based PCM driver implementations.
*/
-int snd_dmaengine_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
+
+int snd_dmaengine_pcm_custom_trigger(struct snd_pcm_substream *substream, int cmd,
+ int (*custom_pcm_prepare_and_submit)(struct snd_pcm_substream *substream))
{
struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream);
struct snd_pcm_runtime *runtime = substream->runtime;
@@ -187,7 +191,7 @@ int snd_dmaengine_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
- ret = dmaengine_pcm_prepare_and_submit(substream);
+ ret = custom_pcm_prepare_and_submit(substream);
if (ret)
return ret;
dma_async_issue_pending(prtd->dma_chan);
@@ -214,6 +218,22 @@ int snd_dmaengine_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
return 0;
}
+EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_custom_trigger);
+
+/**
+ * snd_dmaengine_pcm_trigger - dmaengine based PCM trigger implementation
+ * @substream: PCM substream
+ * @cmd: Trigger command
+ *
+ * Returns 0 on success, a negative error code otherwise.
+ *
+ * This function can be used as the PCM trigger callback for dmaengine based PCM
+ * driver implementations.
+ */
+int snd_dmaengine_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+ return snd_dmaengine_pcm_custom_trigger(substream, cmd, dmaengine_pcm_prepare_and_submit);
+}
EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_trigger);
/**
@@ -173,7 +173,13 @@ static int dmaengine_pcm_close(struct snd_soc_component *component,
static int dmaengine_pcm_trigger(struct snd_soc_component *component,
struct snd_pcm_substream *substream, int cmd)
{
- return snd_dmaengine_pcm_trigger(substream, cmd);
+ struct dmaengine_pcm *pcm = soc_component_to_pcm(component);
+
+ if (pcm->config && pcm->config->custom_pcm_prepare_and_submit)
+ return snd_dmaengine_pcm_custom_trigger(substream, cmd,
+ pcm->config->custom_pcm_prepare_and_submit);
+ else
+ return snd_dmaengine_pcm_trigger(substream, cmd);
}
static struct dma_chan *dmaengine_pcm_compat_request_channel(