greybus: audio: Split start and stop APBridgeA requests
authorMark Greer <mgreer@animalcreek.com>
Mon, 29 Feb 2016 22:31:02 +0000 (15:31 -0700)
committerGreg Kroah-Hartman <gregkh@google.com>
Wed, 2 Mar 2016 06:44:49 +0000 (22:44 -0800)
Provide finer-grained control of the audio streaming on APB1 by
splitting the transmit/receive start and stop requests into prepare,
start, stop, and shutdown.

CC: Vaibhav Agarwal <vaibhav.agarwal@linaro.org>
Signed-off-by: Mark Greer <mgreer@animalcreek.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
drivers/staging/greybus/audio_apbridgea.c
drivers/staging/greybus/audio_apbridgea.h
drivers/staging/greybus/audio_codec.c
drivers/staging/greybus/audio_codec.h

index bed087d3894b5992bec0a6456824a63950170bc9..a6e089d2d1a81e94cb3f9ddc1326bd9a02332efc 100644 (file)
@@ -82,6 +82,19 @@ int gb_audio_apbridgea_get_tx_delay(struct gb_connection *connection,
 }
 EXPORT_SYMBOL_GPL(gb_audio_apbridgea_get_tx_delay);
 
+int gb_audio_apbridgea_prepare_tx(struct gb_connection *connection,
+                                 __u16 i2s_port)
+{
+       struct audio_apbridgea_prepare_tx_request req;
+
+       req.hdr.type = AUDIO_APBRIDGEA_TYPE_PREPARE_TX;
+       req.hdr.i2s_port = cpu_to_le16(i2s_port);
+
+       return gb_hd_output(connection->hd, &req, sizeof(req),
+                           GB_APB_REQUEST_AUDIO_CONTROL, true);
+}
+EXPORT_SYMBOL_GPL(gb_audio_apbridgea_prepare_tx);
+
 int gb_audio_apbridgea_start_tx(struct gb_connection *connection,
                                __u16 i2s_port, __u64 timestamp)
 {
@@ -108,6 +121,19 @@ int gb_audio_apbridgea_stop_tx(struct gb_connection *connection, __u16 i2s_port)
 }
 EXPORT_SYMBOL_GPL(gb_audio_apbridgea_stop_tx);
 
