1 /*
2  * Copyright (C) 2015-2017 Alibaba Group Holding Limited
3  */
4 
5 #ifndef CONTROL_H
6 #define CONTROL_H
7 
8 #include <stdio.h>
9 #include <aos/list.h>
10 #include "control_dev.h"
11 
12 #ifdef __cplusplus
13 extern "C" {
14 #endif
15 
16 struct audio_kcontrol;
17 struct audio_mixer_control;
18 
19 #define	AOS_CTL_ELEM_TYPE_NONE	        (1 << 0) /* invalid */
20 #define	AOS_CTL_ELEM_TYPE_BOOLEAN	    (1 << 1) /* boolean type */
21 #define	AOS_CTL_ELEM_TYPE_INTEGER	    (1 << 2) /* integer type */
22 #define	AOS_CTL_ELEM_TYPE_ENUMERATED	(1 << 3) /* enumerated type */
23 #define	AOS_CTL_ELEM_TYPE_BYTES	        (1 << 4) /* byte array */
24 #define	AOS_CTL_ELEM_TYPE_IEC958	    (1 << 5) /* IEC958 (S/PDIF) setup */
25 #define	AOS_CTL_ELEM_TYPE_INTEGER64	    (1 << 6) /* 64-bit integer type */
26 #define	AOS_CTL_ELEM_TYPE_LAST	        AOS_CTL_ELEM_TYPE_INTEGER64
27 
28 #define	AOS_CTL_ELEM_IFACE_MIXER        (1 << 2) /* virtual mixer device */
29 #define	AOS_CTL_ELEM_IFACE_LAST	        AOS_CTL_ELEM_IFACE_MIXER
30 
31 #define AOS_CTL_ELEM_ACCESS_READ		    (1<<0)
32 #define AOS_CTL_ELEM_ACCESS_WRITE		    (1<<1)
33 #define AOS_CTL_ELEM_ACCESS_READWRITE		(AOS_CTL_ELEM_ACCESS_READ|AOS_CTL_ELEM_ACCESS_WRITE)
34 
35 #define AOS_DOUBLE_VALUE(sreg, left, right, smax, sinvert, sautodisable) \
36 	((unsigned long)&(struct audio_mixer_control) \
37 	{.reg = sreg, .rreg = sreg, .shift = left, \
38 	.rshift = right, .max = smax, .platform_max = smax, \
39 	.invert = sinvert, .autodisable = sautodisable})
40 
41 #define AOS_SINGLE_VALUE(reg, shift, max, invert, autodisable) \
42 	    AOS_DOUBLE_VALUE(reg, shift, shift, max, invert, autodisable)
43 
44 #define SOC_SINGLE_EXT(sname, reg, shift, max, invert, handler_get, handler_put) \
45 {	.iface = AOS_CTL_ELEM_IFACE_MIXER, \
46 	.name = sname, \
47 	.info = get_integer_info, \
48 	.get = handler_get, \
49 	.put = handler_put, \
50 	.private_value = AOS_SINGLE_VALUE(reg, shift, max, invert, 0) \
51 }
52 
53 #define SOC_DOUBLE_EXT(sname, reg, left, right, max, invert, handler_get, handler_put) \
54 {	.iface = AOS_CTL_ELEM_IFACE_MIXER, \
55 	.name = (sname),\
56 	.info = get_integer_info, \
57 	.get = handler_get, \
58 	.put = handler_put, \
59 	.private_value = AOS_DOUBLE_VALUE(reg, left, right, max, invert, 0) \
60 }
61 
62 struct audio_ctl_card_info {
63 	int card;			              /* card number */
64 	unsigned char driverName[16];	  /* Driver name */
65 	unsigned char shortName[32];      /* Short name of card */
66 	unsigned char longName[64];	      /* long name about card */
67 	unsigned char mixerName[64];	  /* visual mixer name */
68 	unsigned char components[64];     /* card components info */
69 };
70 
71 struct audio_ctl_elem_id {
72 	unsigned int id;		          /* element id, zero = invalid */
73 	int iface;	                      /* interface id */
74 	unsigned int deviceId;		      /* device number */
75 	unsigned int subdeviceId;		  /* subdevice (substream) number */
76 	char name[64];		              /* name of item */
77 	unsigned int index;		          /* index of item */
78 };
79 
80 struct audio_ctl_elem_list {
81 	struct audio_ctl_elem_id  *pids;  /* R: IDs */
82 	unsigned int offset;		      /* W: first element offset */
83 	unsigned int space;		          /* W: element count to get */
84 	unsigned int used;		          /* R: element count been set */
85 	unsigned int count;		          /* R: total elements count */
86 };
87 
88 struct audio_ctl_elem_info {
89 	struct audio_ctl_elem_id id;	  /* W: element ID */
90 	int type;	                      /* R: AOS_CTL_ELEM_TYPE_* */
91 	unsigned int access;		      /* R: AOS_CTL_ELEM_ACCESS_* */
92 	unsigned int count;		          /* count of values */
93 	union {
94 		struct {
95 			long min;		          /* R: min value */
96 			long max;		          /* R: max value */
97 			long step;		          /* R: step */
98 		} integer;
99 		struct {
100 			long long min;		      /* R: min value */
101 			long long max;		      /* R: max value */
102 			long long step;		      /* R: step */
103 		} integer64;
104 	} value;
105 };
106 
107 struct audio_ctl_elem_value {
108 	struct audio_ctl_elem_id id;	  /* W: element ID */
109 	union {
110 		union {
111 			long value[64];
112 		} integer;
113 		union {
114 			long long value[64];
115 		} integer64;
116 		union {
117 			unsigned char data[512];
118 		} bytes;
119 	} value;		                  /* RO */
120 };
121 
122 struct audio_ctl_tlv {
123 	unsigned int numid;	              /* control element numeric identification */
124 	unsigned int len;	              /* in bytes aligned to 4 */
125 	unsigned int tlv[0];	          /* first TLV */
126 };
127 
128 /* mixer control */
129 typedef int (audio_kcontrol_info_t) (struct audio_kcontrol * kcontrol, struct audio_ctl_elem_info * uinfo);
130 typedef int (audio_kcontrol_get_t) (struct audio_kcontrol * kcontrol, struct audio_ctl_elem_value * ucontrol);
131 typedef int (audio_kcontrol_put_t) (struct audio_kcontrol * kcontrol, struct audio_ctl_elem_value * ucontrol);
132 typedef int (audio_kcontrol_tlv_rw_t)(struct audio_kcontrol *kcontrol, int op_flag, unsigned int size, unsigned int *tlv);
133 
134 
135 struct audio_mixer_control {
136 	int min, max, platform_max;
137 	int reg, rreg;
138 	unsigned int shift, rshift;
139 	unsigned int sign_bit;
140 	unsigned int invert:1;
141 	unsigned int autodisable:1;
142 };
143 
144 struct audio_kcontrol_volatile {
145 	void *owner;	              /* locked */
146 	unsigned int access;	      /* access rights */
147 };
148 
149 struct audio_kcontrol_new {
150 	unsigned int iface;	          /* interface identifier */
151 	const char *name;	          /* ASCII name of item */
152 	audio_kcontrol_info_t *info;
153 	audio_kcontrol_get_t *get;
154 	audio_kcontrol_put_t *put;
155 	union {
156 		audio_kcontrol_tlv_rw_t *c;
157 		const unsigned int *p;
158 	} tlv;
159 	unsigned long private_value;
160 
161 	unsigned int deviceId;		  /* device ID*/
162 	unsigned int subdeviceId;	  /* subdevice ID */
163 	unsigned int index;		      /* index of item */
164 	unsigned int access;		  /* access rights */
165 	unsigned int count;		      /* count of same elements */
166 };
167 
168 struct audio_kcontrol {
169 	struct dlist_s list;		      /* list of controls */
170 	struct audio_ctl_elem_id id;
171 	unsigned int count;		          /* count of same elements */
172 	audio_kcontrol_info_t *info;
173 	audio_kcontrol_get_t *get;
174 	audio_kcontrol_put_t *put;
175 	union {
176 		audio_kcontrol_tlv_rw_t *c;
177 		const unsigned int *p;
178 	} tlv;
179 	unsigned long private_value;
180 	void *private_data;
181 	void (*private_free)(struct audio_kcontrol *kcontrol);
182 	struct audio_kcontrol_volatile vd[0];	/* volatile data */
183 };
184 
185 enum {
186 	AOS_CTL_TLV_OP_READ = 0,
187 	AOS_CTL_TLV_OP_WRITE = 1,
188 	AOS_CTL_TLV_OP_CMD = -1,
189 };
190 
191 int get_integer_info(struct audio_kcontrol * kcontrol, struct audio_ctl_elem_info * uinfo);
192 int audio_ctl_card_info(ctrl_device_t *dev, struct audio_ctl_card_info *info);
193 int audio_ctl_elem_list(ctrl_device_t *dev, struct audio_ctl_elem_list *list);
194 int audio_ctl_elem_info(ctrl_device_t *dev, struct audio_ctl_elem_info *info);
195 int audio_ctl_elem_read(ctrl_device_t *dev, struct audio_ctl_elem_value *value);
196 int audio_ctl_elem_write(ctrl_device_t *dev, struct audio_ctl_elem_value *value);
197 int audio_ctl_tlv_ioctl(ctrl_device_t *dev, struct audio_ctl_tlv *tlv, int op_flag);
198 int audio_add_controls(ctrl_device_t *dev, const struct audio_kcontrol_new *controls, int num_controls, void *data);
199 
200 #ifdef __cplusplus
201 }
202 #endif
203 
204 #endif /* CONTROL_H */