[alsa-devel] [PATCHv2.1-CA0132 HDA Codec 2/2] Add DSP loader code to CA0132 codec
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
diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c index 825f5b4..45dce9c 100644 --- a/sound/pci/hda/patch_ca0132.c +++ b/sound/pci/hda/patch_ca0132.c @@ -1952,22 +1952,13 @@ struct dma_engine { unsigned short m_converter_format; void *m_buffer_addr; unsigned int m_buffer_size; - unsigned int m_req_size; - struct snd_pcm_substream *substream; };
enum dma_state { - DMA_STATE_RESET = 0, - DMA_STATE_STOP = 1, - DMA_STATE_RUN = 2 + DMA_STATE_STOP = 0, + DMA_STATE_RUN = 1 };
-#define azx_pcm_open(a) (a->ops->open(a)) -#define azx_pcm_close(a) (a->ops->close(a)) -#define azx_pcm_prepare(a) (a->ops->prepare(a)) -#define azx_pcm_trigger(a, b) (a->ops->trigger(a, b)) -#define azx_pcm_hw_free(a) (a->ops->hw_free(a)) - static int dma_convert_to_hda_format( struct hda_stream_format *stream_format, unsigned short *hda_format) @@ -1986,113 +1977,6 @@ static int dma_convert_to_hda_format( return 0; }
-static int dma_init( - struct hda_codec *codec, - struct dma_engine **pp_dma, - struct hda_stream_format *stream_format, - unsigned short *format, - unsigned int req_size) -{ - struct dma_engine *dma; - struct snd_pcm_substream *substream; - struct snd_pcm *pcm; - struct snd_pcm_runtime *runtime; - unsigned int bits; - snd_pcm_uframes_t frames; - - *pp_dma = NULL; - dma = kzalloc(sizeof(*dma), GFP_KERNEL); - memset((void *)dma, 0, sizeof(*dma)); - - dma_convert_to_hda_format(stream_format, format); - dma->m_converter_format = *format; - - dma->substream = NULL; - pcm = codec->pcm_info->pcm; - for (substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; - substream; substream = substream->next) { - if (codec->pcm_info->pcm_type == HDA_PCM_TYPE_SPDIF) - continue; - - if (!SUBSTREAM_BUSY(substream)) { - dma->substream = substream; - break; - } - } - - if (NULL == dma->substream) { - kfree(dma); - return -1; - } - - runtime = kzalloc(sizeof(*runtime), GFP_KERNEL); - memset((void *)runtime, 0, sizeof(*runtime)); - dma->substream->runtime = runtime; - dma->substream->private_data = pcm->private_data; - - azx_pcm_open(dma->substream); - req_size = req_size * 2; - snd_pcm_lib_malloc_pages(dma->substream, req_size); - - runtime->rate = stream_format->sample_rate; - runtime->channels = stream_format->number_channels; - runtime->format = SNDRV_PCM_FORMAT_S32_LE; - runtime->no_period_wakeup = 1; - - bits = snd_pcm_format_physical_width(runtime->format); - runtime->sample_bits = bits; - bits *= runtime->channels; - runtime->frame_bits = bits; - frames = 1; - while (bits % 8 != 0) { - bits *= 2; - frames *= 2; - } - runtime->byte_align = bits / 8; - runtime->min_align = frames; - runtime->buffer_size = bytes_to_frames(runtime, req_size); - runtime->period_size = runtime->buffer_size; - dma->m_req_size = req_size; - dma->codec = codec; - - *pp_dma = dma; - CA0132_LOG("dma_init: succeeded.\n"); - return 0; -} - -static int dma_prepare(struct dma_engine *dma) -{ - struct snd_pcm_runtime *runtime; - int err; - - CA0132_LOG("dma_prepare: begin\n"); - runtime = dma->substream->runtime; - - err = azx_pcm_prepare(dma->substream); - if (err < 0) - return -1; - - dma->m_buffer_size = snd_pcm_lib_buffer_bytes(dma->substream); - dma->m_buffer_addr = runtime->dma_area; - - return 0; -} - -static int dma_reset(struct dma_engine *dma) -{ - struct snd_pcm_runtime *runtime = dma->substream->runtime; - - CA0132_LOG("dma_reset: begin\n"); - azx_pcm_hw_free(dma->substream); - snd_pcm_lib_malloc_pages(dma->substream, dma->m_req_size); - - azx_pcm_prepare(dma->substream); - dma->m_buffer_size = snd_pcm_lib_buffer_bytes(dma->substream); - dma->m_buffer_addr = runtime->dma_area; - - return 0; -} - static int dma_set_state(struct dma_engine *dma, enum dma_state state) { int cmd; @@ -2100,9 +1984,6 @@ static int dma_set_state(struct dma_engine *dma, enum dma_state state) CA0132_LOG("dma_set_state state=%d\n", state);
switch (state) { - case DMA_STATE_RESET: - dma_reset(dma); - return 0; case DMA_STATE_STOP: cmd = SNDRV_PCM_TRIGGER_STOP; break; @@ -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); }
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; -} - static int dma_xfer(struct dma_engine *dma, const unsigned int *data, unsigned int count) @@ -2160,13 +2030,6 @@ static unsigned int dma_get_stream_id(struct dma_engine *dma) return spec->dsp_stream_id; }
-static int dma_exit(struct dma_engine *dma) -{ - CA0132_LOG("dma_exit\n"); - kfree(dma); - return 0; -} - /* * CA0132 chip DSP image segment stuffs */ @@ -2384,7 +2247,6 @@ static int dspxfr_one_seg(struct hda_codec *codec, } CA0132_DSP_LOG("+++++ DMA complete"); dma_set_state(dma_engine, DMA_STATE_STOP); - dma_set_state(dma_engine, DMA_STATE_RESET); }
CTASSERT(run_size_words <= words_to_write); @@ -2413,17 +2275,29 @@ static int dspxfr_image(struct hda_codec *codec, struct dma_engine *dma_engine; unsigned int dma_chan; unsigned int port_map_mask; - unsigned int buf_size;
CTASSERT(fls_data != NULL); if (fls_data == NULL) return -1;
- buf_size = ovly ? DSP_DMA_WRITE_BUFLEN_OVLY : DSP_DMA_WRITE_BUFLEN_INIT; - status = dma_init(codec, &dma_engine, format, &hda_format, buf_size); - - if (FAILED(status)) - return -1; + dma_engine = kzalloc(sizeof(*dma_engine), GFP_KERNEL); + if (!dma_engine) { + status = -ENOMEM; + goto exit; + } + memset((void*)dma_engine, 0, sizeof(*dma_engine)); + + 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); + if (!dma_engine->m_buffer_addr) { + status = -ENOMEM; + goto exit; + }
dma_chan = 0; do { @@ -2434,7 +2308,10 @@ static int dspxfr_image(struct hda_codec *codec, break; }
- status = dma_prepare(dma_engine); + status = load_dsp_prepare(codec->bus, + dma_engine->m_converter_format, + dma_engine->m_buffer_addr, + dma_engine->m_buffer_size); if (FAILED(status)) break;
@@ -2495,15 +2372,9 @@ static int dspxfr_image(struct hda_codec *codec, if (ovly && (dma_chan != INVALID_DMA_CHANNEL)) status = dspio_free_dma_chan(codec, dma_chan);
- status = dma_set_state(dma_engine, DMA_STATE_RESET); - if (FAILED(status)) - status = FAIL_MSG(status, "dma set state Reset fail"); - - status = dma_free_buffer(dma_engine); - if (FAILED(status)) - status = FAIL_MSG(status, "dma free buffer fail"); - - dma_exit(dma_engine); +exit: + kfree(dma_engine->m_buffer_addr); + kfree(dma_engine);
return status; }
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
So the point is to concentrate only on DMA transfer stuff at first. Once after confirmed it's working, continue to the new DSP features.,
Ok, that makes sense.
A remaining question is:
- what is the condition to operate DSP transfer? Must all PCM streams
be closed and streams are released?
Yes, all PCM streams need to be closed and released for the DSP transfer. Since the driver loads the DSP during the init phase, there shouldn't be any active streams at that time.
- Ian
Notice The information in this message is confidential and may be legally privileged. It is intended solely for the addressee. Access to this message by anyone else is unauthorized. If you are not the intended recipient, any disclosure, copying or distribution of the message, or any action taken by you in reliance on it, is prohibited and may be unlawful. This email is for communication purposes only. It is not intended to constitute an offer or form a binding agreement. Our company accepts no liability for the content of this email, or for the consequences of any actions taken on the basis of the information provided. If you have received this message in error, please delete it and contact the sender immediately. Thank you.
Takashi Iwai tiwai@suse.de To 08/11/2012 12:12 AM Ian Minett ian_minett@creativelabs.com cc alsa-devel@alsa-project.org Subject Re: [PATCHv2.1-CA0132 HDA Codec 2/2] Add DSP loader code to CA0132 codec
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
ForwardSourceID:NT0001D94A
From: Ian Minett ian_minett@creativelabs.com
Thanks for the recent feedback - based on that we've updated the recent draft patch for adding the DSP loader to patch_ca0132.c :
- move DMA buffer management out (to be handled in hda_intel) - add call to cleanup DMA - change start/stop flag to boolean
If the changes look acceptable, do we have enough for us to get started on adding the DSP loader updates to patch_ca0132 (working with the 'from scratch' CA0132 as you suggested)?
Please let us know if you can think of anything else that needs to be worked out, or anything we need to provide for the bus op mods.
Thanks very much, Ian
Signed-off-by: Ian Minett ian_minett@creativelabs.com
diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c index 45dce9c..0d07445 100644 --- a/sound/pci/hda/patch_ca0132.c +++ b/sound/pci/hda/patch_ca0132.c @@ -1979,22 +1979,22 @@ static int dma_convert_to_hda_format(
static int dma_set_state(struct dma_engine *dma, enum dma_state state) { - int cmd; + bool cmd;
CA0132_LOG("dma_set_state state=%d\n", state);
switch (state) { case DMA_STATE_STOP: - cmd = SNDRV_PCM_TRIGGER_STOP; + cmd = false; break; case DMA_STATE_RUN: - cmd = SNDRV_PCM_TRIGGER_START; + cmd = true; break; default: return 0; }
- return load_dsp_trigger(dma->codec->bus, cmd); + return snd_hda_codec_load_dsp_trigger(dma->codec, cmd); }
static unsigned int dma_get_buffer_size(struct dma_engine *dma) @@ -2281,10 +2281,8 @@ static int dspxfr_image(struct hda_codec *codec, return -1;
dma_engine = kzalloc(sizeof(*dma_engine), GFP_KERNEL); - if (!dma_engine) { - status = -ENOMEM; - goto exit; - } + if (!dma_engine) + return -ENOMEM; memset((void*)dma_engine, 0, sizeof(*dma_engine)); dma_engine->codec = codec; @@ -2292,12 +2290,6 @@ static int dspxfr_image(struct hda_codec *codec, 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); - if (!dma_engine->m_buffer_addr) { - status = -ENOMEM; - goto exit; - }
dma_chan = 0; do { @@ -2308,11 +2300,11 @@ static int dspxfr_image(struct hda_codec *codec, break; }
- status = load_dsp_prepare(codec->bus, - dma_engine->m_converter_format, - dma_engine->m_buffer_addr, - dma_engine->m_buffer_size); - if (FAILED(status)) + dma_engine->m_buffer_addr = + snd_hda_codec_load_dsp_prepare(codec, + dma_engine->m_converter_format, + dma_engine->m_buffer_size); + if (!dma_engine->m_buffer_addr) break;
if (ovly) { @@ -2372,8 +2364,9 @@ static int dspxfr_image(struct hda_codec *codec, if (ovly && (dma_chan != INVALID_DMA_CHANNEL)) status = dspio_free_dma_chan(codec, dma_chan);
-exit: - kfree(dma_engine->m_buffer_addr); + snd_hda_codec_load_dsp_cleanup(codec, + dma_engine->m_buffer_addr, + dma_engine->m_buffer_size); kfree(dma_engine);
return status;
At Tue, 14 Aug 2012 22:50:06 -0700, Ian Minett wrote:
From: Ian Minett ian_minett@creativelabs.com
Thanks for the recent feedback - based on that we've updated the recent draft patch for adding the DSP loader to patch_ca0132.c :
- move DMA buffer management out (to be handled in hda_intel)
- add call to cleanup DMA
- change start/stop flag to boolean
If the changes look acceptable, do we have enough for us to get started on adding the DSP loader updates to patch_ca0132 (working with the 'from scratch' CA0132 as you suggested)?
Please let us know if you can think of anything else that needs to be worked out, or anything we need to provide for the bus op mods.
Any missing thing will be revealed later once when you start coding the DSP loader part in hda_intel.c :)
So now, as I suggested, start writing a code just loading the firmware DSP code based on the _bare_ upstream tree. That is, don't base on the already modified patch_ca0132.c or hda_intel.c. Write a patch that can be applied on the top of the current Linus tree, for example.
There shouldn't be any addition of controls, etc, at this point. Just do load the firmware. This is the very first start.
I can help debugging or give review / advise. But obviously you are at the better position start writing it since you have the test hardware and the firmware data, both of which are missing for other developers (including me).
Once when a draft patch is ready or you face to a problem, let me know.
thanks,
Takashi
Thanks very much, Ian
Signed-off-by: Ian Minett ian_minett@creativelabs.com
diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c index 45dce9c..0d07445 100644 --- a/sound/pci/hda/patch_ca0132.c +++ b/sound/pci/hda/patch_ca0132.c @@ -1979,22 +1979,22 @@ static int dma_convert_to_hda_format(
static int dma_set_state(struct dma_engine *dma, enum dma_state state) {
- int cmd;
bool cmd;
CA0132_LOG("dma_set_state state=%d\n", state);
switch (state) { case DMA_STATE_STOP:
cmd = SNDRV_PCM_TRIGGER_STOP;
break; case DMA_STATE_RUN:cmd = false;
cmd = SNDRV_PCM_TRIGGER_START;
break; default: return 0; }cmd = true;
- return load_dsp_trigger(dma->codec->bus, cmd);
- return snd_hda_codec_load_dsp_trigger(dma->codec, cmd);
}
static unsigned int dma_get_buffer_size(struct dma_engine *dma) @@ -2281,10 +2281,8 @@ static int dspxfr_image(struct hda_codec *codec, return -1;
dma_engine = kzalloc(sizeof(*dma_engine), GFP_KERNEL);
- if (!dma_engine) {
status = -ENOMEM;
goto exit;
- }
if (!dma_engine)
return -ENOMEM;
memset((void*)dma_engine, 0, sizeof(*dma_engine));
dma_engine->codec = codec;
@@ -2292,12 +2290,6 @@ static int dspxfr_image(struct hda_codec *codec, 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);
if (!dma_engine->m_buffer_addr) {
status = -ENOMEM;
goto exit;
}
dma_chan = 0; do {
@@ -2308,11 +2300,11 @@ static int dspxfr_image(struct hda_codec *codec, break; }
status = load_dsp_prepare(codec->bus,
dma_engine->m_converter_format,
dma_engine->m_buffer_addr,
dma_engine->m_buffer_size);
if (FAILED(status))
dma_engine->m_buffer_addr =
snd_hda_codec_load_dsp_prepare(codec,
dma_engine->m_converter_format,
dma_engine->m_buffer_size);
if (!dma_engine->m_buffer_addr) break;
if (ovly) {
@@ -2372,8 +2364,9 @@ static int dspxfr_image(struct hda_codec *codec, if (ovly && (dma_chan != INVALID_DMA_CHANNEL)) status = dspio_free_dma_chan(codec, dma_chan);
-exit:
- kfree(dma_engine->m_buffer_addr);
snd_hda_codec_load_dsp_cleanup(codec,
dma_engine->m_buffer_addr,
dma_engine->m_buffer_size);
kfree(dma_engine);
return status;
-- 1.7.4.1
There shouldn't be any addition of controls, etc, at this point. Just do load the firmware. This is the very first start.
I can help debugging or give review / advise. But obviously you are at the better position start writing it since you have the test hardware and the firmware data, both of which are missing for other developers (including me).
Once when a draft patch is ready or you face to a problem, let me know.
Ok, thanks. We do seem to be having problems in the DSP load prepare function:
void *(*load_dsp_prepare)(struct hda_codec *codec, unsigned int format, unsigned int byte_size);
This is the place where the buffer gets allocated, and BDL and DMA set up, and the pointer returned. Is there any sample code or other info you could provide, to give us a better idea of how the function and these actions should be implemented?
Thanks very much, - Ian
At Tue, 21 Aug 2012 18:36:01 -0700, Ian Minett wrote:
There shouldn't be any addition of controls, etc, at this point. Just do load the firmware. This is the very first start.
I can help debugging or give review / advise. But obviously you are at the better position start writing it since you have the test hardware and the firmware data, both of which are missing for other developers (including me).
Once when a draft patch is ready or you face to a problem, let me know.
Ok, thanks. We do seem to be having problems in the DSP load prepare function:
void *(*load_dsp_prepare)(struct hda_codec *codec, unsigned int format, unsigned int byte_size);
This is the place where the buffer gets allocated, and BDL and DMA set up, and the pointer returned. Is there any sample code or other info you could provide, to give us a better idea of how the function and these actions should be implemented?
Maybe better to start from a bit clean up of SG buffer handling code in general. The first patch below makes the sg-buffer helpers more generic so that they can be called even without sg-buffer support.
Then, setup_bdle() in hda_intel.c can be changed cleanly by passing struct snd_dma_buffer pointer, as found in the second patch.
The rest of the second patch is the additions of callbacks supposedly needed for your case.
load_dsp_prepare() callback takes parameters of the format value (encoded by snd_hda_calc_stream_format()), the byte size of the buffer to allocate, and a pointer to struct snd_dma_buffer. It'll return the stream tag in success, or a negative error code. The allocated buffer is stored in snd_dma_buffer.area pointer. It'll be an SG-buffer, but can be accessed linearly by that pointer.
Then, the caller should set up the codec by itself. Unlike PCM prepare, it doesn't set up the codec, as the DSP loading might need more special setups.
After setting up these and the buffer is filled, call load_dsp_trigger() callback. It's a simple start/stop of the controller.
Then call load_dsp_clean() callback. The buffer will be released there, too.
Takashi
participants (2)
-
Ian Minett
-
Takashi Iwai