1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Greybus Audio Device Class Protocol helpers
4  *
5  * Copyright 2015-2016 Google Inc.
6  */
7 
8 #include <linux/greybus.h>
9 #include "audio_apbridgea.h"
10 #include "audio_codec.h"
11 
gb_audio_apbridgea_set_config(struct gb_connection * connection,__u16 i2s_port,__u32 format,__u32 rate,__u32 mclk_freq)12 int gb_audio_apbridgea_set_config(struct gb_connection *connection,
13 				  __u16 i2s_port, __u32 format, __u32 rate,
14 				  __u32 mclk_freq)
15 {
16 	struct audio_apbridgea_set_config_request req;
17 
18 	req.hdr.type = AUDIO_APBRIDGEA_TYPE_SET_CONFIG;
19 	req.hdr.i2s_port = cpu_to_le16(i2s_port);
20 	req.format = cpu_to_le32(format);
21 	req.rate = cpu_to_le32(rate);
22 	req.mclk_freq = cpu_to_le32(mclk_freq);
23 
24 	return gb_hd_output(connection->hd, &req, sizeof(req),
25 			    GB_APB_REQUEST_AUDIO_CONTROL, true);
26 }
27 EXPORT_SYMBOL_GPL(gb_audio_apbridgea_set_config);
28 
gb_audio_apbridgea_register_cport(struct gb_connection * connection,__u16 i2s_port,__u16 cportid,__u8 direction)29 int gb_audio_apbridgea_register_cport(struct gb_connection *connection,
30 				      __u16 i2s_port, __u16 cportid,
31 				      __u8 direction)
32 {
33 	struct audio_apbridgea_register_cport_request req;
34 	int ret;
35 
36 	req.hdr.type = AUDIO_APBRIDGEA_TYPE_REGISTER_CPORT;
37 	req.hdr.i2s_port = cpu_to_le16(i2s_port);
38 	req.cport = cpu_to_le16(cportid);
39 	req.direction = direction;
40 
41 	ret = gb_pm_runtime_get_sync(connection->bundle);
42 	if (ret)
43 		return ret;
44 
45 	return gb_hd_output(connection->hd, &req, sizeof(req),
46 			    GB_APB_REQUEST_AUDIO_CONTROL, true);
47 }
48 EXPORT_SYMBOL_GPL(gb_audio_apbridgea_register_cport);
49 
gb_audio_apbridgea_unregister_cport(struct gb_connection * connection,__u16 i2s_port,__u16 cportid,__u8 direction)50 int gb_audio_apbridgea_unregister_cport(struct gb_connection *connection,
51 					__u16 i2s_port, __u16 cportid,
52 					__u8 direction)
53 {
54 	struct audio_apbridgea_unregister_cport_request req;
55 	int ret;
56 
57 	req.hdr.type = AUDIO_APBRIDGEA_TYPE_UNREGISTER_CPORT;
58 	req.hdr.i2s_port = cpu_to_le16(i2s_port);
59 	req.cport = cpu_to_le16(cportid);
60 	req.direction = direction;
61 
62 	ret = gb_hd_output(connection->hd, &req, sizeof(req),
63 			   GB_APB_REQUEST_AUDIO_CONTROL, true);
64 
65 	gb_pm_runtime_put_autosuspend(connection->bundle);
66 
67 	return ret;
68 }
69 EXPORT_SYMBOL_GPL(gb_audio_apbridgea_unregister_cport);
70 
gb_audio_apbridgea_set_tx_data_size(struct gb_connection * connection,__u16 i2s_port,__u16 size)71 int gb_audio_apbridgea_set_tx_data_size(struct gb_connection *connection,
72 					__u16 i2s_port, __u16 size)
73 {
74 	struct audio_apbridgea_set_tx_data_size_request req;
75 
76 	req.hdr.type = AUDIO_APBRIDGEA_TYPE_SET_TX_DATA_SIZE;
77 	req.hdr.i2s_port = cpu_to_le16(i2s_port);
78 	req.size = cpu_to_le16(size);
79 
80 	return gb_hd_output(connection->hd, &req, sizeof(req),
81 			    GB_APB_REQUEST_AUDIO_CONTROL, true);
82 }
83 EXPORT_SYMBOL_GPL(gb_audio_apbridgea_set_tx_data_size);
84 
gb_audio_apbridgea_prepare_tx(struct gb_connection * connection,__u16 i2s_port)85 int gb_audio_apbridgea_prepare_tx(struct gb_connection *connection,
86 				  __u16 i2s_port)
87 {
88 	struct audio_apbridgea_prepare_tx_request req;
89 
90 	req.hdr.type = AUDIO_APBRIDGEA_TYPE_PREPARE_TX;
91 	req.hdr.i2s_port = cpu_to_le16(i2s_port);
92 
93 	return gb_hd_output(connection->hd, &req, sizeof(req),
94 			    GB_APB_REQUEST_AUDIO_CONTROL, true);
95 }
96 EXPORT_SYMBOL_GPL(gb_audio_apbridgea_prepare_tx);
97 
gb_audio_apbridgea_start_tx(struct gb_connection * connection,__u16 i2s_port,__u64 timestamp)98 int gb_audio_apbridgea_start_tx(struct gb_connection *connection,
99 				__u16 i2s_port, __u64 timestamp)
100 {
101 	struct audio_apbridgea_start_tx_request req;
102 
103 	req.hdr.type = AUDIO_APBRIDGEA_TYPE_START_TX;
104 	req.hdr.i2s_port = cpu_to_le16(i2s_port);
105 	req.timestamp = cpu_to_le64(timestamp);
106 
107 	return gb_hd_output(connection->hd, &req, sizeof(req),
108 			    GB_APB_REQUEST_AUDIO_CONTROL, true);
109 }
110 EXPORT_SYMBOL_GPL(gb_audio_apbridgea_start_tx);
111 
gb_audio_apbridgea_stop_tx(struct gb_connection * connection,__u16 i2s_port)112 int gb_audio_apbridgea_stop_tx(struct gb_connection *connection, __u16 i2s_port)
113 {
114 	struct audio_apbridgea_stop_tx_request req;
115 
116 	req.hdr.type = AUDIO_APBRIDGEA_TYPE_STOP_TX;
117 	req.hdr.i2s_port = cpu_to_le16(i2s_port);
118 
119 	return gb_hd_output(connection->hd, &req, sizeof(req),
120 			    GB_APB_REQUEST_AUDIO_CONTROL, true);
121 }
122 EXPORT_SYMBOL_GPL(gb_audio_apbridgea_stop_tx);
123 
gb_audio_apbridgea_shutdown_tx(struct gb_connection * connection,__u16 i2s_port)124 int gb_audio_apbridgea_shutdown_tx(struct gb_connection *connection,
125 				   __u16 i2s_port)
126 {
127 	struct audio_apbridgea_shutdown_tx_request req;
128 
129 	req.hdr.type = AUDIO_APBRIDGEA_TYPE_SHUTDOWN_TX;
130 	req.hdr.i2s_port = cpu_to_le16(i2s_port);
131 
132 	return gb_hd_output(connection->hd, &req, sizeof(req),
133 			    GB_APB_REQUEST_AUDIO_CONTROL, true);
134 }
135 EXPORT_SYMBOL_GPL(gb_audio_apbridgea_shutdown_tx);
136 
gb_audio_apbridgea_set_rx_data_size(struct gb_connection * connection,__u16 i2s_port,__u16 size)137 int gb_audio_apbridgea_set_rx_data_size(struct gb_connection *connection,
138 					__u16 i2s_port, __u16 size)
139 {
140 	struct audio_apbridgea_set_rx_data_size_request req;
141 
142 	req.hdr.type = AUDIO_APBRIDGEA_TYPE_SET_RX_DATA_SIZE;
143 	req.hdr.i2s_port = cpu_to_le16(i2s_port);
144 	req.size = cpu_to_le16(size);
145 
146 	return gb_hd_output(connection->hd, &req, sizeof(req),
147 			    GB_APB_REQUEST_AUDIO_CONTROL, true);
148 }
149 EXPORT_SYMBOL_GPL(gb_audio_apbridgea_set_rx_data_size);
150 
gb_audio_apbridgea_prepare_rx(struct gb_connection * connection,__u16 i2s_port)151 int gb_audio_apbridgea_prepare_rx(struct gb_connection *connection,
152 				  __u16 i2s_port)
153 {
154 	struct audio_apbridgea_prepare_rx_request req;
155 
156 	req.hdr.type = AUDIO_APBRIDGEA_TYPE_PREPARE_RX;
157 	req.hdr.i2s_port = cpu_to_le16(i2s_port);
158 
159 	return gb_hd_output(connection->hd, &req, sizeof(req),
160 			    GB_APB_REQUEST_AUDIO_CONTROL, true);
161 }
162 EXPORT_SYMBOL_GPL(gb_audio_apbridgea_prepare_rx);
163 
gb_audio_apbridgea_start_rx(struct gb_connection * connection,__u16 i2s_port)164 int gb_audio_apbridgea_start_rx(struct gb_connection *connection,
165 				__u16 i2s_port)
166 {
167 	struct audio_apbridgea_start_rx_request req;
168 
169 	req.hdr.type = AUDIO_APBRIDGEA_TYPE_START_RX;
170 	req.hdr.i2s_port = cpu_to_le16(i2s_port);
171 
172 	return gb_hd_output(connection->hd, &req, sizeof(req),
173 			    GB_APB_REQUEST_AUDIO_CONTROL, true);
174 }
175 EXPORT_SYMBOL_GPL(gb_audio_apbridgea_start_rx);
176 
gb_audio_apbridgea_stop_rx(struct gb_connection * connection,__u16 i2s_port)177 int gb_audio_apbridgea_stop_rx(struct gb_connection *connection, __u16 i2s_port)
178 {
179 	struct audio_apbridgea_stop_rx_request req;
180 
181 	req.hdr.type = AUDIO_APBRIDGEA_TYPE_STOP_RX;
182 	req.hdr.i2s_port = cpu_to_le16(i2s_port);
183 
184 	return gb_hd_output(connection->hd, &req, sizeof(req),
185 			    GB_APB_REQUEST_AUDIO_CONTROL, true);
186 }
187 EXPORT_SYMBOL_GPL(gb_audio_apbridgea_stop_rx);
188 
gb_audio_apbridgea_shutdown_rx(struct gb_connection * connection,__u16 i2s_port)189 int gb_audio_apbridgea_shutdown_rx(struct gb_connection *connection,
190 				   __u16 i2s_port)
191 {
192 	struct audio_apbridgea_shutdown_rx_request req;
193 
194 	req.hdr.type = AUDIO_APBRIDGEA_TYPE_SHUTDOWN_RX;
195 	req.hdr.i2s_port = cpu_to_le16(i2s_port);
196 
197 	return gb_hd_output(connection->hd, &req, sizeof(req),
198 			    GB_APB_REQUEST_AUDIO_CONTROL, true);
199 }
200 EXPORT_SYMBOL_GPL(gb_audio_apbridgea_shutdown_rx);
201 
202 MODULE_LICENSE("GPL v2");
203 MODULE_ALIAS("greybus:audio-apbridgea");
204 MODULE_DESCRIPTION("Greybus Special APBridgeA Audio Protocol library");
205 MODULE_AUTHOR("Mark Greer <mgreer@animalcreek.com>");
206