diff options
Diffstat (limited to 'sound/pci/asihpi/hpicmn.c')
-rw-r--r-- | sound/pci/asihpi/hpicmn.c | 496 |
1 files changed, 278 insertions, 218 deletions
diff --git a/sound/pci/asihpi/hpicmn.c b/sound/pci/asihpi/hpicmn.c index dda4f1c6f658..b15a02e91f82 100644 --- a/sound/pci/asihpi/hpicmn.c +++ b/sound/pci/asihpi/hpicmn.c | |||
@@ -26,6 +26,8 @@ | |||
26 | 26 | ||
27 | #include "hpi_internal.h" | 27 | #include "hpi_internal.h" |
28 | #include "hpidebug.h" | 28 | #include "hpidebug.h" |
29 | #include "hpimsginit.h" | ||
30 | |||
29 | #include "hpicmn.h" | 31 | #include "hpicmn.h" |
30 | 32 | ||
31 | struct hpi_adapters_list { | 33 | struct hpi_adapters_list { |
@@ -43,14 +45,24 @@ static struct hpi_adapters_list adapters; | |||
43 | **/ | 45 | **/ |
44 | u16 hpi_validate_response(struct hpi_message *phm, struct hpi_response *phr) | 46 | u16 hpi_validate_response(struct hpi_message *phm, struct hpi_response *phr) |
45 | { | 47 | { |
46 | u16 error = 0; | 48 | if (phr->type != HPI_TYPE_RESPONSE) { |
49 | HPI_DEBUG_LOG(ERROR, "header type %d invalid\n", phr->type); | ||
50 | return HPI_ERROR_INVALID_RESPONSE; | ||
51 | } | ||
52 | |||
53 | if (phr->object != phm->object) { | ||
54 | HPI_DEBUG_LOG(ERROR, "header object %d invalid\n", | ||
55 | phr->object); | ||
56 | return HPI_ERROR_INVALID_RESPONSE; | ||
57 | } | ||
47 | 58 | ||
48 | if ((phr->type != HPI_TYPE_RESPONSE) | 59 | if (phr->function != phm->function) { |
49 | || (phr->object != phm->object) | 60 | HPI_DEBUG_LOG(ERROR, "header type %d invalid\n", |
50 | || (phr->function != phm->function)) | 61 | phr->function); |
51 | error = HPI_ERROR_INVALID_RESPONSE; | 62 | return HPI_ERROR_INVALID_RESPONSE; |
63 | } | ||
52 | 64 | ||
53 | return error; | 65 | return 0; |
54 | } | 66 | } |
55 | 67 | ||
56 | u16 hpi_add_adapter(struct hpi_adapter_obj *pao) | 68 | u16 hpi_add_adapter(struct hpi_adapter_obj *pao) |
@@ -66,8 +78,18 @@ u16 hpi_add_adapter(struct hpi_adapter_obj *pao) | |||
66 | } | 78 | } |
67 | 79 | ||
68 | if (adapters.adapter[pao->index].adapter_type) { | 80 | if (adapters.adapter[pao->index].adapter_type) { |
69 | { | 81 | int a; |
70 | retval = HPI_DUPLICATE_ADAPTER_NUMBER; | 82 | for (a = HPI_MAX_ADAPTERS - 1; a >= 0; a--) { |
83 | if (!adapters.adapter[a].adapter_type) { | ||
84 | HPI_DEBUG_LOG(WARNING, | ||
85 | "ASI%X duplicate index %d moved to %d\n", | ||
86 | pao->adapter_type, pao->index, a); | ||
87 | pao->index = a; | ||
88 | break; | ||
89 | } | ||
90 | } | ||
91 | if (a < 0) { | ||
92 | retval = HPI_ERROR_DUPLICATE_ADAPTER_NUMBER; | ||
71 | goto unlock; | 93 | goto unlock; |
72 | } | 94 | } |
73 | } | 95 | } |
@@ -76,17 +98,22 @@ u16 hpi_add_adapter(struct hpi_adapter_obj *pao) | |||
76 | adapters.gw_num_adapters++; | 98 | adapters.gw_num_adapters++; |
77 | 99 | ||
78 | unlock: | 100 | unlock: |
79 | hpios_alistlock_un_lock(&adapters); | 101 | hpios_alistlock_unlock(&adapters); |
80 | return retval; | 102 | return retval; |
81 | } | 103 | } |
82 | 104 | ||
83 | void hpi_delete_adapter(struct hpi_adapter_obj *pao) | 105 | void hpi_delete_adapter(struct hpi_adapter_obj *pao) |
84 | { | 106 | { |
85 | memset(pao, 0, sizeof(struct hpi_adapter_obj)); | 107 | if (!pao->adapter_type) { |
108 | HPI_DEBUG_LOG(ERROR, "removing null adapter?\n"); | ||
109 | return; | ||
110 | } | ||
86 | 111 | ||
87 | hpios_alistlock_lock(&adapters); | 112 | hpios_alistlock_lock(&adapters); |
88 | adapters.gw_num_adapters--; /* dec the number of adapters */ | 113 | if (adapters.adapter[pao->index].adapter_type) |
89 | hpios_alistlock_un_lock(&adapters); | 114 | adapters.gw_num_adapters--; |
115 | memset(&adapters.adapter[pao->index], 0, sizeof(adapters.adapter[0])); | ||
116 | hpios_alistlock_unlock(&adapters); | ||
90 | } | 117 | } |
91 | 118 | ||
92 | /** | 119 | /** |
@@ -99,7 +126,7 @@ struct hpi_adapter_obj *hpi_find_adapter(u16 adapter_index) | |||
99 | struct hpi_adapter_obj *pao = NULL; | 126 | struct hpi_adapter_obj *pao = NULL; |
100 | 127 | ||
101 | if (adapter_index >= HPI_MAX_ADAPTERS) { | 128 | if (adapter_index >= HPI_MAX_ADAPTERS) { |
102 | HPI_DEBUG_LOG(VERBOSE, "find_adapter invalid index %d ", | 129 | HPI_DEBUG_LOG(VERBOSE, "find_adapter invalid index %d\n", |
103 | adapter_index); | 130 | adapter_index); |
104 | return NULL; | 131 | return NULL; |
105 | } | 132 | } |
@@ -125,51 +152,34 @@ struct hpi_adapter_obj *hpi_find_adapter(u16 adapter_index) | |||
125 | * wipe an HPI_ADAPTERS_LIST structure. | 152 | * wipe an HPI_ADAPTERS_LIST structure. |
126 | * | 153 | * |
127 | **/ | 154 | **/ |
128 | static void wipe_adapter_list(void | 155 | static void wipe_adapter_list(void) |
129 | ) | ||
130 | { | 156 | { |
131 | memset(&adapters, 0, sizeof(adapters)); | 157 | memset(&adapters, 0, sizeof(adapters)); |
132 | } | 158 | } |
133 | 159 | ||
134 | /** | 160 | static void subsys_get_adapter(struct hpi_message *phm, |
135 | * SubSysGetAdapters fills awAdapterList in an struct hpi_response structure | 161 | struct hpi_response *phr) |
136 | * with all adapters in the given HPI_ADAPTERS_LIST. | ||
137 | * | ||
138 | */ | ||
139 | static void subsys_get_adapters(struct hpi_response *phr) | ||
140 | { | 162 | { |
141 | /* fill in the response adapter array with the position */ | 163 | int count = phm->obj_index; |
142 | /* identified by the adapter number/index of the adapters in */ | 164 | u16 index = 0; |
143 | /* this HPI */ | ||
144 | /* i.e. if we have an A120 with it's jumper set to */ | ||
145 | /* Adapter Number 2 then put an Adapter type A120 in the */ | ||
146 | /* array in position 1 */ | ||
147 | /* NOTE: AdapterNumber is 1..N, Index is 0..N-1 */ | ||
148 | |||
149 | /* input: NONE */ | ||
150 | /* output: wNumAdapters */ | ||
151 | /* awAdapter[] */ | ||
152 | /* */ | ||
153 | |||
154 | short i; | ||
155 | struct hpi_adapter_obj *pao = NULL; | ||
156 | |||
157 | HPI_DEBUG_LOG(VERBOSE, "subsys_get_adapters\n"); | ||
158 | 165 | ||
159 | /* for each adapter, place it's type in the position of the array */ | 166 | /* find the nCount'th nonzero adapter in array */ |
160 | /* corresponding to it's adapter number */ | 167 | for (index = 0; index < HPI_MAX_ADAPTERS; index++) { |
161 | for (i = 0; i < adapters.gw_num_adapters; i++) { | 168 | if (adapters.adapter[index].adapter_type) { |
162 | pao = &adapters.adapter[i]; | 169 | if (!count) |
163 | if (phr->u.s.aw_adapter_list[pao->index] != 0) { | 170 | break; |
164 | phr->error = HPI_DUPLICATE_ADAPTER_NUMBER; | 171 | count--; |
165 | phr->specific_error = pao->index; | ||
166 | return; | ||
167 | } | 172 | } |
168 | phr->u.s.aw_adapter_list[pao->index] = pao->adapter_type; | ||
169 | } | 173 | } |
170 | 174 | ||
171 | phr->u.s.num_adapters = adapters.gw_num_adapters; | 175 | if (index < HPI_MAX_ADAPTERS) { |
172 | phr->error = 0; /* the function completed OK; */ | 176 | phr->u.s.adapter_index = adapters.adapter[index].index; |
177 | phr->u.s.adapter_type = adapters.adapter[index].adapter_type; | ||
178 | } else { | ||
179 | phr->u.s.adapter_index = 0; | ||
180 | phr->u.s.adapter_type = 0; | ||
181 | phr->error = HPI_ERROR_BAD_ADAPTER_NUMBER; | ||
182 | } | ||
173 | } | 183 | } |
174 | 184 | ||
175 | static unsigned int control_cache_alloc_check(struct hpi_control_cache *pC) | 185 | static unsigned int control_cache_alloc_check(struct hpi_control_cache *pC) |
@@ -178,67 +188,99 @@ static unsigned int control_cache_alloc_check(struct hpi_control_cache *pC) | |||
178 | int cached = 0; | 188 | int cached = 0; |
179 | if (!pC) | 189 | if (!pC) |
180 | return 0; | 190 | return 0; |
181 | if ((!pC->init) && (pC->p_cache != NULL) && (pC->control_count) | 191 | |
182 | && (pC->cache_size_in_bytes) | 192 | if (pC->init) |
183 | ) { | 193 | return pC->init; |
184 | u32 *p_master_cache; | 194 | |
185 | pC->init = 1; | 195 | if (!pC->p_cache) |
186 | 196 | return 0; | |
187 | p_master_cache = (u32 *)pC->p_cache; | 197 | |
188 | HPI_DEBUG_LOG(VERBOSE, "check %d controls\n", | 198 | if (pC->control_count && pC->cache_size_in_bytes) { |
199 | char *p_master_cache; | ||
200 | unsigned int byte_count = 0; | ||
201 | |||
202 | p_master_cache = (char *)pC->p_cache; | ||
203 | HPI_DEBUG_LOG(DEBUG, "check %d controls\n", | ||
189 | pC->control_count); | 204 | pC->control_count); |
190 | for (i = 0; i < pC->control_count; i++) { | 205 | for (i = 0; i < pC->control_count; i++) { |
191 | struct hpi_control_cache_info *info = | 206 | struct hpi_control_cache_info *info = |
192 | (struct hpi_control_cache_info *) | 207 | (struct hpi_control_cache_info *) |
193 | p_master_cache; | 208 | &p_master_cache[byte_count]; |
209 | |||
210 | if (!info->size_in32bit_words) { | ||
211 | if (!i) { | ||
212 | HPI_DEBUG_LOG(INFO, | ||
213 | "adap %d cache not ready?\n", | ||
214 | pC->adap_idx); | ||
215 | return 0; | ||
216 | } | ||
217 | /* The cache is invalid. | ||
218 | * Minimum valid entry size is | ||
219 | * sizeof(struct hpi_control_cache_info) | ||
220 | */ | ||
221 | HPI_DEBUG_LOG(ERROR, | ||
222 | "adap %d zero size cache entry %d\n", | ||
223 | pC->adap_idx, i); | ||
224 | break; | ||
225 | } | ||
194 | 226 | ||
195 | if (info->control_type) { | 227 | if (info->control_type) { |
196 | pC->p_info[i] = info; | 228 | pC->p_info[info->control_index] = info; |
197 | cached++; | 229 | cached++; |
198 | } else | 230 | } else { /* dummy cache entry */ |
199 | pC->p_info[i] = NULL; | 231 | pC->p_info[info->control_index] = NULL; |
232 | } | ||
200 | 233 | ||
201 | if (info->size_in32bit_words) | 234 | byte_count += info->size_in32bit_words * 4; |
202 | p_master_cache += info->size_in32bit_words; | ||
203 | else | ||
204 | p_master_cache += | ||
205 | sizeof(struct | ||
206 | hpi_control_cache_single) / | ||
207 | sizeof(u32); | ||
208 | 235 | ||
209 | HPI_DEBUG_LOG(VERBOSE, | 236 | HPI_DEBUG_LOG(VERBOSE, |
210 | "cached %d, pinfo %p index %d type %d\n", | 237 | "cached %d, pinfo %p index %d type %d size %d\n", |
211 | cached, pC->p_info[i], info->control_index, | 238 | cached, pC->p_info[info->control_index], |
212 | info->control_type); | 239 | info->control_index, info->control_type, |
240 | info->size_in32bit_words); | ||
241 | |||
242 | /* quit loop early if whole cache has been scanned. | ||
243 | * dwControlCount is the maximum possible entries | ||
244 | * but some may be absent from the cache | ||
245 | */ | ||
246 | if (byte_count >= pC->cache_size_in_bytes) | ||
247 | break; | ||
248 | /* have seen last control index */ | ||
249 | if (info->control_index == pC->control_count - 1) | ||
250 | break; | ||
213 | } | 251 | } |
214 | /* | 252 | |
215 | We didn't find anything to cache, so try again later ! | 253 | if (byte_count != pC->cache_size_in_bytes) |
216 | */ | 254 | HPI_DEBUG_LOG(WARNING, |
217 | if (!cached) | 255 | "adap %d bytecount %d != cache size %d\n", |
218 | pC->init = 0; | 256 | pC->adap_idx, byte_count, |
257 | pC->cache_size_in_bytes); | ||
258 | else | ||
259 | HPI_DEBUG_LOG(DEBUG, | ||
260 | "adap %d cache good, bytecount == cache size = %d\n", | ||
261 | pC->adap_idx, byte_count); | ||
262 | |||
263 | pC->init = (u16)cached; | ||
219 | } | 264 | } |
220 | return pC->init; | 265 | return pC->init; |
221 | } | 266 | } |
222 | 267 | ||
223 | /** Find a control. | 268 | /** Find a control. |
224 | */ | 269 | */ |
225 | static short find_control(struct hpi_message *phm, | 270 | static short find_control(u16 control_index, |
226 | struct hpi_control_cache *p_cache, struct hpi_control_cache_info **pI, | 271 | struct hpi_control_cache *p_cache, struct hpi_control_cache_info **pI) |
227 | u16 *pw_control_index) | ||
228 | { | 272 | { |
229 | *pw_control_index = phm->obj_index; | ||
230 | |||
231 | if (!control_cache_alloc_check(p_cache)) { | 273 | if (!control_cache_alloc_check(p_cache)) { |
232 | HPI_DEBUG_LOG(VERBOSE, | 274 | HPI_DEBUG_LOG(VERBOSE, |
233 | "control_cache_alloc_check() failed. adap%d ci%d\n", | 275 | "control_cache_alloc_check() failed %d\n", |
234 | phm->adapter_index, *pw_control_index); | 276 | control_index); |
235 | return 0; | 277 | return 0; |
236 | } | 278 | } |
237 | 279 | ||
238 | *pI = p_cache->p_info[*pw_control_index]; | 280 | *pI = p_cache->p_info[control_index]; |
239 | if (!*pI) { | 281 | if (!*pI) { |
240 | HPI_DEBUG_LOG(VERBOSE, "uncached adap %d, control %d\n", | 282 | HPI_DEBUG_LOG(VERBOSE, "Uncached Control %d\n", |
241 | phm->adapter_index, *pw_control_index); | 283 | control_index); |
242 | return 0; | 284 | return 0; |
243 | } else { | 285 | } else { |
244 | HPI_DEBUG_LOG(VERBOSE, "find_control() type %d\n", | 286 | HPI_DEBUG_LOG(VERBOSE, "find_control() type %d\n", |
@@ -247,25 +289,6 @@ static short find_control(struct hpi_message *phm, | |||
247 | return 1; | 289 | return 1; |
248 | } | 290 | } |
249 | 291 | ||
250 | /** Used by the kernel driver to figure out if a buffer needs mapping. | ||
251 | */ | ||
252 | short hpi_check_buffer_mapping(struct hpi_control_cache *p_cache, | ||
253 | struct hpi_message *phm, void **p, unsigned int *pN) | ||
254 | { | ||
255 | *pN = 0; | ||
256 | *p = NULL; | ||
257 | if ((phm->function == HPI_CONTROL_GET_STATE) | ||
258 | && (phm->object == HPI_OBJ_CONTROLEX) | ||
259 | ) { | ||
260 | u16 control_index; | ||
261 | struct hpi_control_cache_info *pI; | ||
262 | |||
263 | if (!find_control(phm, p_cache, &pI, &control_index)) | ||
264 | return 0; | ||
265 | } | ||
266 | return 0; | ||
267 | } | ||
268 | |||
269 | /* allow unified treatment of several string fields within struct */ | 292 | /* allow unified treatment of several string fields within struct */ |
270 | #define HPICMN_PAD_OFS_AND_SIZE(m) {\ | 293 | #define HPICMN_PAD_OFS_AND_SIZE(m) {\ |
271 | offsetof(struct hpi_control_cache_pad, m), \ | 294 | offsetof(struct hpi_control_cache_pad, m), \ |
@@ -276,7 +299,7 @@ struct pad_ofs_size { | |||
276 | unsigned int field_size; | 299 | unsigned int field_size; |
277 | }; | 300 | }; |
278 | 301 | ||
279 | static struct pad_ofs_size pad_desc[] = { | 302 | static const struct pad_ofs_size pad_desc[] = { |
280 | HPICMN_PAD_OFS_AND_SIZE(c_channel), /* HPI_PAD_CHANNEL_NAME */ | 303 | HPICMN_PAD_OFS_AND_SIZE(c_channel), /* HPI_PAD_CHANNEL_NAME */ |
281 | HPICMN_PAD_OFS_AND_SIZE(c_artist), /* HPI_PAD_ARTIST */ | 304 | HPICMN_PAD_OFS_AND_SIZE(c_artist), /* HPI_PAD_ARTIST */ |
282 | HPICMN_PAD_OFS_AND_SIZE(c_title), /* HPI_PAD_TITLE */ | 305 | HPICMN_PAD_OFS_AND_SIZE(c_title), /* HPI_PAD_TITLE */ |
@@ -290,13 +313,16 @@ short hpi_check_control_cache(struct hpi_control_cache *p_cache, | |||
290 | struct hpi_message *phm, struct hpi_response *phr) | 313 | struct hpi_message *phm, struct hpi_response *phr) |
291 | { | 314 | { |
292 | short found = 1; | 315 | short found = 1; |
293 | u16 control_index; | ||
294 | struct hpi_control_cache_info *pI; | 316 | struct hpi_control_cache_info *pI; |
295 | struct hpi_control_cache_single *pC; | 317 | struct hpi_control_cache_single *pC; |
296 | struct hpi_control_cache_pad *p_pad; | 318 | struct hpi_control_cache_pad *p_pad; |
297 | 319 | ||
298 | if (!find_control(phm, p_cache, &pI, &control_index)) | 320 | if (!find_control(phm->obj_index, p_cache, &pI)) { |
321 | HPI_DEBUG_LOG(VERBOSE, | ||
322 | "HPICMN find_control() failed for adap %d\n", | ||
323 | phm->adapter_index); | ||
299 | return 0; | 324 | return 0; |
325 | } | ||
300 | 326 | ||
301 | phr->error = 0; | 327 | phr->error = 0; |
302 | 328 | ||
@@ -310,55 +336,79 @@ short hpi_check_control_cache(struct hpi_control_cache *p_cache, | |||
310 | 336 | ||
311 | case HPI_CONTROL_METER: | 337 | case HPI_CONTROL_METER: |
312 | if (phm->u.c.attribute == HPI_METER_PEAK) { | 338 | if (phm->u.c.attribute == HPI_METER_PEAK) { |
313 | phr->u.c.an_log_value[0] = pC->u.p.an_log_peak[0]; | 339 | phr->u.c.an_log_value[0] = pC->u.meter.an_log_peak[0]; |
314 | phr->u.c.an_log_value[1] = pC->u.p.an_log_peak[1]; | 340 | phr->u.c.an_log_value[1] = pC->u.meter.an_log_peak[1]; |
315 | } else if (phm->u.c.attribute == HPI_METER_RMS) { | 341 | } else if (phm->u.c.attribute == HPI_METER_RMS) { |
316 | phr->u.c.an_log_value[0] = pC->u.p.an_logRMS[0]; | 342 | if (pC->u.meter.an_logRMS[0] == |
317 | phr->u.c.an_log_value[1] = pC->u.p.an_logRMS[1]; | 343 | HPI_CACHE_INVALID_SHORT) { |
344 | phr->error = | ||
345 | HPI_ERROR_INVALID_CONTROL_ATTRIBUTE; | ||
346 | phr->u.c.an_log_value[0] = HPI_METER_MINIMUM; | ||
347 | phr->u.c.an_log_value[1] = HPI_METER_MINIMUM; | ||
348 | } else { | ||
349 | phr->u.c.an_log_value[0] = | ||
350 | pC->u.meter.an_logRMS[0]; | ||
351 | phr->u.c.an_log_value[1] = | ||
352 | pC->u.meter.an_logRMS[1]; | ||
353 | } | ||
318 | } else | 354 | } else |
319 | found = 0; | 355 | found = 0; |
320 | break; | 356 | break; |
321 | case HPI_CONTROL_VOLUME: | 357 | case HPI_CONTROL_VOLUME: |
322 | if (phm->u.c.attribute == HPI_VOLUME_GAIN) { | 358 | if (phm->u.c.attribute == HPI_VOLUME_GAIN) { |
323 | phr->u.c.an_log_value[0] = pC->u.v.an_log[0]; | 359 | phr->u.c.an_log_value[0] = pC->u.vol.an_log[0]; |
324 | phr->u.c.an_log_value[1] = pC->u.v.an_log[1]; | 360 | phr->u.c.an_log_value[1] = pC->u.vol.an_log[1]; |
325 | } else | 361 | } else if (phm->u.c.attribute == HPI_VOLUME_MUTE) { |
362 | if (pC->u.vol.flags & HPI_VOLUME_FLAG_HAS_MUTE) { | ||
363 | if (pC->u.vol.flags & HPI_VOLUME_FLAG_MUTED) | ||
364 | phr->u.c.param1 = | ||
365 | HPI_BITMASK_ALL_CHANNELS; | ||
366 | else | ||
367 | phr->u.c.param1 = 0; | ||
368 | } else { | ||
369 | phr->error = | ||
370 | HPI_ERROR_INVALID_CONTROL_ATTRIBUTE; | ||
371 | phr->u.c.param1 = 0; | ||
372 | } | ||
373 | } else { | ||
326 | found = 0; | 374 | found = 0; |
375 | } | ||
327 | break; | 376 | break; |
328 | case HPI_CONTROL_MULTIPLEXER: | 377 | case HPI_CONTROL_MULTIPLEXER: |
329 | if (phm->u.c.attribute == HPI_MULTIPLEXER_SOURCE) { | 378 | if (phm->u.c.attribute == HPI_MULTIPLEXER_SOURCE) { |
330 | phr->u.c.param1 = pC->u.x.source_node_type; | 379 | phr->u.c.param1 = pC->u.mux.source_node_type; |
331 | phr->u.c.param2 = pC->u.x.source_node_index; | 380 | phr->u.c.param2 = pC->u.mux.source_node_index; |
332 | } else { | 381 | } else { |
333 | found = 0; | 382 | found = 0; |
334 | } | 383 | } |
335 | break; | 384 | break; |
336 | case HPI_CONTROL_CHANNEL_MODE: | 385 | case HPI_CONTROL_CHANNEL_MODE: |
337 | if (phm->u.c.attribute == HPI_CHANNEL_MODE_MODE) | 386 | if (phm->u.c.attribute == HPI_CHANNEL_MODE_MODE) |
338 | phr->u.c.param1 = pC->u.m.mode; | 387 | phr->u.c.param1 = pC->u.mode.mode; |
339 | else | 388 | else |
340 | found = 0; | 389 | found = 0; |
341 | break; | 390 | break; |
342 | case HPI_CONTROL_LEVEL: | 391 | case HPI_CONTROL_LEVEL: |
343 | if (phm->u.c.attribute == HPI_LEVEL_GAIN) { | 392 | if (phm->u.c.attribute == HPI_LEVEL_GAIN) { |
344 | phr->u.c.an_log_value[0] = pC->u.l.an_log[0]; | 393 | phr->u.c.an_log_value[0] = pC->u.level.an_log[0]; |
345 | phr->u.c.an_log_value[1] = pC->u.l.an_log[1]; | 394 | phr->u.c.an_log_value[1] = pC->u.level.an_log[1]; |
346 | } else | 395 | } else |
347 | found = 0; | 396 | found = 0; |
348 | break; | 397 | break; |
349 | case HPI_CONTROL_TUNER: | 398 | case HPI_CONTROL_TUNER: |
350 | if (phm->u.c.attribute == HPI_TUNER_FREQ) | 399 | if (phm->u.c.attribute == HPI_TUNER_FREQ) |
351 | phr->u.c.param1 = pC->u.t.freq_ink_hz; | 400 | phr->u.c.param1 = pC->u.tuner.freq_ink_hz; |
352 | else if (phm->u.c.attribute == HPI_TUNER_BAND) | 401 | else if (phm->u.c.attribute == HPI_TUNER_BAND) |
353 | phr->u.c.param1 = pC->u.t.band; | 402 | phr->u.c.param1 = pC->u.tuner.band; |
354 | else if ((phm->u.c.attribute == HPI_TUNER_LEVEL) | 403 | else if (phm->u.c.attribute == HPI_TUNER_LEVEL_AVG) |
355 | && (phm->u.c.param1 == HPI_TUNER_LEVEL_AVERAGE)) | 404 | if (pC->u.tuner.s_level_avg == |
356 | if (pC->u.t.level == HPI_ERROR_ILLEGAL_CACHE_VALUE) { | 405 | HPI_CACHE_INVALID_SHORT) { |
357 | phr->u.c.param1 = 0; | 406 | phr->u.cu.tuner.s_level = 0; |
358 | phr->error = | 407 | phr->error = |
359 | HPI_ERROR_INVALID_CONTROL_ATTRIBUTE; | 408 | HPI_ERROR_INVALID_CONTROL_ATTRIBUTE; |
360 | } else | 409 | } else |
361 | phr->u.c.param1 = pC->u.t.level; | 410 | phr->u.cu.tuner.s_level = |
411 | pC->u.tuner.s_level_avg; | ||
362 | else | 412 | else |
363 | found = 0; | 413 | found = 0; |
364 | break; | 414 | break; |
@@ -366,7 +416,7 @@ short hpi_check_control_cache(struct hpi_control_cache *p_cache, | |||
366 | if (phm->u.c.attribute == HPI_AESEBURX_ERRORSTATUS) | 416 | if (phm->u.c.attribute == HPI_AESEBURX_ERRORSTATUS) |
367 | phr->u.c.param1 = pC->u.aes3rx.error_status; | 417 | phr->u.c.param1 = pC->u.aes3rx.error_status; |
368 | else if (phm->u.c.attribute == HPI_AESEBURX_FORMAT) | 418 | else if (phm->u.c.attribute == HPI_AESEBURX_FORMAT) |
369 | phr->u.c.param1 = pC->u.aes3rx.source; | 419 | phr->u.c.param1 = pC->u.aes3rx.format; |
370 | else | 420 | else |
371 | found = 0; | 421 | found = 0; |
372 | break; | 422 | break; |
@@ -385,13 +435,12 @@ short hpi_check_control_cache(struct hpi_control_cache *p_cache, | |||
385 | case HPI_CONTROL_SILENCEDETECTOR: | 435 | case HPI_CONTROL_SILENCEDETECTOR: |
386 | if (phm->u.c.attribute == HPI_SILENCEDETECTOR_STATE) { | 436 | if (phm->u.c.attribute == HPI_SILENCEDETECTOR_STATE) { |
387 | phr->u.c.param1 = pC->u.silence.state; | 437 | phr->u.c.param1 = pC->u.silence.state; |
388 | phr->u.c.param2 = pC->u.silence.count; | ||
389 | } else | 438 | } else |
390 | found = 0; | 439 | found = 0; |
391 | break; | 440 | break; |
392 | case HPI_CONTROL_MICROPHONE: | 441 | case HPI_CONTROL_MICROPHONE: |
393 | if (phm->u.c.attribute == HPI_MICROPHONE_PHANTOM_POWER) | 442 | if (phm->u.c.attribute == HPI_MICROPHONE_PHANTOM_POWER) |
394 | phr->u.c.param1 = pC->u.phantom_power.state; | 443 | phr->u.c.param1 = pC->u.microphone.phantom_state; |
395 | else | 444 | else |
396 | found = 0; | 445 | found = 0; |
397 | break; | 446 | break; |
@@ -400,7 +449,7 @@ short hpi_check_control_cache(struct hpi_control_cache *p_cache, | |||
400 | phr->u.c.param1 = pC->u.clk.source; | 449 | phr->u.c.param1 = pC->u.clk.source; |
401 | else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE_INDEX) { | 450 | else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE_INDEX) { |
402 | if (pC->u.clk.source_index == | 451 | if (pC->u.clk.source_index == |
403 | HPI_ERROR_ILLEGAL_CACHE_VALUE) { | 452 | HPI_CACHE_INVALID_UINT16) { |
404 | phr->u.c.param1 = 0; | 453 | phr->u.c.param1 = 0; |
405 | phr->error = | 454 | phr->error = |
406 | HPI_ERROR_INVALID_CONTROL_ATTRIBUTE; | 455 | HPI_ERROR_INVALID_CONTROL_ATTRIBUTE; |
@@ -411,60 +460,63 @@ short hpi_check_control_cache(struct hpi_control_cache *p_cache, | |||
411 | else | 460 | else |
412 | found = 0; | 461 | found = 0; |
413 | break; | 462 | break; |
414 | case HPI_CONTROL_PAD: | 463 | case HPI_CONTROL_PAD:{ |
415 | 464 | struct hpi_control_cache_pad *p_pad; | |
416 | if (!(p_pad->field_valid_flags & (1 << | 465 | p_pad = (struct hpi_control_cache_pad *)pI; |
417 | HPI_CTL_ATTR_INDEX(phm->u.c. | ||
418 | attribute)))) { | ||
419 | phr->error = HPI_ERROR_INVALID_CONTROL_ATTRIBUTE; | ||
420 | break; | ||
421 | } | ||
422 | 466 | ||
423 | if (phm->u.c.attribute == HPI_PAD_PROGRAM_ID) | 467 | if (!(p_pad->field_valid_flags & (1 << |
424 | phr->u.c.param1 = p_pad->pI; | 468 | HPI_CTL_ATTR_INDEX(phm->u.c. |
425 | else if (phm->u.c.attribute == HPI_PAD_PROGRAM_TYPE) | 469 | attribute)))) { |
426 | phr->u.c.param1 = p_pad->pTY; | ||
427 | else { | ||
428 | unsigned int index = | ||
429 | HPI_CTL_ATTR_INDEX(phm->u.c.attribute) - 1; | ||
430 | unsigned int offset = phm->u.c.param1; | ||
431 | unsigned int pad_string_len, field_size; | ||
432 | char *pad_string; | ||
433 | unsigned int tocopy; | ||
434 | |||
435 | HPI_DEBUG_LOG(VERBOSE, "PADS HPI_PADS_ %d\n", | ||
436 | phm->u.c.attribute); | ||
437 | |||
438 | if (index > ARRAY_SIZE(pad_desc) - 1) { | ||
439 | phr->error = | 470 | phr->error = |
440 | HPI_ERROR_INVALID_CONTROL_ATTRIBUTE; | 471 | HPI_ERROR_INVALID_CONTROL_ATTRIBUTE; |
441 | break; | 472 | break; |
442 | } | 473 | } |
443 | 474 | ||
444 | pad_string = ((char *)p_pad) + pad_desc[index].offset; | 475 | if (phm->u.c.attribute == HPI_PAD_PROGRAM_ID) |
445 | field_size = pad_desc[index].field_size; | 476 | phr->u.c.param1 = p_pad->pI; |
446 | /* Ensure null terminator */ | 477 | else if (phm->u.c.attribute == HPI_PAD_PROGRAM_TYPE) |
447 | pad_string[field_size - 1] = 0; | 478 | phr->u.c.param1 = p_pad->pTY; |
448 | 479 | else { | |
449 | pad_string_len = strlen(pad_string) + 1; | 480 | unsigned int index = |
450 | 481 | HPI_CTL_ATTR_INDEX(phm->u.c. | |
451 | if (offset > pad_string_len) { | 482 | attribute) - 1; |
452 | phr->error = HPI_ERROR_INVALID_CONTROL_VALUE; | 483 | unsigned int offset = phm->u.c.param1; |
453 | break; | 484 | unsigned int pad_string_len, field_size; |
485 | char *pad_string; | ||
486 | unsigned int tocopy; | ||
487 | |||
488 | if (index > ARRAY_SIZE(pad_desc) - 1) { | ||
489 | phr->error = | ||
490 | HPI_ERROR_INVALID_CONTROL_ATTRIBUTE; | ||
491 | break; | ||
492 | } | ||
493 | |||
494 | pad_string = | ||
495 | ((char *)p_pad) + | ||
496 | pad_desc[index].offset; | ||
497 | field_size = pad_desc[index].field_size; | ||
498 | /* Ensure null terminator */ | ||
499 | pad_string[field_size - 1] = 0; | ||
500 | |||
501 | pad_string_len = strlen(pad_string) + 1; | ||
502 | |||
503 | if (offset > pad_string_len) { | ||
504 | phr->error = | ||
505 | HPI_ERROR_INVALID_CONTROL_VALUE; | ||
506 | break; | ||
507 | } | ||
508 | |||
509 | tocopy = pad_string_len - offset; | ||
510 | if (tocopy > sizeof(phr->u.cu.chars8.sz_data)) | ||
511 | tocopy = sizeof(phr->u.cu.chars8. | ||
512 | sz_data); | ||
513 | |||
514 | memcpy(phr->u.cu.chars8.sz_data, | ||
515 | &pad_string[offset], tocopy); | ||
516 | |||
517 | phr->u.cu.chars8.remaining_chars = | ||
518 | pad_string_len - offset - tocopy; | ||
454 | } | 519 | } |
455 | |||
456 | tocopy = pad_string_len - offset; | ||
457 | if (tocopy > sizeof(phr->u.cu.chars8.sz_data)) | ||
458 | tocopy = sizeof(phr->u.cu.chars8.sz_data); | ||
459 | |||
460 | HPI_DEBUG_LOG(VERBOSE, | ||
461 | "PADS memcpy(%d), offset %d \n", tocopy, | ||
462 | offset); | ||
463 | memcpy(phr->u.cu.chars8.sz_data, &pad_string[offset], | ||
464 | tocopy); | ||
465 | |||
466 | phr->u.cu.chars8.remaining_chars = | ||
467 | pad_string_len - offset - tocopy; | ||
468 | } | 520 | } |
469 | break; | 521 | break; |
470 | default: | 522 | default: |
@@ -472,16 +524,9 @@ short hpi_check_control_cache(struct hpi_control_cache *p_cache, | |||
472 | break; | 524 | break; |
473 | } | 525 | } |
474 | 526 | ||
475 | if (found) | 527 | HPI_DEBUG_LOG(VERBOSE, "%s Adap %d, Ctl %d, Type %d, Attr %d\n", |
476 | HPI_DEBUG_LOG(VERBOSE, | 528 | found ? "Cached" : "Uncached", phm->adapter_index, |
477 | "cached adap %d, ctl %d, type %d, attr %d\n", | 529 | pI->control_index, pI->control_type, phm->u.c.attribute); |
478 | phm->adapter_index, pI->control_index, | ||
479 | pI->control_type, phm->u.c.attribute); | ||
480 | else | ||
481 | HPI_DEBUG_LOG(VERBOSE, | ||
482 | "uncached adap %d, ctl %d, ctl type %d\n", | ||
483 | phm->adapter_index, pI->control_index, | ||
484 | pI->control_type); | ||
485 | 530 | ||
486 | if (found) | 531 | if (found) |
487 | phr->size = | 532 | phr->size = |
@@ -497,18 +542,21 @@ Only update if no error. | |||
497 | Volume and Level return the limited values in the response, so use these | 542 | Volume and Level return the limited values in the response, so use these |
498 | Multiplexer does so use sent values | 543 | Multiplexer does so use sent values |
499 | */ | 544 | */ |
500 | void hpi_sync_control_cache(struct hpi_control_cache *p_cache, | 545 | void hpi_cmn_control_cache_sync_to_msg(struct hpi_control_cache *p_cache, |
501 | struct hpi_message *phm, struct hpi_response *phr) | 546 | struct hpi_message *phm, struct hpi_response *phr) |
502 | { | 547 | { |
503 | u16 control_index; | ||
504 | struct hpi_control_cache_single *pC; | 548 | struct hpi_control_cache_single *pC; |
505 | struct hpi_control_cache_info *pI; | 549 | struct hpi_control_cache_info *pI; |
506 | 550 | ||
507 | if (phr->error) | 551 | if (phr->error) |
508 | return; | 552 | return; |
509 | 553 | ||
510 | if (!find_control(phm, p_cache, &pI, &control_index)) | 554 | if (!find_control(phm->obj_index, p_cache, &pI)) { |
555 | HPI_DEBUG_LOG(VERBOSE, | ||
556 | "HPICMN find_control() failed for adap %d\n", | ||
557 | phm->adapter_index); | ||
511 | return; | 558 | return; |
559 | } | ||
512 | 560 | ||
513 | /* pC is the default cached control strucure. | 561 | /* pC is the default cached control strucure. |
514 | May be cast to something else in the following switch statement. | 562 | May be cast to something else in the following switch statement. |
@@ -518,31 +566,36 @@ void hpi_sync_control_cache(struct hpi_control_cache *p_cache, | |||
518 | switch (pI->control_type) { | 566 | switch (pI->control_type) { |
519 | case HPI_CONTROL_VOLUME: | 567 | case HPI_CONTROL_VOLUME: |
520 | if (phm->u.c.attribute == HPI_VOLUME_GAIN) { | 568 | if (phm->u.c.attribute == HPI_VOLUME_GAIN) { |
521 | pC->u.v.an_log[0] = phr->u.c.an_log_value[0]; | 569 | pC->u.vol.an_log[0] = phr->u.c.an_log_value[0]; |
522 | pC->u.v.an_log[1] = phr->u.c.an_log_value[1]; | 570 | pC->u.vol.an_log[1] = phr->u.c.an_log_value[1]; |
571 | } else if (phm->u.c.attribute == HPI_VOLUME_MUTE) { | ||
572 | if (phm->u.c.param1) | ||
573 | pC->u.vol.flags |= HPI_VOLUME_FLAG_MUTED; | ||
574 | else | ||
575 | pC->u.vol.flags &= ~HPI_VOLUME_FLAG_MUTED; | ||
523 | } | 576 | } |
524 | break; | 577 | break; |
525 | case HPI_CONTROL_MULTIPLEXER: | 578 | case HPI_CONTROL_MULTIPLEXER: |
526 | /* mux does not return its setting on Set command. */ | 579 | /* mux does not return its setting on Set command. */ |
527 | if (phm->u.c.attribute == HPI_MULTIPLEXER_SOURCE) { | 580 | if (phm->u.c.attribute == HPI_MULTIPLEXER_SOURCE) { |
528 | pC->u.x.source_node_type = (u16)phm->u.c.param1; | 581 | pC->u.mux.source_node_type = (u16)phm->u.c.param1; |
529 | pC->u.x.source_node_index = (u16)phm->u.c.param2; | 582 | pC->u.mux.source_node_index = (u16)phm->u.c.param2; |
530 | } | 583 | } |
531 | break; | 584 | break; |
532 | case HPI_CONTROL_CHANNEL_MODE: | 585 | case HPI_CONTROL_CHANNEL_MODE: |
533 | /* mode does not return its setting on Set command. */ | 586 | /* mode does not return its setting on Set command. */ |
534 | if (phm->u.c.attribute == HPI_CHANNEL_MODE_MODE) | 587 | if (phm->u.c.attribute == HPI_CHANNEL_MODE_MODE) |
535 | pC->u.m.mode = (u16)phm->u.c.param1; | 588 | pC->u.mode.mode = (u16)phm->u.c.param1; |
536 | break; | 589 | break; |
537 | case HPI_CONTROL_LEVEL: | 590 | case HPI_CONTROL_LEVEL: |
538 | if (phm->u.c.attribute == HPI_LEVEL_GAIN) { | 591 | if (phm->u.c.attribute == HPI_LEVEL_GAIN) { |
539 | pC->u.v.an_log[0] = phr->u.c.an_log_value[0]; | 592 | pC->u.vol.an_log[0] = phr->u.c.an_log_value[0]; |
540 | pC->u.v.an_log[1] = phr->u.c.an_log_value[1]; | 593 | pC->u.vol.an_log[1] = phr->u.c.an_log_value[1]; |
541 | } | 594 | } |
542 | break; | 595 | break; |
543 | case HPI_CONTROL_MICROPHONE: | 596 | case HPI_CONTROL_MICROPHONE: |
544 | if (phm->u.c.attribute == HPI_MICROPHONE_PHANTOM_POWER) | 597 | if (phm->u.c.attribute == HPI_MICROPHONE_PHANTOM_POWER) |
545 | pC->u.phantom_power.state = (u16)phm->u.c.param1; | 598 | pC->u.microphone.phantom_state = (u16)phm->u.c.param1; |
546 | break; | 599 | break; |
547 | case HPI_CONTROL_AESEBU_TRANSMITTER: | 600 | case HPI_CONTROL_AESEBU_TRANSMITTER: |
548 | if (phm->u.c.attribute == HPI_AESEBUTX_FORMAT) | 601 | if (phm->u.c.attribute == HPI_AESEBUTX_FORMAT) |
@@ -550,7 +603,7 @@ void hpi_sync_control_cache(struct hpi_control_cache *p_cache, | |||
550 | break; | 603 | break; |
551 | case HPI_CONTROL_AESEBU_RECEIVER: | 604 | case HPI_CONTROL_AESEBU_RECEIVER: |
552 | if (phm->u.c.attribute == HPI_AESEBURX_FORMAT) | 605 | if (phm->u.c.attribute == HPI_AESEBURX_FORMAT) |
553 | pC->u.aes3rx.source = phm->u.c.param1; | 606 | pC->u.aes3rx.format = phm->u.c.param1; |
554 | break; | 607 | break; |
555 | case HPI_CONTROL_SAMPLECLOCK: | 608 | case HPI_CONTROL_SAMPLECLOCK: |
556 | if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE) | 609 | if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE) |
@@ -565,53 +618,60 @@ void hpi_sync_control_cache(struct hpi_control_cache *p_cache, | |||
565 | } | 618 | } |
566 | } | 619 | } |
567 | 620 | ||
568 | struct hpi_control_cache *hpi_alloc_control_cache(const u32 | 621 | /** Allocate control cache. |
569 | number_of_controls, const u32 size_in_bytes, | 622 | |
570 | struct hpi_control_cache_info *pDSP_control_buffer) | 623 | \return Cache pointer, or NULL if allocation fails. |
624 | */ | ||
625 | struct hpi_control_cache *hpi_alloc_control_cache(const u32 control_count, | ||
626 | const u32 size_in_bytes, u8 *p_dsp_control_buffer) | ||
571 | { | 627 | { |
572 | struct hpi_control_cache *p_cache = | 628 | struct hpi_control_cache *p_cache = |
573 | kmalloc(sizeof(*p_cache), GFP_KERNEL); | 629 | kmalloc(sizeof(*p_cache), GFP_KERNEL); |
630 | if (!p_cache) | ||
631 | return NULL; | ||
632 | |||
633 | p_cache->p_info = | ||
634 | kmalloc(sizeof(*p_cache->p_info) * control_count, GFP_KERNEL); | ||
635 | if (!p_cache->p_info) { | ||
636 | kfree(p_cache); | ||
637 | return NULL; | ||
638 | } | ||
639 | memset(p_cache->p_info, 0, sizeof(*p_cache->p_info) * control_count); | ||
574 | p_cache->cache_size_in_bytes = size_in_bytes; | 640 | p_cache->cache_size_in_bytes = size_in_bytes; |
575 | p_cache->control_count = number_of_controls; | 641 | p_cache->control_count = control_count; |
576 | p_cache->p_cache = | 642 | p_cache->p_cache = p_dsp_control_buffer; |
577 | (struct hpi_control_cache_single *)pDSP_control_buffer; | ||
578 | p_cache->init = 0; | 643 | p_cache->init = 0; |
579 | p_cache->p_info = | ||
580 | kmalloc(sizeof(*p_cache->p_info) * p_cache->control_count, | ||
581 | GFP_KERNEL); | ||
582 | return p_cache; | 644 | return p_cache; |
583 | } | 645 | } |
584 | 646 | ||
585 | void hpi_free_control_cache(struct hpi_control_cache *p_cache) | 647 | void hpi_free_control_cache(struct hpi_control_cache *p_cache) |
586 | { | 648 | { |
587 | if (p_cache->init) { | 649 | if (p_cache) { |
588 | kfree(p_cache->p_info); | 650 | kfree(p_cache->p_info); |
589 | p_cache->p_info = NULL; | ||
590 | p_cache->init = 0; | ||
591 | kfree(p_cache); | 651 | kfree(p_cache); |
592 | } | 652 | } |
593 | } | 653 | } |
594 | 654 | ||
595 | static void subsys_message(struct hpi_message *phm, struct hpi_response *phr) | 655 | static void subsys_message(struct hpi_message *phm, struct hpi_response *phr) |
596 | { | 656 | { |
657 | hpi_init_response(phr, HPI_OBJ_SUBSYSTEM, phm->function, 0); | ||
597 | 658 | ||
598 | switch (phm->function) { | 659 | switch (phm->function) { |
599 | case HPI_SUBSYS_OPEN: | 660 | case HPI_SUBSYS_OPEN: |
600 | case HPI_SUBSYS_CLOSE: | 661 | case HPI_SUBSYS_CLOSE: |
601 | case HPI_SUBSYS_DRIVER_UNLOAD: | 662 | case HPI_SUBSYS_DRIVER_UNLOAD: |
602 | phr->error = 0; | ||
603 | break; | 663 | break; |
604 | case HPI_SUBSYS_DRIVER_LOAD: | 664 | case HPI_SUBSYS_DRIVER_LOAD: |
605 | wipe_adapter_list(); | 665 | wipe_adapter_list(); |
606 | hpios_alistlock_init(&adapters); | 666 | hpios_alistlock_init(&adapters); |
607 | phr->error = 0; | ||
608 | break; | 667 | break; |
609 | case HPI_SUBSYS_GET_INFO: | 668 | case HPI_SUBSYS_GET_ADAPTER: |
610 | subsys_get_adapters(phr); | 669 | subsys_get_adapter(phm, phr); |
670 | break; | ||
671 | case HPI_SUBSYS_GET_NUM_ADAPTERS: | ||
672 | phr->u.s.num_adapters = adapters.gw_num_adapters; | ||
611 | break; | 673 | break; |
612 | case HPI_SUBSYS_CREATE_ADAPTER: | 674 | case HPI_SUBSYS_CREATE_ADAPTER: |
613 | case HPI_SUBSYS_DELETE_ADAPTER: | ||
614 | phr->error = 0; | ||
615 | break; | 675 | break; |
616 | default: | 676 | default: |
617 | phr->error = HPI_ERROR_INVALID_FUNC; | 677 | phr->error = HPI_ERROR_INVALID_FUNC; |