diff options
Diffstat (limited to 'sound/oss/dmasound/tas_common.h')
-rw-r--r-- | sound/oss/dmasound/tas_common.h | 284 |
1 files changed, 284 insertions, 0 deletions
diff --git a/sound/oss/dmasound/tas_common.h b/sound/oss/dmasound/tas_common.h new file mode 100644 index 000000000000..3a6d48666db0 --- /dev/null +++ b/sound/oss/dmasound/tas_common.h | |||
@@ -0,0 +1,284 @@ | |||
1 | #ifndef _TAS_COMMON_H_ | ||
2 | #define _TAS_COMMON_H_ | ||
3 | |||
4 | #include <linux/i2c.h> | ||
5 | #include <linux/soundcard.h> | ||
6 | #include <asm/string.h> | ||
7 | |||
8 | #define I2C_DRIVERID_TAS_BASE (0xFEBA) | ||
9 | |||
10 | #define SET_4_20(shadow, offset, val) \ | ||
11 | do { \ | ||
12 | (shadow)[(offset)+0] = ((val) >> 16) & 0xff; \ | ||
13 | (shadow)[(offset)+1] = ((val) >> 8) & 0xff; \ | ||
14 | (shadow)[(offset)+2] = ((val) >> 0) & 0xff; \ | ||
15 | } while (0) | ||
16 | |||
17 | #define GET_4_20(shadow, offset) \ | ||
18 | (((u_int)((shadow)[(offset)+0]) << 16) | \ | ||
19 | ((u_int)((shadow)[(offset)+1]) << 8) | \ | ||
20 | ((u_int)((shadow)[(offset)+2]) << 0)) | ||
21 | |||
22 | |||
23 | #define TAS_BIQUAD_FAST_LOAD 0x01 | ||
24 | |||
25 | #define TAS_DRCE_ENABLE 0x01 | ||
26 | #define TAS_DRCE_ABOVE_RATIO 0x02 | ||
27 | #define TAS_DRCE_BELOW_RATIO 0x04 | ||
28 | #define TAS_DRCE_THRESHOLD 0x08 | ||
29 | #define TAS_DRCE_ENERGY 0x10 | ||
30 | #define TAS_DRCE_ATTACK 0x20 | ||
31 | #define TAS_DRCE_DECAY 0x40 | ||
32 | |||
33 | #define TAS_DRCE_ALL 0x7f | ||
34 | |||
35 | |||
36 | #define TAS_OUTPUT_HEADPHONES 0x00 | ||
37 | #define TAS_OUTPUT_INTERNAL_SPKR 0x01 | ||
38 | #define TAS_OUTPUT_EXTERNAL_SPKR 0x02 | ||
39 | |||
40 | |||
41 | union tas_biquad_t { | ||
42 | struct { | ||
43 | int b0,b1,b2,a1,a2; | ||
44 | } coeff; | ||
45 | int buf[5]; | ||
46 | }; | ||
47 | |||
48 | struct tas_biquad_ctrl_t { | ||
49 | u_int channel:4; | ||
50 | u_int filter:4; | ||
51 | |||
52 | union tas_biquad_t data; | ||
53 | }; | ||
54 | |||
55 | struct tas_biquad_ctrl_list_t { | ||
56 | int flags; | ||
57 | int filter_count; | ||
58 | struct tas_biquad_ctrl_t biquads[0]; | ||
59 | }; | ||
60 | |||
61 | struct tas_ratio_t { | ||
62 | unsigned short val; /* 8.8 */ | ||
63 | unsigned short expand; /* 0 = compress, !0 = expand. */ | ||
64 | }; | ||
65 | |||
66 | struct tas_drce_t { | ||
67 | unsigned short enable; | ||
68 | struct tas_ratio_t above; | ||
69 | struct tas_ratio_t below; | ||
70 | short threshold; /* dB, 8.8 signed */ | ||
71 | unsigned short energy; /* seconds, 4.12 unsigned */ | ||
72 | unsigned short attack; /* seconds, 4.12 unsigned */ | ||
73 | unsigned short decay; /* seconds, 4.12 unsigned */ | ||
74 | }; | ||
75 | |||
76 | struct tas_drce_ctrl_t { | ||
77 | uint flags; | ||
78 | |||
79 | struct tas_drce_t data; | ||
80 | }; | ||
81 | |||
82 | struct tas_gain_t | ||
83 | { | ||
84 | unsigned int *master; | ||
85 | unsigned int *treble; | ||
86 | unsigned int *bass; | ||
87 | unsigned int *mixer; | ||
88 | }; | ||
89 | |||
90 | typedef char tas_shadow_t[0x45]; | ||
91 | |||
92 | struct tas_data_t | ||
93 | { | ||
94 | struct i2c_client *client; | ||
95 | tas_shadow_t *shadow; | ||
96 | uint mixer[SOUND_MIXER_NRDEVICES]; | ||
97 | }; | ||
98 | |||
99 | typedef int (*tas_hook_init_t)(struct i2c_client *); | ||
100 | typedef int (*tas_hook_post_init_t)(struct tas_data_t *); | ||
101 | typedef void (*tas_hook_uninit_t)(struct tas_data_t *); | ||
102 | |||
103 | typedef int (*tas_hook_get_mixer_level_t)(struct tas_data_t *,int,uint *); | ||
104 | typedef int (*tas_hook_set_mixer_level_t)(struct tas_data_t *,int,uint); | ||
105 | |||
106 | typedef int (*tas_hook_enter_sleep_t)(struct tas_data_t *); | ||
107 | typedef int (*tas_hook_leave_sleep_t)(struct tas_data_t *); | ||
108 | |||
109 | typedef int (*tas_hook_supported_mixers_t)(struct tas_data_t *); | ||
110 | typedef int (*tas_hook_mixer_is_stereo_t)(struct tas_data_t *,int); | ||
111 | typedef int (*tas_hook_stereo_mixers_t)(struct tas_data_t *); | ||
112 | |||
113 | typedef int (*tas_hook_output_device_change_t)(struct tas_data_t *,int,int,int); | ||
114 | typedef int (*tas_hook_device_ioctl_t)(struct tas_data_t *,u_int,u_long); | ||
115 | |||
116 | struct tas_driver_hooks_t { | ||
117 | /* | ||
118 | * All hardware initialisation must be performed in | ||
119 | * post_init(), as tas_dmasound_init() does a hardware reset. | ||
120 | * | ||
121 | * init() is called before tas_dmasound_init() so that | ||
122 | * ouput_device_change() is always called after i2c driver | ||
123 | * initialisation. The implication is that | ||
124 | * output_device_change() must cope with the fact that it | ||
125 | * may be called before post_init(). | ||
126 | */ | ||
127 | |||
128 | tas_hook_init_t init; | ||
129 | tas_hook_post_init_t post_init; | ||
130 | tas_hook_uninit_t uninit; | ||
131 | |||
132 | tas_hook_get_mixer_level_t get_mixer_level; | ||
133 | tas_hook_set_mixer_level_t set_mixer_level; | ||
134 | |||
135 | tas_hook_enter_sleep_t enter_sleep; | ||
136 | tas_hook_leave_sleep_t leave_sleep; | ||
137 | |||
138 | tas_hook_supported_mixers_t supported_mixers; | ||
139 | tas_hook_mixer_is_stereo_t mixer_is_stereo; | ||
140 | tas_hook_stereo_mixers_t stereo_mixers; | ||
141 | |||
142 | tas_hook_output_device_change_t output_device_change; | ||
143 | tas_hook_device_ioctl_t device_ioctl; | ||
144 | }; | ||
145 | |||
146 | enum tas_write_mode_t { | ||
147 | WRITE_HW = 0x01, | ||
148 | WRITE_SHADOW = 0x02, | ||
149 | WRITE_NORMAL = 0x03, | ||
150 | FORCE_WRITE = 0x04 | ||
151 | }; | ||
152 | |||
153 | static inline uint | ||
154 | tas_mono_to_stereo(uint mono) | ||
155 | { | ||
156 | mono &=0xff; | ||
157 | return mono | (mono<<8); | ||
158 | } | ||
159 | |||
160 | /* | ||
161 | * Todo: make these functions a bit more efficient ! | ||
162 | */ | ||
163 | static inline int | ||
164 | tas_write_register( struct tas_data_t *self, | ||
165 | uint reg_num, | ||
166 | uint reg_width, | ||
167 | char *data, | ||
168 | uint write_mode) | ||
169 | { | ||
170 | int rc; | ||
171 | |||
172 | if (reg_width==0 || data==NULL || self==NULL) | ||
173 | return -EINVAL; | ||
174 | if (!(write_mode & FORCE_WRITE) && | ||
175 | !memcmp(data,self->shadow[reg_num],reg_width)) | ||
176 | return 0; | ||
177 | |||
178 | if (write_mode & WRITE_SHADOW) | ||
179 | memcpy(self->shadow[reg_num],data,reg_width); | ||
180 | if (write_mode & WRITE_HW) { | ||
181 | rc=i2c_smbus_write_block_data(self->client, | ||
182 | reg_num, | ||
183 | reg_width, | ||
184 | data); | ||
185 | if (rc < 0) { | ||
186 | printk("tas: I2C block write failed \n"); | ||
187 | return rc; | ||
188 | } | ||
189 | } | ||
190 | return 0; | ||
191 | } | ||
192 | |||
193 | static inline int | ||
194 | tas_sync_register( struct tas_data_t *self, | ||
195 | uint reg_num, | ||
196 | uint reg_width) | ||
197 | { | ||
198 | int rc; | ||
199 | |||
200 | if (reg_width==0 || self==NULL) | ||
201 | return -EINVAL; | ||
202 | rc=i2c_smbus_write_block_data(self->client, | ||
203 | reg_num, | ||
204 | reg_width, | ||
205 | self->shadow[reg_num]); | ||
206 | if (rc < 0) { | ||
207 | printk("tas: I2C block write failed \n"); | ||
208 | return rc; | ||
209 | } | ||
210 | return 0; | ||
211 | } | ||
212 | |||
213 | static inline int | ||
214 | tas_write_byte_register( struct tas_data_t *self, | ||
215 | uint reg_num, | ||
216 | char data, | ||
217 | uint write_mode) | ||
218 | { | ||
219 | if (self==NULL) | ||
220 | return -1; | ||
221 | if (!(write_mode & FORCE_WRITE) && data != self->shadow[reg_num][0]) | ||
222 | return 0; | ||
223 | if (write_mode & WRITE_SHADOW) | ||
224 | self->shadow[reg_num][0]=data; | ||
225 | if (write_mode & WRITE_HW) { | ||
226 | if (i2c_smbus_write_byte_data(self->client, reg_num, data) < 0) { | ||
227 | printk("tas: I2C byte write failed \n"); | ||
228 | return -1; | ||
229 | } | ||
230 | } | ||
231 | return 0; | ||
232 | } | ||
233 | |||
234 | static inline int | ||
235 | tas_sync_byte_register( struct tas_data_t *self, | ||
236 | uint reg_num, | ||
237 | uint reg_width) | ||
238 | { | ||
239 | if (reg_width==0 || self==NULL) | ||
240 | return -1; | ||
241 | if (i2c_smbus_write_byte_data( | ||
242 | self->client, reg_num, self->shadow[reg_num][0]) < 0) { | ||
243 | printk("tas: I2C byte write failed \n"); | ||
244 | return -1; | ||
245 | } | ||
246 | return 0; | ||
247 | } | ||
248 | |||
249 | static inline int | ||
250 | tas_read_register( struct tas_data_t *self, | ||
251 | uint reg_num, | ||
252 | uint reg_width, | ||
253 | char *data) | ||
254 | { | ||
255 | if (reg_width==0 || data==NULL || self==NULL) | ||
256 | return -1; | ||
257 | memcpy(data,self->shadow[reg_num],reg_width); | ||
258 | return 0; | ||
259 | } | ||
260 | |||
261 | extern int tas_register_driver(struct tas_driver_hooks_t *hooks); | ||
262 | |||
263 | extern int tas_get_mixer_level(int mixer,uint *level); | ||
264 | extern int tas_set_mixer_level(int mixer,uint level); | ||
265 | extern int tas_enter_sleep(void); | ||
266 | extern int tas_leave_sleep(void); | ||
267 | extern int tas_supported_mixers(void); | ||
268 | extern int tas_mixer_is_stereo(int mixer); | ||
269 | extern int tas_stereo_mixers(void); | ||
270 | extern int tas_output_device_change(int,int,int); | ||
271 | extern int tas_device_ioctl(u_int, u_long); | ||
272 | |||
273 | extern void tas_cleanup(void); | ||
274 | extern int tas_init(int driver_id,const char *driver_name); | ||
275 | extern int tas_post_init(void); | ||
276 | |||
277 | #endif /* _TAS_COMMON_H_ */ | ||
278 | /* | ||
279 | * Local Variables: | ||
280 | * tab-width: 8 | ||
281 | * indent-tabs-mode: t | ||
282 | * c-basic-offset: 8 | ||
283 | * End: | ||
284 | */ | ||