]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
greybus: gb-audio: Activate TX CPort in PCM workqueue
authorMark A. Greer <mgreer@animalcreek.com>
Thu, 21 May 2015 22:57:01 +0000 (15:57 -0700)
committerGreg Kroah-Hartman <gregkh@google.com>
Sat, 23 May 2015 23:26:41 +0000 (16:26 -0700)
Currently, the I2S TX CPort is configured and activated during
the Greybus audio initialization.  Unfortunately, this prevents
the audio driver from ever changing the I2S configuration.

To allow the I2S configuration to change according to ASOC requests,
move the CPort activation & deactivation to the audio-pcm workqueue.
Now, when audio is running but the CPort is not active, it will be
activated.  When audio is not running and the CPort is active, it
will be deactivated.

This has the side-effect of sending the first piece of audio data
immediately after activating the CPort which is really how it should
work anyway.

Signed-off-by: Mark A. Greer <mgreer@animalcreek.com>
Acked-by: John Stultz <john.stultz@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
drivers/staging/greybus/audio-gb-cmds.c
drivers/staging/greybus/audio-pcm.c
drivers/staging/greybus/audio.c
drivers/staging/greybus/audio.h

index 8a101286d7bee7f86554433de3674ba9b02cd6d1..d625f782b5132c9855ad2b50fccace98f9f4ef37 100644 (file)
@@ -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);
index 92436300b3ebffdd1c71c9bd57ea0c912fe67b03..8eb803a7a40a6d6e6154ec65320249121695576b 100644 (file)
@@ -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)
index 1cc7c04d562b18082f46878ceb0162135d11a2c9..1057e468d5d4f3240745177ba6bf04b15576246f 100644 (file)
@@ -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 @@ err_free_snd_dev:
 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;
index 020a8fc1d26726edd4d341cc3caf73b342ae0c53..50a9ebb6612ee9035b28eeb5c329dc2fec38549d 100644 (file)
@@ -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;