At Fri, 10 Aug 2012 23:17:52 -0700, Ian Minett wrote:
From: Ian Minett ian_minett@creativelabs.com
Draft patch to add new DSP loader code, with calls to load_dsp_xxxx() functions.
Signed-off-by: Ian Minett ian_minett@creativelabs.com
(snip)
@@ -2113,9 +1994,7 @@ static int dma_set_state(struct dma_engine *dma, enum dma_state state) return 0; }
- azx_pcm_trigger(dma->substream, cmd);
- return 0;
- return load_dsp_trigger(dma->codec->bus, cmd);
Maybe we just need to pass a boolean to start/stop.
static unsigned int dma_get_buffer_size(struct dma_engine *dma) @@ -2128,15 +2007,6 @@ static unsigned int *dma_get_buffer_addr(struct dma_engine *dma) return dma->m_buffer_addr; }
-static int dma_free_buffer(struct dma_engine *dma) -{
- azx_pcm_hw_free(dma->substream);
- azx_pcm_close(dma->substream);
- kfree(dma->substream->runtime);
- dma->substream->runtime = NULL;
- return 0;
OK, I forgot that a cleanup callback is also required...
- dma_engine->codec = codec;
- dma_convert_to_hda_format(format, &hda_format);
- dma_engine->m_converter_format = hda_format;
- dma_engine->m_buffer_size =
ovly ? DSP_DMA_WRITE_BUFLEN_OVLY : DSP_DMA_WRITE_BUFLEN_INIT;
- dma_engine->m_buffer_addr = kzalloc(dma_engine->m_buffer_size,
GFP_KERNEL);
Allocating the DMA transfer buffer via kmalloc doesn't work. The buffer must be aligned and coherent. Thus it's better to let the buffer management in hda_intel.c.
In the end, what we need in hda_intel.c are: - a function to allocate buffer, setup BDL and DMA, return the pointer - a function to start/stop transfer - a function to clean up DMA, release the buffer
Thus the hda_bus_ops will gain the following ops:
/* bus operators */ struct hda_bus_ops { ... #ifdef CONFIG_SND_HDA_LOAD_DSP /* prepare DSP transfer */ void *(*load_dsp_prepare)(struct hda_codec *codec, unsigned int format, unsigned int byte_size); /* start/stop DSP transfer */ void (*load_dsp_trigger)(struct hda_codec *codec, bool start); /* clean up DSP transfer */ void (*load_dsp_cleanup)(struct hda_codec *codec, void *buf, unsigned int byte_size); #endif };
Then define the function like
static inline void * snd_hda_codec_load_dsp_prepare(struct hda_codec *codec, unsigned int format, unsigned int size) { return codec->bus->ops.load_dsp_prepare(codec, format, size); }
and so on.
A remaining question is: - what is the condition to operate DSP transfer? Must all PCM streams be closed and streams are released?
Takashi