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