+int gb_audio_apbridgea_shutdown_tx(struct gb_connection *connection,
+                                  __u16 i2s_port)
+{
+       struct audio_apbridgea_shutdown_tx_request req;
+
+       req.hdr.type = AUDIO_APBRIDGEA_TYPE_SHUTDOWN_TX;
+       req.hdr.i2s_port = cpu_to_le16(i2s_port);
+
+       return gb_hd_output(connection->hd, &req, sizeof(req),
+                           GB_APB_REQUEST_AUDIO_CONTROL, true);
+}
+EXPORT_SYMBOL_GPL(gb_audio_apbridgea_shutdown_tx);
+
 int gb_audio_apbridgea_set_rx_data_size(struct gb_connection *connection,
                                        __u16 i2s_port, __u16 size)
 {
@@ -130,6 +156,19 @@ int gb_audio_apbridgea_get_rx_delay(struct gb_connection *connection,
 }
 EXPORT_SYMBOL_GPL(gb_audio_apbridgea_get_rx_delay);
 
+int gb_audio_apbridgea_prepare_rx(struct gb_connection *connection,
+                                 __u16 i2s_port)
+{
+       struct audio_apbridgea_prepare_rx_request req;
+
+       req.hdr.type = AUDIO_APBRIDGEA_TYPE_PREPARE_RX;
+       req.hdr.i2s_port = cpu_to_le16(i2s_port);
+
+       return gb_hd_output(connection->hd, &req, sizeof(req),
+                           GB_APB_REQUEST_AUDIO_CONTROL, true);
+}
+EXPORT_SYMBOL_GPL(gb_audio_apbridgea_prepare_rx);
+
 int gb_audio_apbridgea_start_rx(struct gb_connection *connection,
                                __u16 i2s_port)
 {
@@ -155,6 +194,19 @@ int gb_audio_apbridgea_stop_rx(struct gb_connection *connection, __u16 i2s_port)
 }
 EXPORT_SYMBOL_GPL(gb_audio_apbridgea_stop_rx);
 
+int gb_audio_apbridgea_shutdown_rx(struct gb_connection *connection,
+                                  __u16 i2s_port)
+{
+       struct audio_apbridgea_shutdown_rx_request req;
+
+       req.hdr.type = AUDIO_APBRIDGEA_TYPE_SHUTDOWN_RX;
+       req.hdr.i2s_port = cpu_to_le16(i2s_port);
+
+       return gb_hd_output(connection->hd, &req, sizeof(req),
+                           GB_APB_REQUEST_AUDIO_CONTROL, true);
+}
+EXPORT_SYMBOL_GPL(gb_audio_apbridgea_shutdown_rx);
+
 MODULE_LICENSE("GPL v2");
 MODULE_ALIAS("greybus:audio-apbridgea");
 MODULE_DESCRIPTION("Greybus Special APBridgeA Audio Protocol library");
index c543e399ca0450f0910839181349e1e77da26211..a48f815bc56bf512715f69095347de93a0062970 100644 (file)
 #define AUDIO_APBRIDGEA_TYPE_UNREGISTER_CPORT          0x03
 #define AUDIO_APBRIDGEA_TYPE_SET_TX_DATA_SIZE          0x04
 #define AUDIO_APBRIDGEA_TYPE_GET_TX_DELAY              0x05
-#define AUDIO_APBRIDGEA_TYPE_START_TX                  0x06
-#define AUDIO_APBRIDGEA_TYPE_STOP_TX                   0x07
-#define AUDIO_APBRIDGEA_TYPE_SET_RX_DATA_SIZE          0x08
-#define AUDIO_APBRIDGEA_TYPE_GET_RX_DELAY              0x09
-#define AUDIO_APBRIDGEA_TYPE_START_RX                  0x0a
-#define AUDIO_APBRIDGEA_TYPE_STOP_RX                   0x0b
+#define AUDIO_APBRIDGEA_TYPE_PREPARE_TX                        0x06
+#define AUDIO_APBRIDGEA_TYPE_START_TX                  0x07
+#define AUDIO_APBRIDGEA_TYPE_STOP_TX                   0x08
+#define AUDIO_APBRIDGEA_TYPE_SHUTDOWN_TX               0x09
+#define AUDIO_APBRIDGEA_TYPE_SET_RX_DATA_SIZE          0x0a
+#define AUDIO_APBRIDGEA_TYPE_GET_RX_DELAY              0x0b
+#define AUDIO_APBRIDGEA_TYPE_PREPARE_RX                        0x0c
+#define AUDIO_APBRIDGEA_TYPE_START_RX                  0x0d
+#define AUDIO_APBRIDGEA_TYPE_STOP_RX                   0x0e
+#define AUDIO_APBRIDGEA_TYPE_SHUTDOWN_RX               0x0f
 
 #define AUDIO_APBRIDGEA_PCM_FMT_8                      BIT(0)
 #define AUDIO_APBRIDGEA_PCM_FMT_16                     BIT(1)
@@ -120,6 +124,10 @@ struct audio_apbridgea_get_tx_delay_response {
        __le16                          delay;
 } __packed;
 
+struct audio_apbridgea_prepare_tx_request {
+       struct audio_apbridgea_hdr      hdr;
+} __packed;
+
 struct audio_apbridgea_start_tx_request {
        struct audio_apbridgea_hdr      hdr;
        __le64                          timestamp;
@@ -129,6 +137,10 @@ struct audio_apbridgea_stop_tx_request {
        struct audio_apbridgea_hdr      hdr;
 } __packed;
 
+struct audio_apbridgea_shutdown_tx_request {
+       struct audio_apbridgea_hdr      hdr;
+} __packed;
+
 struct audio_apbridgea_set_rx_data_size_request {
        struct audio_apbridgea_hdr      hdr;
        __le16                          size;
@@ -143,6 +155,10 @@ struct audio_apbridgea_get_rx_delay_response {
        __le16                          delay;
 } __packed;
 
+struct audio_apbridgea_prepare_rx_request {
+       struct audio_apbridgea_hdr      hdr;
+} __packed;
+
 struct audio_apbridgea_start_rx_request {
        struct audio_apbridgea_hdr      hdr;
 } __packed;
@@ -151,4 +167,8 @@ struct audio_apbridgea_stop_rx_request {
        struct audio_apbridgea_hdr      hdr;
 } __packed;
 
+struct audio_apbridgea_shutdown_rx_request {
+       struct audio_apbridgea_hdr      hdr;
+} __packed;
+
 #endif /*__AUDIO_APBRIDGEA_H */
index 5e29694139f7da1d098897868abd94802a6d2c4c..d7cae772dbf5ed9691f04e9e53779bb37d788eb8 100644 (file)
@@ -345,17 +345,33 @@ static int gbcodec_trigger(struct snd_pcm_substream *substream, int cmd,
                goto func_exit;
        }
 
-       if (start && tx)
-               ret = gb_audio_apbridgea_start_tx(gb_dai->connection, 0, 0);
+       if (start && tx) {
+               ret = gb_audio_apbridgea_prepare_tx(gb_dai->connection, 0);
+               if (!ret)
+                       ret = gb_audio_apbridgea_start_tx(gb_dai->connection, 0,
+                                                         0);
+       }
 
-       else if (start && rx)
-               ret = gb_audio_apbridgea_start_rx(gb_dai->connection, 0);
+       else if (start && rx) {
+               ret = gb_audio_apbridgea_prepare_rx(gb_dai->connection, 0);
+               if (!ret)
+                       ret = gb_audio_apbridgea_start_rx(gb_dai->connection,
+                                                         0);
+       }
 
-       else if (stop && tx)
+       else if (stop && tx) {
                ret = gb_audio_apbridgea_stop_tx(gb_dai->connection, 0);
+               if (!ret)
+                       ret = gb_audio_apbridgea_shutdown_tx(gb_dai->connection,
+                                                            0);
+       }
 
-       else if (stop && rx)
+       else if (stop && rx) {
                ret = gb_audio_apbridgea_stop_rx(gb_dai->connection, 0);
+               if (!ret)
+                       ret = gb_audio_apbridgea_shutdown_rx(gb_dai->connection,
+                                                            0);
+       }
 
        else
                ret = -EINVAL;
@@ -488,6 +504,10 @@ static void gb_audio_cleanup(struct gbaudio_codec_info *gb)
                        if (ret)
                                dev_info(dev, "%d:Failed during APBridge stop_tx\n",
                                         ret);
+                       ret = gb_audio_apbridgea_shutdown_tx(connection, 0);
+                       if (ret)
+                               dev_info(dev, "%d:Failed during APBridge shutdown_tx\n",
+                                        ret);
                        cportid = connection->intf_cport_id;
                        ret = gb_audio_gb_deactivate_tx(gb->mgmt_connection,
                                                        cportid);
index 06312031af356ed43ab151416053187b53348157..9197adcbc32ecc01fb9b0d15f5d2b5fa48771396 100644 (file)
@@ -207,17 +207,25 @@ extern int gb_audio_apbridgea_set_tx_data_size(struct gb_connection *connection,
                                               __u16 i2s_port, __u16 size);
 extern int gb_audio_apbridgea_get_tx_delay(struct gb_connection *connection,
                                           __u16 i2s_port, __u32 *delay);
+extern int gb_audio_apbridgea_prepare_tx(struct gb_connection *connection,
+                                        __u16 i2s_port);
 extern int gb_audio_apbridgea_start_tx(struct gb_connection *connection,
                                       __u16 i2s_port, __u64 timestamp);
 extern int gb_audio_apbridgea_stop_tx(struct gb_connection *connection,
                                      __u16 i2s_port);
+extern int gb_audio_apbridgea_shutdown_tx(struct gb_connection *connection,
+                                         __u16 i2s_port);
 extern int gb_audio_apbridgea_set_rx_data_size(struct gb_connection *connection,
                                               __u16 i2s_port, __u16 size);
 extern int gb_audio_apbridgea_get_rx_delay(struct gb_connection *connection,
                                           __u16 i2s_port, __u32 *delay);
+extern int gb_audio_apbridgea_prepare_rx(struct gb_connection *connection,
+                                        __u16 i2s_port);
 extern int gb_audio_apbridgea_start_rx(struct gb_connection *connection,
                                       __u16 i2s_port);
 extern int gb_audio_apbridgea_stop_rx(struct gb_connection *connection,
                                      __u16 i2s_port);
+extern int gb_audio_apbridgea_shutdown_rx(struct gb_connection *connection,
+                                         __u16 i2s_port);
 
 #endif /* __LINUX_GBAUDIO_CODEC_H */