diff --git a/drivers/staging/greybus/audio-gb-cmds.c b/drivers/staging/greybus/audio-gb-cmds.c index 8a101286d7bee7f86554433de3674ba9b02cd6d1..d625f782b5132c9855ad2b50fccace98f9f4ef37 100644 --- a/drivers/staging/greybus/audio-gb-cmds.c +++ b/drivers/staging/greybus/audio-gb-cmds.c @@ -165,17 +165,8 @@ int gb_i2s_mgmt_setup(struct gb_connection *connection) ret = gb_i2s_mgmt_set_samples_per_message(connection, CONFIG_SAMPLES_PER_MSG); - if (ret) { + if (ret) pr_err("set_samples_per_msg failed: %d\n", ret); - goto free_get_cfg; - } - - ret = gb_i2s_mgmt_activate_cport(connection, - CONFIG_I2S_REMOTE_DATA_CPORT); - if (ret) { - pr_err("activate_cport failed: %d\n", ret); - goto free_get_cfg; - } free_get_cfg: kfree(get_cfg); diff --git a/drivers/staging/greybus/audio-pcm.c b/drivers/staging/greybus/audio-pcm.c index 92436300b3ebffdd1c71c9bd57ea0c912fe67b03..8eb803a7a40a6d6e6154ec65320249121695576b 100644 --- a/drivers/staging/greybus/audio-pcm.c +++ b/drivers/staging/greybus/audio-pcm.c @@ -32,15 +32,33 @@ static void gb_pcm_work(struct work_struct *work) struct snd_pcm_substream *substream = snd_dev->substream; struct snd_pcm_runtime *runtime = substream->runtime; unsigned int stride, frames, oldptr; - int period_elapsed; + int period_elapsed, ret; char *address; long len; if (!snd_dev) return; - if (!atomic_read(&snd_dev->running)) + if (!atomic_read(&snd_dev->running)) { + if (snd_dev->cport_active) { + ret = gb_i2s_mgmt_deactivate_cport( + snd_dev->mgmt_connection, + CONFIG_I2S_REMOTE_DATA_CPORT); + if (ret) /* XXX Do what else with failure? */ + pr_err("deactivate_cport failed: %d\n", ret); + + snd_dev->cport_active = false; + } + return; + } else if (!snd_dev->cport_active) { + ret = gb_i2s_mgmt_activate_cport(snd_dev->mgmt_connection, + CONFIG_I2S_REMOTE_DATA_CPORT); + if (ret) + pr_err("activate_cport failed: %d\n", ret); + + snd_dev->cport_active = true; + } address = runtime->dma_area + snd_dev->hwptr_done; @@ -88,6 +106,7 @@ static enum hrtimer_restart gb_pcm_timer_function(struct hrtimer *hrtimer) void gb_pcm_hrtimer_start(struct gb_snd *snd_dev) { atomic_set(&snd_dev->running, 1); + queue_work(snd_dev->workqueue, &snd_dev->work); /* Activates CPort */ hrtimer_start(&snd_dev->timer, ns_to_ktime(CONFIG_PERIOD_NS), HRTIMER_MODE_REL); } @@ -96,6 +115,7 @@ void gb_pcm_hrtimer_stop(struct gb_snd *snd_dev) { atomic_set(&snd_dev->running, 0); hrtimer_cancel(&snd_dev->timer); + queue_work(snd_dev->workqueue, &snd_dev->work); /* Deactivates CPort */ } static int gb_pcm_hrtimer_init(struct gb_snd *snd_dev) diff --git a/drivers/staging/greybus/audio.c b/drivers/staging/greybus/audio.c index 1cc7c04d562b18082f46878ceb0162135d11a2c9..1057e468d5d4f3240745177ba6bf04b15576246f 100644 --- a/drivers/staging/greybus/audio.c +++ b/drivers/staging/greybus/audio.c @@ -292,13 +292,11 @@ static int gb_i2s_mgmt_connection_init(struct gb_connection *connection) if (!snd_dev->send_data_req_buf) { ret = -ENOMEM; - goto err_deactivate_cport; + goto err_free_snd_dev; } return 0; -err_deactivate_cport: - gb_i2s_mgmt_deactivate_cport(connection, CONFIG_I2S_REMOTE_DATA_CPORT); err_free_snd_dev: gb_free_snd(snd_dev); return ret; @@ -307,12 +305,6 @@ static int gb_i2s_mgmt_connection_init(struct gb_connection *connection) static void gb_i2s_mgmt_connection_exit(struct gb_connection *connection) { struct gb_snd *snd_dev = (struct gb_snd *)connection->private; - int ret; - - ret = gb_i2s_mgmt_deactivate_cport(connection, - CONFIG_I2S_REMOTE_DATA_CPORT); - if (ret) - pr_err("deactivate_cport failed: %d\n", ret); kfree(snd_dev->send_data_req_buf); snd_dev->send_data_req_buf = NULL; diff --git a/drivers/staging/greybus/audio.h b/drivers/staging/greybus/audio.h index 020a8fc1d26726edd4d341cc3caf73b342ae0c53..50a9ebb6612ee9035b28eeb5c329dc2fec38549d 100644 --- a/drivers/staging/greybus/audio.h +++ b/drivers/staging/greybus/audio.h @@ -53,6 +53,7 @@ struct gb_snd { struct snd_pcm_substream *substream; struct hrtimer timer; atomic_t running; + bool cport_active; struct workqueue_struct *workqueue; struct work_struct work; int hwptr_done;