summaryrefslogtreecommitdiffstats
path: root/sound/soc/intel/atom
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2018-04-02 19:51:39 +0200
committerTakashi Iwai <tiwai@suse.de>2018-04-02 19:51:39 +0200
commit903d271a3f83826ef810a4b5dbbd9842cf0465d6 (patch)
tree07fd60b1d7ad07ba36c82b2e83ece7c7eb6e6ce9 /sound/soc/intel/atom
parentbc334cb61b9ee6e85b9bb01519989a3ae8fe03f6 (diff)
parent445bb423f6a3c50788529a33b82e45148001e855 (diff)
downloadtalos-op-linux-903d271a3f83826ef810a4b5dbbd9842cf0465d6.tar.gz
talos-op-linux-903d271a3f83826ef810a4b5dbbd9842cf0465d6.zip
Merge tag 'asoc-v4.17' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into for-linus
ASoC: Updates for v4.17 This is a *very* big release for ASoC. Not much change in the core but there s the transition of all the individual drivers over to components which is intended to support further core work. The goal is to make it easier to do further core work by removing the need to special case all the different driver classes in the core, many of the devices end up being used in multiple roles in modern systems. We also have quite a lot of new drivers added this month of all kinds, quite a few for simple devices but also some more advanced ones with more substantial code. - The biggest thing is the huge series from Morimoto-san which converted everything over to components. This is a huge change by code volume but was fairly mechanical - Many fixes for some of the Realtek based Baytrail systems covering both the CODECs and the CPUs, contributed by Hans de Goode. - Lots of cleanups for Samsung based Odroid systems from Sylwester Nawrocki. - The Freescale SSI driver also got a lot of cleanups from Nicolin Chen. - The Blackfin drivers have been removed as part of the removal of the architecture. - New drivers for AKM AK4458 and AK5558, several AMD based machines, several Intel based machines, Maxim MAX9759, Motorola CPCAP, Socionext Uniphier SoCs, and TI PCM1789 and TDA7419
Diffstat (limited to 'sound/soc/intel/atom')
-rw-r--r--sound/soc/intel/atom/sst-atom-controls.c36
-rw-r--r--sound/soc/intel/atom/sst-mfld-platform-compress.c4
-rw-r--r--sound/soc/intel/atom/sst-mfld-platform-pcm.c32
-rw-r--r--sound/soc/intel/atom/sst-mfld-platform.h4
-rw-r--r--sound/soc/intel/atom/sst/sst.c24
-rw-r--r--sound/soc/intel/atom/sst/sst.h20
-rw-r--r--sound/soc/intel/atom/sst/sst_acpi.c3
-rw-r--r--sound/soc/intel/atom/sst/sst_drv_interface.c19
-rw-r--r--sound/soc/intel/atom/sst/sst_pvt.c8
-rw-r--r--sound/soc/intel/atom/sst/sst_stream.c117
10 files changed, 143 insertions, 124 deletions
diff --git a/sound/soc/intel/atom/sst-atom-controls.c b/sound/soc/intel/atom/sst-atom-controls.c
index 0f3604b55942..3672d36b4b66 100644
--- a/sound/soc/intel/atom/sst-atom-controls.c
+++ b/sound/soc/intel/atom/sst-atom-controls.c
@@ -1414,11 +1414,11 @@ static int sst_fill_module_list(struct snd_kcontrol *kctl,
* name. First part of control name contains the pipe name (widget name).
*/
static int sst_fill_widget_module_info(struct snd_soc_dapm_widget *w,
- struct snd_soc_platform *platform)
+ struct snd_soc_component *component)
{
struct snd_kcontrol *kctl;
int index, ret = 0;
- struct snd_card *card = platform->component.card->snd_card;
+ struct snd_card *card = component->card->snd_card;
char *idx;
down_read(&card->controls_rwsem);
@@ -1468,13 +1468,13 @@ static int sst_fill_widget_module_info(struct snd_soc_dapm_widget *w,
/**
* sst_fill_linked_widgets - fill the parent pointer for the linked widget
*/
-static void sst_fill_linked_widgets(struct snd_soc_platform *platform,
+static void sst_fill_linked_widgets(struct snd_soc_component *component,
struct sst_ids *ids)
{
struct snd_soc_dapm_widget *w;
unsigned int len = strlen(ids->parent_wname);
- list_for_each_entry(w, &platform->component.card->widgets, list) {
+ list_for_each_entry(w, &component->card->widgets, list) {
if (!strncmp(ids->parent_wname, w->name, len)) {
ids->parent_w = w;
break;
@@ -1485,41 +1485,41 @@ static void sst_fill_linked_widgets(struct snd_soc_platform *platform,
/**
* sst_map_modules_to_pipe - fill algo/gains list for all pipes
*/
-static int sst_map_modules_to_pipe(struct snd_soc_platform *platform)
+static int sst_map_modules_to_pipe(struct snd_soc_component *component)
{
struct snd_soc_dapm_widget *w;
int ret = 0;
- list_for_each_entry(w, &platform->component.card->widgets, list) {
+ list_for_each_entry(w, &component->card->widgets, list) {
if (is_sst_dapm_widget(w) && (w->priv)) {
struct sst_ids *ids = w->priv;
- dev_dbg(platform->dev, "widget type=%d name=%s\n",
+ dev_dbg(component->dev, "widget type=%d name=%s\n",
w->id, w->name);
INIT_LIST_HEAD(&ids->algo_list);
INIT_LIST_HEAD(&ids->gain_list);
- ret = sst_fill_widget_module_info(w, platform);
+ ret = sst_fill_widget_module_info(w, component);
if (ret < 0)
return ret;
/* fill linked widgets */
if (ids->parent_wname != NULL)
- sst_fill_linked_widgets(platform, ids);
+ sst_fill_linked_widgets(component, ids);
}
}
return 0;
}
-int sst_dsp_init_v2_dpcm(struct snd_soc_platform *platform)
+int sst_dsp_init_v2_dpcm(struct snd_soc_component *component)
{
int i, ret = 0;
struct snd_soc_dapm_context *dapm =
- snd_soc_component_get_dapm(&platform->component);
- struct sst_data *drv = snd_soc_platform_get_drvdata(platform);
+ snd_soc_component_get_dapm(component);
+ struct sst_data *drv = snd_soc_component_get_drvdata(component);
unsigned int gains = ARRAY_SIZE(sst_gain_controls)/3;
- drv->byte_stream = devm_kzalloc(platform->dev,
+ drv->byte_stream = devm_kzalloc(component->dev,
SST_MAX_BIN_BYTES, GFP_KERNEL);
if (!drv->byte_stream)
return -ENOMEM;
@@ -1537,26 +1537,26 @@ int sst_dsp_init_v2_dpcm(struct snd_soc_platform *platform)
sst_gains[i].ramp_duration = SST_GAIN_RAMP_DURATION_DEFAULT;
}
- ret = snd_soc_add_platform_controls(platform, sst_gain_controls,
+ ret = snd_soc_add_component_controls(component, sst_gain_controls,
ARRAY_SIZE(sst_gain_controls));
if (ret)
return ret;
/* Initialize algo control params */
- ret = sst_algo_control_init(platform->dev);
+ ret = sst_algo_control_init(component->dev);
if (ret)
return ret;
- ret = snd_soc_add_platform_controls(platform, sst_algo_controls,
+ ret = snd_soc_add_component_controls(component, sst_algo_controls,
ARRAY_SIZE(sst_algo_controls));
if (ret)
return ret;
- ret = snd_soc_add_platform_controls(platform, sst_slot_controls,
+ ret = snd_soc_add_component_controls(component, sst_slot_controls,
ARRAY_SIZE(sst_slot_controls));
if (ret)
return ret;
- ret = sst_map_modules_to_pipe(platform);
+ ret = sst_map_modules_to_pipe(component);
return ret;
}
diff --git a/sound/soc/intel/atom/sst-mfld-platform-compress.c b/sound/soc/intel/atom/sst-mfld-platform-compress.c
index 1dbcab5a6ff0..6a44b19423cf 100644
--- a/sound/soc/intel/atom/sst-mfld-platform-compress.c
+++ b/sound/soc/intel/atom/sst-mfld-platform-compress.c
@@ -107,8 +107,8 @@ static int sst_platform_compr_set_params(struct snd_compr_stream *cstream,
struct snd_sst_params str_params;
struct sst_compress_cb cb;
struct snd_soc_pcm_runtime *rtd = cstream->private_data;
- struct snd_soc_platform *platform = rtd->platform;
- struct sst_data *ctx = snd_soc_platform_get_drvdata(platform);
+ struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
+ struct sst_data *ctx = snd_soc_component_get_drvdata(component);
stream = cstream->runtime->private_data;
/* construct fw structure for this*/
diff --git a/sound/soc/intel/atom/sst-mfld-platform-pcm.c b/sound/soc/intel/atom/sst-mfld-platform-pcm.c
index 43e7fdd19f29..6c36da560877 100644
--- a/sound/soc/intel/atom/sst-mfld-platform-pcm.c
+++ b/sound/soc/intel/atom/sst-mfld-platform-pcm.c
@@ -697,26 +697,22 @@ static int sst_pcm_new(struct snd_soc_pcm_runtime *rtd)
return retval;
}
-static int sst_soc_probe(struct snd_soc_platform *platform)
+static int sst_soc_probe(struct snd_soc_component *component)
{
- struct sst_data *drv = dev_get_drvdata(platform->dev);
+ struct sst_data *drv = dev_get_drvdata(component->dev);
- drv->soc_card = platform->component.card;
- return sst_dsp_init_v2_dpcm(platform);
+ drv->soc_card = component->card;
+ return sst_dsp_init_v2_dpcm(component);
}
-static const struct snd_soc_platform_driver sst_soc_platform_drv = {
+static const struct snd_soc_component_driver sst_soc_platform_drv = {
+ .name = DRV_NAME,
.probe = sst_soc_probe,
.ops = &sst_platform_ops,
.compr_ops = &sst_platform_compr_ops,
.pcm_new = sst_pcm_new,
};
-static const struct snd_soc_component_driver sst_component = {
- .name = "sst",
-};
-
-
static int sst_platform_probe(struct platform_device *pdev)
{
struct sst_data *drv;
@@ -740,26 +736,16 @@ static int sst_platform_probe(struct platform_device *pdev)
mutex_init(&drv->lock);
dev_set_drvdata(&pdev->dev, drv);
- ret = snd_soc_register_platform(&pdev->dev, &sst_soc_platform_drv);
- if (ret) {
- dev_err(&pdev->dev, "registering soc platform failed\n");
- return ret;
- }
-
- ret = snd_soc_register_component(&pdev->dev, &sst_component,
+ ret = devm_snd_soc_register_component(&pdev->dev, &sst_soc_platform_drv,
sst_platform_dai, ARRAY_SIZE(sst_platform_dai));
- if (ret) {
+ if (ret)
dev_err(&pdev->dev, "registering cpu dais failed\n");
- snd_soc_unregister_platform(&pdev->dev);
- }
+
return ret;
}
static int sst_platform_remove(struct platform_device *pdev)
{
-
- snd_soc_unregister_component(&pdev->dev);
- snd_soc_unregister_platform(&pdev->dev);
dev_dbg(&pdev->dev, "sst_platform_remove success\n");
return 0;
}
diff --git a/sound/soc/intel/atom/sst-mfld-platform.h b/sound/soc/intel/atom/sst-mfld-platform.h
index 31a58c25472c..5f729df57bb5 100644
--- a/sound/soc/intel/atom/sst-mfld-platform.h
+++ b/sound/soc/intel/atom/sst-mfld-platform.h
@@ -27,6 +27,8 @@
extern struct sst_device *sst;
extern const struct snd_compr_ops sst_platform_compr_ops;
+#define DRV_NAME "sst"
+
#define SST_MONO 1
#define SST_STEREO 2
#define SST_MAX_CAP 5
@@ -155,7 +157,7 @@ struct sst_device {
struct sst_data;
-int sst_dsp_init_v2_dpcm(struct snd_soc_platform *platform);
+int sst_dsp_init_v2_dpcm(struct snd_soc_component *component);
int sst_send_pipe_gains(struct snd_soc_dai *dai, int stream, int mute);
int send_ssp_cmd(struct snd_soc_dai *dai, const char *id, bool enable);
int sst_handle_vb_timer(struct snd_soc_dai *dai, bool enable);
diff --git a/sound/soc/intel/atom/sst/sst.c b/sound/soc/intel/atom/sst/sst.c
index 8afdff457579..0962bc9adc62 100644
--- a/sound/soc/intel/atom/sst/sst.c
+++ b/sound/soc/intel/atom/sst/sst.c
@@ -449,6 +449,13 @@ static int intel_sst_suspend(struct device *dev)
dev_err(dev, "stream %d is running, can't suspend, abort\n", i);
return -EBUSY;
}
+
+ if (ctx->pdata->streams_lost_on_suspend) {
+ stream->resume_status = stream->status;
+ stream->resume_prev = stream->prev;
+ if (stream->status != STREAM_UN_INIT)
+ sst_free_stream(ctx, i);
+ }
}
synchronize_irq(ctx->irq_num);
flush_workqueue(ctx->post_msg_wq);
@@ -509,8 +516,8 @@ static int intel_sst_resume(struct device *dev)
{
struct intel_sst_drv *ctx = dev_get_drvdata(dev);
struct sst_fw_save *fw_save = ctx->fw_save;
- int ret = 0;
struct sst_block *block;
+ int i, ret = 0;
if (!fw_save)
return 0;
@@ -550,6 +557,21 @@ static int intel_sst_resume(struct device *dev)
sst_set_fw_state_locked(ctx, SST_FW_RUNNING);
}
+ if (ctx->pdata->streams_lost_on_suspend) {
+ for (i = 1; i <= ctx->info.max_streams; i++) {
+ struct stream_info *stream = &ctx->streams[i];
+
+ if (stream->resume_status != STREAM_UN_INIT) {
+ dev_dbg(ctx->dev, "Re-allocing stream %d status %d prev %d\n",
+ i, stream->resume_status,
+ stream->resume_prev);
+ sst_realloc_stream(ctx, i);
+ stream->status = stream->resume_status;
+ stream->prev = stream->resume_prev;
+ }
+ }
+ }
+
sst_free_block(ctx, block);
return ret;
}
diff --git a/sound/soc/intel/atom/sst/sst.h b/sound/soc/intel/atom/sst/sst.h
index e02e2b4cc08f..b2a705dc9304 100644
--- a/sound/soc/intel/atom/sst/sst.h
+++ b/sound/soc/intel/atom/sst/sst.h
@@ -65,9 +65,7 @@ enum sst_stream_states {
STREAM_UN_INIT = 0, /* Freed/Not used stream */
STREAM_RUNNING = 1, /* Running */
STREAM_PAUSED = 2, /* Paused stream */
- STREAM_DECODE = 3, /* stream is in decoding only state */
- STREAM_INIT = 4, /* stream init, waiting for data */
- STREAM_RESET = 5, /* force reset on recovery */
+ STREAM_INIT = 3, /* stream init, waiting for data */
};
enum sst_ram_type {
@@ -181,22 +179,22 @@ struct sst_block {
*
* @status : stream current state
* @prev : stream prev state
- * @ops : stream operation pb/cp/drm...
- * @bufs: stream buffer list
+ * @resume_status : stream current state to restore on resume
+ * @resume_prev : stream prev state to restore on resume
* @lock : stream mutex for protecting state
+ * @alloc_param : parameters used for stream (re-)allocation
* @pcm_substream : PCM substream
* @period_elapsed : PCM period elapsed callback
* @sfreq : stream sampling freq
- * @str_type : stream type
* @cumm_bytes : cummulative bytes decoded
- * @str_type : stream type
- * @src : stream source
*/
struct stream_info {
unsigned int status;
unsigned int prev;
- unsigned int ops;
+ unsigned int resume_status;
+ unsigned int resume_prev;
struct mutex lock;
+ struct snd_sst_alloc_mrfld alloc_param;
void *pcm_substream;
void (*period_elapsed)(void *pcm_substream);
@@ -212,7 +210,6 @@ struct stream_info {
unsigned int num_ch;
unsigned int pipe_id;
- unsigned int str_id;
unsigned int task_id;
};
@@ -438,6 +435,7 @@ struct intel_sst_ops {
void (*post_download)(struct intel_sst_drv *sst);
};
+int sst_realloc_stream(struct intel_sst_drv *sst_drv_ctx, int str_id);
int sst_pause_stream(struct intel_sst_drv *sst_drv_ctx, int id);
int sst_resume_stream(struct intel_sst_drv *sst_drv_ctx, int id);
int sst_drop_stream(struct intel_sst_drv *sst_drv_ctx, int id);
@@ -501,8 +499,6 @@ int sst_prepare_and_post_msg(struct intel_sst_drv *sst,
void sst_process_pending_msg(struct work_struct *work);
int sst_assign_pvt_id(struct intel_sst_drv *sst_drv_ctx);
-void sst_init_stream(struct stream_info *stream,
- int codec, int sst_id, int ops, u8 slot);
int sst_validate_strid(struct intel_sst_drv *sst_drv_ctx, int str_id);
struct stream_info *get_stream_info(struct intel_sst_drv *sst_drv_ctx,
int str_id);
diff --git a/sound/soc/intel/atom/sst/sst_acpi.c b/sound/soc/intel/atom/sst/sst_acpi.c
index 6cd481bec275..c90b04cc071d 100644
--- a/sound/soc/intel/atom/sst/sst_acpi.c
+++ b/sound/soc/intel/atom/sst/sst_acpi.c
@@ -143,10 +143,11 @@ static struct sst_platform_info byt_rvp_platform_data = {
.lib_info = &byt_lib_dnld_info,
.res_info = &byt_rvp_res_info,
.platform = "sst-mfld-platform",
+ .streams_lost_on_suspend = true,
};
/* Cherryview (Cherrytrail and Braswell) uses same mrfld dpcm fw as Baytrail,
- * so pdata is same as Baytrail.
+ * so pdata is same as Baytrail, minus the streams_lost_on_suspend quirk.
*/
static struct sst_platform_info chv_platform_data = {
.probe_data = &byt_fwparse_info,
diff --git a/sound/soc/intel/atom/sst/sst_drv_interface.c b/sound/soc/intel/atom/sst/sst_drv_interface.c
index 71af5449be90..6a8b253c58d2 100644
--- a/sound/soc/intel/atom/sst/sst_drv_interface.c
+++ b/sound/soc/intel/atom/sst/sst_drv_interface.c
@@ -238,16 +238,7 @@ static int sst_cdev_close(struct device *dev, unsigned int str_id)
return -EINVAL;
}
- if (stream->status == STREAM_RESET) {
- dev_dbg(dev, "stream in reset state...\n");
- stream->status = STREAM_UN_INIT;
-
- retval = 0;
- goto put;
- }
-
retval = sst_free_stream(ctx, str_id);
-put:
stream->compr_cb_param = NULL;
stream->compr_cb = NULL;
@@ -256,7 +247,6 @@ put:
dev_dbg(dev, "End\n");
return retval;
-
}
static int sst_cdev_ack(struct device *dev, unsigned int str_id,
@@ -486,16 +476,7 @@ static int sst_close_pcm_stream(struct device *dev, unsigned int str_id)
return -EINVAL;
}
- if (stream->status == STREAM_RESET) {
- /* silently fail here as we have cleaned the stream earlier */
- dev_dbg(ctx->dev, "stream in reset state...\n");
-
- retval = 0;
- goto put;
- }
-
retval = free_stream_context(ctx, str_id);
-put:
stream->pcm_substream = NULL;
stream->status = STREAM_UN_INIT;
stream->period_elapsed = NULL;
diff --git a/sound/soc/intel/atom/sst/sst_pvt.c b/sound/soc/intel/atom/sst/sst_pvt.c
index b1e6b8f34a6a..af93244b4868 100644
--- a/sound/soc/intel/atom/sst/sst_pvt.c
+++ b/sound/soc/intel/atom/sst/sst_pvt.c
@@ -360,14 +360,6 @@ int sst_assign_pvt_id(struct intel_sst_drv *drv)
return local;
}
-void sst_init_stream(struct stream_info *stream,
- int codec, int sst_id, int ops, u8 slot)
-{
- stream->status = STREAM_INIT;
- stream->prev = STREAM_UN_INIT;
- stream->ops = ops;
-}
-
int sst_validate_strid(
struct intel_sst_drv *sst_drv_ctx, int str_id)
{
diff --git a/sound/soc/intel/atom/sst/sst_stream.c b/sound/soc/intel/atom/sst/sst_stream.c
index 7ee6aeb7e0af..107271f7dd63 100644
--- a/sound/soc/intel/atom/sst/sst_stream.c
+++ b/sound/soc/intel/atom/sst/sst_stream.c
@@ -35,29 +35,31 @@
int sst_alloc_stream_mrfld(struct intel_sst_drv *sst_drv_ctx, void *params)
{
- struct snd_sst_alloc_mrfld alloc_param;
+ struct snd_pcm_params *pcm_params;
struct snd_sst_params *str_params;
struct snd_sst_tstamp fw_tstamp;
struct stream_info *str_info;
- struct snd_sst_alloc_response *response;
- unsigned int str_id, pipe_id, task_id;
- int i, num_ch, ret = 0;
- void *data = NULL;
+ int i, num_ch, str_id;
dev_dbg(sst_drv_ctx->dev, "Enter\n");
str_params = (struct snd_sst_params *)params;
- memset(&alloc_param, 0, sizeof(alloc_param));
- alloc_param.operation = str_params->ops;
- alloc_param.codec_type = str_params->codec;
- alloc_param.sg_count = str_params->aparams.sg_count;
- alloc_param.ring_buf_info[0].addr =
+ str_id = str_params->stream_id;
+ str_info = get_stream_info(sst_drv_ctx, str_id);
+ if (!str_info)
+ return -EINVAL;
+
+ memset(&str_info->alloc_param, 0, sizeof(str_info->alloc_param));
+ str_info->alloc_param.operation = str_params->ops;
+ str_info->alloc_param.codec_type = str_params->codec;
+ str_info->alloc_param.sg_count = str_params->aparams.sg_count;
+ str_info->alloc_param.ring_buf_info[0].addr =
str_params->aparams.ring_buf_info[0].addr;
- alloc_param.ring_buf_info[0].size =
+ str_info->alloc_param.ring_buf_info[0].size =
str_params->aparams.ring_buf_info[0].size;
- alloc_param.frag_size = str_params->aparams.frag_size;
+ str_info->alloc_param.frag_size = str_params->aparams.frag_size;
- memcpy(&alloc_param.codec_params, &str_params->sparams,
+ memcpy(&str_info->alloc_param.codec_params, &str_params->sparams,
sizeof(struct snd_sst_stream_params));
/*
@@ -67,47 +69,62 @@ int sst_alloc_stream_mrfld(struct intel_sst_drv *sst_drv_ctx, void *params)
* Currently hardcoding as per FW reqm.
*/
num_ch = sst_get_num_channel(str_params);
+ pcm_params = &str_info->alloc_param.codec_params.uc.pcm_params;
for (i = 0; i < 8; i++) {
if (i < num_ch)
- alloc_param.codec_params.uc.pcm_params.channel_map[i] = i;
+ pcm_params->channel_map[i] = i;
else
- alloc_param.codec_params.uc.pcm_params.channel_map[i] = 0xFF;
+ pcm_params->channel_map[i] = 0xff;
}
- str_id = str_params->stream_id;
- str_info = get_stream_info(sst_drv_ctx, str_id);
- if (str_info == NULL) {
- dev_err(sst_drv_ctx->dev, "get stream info returned null\n");
- return -EINVAL;
- }
-
- pipe_id = str_params->device_type;
- task_id = str_params->task;
- sst_drv_ctx->streams[str_id].pipe_id = pipe_id;
- sst_drv_ctx->streams[str_id].task_id = task_id;
+ sst_drv_ctx->streams[str_id].status = STREAM_INIT;
+ sst_drv_ctx->streams[str_id].prev = STREAM_UN_INIT;
+ sst_drv_ctx->streams[str_id].pipe_id = str_params->device_type;
+ sst_drv_ctx->streams[str_id].task_id = str_params->task;
sst_drv_ctx->streams[str_id].num_ch = num_ch;
if (sst_drv_ctx->info.lpe_viewpt_rqd)
- alloc_param.ts = sst_drv_ctx->info.mailbox_start +
+ str_info->alloc_param.ts = sst_drv_ctx->info.mailbox_start +
sst_drv_ctx->tstamp + (str_id * sizeof(fw_tstamp));
else
- alloc_param.ts = sst_drv_ctx->mailbox_add +
+ str_info->alloc_param.ts = sst_drv_ctx->mailbox_add +
sst_drv_ctx->tstamp + (str_id * sizeof(fw_tstamp));
dev_dbg(sst_drv_ctx->dev, "alloc tstamp location = 0x%x\n",
- alloc_param.ts);
+ str_info->alloc_param.ts);
dev_dbg(sst_drv_ctx->dev, "assigned pipe id 0x%x to task %d\n",
- pipe_id, task_id);
+ str_info->pipe_id, str_info->task_id);
+
+ return sst_realloc_stream(sst_drv_ctx, str_id);
+}
+
+/**
+ * sst_realloc_stream - Send msg for (re-)allocating a stream using the
+ * @sst_drv_ctx intel_sst_drv context pointer
+ * @str_id: stream ID
+ *
+ * Send a msg for (re-)allocating a stream using the parameters previously
+ * passed to sst_alloc_stream_mrfld() for the same stream ID.
+ * Return: 0 or negative errno value.
+ */
+int sst_realloc_stream(struct intel_sst_drv *sst_drv_ctx, int str_id)
+{
+ struct snd_sst_alloc_response *response;
+ struct stream_info *str_info;
+ void *data = NULL;
+ int ret;
- /* allocate device type context */
- sst_init_stream(&sst_drv_ctx->streams[str_id], alloc_param.codec_type,
- str_id, alloc_param.operation, 0);
+ str_info = get_stream_info(sst_drv_ctx, str_id);
+ if (!str_info)
+ return -EINVAL;
dev_dbg(sst_drv_ctx->dev, "Alloc for str %d pipe %#x\n",
- str_id, pipe_id);
- ret = sst_prepare_and_post_msg(sst_drv_ctx, task_id, IPC_CMD,
- IPC_IA_ALLOC_STREAM_MRFLD, pipe_id, sizeof(alloc_param),
- &alloc_param, &data, true, true, false, true);
+ str_id, str_info->pipe_id);
+
+ ret = sst_prepare_and_post_msg(sst_drv_ctx, str_info->task_id, IPC_CMD,
+ IPC_IA_ALLOC_STREAM_MRFLD, str_info->pipe_id,
+ sizeof(str_info->alloc_param), &str_info->alloc_param,
+ &data, true, true, false, true);
if (ret < 0) {
dev_err(sst_drv_ctx->dev, "FW alloc failed ret %d\n", ret);
@@ -253,7 +270,7 @@ int sst_pause_stream(struct intel_sst_drv *sst_drv_ctx, int str_id)
if (retval == 0) {
str_info->prev = str_info->status;
str_info->status = STREAM_PAUSED;
- } else if (retval == SST_ERR_INVALID_STREAM_ID) {
+ } else if (retval == -SST_ERR_INVALID_STREAM_ID) {
retval = -EINVAL;
mutex_lock(&sst_drv_ctx->sst_lock);
sst_clean_stream(str_info);
@@ -285,7 +302,29 @@ int sst_resume_stream(struct intel_sst_drv *sst_drv_ctx, int str_id)
return -EINVAL;
if (str_info->status == STREAM_RUNNING)
return 0;
- if (str_info->status == STREAM_PAUSED) {
+
+ if (str_info->resume_status == STREAM_PAUSED &&
+ str_info->resume_prev == STREAM_RUNNING) {
+ /*
+ * Stream was running before suspend and re-created on resume,
+ * start it to get back to running state.
+ */
+ dev_dbg(sst_drv_ctx->dev, "restart recreated stream after resume\n");
+ str_info->status = STREAM_RUNNING;
+ str_info->prev = STREAM_PAUSED;
+ retval = sst_start_stream(sst_drv_ctx, str_id);
+ str_info->resume_status = STREAM_UN_INIT;
+ } else if (str_info->resume_status == STREAM_PAUSED &&
+ str_info->resume_prev == STREAM_INIT) {
+ /*
+ * Stream was idle before suspend and re-created on resume,
+ * keep it as is.
+ */
+ dev_dbg(sst_drv_ctx->dev, "leaving recreated stream idle after resume\n");
+ str_info->status = STREAM_INIT;
+ str_info->prev = STREAM_PAUSED;
+ str_info->resume_status = STREAM_UN_INIT;
+ } else if (str_info->status == STREAM_PAUSED) {
retval = sst_prepare_and_post_msg(sst_drv_ctx, str_info->task_id,
IPC_CMD, IPC_IA_RESUME_STREAM_MRFLD,
str_info->pipe_id, 0, NULL, NULL,
OpenPOWER on IntegriCloud