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