brintos

brintos / linux-shallow public Read only

0
0
Text · 7.6 KiB · 022df09 Raw
332 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * bebob_command.c - driver for BeBoB based devices4 *5 * Copyright (c) 2013-2014 Takashi Sakamoto6 */7 8#include "./bebob.h"9 10int 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	else42		err = 0;43 44	kfree(buf);45	return err;46}47 48int 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;86end:87	kfree(buf);88	return err;89}90 91static inline void92avc_bridgeco_fill_extension_addr(u8 *buf, u8 *addr)93{94	buf[1] = addr[0];95	memcpy(buf + 4, addr + 1, 5);96}97 98static inline void99avc_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 109int 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;141end:142	kfree(buf);143	return err;144}145 146int 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 IMPLEMENTED167		err = -ENOSYS;168	else if (buf[0] == 0x0a) // REJECTED169		err = -EINVAL;170	else if (buf[0] == 0x0b) // IN TRANSITION171		err = -EAGAIN;172	if (err < 0)173		goto end;174 175	*ch_count = buf[10];176	err = 0;177end:178	kfree(buf);179	return err;180}181 182int 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;210end:211	return err;212}213 214int 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;248end:249	kfree(buf);250	return err;251}252 253int 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;284end:285	kfree(buf);286	return err;287}288 289int 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;329end:330	return err;331}332