greybus: audio: Register CPorts for specific directions
authorMark Greer <mgreer@animalcreek.com>
Sat, 27 Feb 2016 00:04:36 +0000 (17:04 -0700)
committerGreg Kroah-Hartman <gregkh@google.com>
Mon, 29 Feb 2016 21:37:39 +0000 (13:37 -0800)
Currently, it is assumed that all audio data CPorts registered on
APB1 are used for transmitting audio data.  That may not always be
true like when a microphone is connected but no speakers.  Also,
the current special protocol lacks a way to tell APB1 whether the CPort
being registered is for transmitting, receiving, or both.

Fix by adding a 'direction' field to the register and unregister CPort
requests and define bits indicating which direction (or both) audio
data will go on that CPort.

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 75c8c3c..bed087d 100644 (file)
@@ -29,13 +29,15 @@ int gb_audio_apbridgea_set_config(struct gb_connection *connection,
 EXPORT_SYMBOL_GPL(gb_audio_apbridgea_set_config);
 
 int gb_audio_apbridgea_register_cport(struct gb_connection *connection,
-                                     __u16 i2s_port, __u16 cportid)
+                                     __u16 i2s_port, __u16 cportid,
+                                     __u8 direction)
 {
        struct audio_apbridgea_register_cport_request req;
 
        req.hdr.type = AUDIO_APBRIDGEA_TYPE_REGISTER_CPORT;
        req.hdr.i2s_port = cpu_to_le16(i2s_port);
        req.cport = cpu_to_le16(cportid);
+       req.direction = direction;
 
        return gb_hd_output(connection->hd, &req, sizeof(req),
                            GB_APB_REQUEST_AUDIO_CONTROL, true);
@@ -43,13 +45,15 @@ int gb_audio_apbridgea_register_cport(struct gb_connection *connection,
 EXPORT_SYMBOL_GPL(gb_audio_apbridgea_register_cport);
 
 int gb_audio_apbridgea_unregister_cport(struct gb_connection *connection,
-                                       __u16 i2s_port, __u16 cportid)
+                                       __u16 i2s_port, __u16 cportid,
+                                       __u8 direction)
 {
        struct audio_apbridgea_unregister_cport_request req;
 
        req.hdr.type = AUDIO_APBRIDGEA_TYPE_UNREGISTER_CPORT;
        req.hdr.i2s_port = cpu_to_le16(i2s_port);
        req.cport = cpu_to_le16(cportid);
+       req.direction = direction;
 
        return gb_hd_output(connection->hd, &req, sizeof(req),
                            GB_APB_REQUEST_AUDIO_CONTROL, true);
index d1d56b7..c543e39 100644 (file)
@@ -75,6 +75,9 @@
 #define AUDIO_APBRIDGEA_PCM_RATE_176400                        BIT(11)
 #define AUDIO_APBRIDGEA_PCM_RATE_192000                        BIT(12)
 
+#define AUDIO_APBRIDGEA_DIRECTION_TX                   BIT(0)
+#define AUDIO_APBRIDGEA_DIRECTION_RX                   BIT(1)
+
 /* The I2S port is passed in the 'index' parameter of the USB request */
 /* The CPort is passed in the 'value' parameter of the USB request */
 
@@ -94,11 +97,13 @@ struct audio_apbridgea_set_config_request {
 struct audio_apbridgea_register_cport_request {
        struct audio_apbridgea_hdr      hdr;
        __le16                          cport;
+       __u8                            direction;
 } __packed;
 
 struct audio_apbridgea_unregister_cport_request {
        struct audio_apbridgea_hdr      hdr;
        __le16                          cport;
+       __u8                            direction;
 } __packed;
 
 struct audio_apbridgea_set_tx_data_size_request {
index d820116..5e29694 100644 (file)
@@ -60,7 +60,8 @@ static int gbcodec_startup(struct snd_pcm_substream *substream,
        i2s_port = 0;   /* fixed for now */
        cportid = gb_dai->connection->hd_cport_id;
        ret = gb_audio_apbridgea_register_cport(gb_dai->connection, i2s_port,
-                                               cportid);
+                                               cportid,
+                                               AUDIO_APBRIDGEA_DIRECTION_TX);
        dev_dbg(dai->dev, "Register %s:%d DAI, ret:%d\n", dai->name, cportid,
                ret);
 
@@ -117,7 +118,8 @@ static void gbcodec_shutdown(struct snd_pcm_substream *substream,
        /* un register cport */
        i2s_port = 0;   /* fixed for now */
        ret = gb_audio_apbridgea_unregister_cport(gb_dai->connection, i2s_port,
-                                       gb_dai->connection->hd_cport_id);
+                                       gb_dai->connection->hd_cport_id,
+                                       AUDIO_APBRIDGEA_DIRECTION_TX);
 
        dev_dbg(dai->dev, "Unregister %s:%d DAI, ret:%d\n", dai->name,
                gb_dai->connection->hd_cport_id, ret);
@@ -495,7 +497,8 @@ static void gb_audio_cleanup(struct gbaudio_codec_info *gb)
                                         ret);
                        cportid = connection->hd_cport_id;
                        ret = gb_audio_apbridgea_unregister_cport(connection, 0,
-                                                                 cportid);
+                                               cportid,
+                                               AUDIO_APBRIDGEA_DIRECTION_TX);
                        if (ret)
                                dev_info(dev, "%d:Failed during unregister cport\n",
                                         ret);
index fc60c36..0631203 100644 (file)
@@ -198,9 +198,11 @@ extern int gb_audio_apbridgea_set_config(struct gb_connection *connection,
                                         __u16 i2s_port, __u32 format,
                                         __u32 rate, __u32 mclk_freq);
 extern int gb_audio_apbridgea_register_cport(struct gb_connection *connection,
-                                            __u16 i2s_port, __u16 cportid);
+                                            __u16 i2s_port, __u16 cportid,
+                                            __u8 direction);
 extern int gb_audio_apbridgea_unregister_cport(struct gb_connection *connection,
-                                              __u16 i2s_port, __u16 cportid);
+                                              __u16 i2s_port, __u16 cportid,
+                                              __u8 direction);
 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,