summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorMark Greer <mgreer@animalcreek.com>2016-02-29 15:31:02 -0700
committerGreg Kroah-Hartman <gregkh@google.com>2016-03-01 22:44:49 -0800
commit5bbe14b7acc2a00f51b23812ffc596577d94e80b (patch)
tree0f71167f46735107345ac0f3ed7e407134943a69 /drivers
parent9250c0ee2626d371753027b1b5ede697676de6d1 (diff)
greybus: audio: Split start and stop APBridgeA requests
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>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/staging/greybus/audio_apbridgea.c52
-rw-r--r--drivers/staging/greybus/audio_apbridgea.h32
-rw-r--r--drivers/staging/greybus/audio_codec.c32
-rw-r--r--drivers/staging/greybus/audio_codec.h8
4 files changed, 112 insertions, 12 deletions
diff --git a/drivers/staging/greybus/audio_apbridgea.c b/drivers/staging/greybus/audio_apbridgea.c
index bed087d3894b..a6e089d2d1a8 100644
--- a/drivers/staging/greybus/audio_apbridgea.c
+++ b/drivers/staging/greybus/audio_apbridgea.c
@@ -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");
diff --git a/drivers/staging/greybus/audio_apbridgea.h b/drivers/staging/greybus/audio_apbridgea.h
index c543e399ca04..a48f815bc56b 100644
--- a/drivers/staging/greybus/audio_apbridgea.h
+++ b/drivers/staging/greybus/audio_apbridgea.h
@@ -48,12 +48,16 @@
#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 */
diff --git a/drivers/staging/greybus/audio_codec.c b/drivers/staging/greybus/audio_codec.c
index 5e29694139f7..d7cae772dbf5 100644
--- a/drivers/staging/greybus/audio_codec.c
+++ b/drivers/staging/greybus/audio_codec.c
@@ -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);
diff --git a/drivers/staging/greybus/audio_codec.h b/drivers/staging/greybus/audio_codec.h
index 06312031af35..9197adcbc32e 100644
--- a/drivers/staging/greybus/audio_codec.h
+++ b/drivers/staging/greybus/audio_codec.h
@@ -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 */