ALSA: asihpi - Change compander API and tidy
[deliverable/linux.git] / sound / pci / asihpi / hpicmn.c
CommitLineData
719f82d3
EB
1/******************************************************************************
2
3 AudioScience HPI driver
4 Copyright (C) 1997-2010 AudioScience Inc. <support@audioscience.com>
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of version 2 of the GNU General Public License as
8 published by the Free Software Foundation;
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
19\file hpicmn.c
20
21 Common functions used by hpixxxx.c modules
22
23(C) Copyright AudioScience Inc. 1998-2003
24*******************************************************************************/
25#define SOURCEFILE_NAME "hpicmn.c"
26
27#include "hpi_internal.h"
28#include "hpidebug.h"
29#include "hpicmn.h"
30
31struct hpi_adapters_list {
32 struct hpios_spinlock list_lock;
33 struct hpi_adapter_obj adapter[HPI_MAX_ADAPTERS];
34 u16 gw_num_adapters;
35};
36
37static struct hpi_adapters_list adapters;
38
39/**
40* Given an HPI Message that was sent out and a response that was received,
41* validate that the response has the correct fields filled in,
42* i.e ObjectType, Function etc
43**/
44u16 hpi_validate_response(struct hpi_message *phm, struct hpi_response *phr)
45{
46 u16 error = 0;
47
48 if ((phr->type != HPI_TYPE_RESPONSE)
49 || (phr->object != phm->object)
50 || (phr->function != phm->function))
51 error = HPI_ERROR_INVALID_RESPONSE;
52
53 return error;
54}
55
56u16 hpi_add_adapter(struct hpi_adapter_obj *pao)
57{
58 u16 retval = 0;
59 /*HPI_ASSERT(pao->wAdapterType); */
60
61 hpios_alistlock_lock(&adapters);
62
63 if (pao->index >= HPI_MAX_ADAPTERS) {
64 retval = HPI_ERROR_BAD_ADAPTER_NUMBER;
65 goto unlock;
66 }
67
68 if (adapters.adapter[pao->index].adapter_type) {
69 {
70 retval = HPI_DUPLICATE_ADAPTER_NUMBER;
71 goto unlock;
72 }
73 }
74 adapters.adapter[pao->index] = *pao;
75 hpios_dsplock_init(&adapters.adapter[pao->index]);
76 adapters.gw_num_adapters++;
77
78unlock:
79 hpios_alistlock_un_lock(&adapters);
80 return retval;
81}
82
83void hpi_delete_adapter(struct hpi_adapter_obj *pao)
84{
85 memset(pao, 0, sizeof(struct hpi_adapter_obj));
86
87 hpios_alistlock_lock(&adapters);
88 adapters.gw_num_adapters--; /* dec the number of adapters */
89 hpios_alistlock_un_lock(&adapters);
90}
91
92/**
93* FindAdapter returns a pointer to the struct hpi_adapter_obj with
94* index wAdapterIndex in an HPI_ADAPTERS_LIST structure.
95*
96*/
97struct hpi_adapter_obj *hpi_find_adapter(u16 adapter_index)
98{
99 struct hpi_adapter_obj *pao = NULL;
100
101 if (adapter_index >= HPI_MAX_ADAPTERS) {
102 HPI_DEBUG_LOG(VERBOSE, "find_adapter invalid index %d ",
103 adapter_index);
104 return NULL;
105 }
106
107 pao = &adapters.adapter[adapter_index];
108 if (pao->adapter_type != 0) {
109 /*
110 HPI_DEBUG_LOG(VERBOSE, "Found adapter index %d\n",
111 wAdapterIndex);
112 */
113 return pao;
114 } else {
115 /*
116 HPI_DEBUG_LOG(VERBOSE, "No adapter index %d\n",
117 wAdapterIndex);
118 */
119 return NULL;
120 }
121}
122
123/**
124*
125* wipe an HPI_ADAPTERS_LIST structure.
126*
127**/
128static void wipe_adapter_list(void
129 )
130{
131 memset(&adapters, 0, sizeof(adapters));
132}
133
134/**
135* SubSysGetAdapters fills awAdapterList in an struct hpi_response structure
136* with all adapters in the given HPI_ADAPTERS_LIST.
137*
138*/
139static void subsys_get_adapters(struct hpi_response *phr)
140{
141 /* fill in the response adapter array with the position */
142 /* identified by the adapter number/index of the adapters in */
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
159 /* for each adapter, place it's type in the position of the array */
160 /* corresponding to it's adapter number */
161 for (i = 0; i < adapters.gw_num_adapters; i++) {
162 pao = &adapters.adapter[i];
163 if (phr->u.s.aw_adapter_list[pao->index] != 0) {
164 phr->error = HPI_DUPLICATE_ADAPTER_NUMBER;
165 phr->specific_error = pao->index;
166 return;
167 }
168 phr->u.s.aw_adapter_list[pao->index] = pao->adapter_type;
169 }
170
171 phr->u.s.num_adapters = adapters.gw_num_adapters;
172 phr->error = 0; /* the function completed OK; */
173}
174
175static unsigned int control_cache_alloc_check(struct hpi_control_cache *pC)
176{
177 unsigned int i;
178 int cached = 0;
179 if (!pC)
180 return 0;
181 if ((!pC->init) && (pC->p_cache != NULL) && (pC->control_count)
182 && (pC->cache_size_in_bytes)
183 ) {
184 u32 *p_master_cache;
185 pC->init = 1;
186
187 p_master_cache = (u32 *)pC->p_cache;
188 HPI_DEBUG_LOG(VERBOSE, "check %d controls\n",
189 pC->control_count);
190 for (i = 0; i < pC->control_count; i++) {
191 struct hpi_control_cache_info *info =
192 (struct hpi_control_cache_info *)
193 p_master_cache;
194
195 if (info->control_type) {
196 pC->p_info[i] = info;
197 cached++;
198 } else
199 pC->p_info[i] = NULL;
200
201 if (info->size_in32bit_words)
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
209 HPI_DEBUG_LOG(VERBOSE,
210 "cached %d, pinfo %p index %d type %d\n",
211 cached, pC->p_info[i], info->control_index,
212 info->control_type);
213 }
214 /*
215 We didn't find anything to cache, so try again later !
216 */
217 if (!cached)
218 pC->init = 0;
219 }
220 return pC->init;
221}
222
223/** Find a control.
224*/
225static short find_control(struct hpi_message *phm,
226 struct hpi_control_cache *p_cache, struct hpi_control_cache_info **pI,
227 u16 *pw_control_index)
228{
229 *pw_control_index = phm->obj_index;
230
231 if (!control_cache_alloc_check(p_cache)) {
232 HPI_DEBUG_LOG(VERBOSE,
233 "control_cache_alloc_check() failed. adap%d ci%d\n",
234 phm->adapter_index, *pw_control_index);
235 return 0;
236 }
237
238 *pI = p_cache->p_info[*pw_control_index];
239 if (!*pI) {
240 HPI_DEBUG_LOG(VERBOSE, "uncached adap %d, control %d\n",
241 phm->adapter_index, *pw_control_index);
242 return 0;
243 } else {
244 HPI_DEBUG_LOG(VERBOSE, "find_control() type %d\n",
245 (*pI)->control_type);
246 }
247 return 1;
248}
249
250/** Used by the kernel driver to figure out if a buffer needs mapping.
251 */
252short 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 */
270#define HPICMN_PAD_OFS_AND_SIZE(m) {\
271 offsetof(struct hpi_control_cache_pad, m), \
272 sizeof(((struct hpi_control_cache_pad *)(NULL))->m) }
273
274struct pad_ofs_size {
275 unsigned int offset;
276 unsigned int field_size;
277};
278
279static struct pad_ofs_size pad_desc[] = {
280 HPICMN_PAD_OFS_AND_SIZE(c_channel), /* HPI_PAD_CHANNEL_NAME */
281 HPICMN_PAD_OFS_AND_SIZE(c_artist), /* HPI_PAD_ARTIST */
282 HPICMN_PAD_OFS_AND_SIZE(c_title), /* HPI_PAD_TITLE */
283 HPICMN_PAD_OFS_AND_SIZE(c_comment), /* HPI_PAD_COMMENT */
284};
285
286/** CheckControlCache checks the cache and fills the struct hpi_response
287 * accordingly. It returns one if a cache hit occurred, zero otherwise.
288 */
289short hpi_check_control_cache(struct hpi_control_cache *p_cache,
290 struct hpi_message *phm, struct hpi_response *phr)
291{
292 short found = 1;
293 u16 control_index;
294 struct hpi_control_cache_info *pI;
295 struct hpi_control_cache_single *pC;
296 struct hpi_control_cache_pad *p_pad;
297
298 if (!find_control(phm, p_cache, &pI, &control_index))
299 return 0;
300
301 phr->error = 0;
302
303 /* pC is the default cached control strucure. May be cast to
304 something else in the following switch statement.
305 */
306 pC = (struct hpi_control_cache_single *)pI;
307 p_pad = (struct hpi_control_cache_pad *)pI;
308
309 switch (pI->control_type) {
310
311 case HPI_CONTROL_METER:
312 if (phm->u.c.attribute == HPI_METER_PEAK) {
313 phr->u.c.an_log_value[0] = pC->u.p.an_log_peak[0];
314 phr->u.c.an_log_value[1] = pC->u.p.an_log_peak[1];
315 } else if (phm->u.c.attribute == HPI_METER_RMS) {
316 phr->u.c.an_log_value[0] = pC->u.p.an_logRMS[0];
317 phr->u.c.an_log_value[1] = pC->u.p.an_logRMS[1];
318 } else
319 found = 0;
320 break;
321 case HPI_CONTROL_VOLUME:
322 if (phm->u.c.attribute == HPI_VOLUME_GAIN) {
323 phr->u.c.an_log_value[0] = pC->u.v.an_log[0];
324 phr->u.c.an_log_value[1] = pC->u.v.an_log[1];
325 } else
326 found = 0;
327 break;
328 case HPI_CONTROL_MULTIPLEXER:
329 if (phm->u.c.attribute == HPI_MULTIPLEXER_SOURCE) {
330 phr->u.c.param1 = pC->u.x.source_node_type;
331 phr->u.c.param2 = pC->u.x.source_node_index;
332 } else {
333 found = 0;
334 }
335 break;
336 case HPI_CONTROL_CHANNEL_MODE:
337 if (phm->u.c.attribute == HPI_CHANNEL_MODE_MODE)
338 phr->u.c.param1 = pC->u.m.mode;
339 else
340 found = 0;
341 break;
342 case HPI_CONTROL_LEVEL:
343 if (phm->u.c.attribute == HPI_LEVEL_GAIN) {
344 phr->u.c.an_log_value[0] = pC->u.l.an_log[0];
345 phr->u.c.an_log_value[1] = pC->u.l.an_log[1];
346 } else
347 found = 0;
348 break;
349 case HPI_CONTROL_TUNER:
3ee317fe
EB
350 if (phm->u.c.attribute == HPI_TUNER_FREQ)
351 phr->u.c.param1 = pC->u.t.freq_ink_hz;
352 else if (phm->u.c.attribute == HPI_TUNER_BAND)
353 phr->u.c.param1 = pC->u.t.band;
354 else if ((phm->u.c.attribute == HPI_TUNER_LEVEL)
355 && (phm->u.c.param1 == HPI_TUNER_LEVEL_AVERAGE))
356 phr->u.c.param1 = pC->u.t.level;
357 else
358 found = 0;
719f82d3
EB
359 break;
360 case HPI_CONTROL_AESEBU_RECEIVER:
361 if (phm->u.c.attribute == HPI_AESEBURX_ERRORSTATUS)
362 phr->u.c.param1 = pC->u.aes3rx.error_status;
363 else if (phm->u.c.attribute == HPI_AESEBURX_FORMAT)
364 phr->u.c.param1 = pC->u.aes3rx.source;
365 else
366 found = 0;
367 break;
368 case HPI_CONTROL_AESEBU_TRANSMITTER:
369 if (phm->u.c.attribute == HPI_AESEBUTX_FORMAT)
370 phr->u.c.param1 = pC->u.aes3tx.format;
371 else
372 found = 0;
373 break;
374 case HPI_CONTROL_TONEDETECTOR:
375 if (phm->u.c.attribute == HPI_TONEDETECTOR_STATE)
376 phr->u.c.param1 = pC->u.tone.state;
377 else
378 found = 0;
379 break;
380 case HPI_CONTROL_SILENCEDETECTOR:
381 if (phm->u.c.attribute == HPI_SILENCEDETECTOR_STATE) {
382 phr->u.c.param1 = pC->u.silence.state;
383 phr->u.c.param2 = pC->u.silence.count;
384 } else
385 found = 0;
386 break;
387 case HPI_CONTROL_MICROPHONE:
388 if (phm->u.c.attribute == HPI_MICROPHONE_PHANTOM_POWER)
389 phr->u.c.param1 = pC->u.phantom_power.state;
390 else
391 found = 0;
392 break;
393 case HPI_CONTROL_SAMPLECLOCK:
394 if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE)
395 phr->u.c.param1 = pC->u.clk.source;
396 else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE_INDEX) {
397 if (pC->u.clk.source_index ==
398 HPI_ERROR_ILLEGAL_CACHE_VALUE) {
399 phr->u.c.param1 = 0;
400 phr->error = HPI_ERROR_INVALID_OPERATION;
401 } else
402 phr->u.c.param1 = pC->u.clk.source_index;
403 } else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SAMPLERATE)
404 phr->u.c.param1 = pC->u.clk.sample_rate;
405 else
406 found = 0;
407 break;
408 case HPI_CONTROL_PAD:
409
410 if (!(p_pad->field_valid_flags & (1 <<
411 HPI_CTL_ATTR_INDEX(phm->u.c.
412 attribute)))) {
413 phr->error = HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
414 break;
415 }
416
417 if (phm->u.c.attribute == HPI_PAD_PROGRAM_ID)
418 phr->u.c.param1 = p_pad->pI;
419 else if (phm->u.c.attribute == HPI_PAD_PROGRAM_TYPE)
420 phr->u.c.param1 = p_pad->pTY;
421 else {
422 unsigned int index =
423 HPI_CTL_ATTR_INDEX(phm->u.c.attribute) - 1;
424 unsigned int offset = phm->u.c.param1;
425 unsigned int pad_string_len, field_size;
426 char *pad_string;
427 unsigned int tocopy;
428
429 HPI_DEBUG_LOG(VERBOSE, "PADS HPI_PADS_ %d\n",
430 phm->u.c.attribute);
431
432 if (index > ARRAY_SIZE(pad_desc) - 1) {
433 phr->error =
434 HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
435 break;
436 }
437
438 pad_string = ((char *)p_pad) + pad_desc[index].offset;
439 field_size = pad_desc[index].field_size;
440 /* Ensure null terminator */
441 pad_string[field_size - 1] = 0;
442
443 pad_string_len = strlen(pad_string) + 1;
444
445 if (offset > pad_string_len) {
446 phr->error = HPI_ERROR_INVALID_CONTROL_VALUE;
447 break;
448 }
449
450 tocopy = pad_string_len - offset;
451 if (tocopy > sizeof(phr->u.cu.chars8.sz_data))
452 tocopy = sizeof(phr->u.cu.chars8.sz_data);
453
454 HPI_DEBUG_LOG(VERBOSE,
455 "PADS memcpy(%d), offset %d \n", tocopy,
456 offset);
457 memcpy(phr->u.cu.chars8.sz_data, &pad_string[offset],
458 tocopy);
459
460 phr->u.cu.chars8.remaining_chars =
461 pad_string_len - offset - tocopy;
462 }
463 break;
464 default:
465 found = 0;
466 break;
467 }
468
469 if (found)
470 HPI_DEBUG_LOG(VERBOSE,
471 "cached adap %d, ctl %d, type %d, attr %d\n",
472 phm->adapter_index, pI->control_index,
473 pI->control_type, phm->u.c.attribute);
474 else
475 HPI_DEBUG_LOG(VERBOSE,
476 "uncached adap %d, ctl %d, ctl type %d\n",
477 phm->adapter_index, pI->control_index,
478 pI->control_type);
479
480 if (found)
481 phr->size =
482 sizeof(struct hpi_response_header) +
483 sizeof(struct hpi_control_res);
484
485 return found;
486}
487
488/** Updates the cache with Set values.
489
490Only update if no error.
491Volume and Level return the limited values in the response, so use these
492Multiplexer does so use sent values
493*/
494void hpi_sync_control_cache(struct hpi_control_cache *p_cache,
495 struct hpi_message *phm, struct hpi_response *phr)
496{
497 u16 control_index;
498 struct hpi_control_cache_single *pC;
499 struct hpi_control_cache_info *pI;
500
3ee317fe
EB
501 if (phr->error)
502 return;
503
719f82d3
EB
504 if (!find_control(phm, p_cache, &pI, &control_index))
505 return;
506
507 /* pC is the default cached control strucure.
508 May be cast to something else in the following switch statement.
509 */
510 pC = (struct hpi_control_cache_single *)pI;
511
512 switch (pI->control_type) {
513 case HPI_CONTROL_VOLUME:
514 if (phm->u.c.attribute == HPI_VOLUME_GAIN) {
515 pC->u.v.an_log[0] = phr->u.c.an_log_value[0];
516 pC->u.v.an_log[1] = phr->u.c.an_log_value[1];
517 }
518 break;
519 case HPI_CONTROL_MULTIPLEXER:
520 /* mux does not return its setting on Set command. */
719f82d3
EB
521 if (phm->u.c.attribute == HPI_MULTIPLEXER_SOURCE) {
522 pC->u.x.source_node_type = (u16)phm->u.c.param1;
523 pC->u.x.source_node_index = (u16)phm->u.c.param2;
524 }
525 break;
526 case HPI_CONTROL_CHANNEL_MODE:
527 /* mode does not return its setting on Set command. */
719f82d3
EB
528 if (phm->u.c.attribute == HPI_CHANNEL_MODE_MODE)
529 pC->u.m.mode = (u16)phm->u.c.param1;
530 break;
531 case HPI_CONTROL_LEVEL:
532 if (phm->u.c.attribute == HPI_LEVEL_GAIN) {
533 pC->u.v.an_log[0] = phr->u.c.an_log_value[0];
534 pC->u.v.an_log[1] = phr->u.c.an_log_value[1];
535 }
536 break;
537 case HPI_CONTROL_MICROPHONE:
538 if (phm->u.c.attribute == HPI_MICROPHONE_PHANTOM_POWER)
539 pC->u.phantom_power.state = (u16)phm->u.c.param1;
540 break;
541 case HPI_CONTROL_AESEBU_TRANSMITTER:
719f82d3
EB
542 if (phm->u.c.attribute == HPI_AESEBUTX_FORMAT)
543 pC->u.aes3tx.format = phm->u.c.param1;
544 break;
545 case HPI_CONTROL_AESEBU_RECEIVER:
719f82d3
EB
546 if (phm->u.c.attribute == HPI_AESEBURX_FORMAT)
547 pC->u.aes3rx.source = phm->u.c.param1;
548 break;
549 case HPI_CONTROL_SAMPLECLOCK:
719f82d3
EB
550 if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE)
551 pC->u.clk.source = (u16)phm->u.c.param1;
552 else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE_INDEX)
553 pC->u.clk.source_index = (u16)phm->u.c.param1;
554 else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SAMPLERATE)
555 pC->u.clk.sample_rate = phm->u.c.param1;
556 break;
557 default:
558 break;
559 }
560}
561
562struct hpi_control_cache *hpi_alloc_control_cache(const u32
563 number_of_controls, const u32 size_in_bytes,
564 struct hpi_control_cache_info *pDSP_control_buffer)
565{
566 struct hpi_control_cache *p_cache =
567 kmalloc(sizeof(*p_cache), GFP_KERNEL);
568 p_cache->cache_size_in_bytes = size_in_bytes;
569 p_cache->control_count = number_of_controls;
570 p_cache->p_cache =
571 (struct hpi_control_cache_single *)pDSP_control_buffer;
572 p_cache->init = 0;
573 p_cache->p_info =
574 kmalloc(sizeof(*p_cache->p_info) * p_cache->control_count,
575 GFP_KERNEL);
576 return p_cache;
577}
578
579void hpi_free_control_cache(struct hpi_control_cache *p_cache)
580{
3ee317fe 581 if (p_cache->init) {
719f82d3
EB
582 kfree(p_cache->p_info);
583 p_cache->p_info = NULL;
584 p_cache->init = 0;
585 kfree(p_cache);
586 }
587}
588
589static void subsys_message(struct hpi_message *phm, struct hpi_response *phr)
590{
591
592 switch (phm->function) {
593 case HPI_SUBSYS_OPEN:
594 case HPI_SUBSYS_CLOSE:
595 case HPI_SUBSYS_DRIVER_UNLOAD:
596 phr->error = 0;
597 break;
598 case HPI_SUBSYS_DRIVER_LOAD:
599 wipe_adapter_list();
600 hpios_alistlock_init(&adapters);
601 phr->error = 0;
602 break;
603 case HPI_SUBSYS_GET_INFO:
604 subsys_get_adapters(phr);
605 break;
606 case HPI_SUBSYS_CREATE_ADAPTER:
607 case HPI_SUBSYS_DELETE_ADAPTER:
608 phr->error = 0;
609 break;
610 default:
611 phr->error = HPI_ERROR_INVALID_FUNC;
612 break;
613 }
614}
615
616void HPI_COMMON(struct hpi_message *phm, struct hpi_response *phr)
617{
618 switch (phm->type) {
619 case HPI_TYPE_MESSAGE:
620 switch (phm->object) {
621 case HPI_OBJ_SUBSYSTEM:
622 subsys_message(phm, phr);
623 break;
624 }
625 break;
626
627 default:
628 phr->error = HPI_ERROR_INVALID_TYPE;
629 break;
630 }
631}
This page took 0.070799 seconds and 5 git commands to generate.