arm64: dts: qcom: sm8550: add TRNG node
[linux-modified.git] / sound / firewire / bebob / bebob_command.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * bebob_command.c - driver for BeBoB based devices
4  *
5  * Copyright (c) 2013-2014 Takashi Sakamoto
6  */
7
8 #include "./bebob.h"
9
10 int avc_audio_set_selector(struct fw_unit *unit, unsigned int subunit_id,
11                            unsigned int fb_id, unsigned int num)
12 {
13         u8 *buf;
14         int err;
15
16         buf = kzalloc(12, GFP_KERNEL);
17         if (buf == NULL)
18                 return -ENOMEM;
19
20         buf[0]  = 0x00;         /* AV/C CONTROL */
21         buf[1]  = 0x08 | (0x07 & subunit_id);   /* AUDIO SUBUNIT ID */
22         buf[2]  = 0xb8;         /* FUNCTION BLOCK  */
23         buf[3]  = 0x80;         /* type is 'selector'*/
24         buf[4]  = 0xff & fb_id; /* function block id */
25         buf[5]  = 0x10;         /* control attribute is CURRENT */
26         buf[6]  = 0x02;         /* selector length is 2 */
27         buf[7]  = 0xff & num;   /* input function block plug number */
28         buf[8]  = 0x01;         /* control selector is SELECTOR_CONTROL */
29
30         err = fcp_avc_transaction(unit, buf, 12, buf, 12,
31                                   BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) |
32                                   BIT(6) | BIT(7) | BIT(8));
33         if (err < 0)
34                 ;
35         else if (err < 9)
36                 err = -EIO;
37         else if (buf[0] == 0x08) /* NOT IMPLEMENTED */
38                 err = -ENOSYS;
39         else if (buf[0] == 0x0a) /* REJECTED */
40                 err = -EINVAL;
41         else
42                 err = 0;
43
44         kfree(buf);
45         return err;
46 }
47
48 int avc_audio_get_selector(struct fw_unit *unit, unsigned int subunit_id,
49                            unsigned int fb_id, unsigned int *num)
50 {
51         u8 *buf;
52         int err;
53
54         buf = kzalloc(12, GFP_KERNEL);
55         if (buf == NULL)
56                 return -ENOMEM;
57
58         buf[0]  = 0x01;         /* AV/C STATUS */
59         buf[1]  = 0x08 | (0x07 & subunit_id);   /* AUDIO SUBUNIT ID */
60         buf[2]  = 0xb8;         /* FUNCTION BLOCK */
61         buf[3]  = 0x80;         /* type is 'selector'*/
62         buf[4]  = 0xff & fb_id; /* function block id */
63         buf[5]  = 0x10;         /* control attribute is CURRENT */
64         buf[6]  = 0x02;         /* selector length is 2 */
65         buf[7]  = 0xff;         /* input function block plug number */
66         buf[8]  = 0x01;         /* control selector is SELECTOR_CONTROL */
67
68         err = fcp_avc_transaction(unit, buf, 12, buf, 12,
69                                   BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) |
70                                   BIT(6) | BIT(8));
71         if (err < 0)
72                 ;
73         else if (err < 9)
74                 err = -EIO;
75         else if (buf[0] == 0x08) /* NOT IMPLEMENTED */
76                 err = -ENOSYS;
77         else if (buf[0] == 0x0a) /* REJECTED */
78                 err = -EINVAL;
79         else if (buf[0] == 0x0b) /* IN TRANSITION */
80                 err = -EAGAIN;
81         if (err < 0)
82                 goto end;
83
84         *num = buf[7];
85         err = 0;
86 end:
87         kfree(buf);
88         return err;
89 }
90
91 static inline void
92 avc_bridgeco_fill_extension_addr(u8 *buf, u8 *addr)
93 {
94         buf[1] = addr[0];
95         memcpy(buf + 4, addr + 1, 5);
96 }
97
98 static inline void
99 avc_bridgeco_fill_plug_info_extension_command(u8 *buf, u8 *addr,
100                                               unsigned int itype)
101 {
102         buf[0] = 0x01;  /* AV/C STATUS */
103         buf[2] = 0x02;  /* AV/C GENERAL PLUG INFO */
104         buf[3] = 0xc0;  /* BridgeCo extension */
105         avc_bridgeco_fill_extension_addr(buf, addr);
106         buf[9] = itype; /* info type */
107 }
108
109 int avc_bridgeco_get_plug_type(struct fw_unit *unit,
110                                u8 addr[AVC_BRIDGECO_ADDR_BYTES],
111                                enum avc_bridgeco_plug_type *type)
112 {
113         u8 *buf;
114         int err;
115
116         buf = kzalloc(12, GFP_KERNEL);
117         if (buf == NULL)
118                 return -ENOMEM;
119
120         /* Info type is 'plug type'. */
121         avc_bridgeco_fill_plug_info_extension_command(buf, addr, 0x00);
122
123         err = fcp_avc_transaction(unit, buf, 12, buf, 12,
124                                   BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) |
125                                   BIT(6) | BIT(7) | BIT(9));
126         if (err < 0)
127                 ;
128         else if (err < 11)
129                 err = -EIO;
130         else if (buf[0] == 0x08) /* NOT IMPLEMENTED */
131                 err = -ENOSYS;
132         else if (buf[0] == 0x0a) /* REJECTED */
133                 err = -EINVAL;
134         else if (buf[0] == 0x0b) /* IN TRANSITION */
135                 err = -EAGAIN;
136         if (err < 0)
137                 goto end;
138
139         *type = buf[10];
140         err = 0;
141 end:
142         kfree(buf);
143         return err;
144 }
145
146 int avc_bridgeco_get_plug_ch_count(struct fw_unit *unit, u8 addr[AVC_BRIDGECO_ADDR_BYTES],
147                                    unsigned int *ch_count)
148 {
149         u8 *buf;
150         int err;
151
152         buf = kzalloc(12, GFP_KERNEL);
153         if (buf == NULL)
154                 return -ENOMEM;
155
156         // Info type is 'plug type'.
157         avc_bridgeco_fill_plug_info_extension_command(buf, addr, 0x02);
158
159         err = fcp_avc_transaction(unit, buf, 12, buf, 12,
160                                   BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) |
161                                   BIT(6) | BIT(7) | BIT(9));
162         if (err < 0)
163                 ;
164         else if (err < 11)
165                 err = -EIO;
166         else if (buf[0] == 0x08) // NOT IMPLEMENTED
167                 err = -ENOSYS;
168         else if (buf[0] == 0x0a) // REJECTED
169                 err = -EINVAL;
170         else if (buf[0] == 0x0b) // IN TRANSITION
171                 err = -EAGAIN;
172         if (err < 0)
173                 goto end;
174
175         *ch_count = buf[10];
176         err = 0;
177 end:
178         kfree(buf);
179         return err;
180 }
181
182 int avc_bridgeco_get_plug_ch_pos(struct fw_unit *unit,
183                                  u8 addr[AVC_BRIDGECO_ADDR_BYTES],
184                                  u8 *buf, unsigned int len)
185 {
186         int err;
187
188         /* Info type is 'channel position'. */
189         avc_bridgeco_fill_plug_info_extension_command(buf, addr, 0x03);
190
191         err = fcp_avc_transaction(unit, buf, 12, buf, 256,
192                                   BIT(1) | BIT(2) | BIT(3) | BIT(4) |
193                                   BIT(5) | BIT(6) | BIT(7) | BIT(9));
194         if (err < 0)
195                 ;
196         else if (err < 11)
197                 err = -EIO;
198         else if (buf[0] == 0x08) /* NOT IMPLEMENTED */
199                 err = -ENOSYS;
200         else if (buf[0] == 0x0a) /* REJECTED */
201                 err = -EINVAL;
202         else if (buf[0] == 0x0b) /* IN TRANSITION */
203                 err = -EAGAIN;
204         if (err < 0)
205                 goto end;
206
207         /* Pick up specific data. */
208         memmove(buf, buf + 10, err - 10);
209         err = 0;
210 end:
211         return err;
212 }
213
214 int avc_bridgeco_get_plug_section_type(struct fw_unit *unit,
215                                        u8 addr[AVC_BRIDGECO_ADDR_BYTES],
216                                        unsigned int id, u8 *type)
217 {
218         u8 *buf;
219         int err;
220
221         /* section info includes charactors but this module don't need it */
222         buf = kzalloc(12, GFP_KERNEL);
223         if (buf == NULL)
224                 return -ENOMEM;
225
226         /* Info type is 'section info'. */
227         avc_bridgeco_fill_plug_info_extension_command(buf, addr, 0x07);
228         buf[10] = 0xff & ++id;  /* section id */
229
230         err = fcp_avc_transaction(unit, buf, 12, buf, 12,
231                                   BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) |
232                                   BIT(6) | BIT(7) | BIT(9) | BIT(10));
233         if (err < 0)
234                 ;
235         else if (err < 12)
236                 err = -EIO;
237         else if (buf[0] == 0x08) /* NOT IMPLEMENTED */
238                 err = -ENOSYS;
239         else if (buf[0] == 0x0a) /* REJECTED */
240                 err = -EINVAL;
241         else if (buf[0] == 0x0b) /* IN TRANSITION */
242                 err = -EAGAIN;
243         if (err < 0)
244                 goto end;
245
246         *type = buf[11];
247         err = 0;
248 end:
249         kfree(buf);
250         return err;
251 }
252
253 int avc_bridgeco_get_plug_input(struct fw_unit *unit,
254                                 u8 addr[AVC_BRIDGECO_ADDR_BYTES], u8 input[7])
255 {
256         int err;
257         u8 *buf;
258
259         buf = kzalloc(18, GFP_KERNEL);
260         if (buf == NULL)
261                 return -ENOMEM;
262
263         /* Info type is 'plug input'. */
264         avc_bridgeco_fill_plug_info_extension_command(buf, addr, 0x05);
265
266         err = fcp_avc_transaction(unit, buf, 16, buf, 16,
267                                   BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) |
268                                   BIT(6) | BIT(7));
269         if (err < 0)
270                 ;
271         else if (err < 16)
272                 err = -EIO;
273         else if (buf[0] == 0x08) /* NOT IMPLEMENTED */
274                 err = -ENOSYS;
275         else if (buf[0] == 0x0a) /* REJECTED */
276                 err = -EINVAL;
277         else if (buf[0] == 0x0b) /* IN TRANSITION */
278                 err = -EAGAIN;
279         if (err < 0)
280                 goto end;
281
282         memcpy(input, buf + 10, 5);
283         err = 0;
284 end:
285         kfree(buf);
286         return err;
287 }
288
289 int avc_bridgeco_get_plug_strm_fmt(struct fw_unit *unit,
290                                    u8 addr[AVC_BRIDGECO_ADDR_BYTES], u8 *buf,
291                                    unsigned int *len, unsigned int eid)
292 {
293         int err;
294
295         /* check given buffer */
296         if ((buf == NULL) || (*len < 12)) {
297                 err = -EINVAL;
298                 goto end;
299         }
300
301         buf[0] = 0x01;  /* AV/C STATUS */
302         buf[2] = 0x2f;  /* AV/C STREAM FORMAT SUPPORT */
303         buf[3] = 0xc1;  /* Bridgeco extension - List Request */
304         avc_bridgeco_fill_extension_addr(buf, addr);
305         buf[10] = 0xff & eid;   /* Entry ID */
306
307         err = fcp_avc_transaction(unit, buf, 12, buf, *len,
308                                   BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) |
309                                   BIT(6) | BIT(7) | BIT(10));
310         if (err < 0)
311                 ;
312         else if (err < 12)
313                 err = -EIO;
314         else if (buf[0] == 0x08)        /* NOT IMPLEMENTED */
315                 err = -ENOSYS;
316         else if (buf[0] == 0x0a)        /* REJECTED */
317                 err = -EINVAL;
318         else if (buf[0] == 0x0b)        /* IN TRANSITION */
319                 err = -EAGAIN;
320         else if (buf[10] != eid)
321                 err = -EIO;
322         if (err < 0)
323                 goto end;
324
325         /* Pick up 'stream format info'. */
326         memmove(buf, buf + 11, err - 11);
327         *len = err - 11;
328         err = 0;
329 end:
330         return err;
331 }