1 // SPDX-License-Identifier: GPL-2.0-only
3 * bebob_command.c - driver for BeBoB based devices
5 * Copyright (c) 2013-2014 Takashi Sakamoto
10 int avc_audio_set_selector(struct fw_unit
*unit
, unsigned int subunit_id
,
11 unsigned int fb_id
, unsigned int num
)
16 buf
= kzalloc(12, GFP_KERNEL
);
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 */
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));
37 else if (buf
[0] == 0x08) /* NOT IMPLEMENTED */
39 else if (buf
[0] == 0x0a) /* REJECTED */
48 int avc_audio_get_selector(struct fw_unit
*unit
, unsigned int subunit_id
,
49 unsigned int fb_id
, unsigned int *num
)
54 buf
= kzalloc(12, GFP_KERNEL
);
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 */
68 err
= fcp_avc_transaction(unit
, buf
, 12, buf
, 12,
69 BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) |
75 else if (buf
[0] == 0x08) /* NOT IMPLEMENTED */
77 else if (buf
[0] == 0x0a) /* REJECTED */
79 else if (buf
[0] == 0x0b) /* IN TRANSITION */
92 avc_bridgeco_fill_extension_addr(u8
*buf
, u8
*addr
)
95 memcpy(buf
+ 4, addr
+ 1, 5);
99 avc_bridgeco_fill_plug_info_extension_command(u8
*buf
, u8
*addr
,
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 */
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
)
116 buf
= kzalloc(12, GFP_KERNEL
);
120 /* Info type is 'plug type'. */
121 avc_bridgeco_fill_plug_info_extension_command(buf
, addr
, 0x00);
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));
130 else if (buf
[0] == 0x08) /* NOT IMPLEMENTED */
132 else if (buf
[0] == 0x0a) /* REJECTED */
134 else if (buf
[0] == 0x0b) /* IN TRANSITION */
146 int avc_bridgeco_get_plug_ch_pos(struct fw_unit
*unit
,
147 u8 addr
[AVC_BRIDGECO_ADDR_BYTES
],
148 u8
*buf
, unsigned int len
)
152 /* Info type is 'channel position'. */
153 avc_bridgeco_fill_plug_info_extension_command(buf
, addr
, 0x03);
155 err
= fcp_avc_transaction(unit
, buf
, 12, buf
, 256,
156 BIT(1) | BIT(2) | BIT(3) | BIT(4) |
157 BIT(5) | BIT(6) | BIT(7) | BIT(9));
162 else if (buf
[0] == 0x08) /* NOT IMPLEMENTED */
164 else if (buf
[0] == 0x0a) /* REJECTED */
166 else if (buf
[0] == 0x0b) /* IN TRANSITION */
171 /* Pick up specific data. */
172 memmove(buf
, buf
+ 10, err
- 10);
178 int avc_bridgeco_get_plug_section_type(struct fw_unit
*unit
,
179 u8 addr
[AVC_BRIDGECO_ADDR_BYTES
],
180 unsigned int id
, u8
*type
)
185 /* section info includes charactors but this module don't need it */
186 buf
= kzalloc(12, GFP_KERNEL
);
190 /* Info type is 'section info'. */
191 avc_bridgeco_fill_plug_info_extension_command(buf
, addr
, 0x07);
192 buf
[10] = 0xff & ++id
; /* section id */
194 err
= fcp_avc_transaction(unit
, buf
, 12, buf
, 12,
195 BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) |
196 BIT(6) | BIT(7) | BIT(9) | BIT(10));
201 else if (buf
[0] == 0x08) /* NOT IMPLEMENTED */
203 else if (buf
[0] == 0x0a) /* REJECTED */
205 else if (buf
[0] == 0x0b) /* IN TRANSITION */
217 int avc_bridgeco_get_plug_input(struct fw_unit
*unit
,
218 u8 addr
[AVC_BRIDGECO_ADDR_BYTES
], u8 input
[7])
223 buf
= kzalloc(18, GFP_KERNEL
);
227 /* Info type is 'plug input'. */
228 avc_bridgeco_fill_plug_info_extension_command(buf
, addr
, 0x05);
230 err
= fcp_avc_transaction(unit
, buf
, 16, buf
, 16,
231 BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) |
237 else if (buf
[0] == 0x08) /* NOT IMPLEMENTED */
239 else if (buf
[0] == 0x0a) /* REJECTED */
241 else if (buf
[0] == 0x0b) /* IN TRANSITION */
246 memcpy(input
, buf
+ 10, 5);
253 int avc_bridgeco_get_plug_strm_fmt(struct fw_unit
*unit
,
254 u8 addr
[AVC_BRIDGECO_ADDR_BYTES
], u8
*buf
,
255 unsigned int *len
, unsigned int eid
)
259 /* check given buffer */
260 if ((buf
== NULL
) || (*len
< 12)) {
265 buf
[0] = 0x01; /* AV/C STATUS */
266 buf
[2] = 0x2f; /* AV/C STREAM FORMAT SUPPORT */
267 buf
[3] = 0xc1; /* Bridgeco extension - List Request */
268 avc_bridgeco_fill_extension_addr(buf
, addr
);
269 buf
[10] = 0xff & eid
; /* Entry ID */
271 err
= fcp_avc_transaction(unit
, buf
, 12, buf
, *len
,
272 BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) |
273 BIT(6) | BIT(7) | BIT(10));
278 else if (buf
[0] == 0x08) /* NOT IMPLEMENTED */
280 else if (buf
[0] == 0x0a) /* REJECTED */
282 else if (buf
[0] == 0x0b) /* IN TRANSITION */
284 else if (buf
[10] != eid
)
289 /* Pick up 'stream format info'. */
290 memmove(buf
, buf
+ 11, err
- 11);