• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6.36/sound/pci/asihpi/
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:
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			if (pC->u.t.level == HPI_ERROR_ILLEGAL_CACHE_VALUE) {
357				phr->u.c.param1 = 0;
358				phr->error =
359					HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
360			} else
361				phr->u.c.param1 = pC->u.t.level;
362		else
363			found = 0;
364		break;
365	case HPI_CONTROL_AESEBU_RECEIVER:
366		if (phm->u.c.attribute == HPI_AESEBURX_ERRORSTATUS)
367			phr->u.c.param1 = pC->u.aes3rx.error_status;
368		else if (phm->u.c.attribute == HPI_AESEBURX_FORMAT)
369			phr->u.c.param1 = pC->u.aes3rx.source;
370		else
371			found = 0;
372		break;
373	case HPI_CONTROL_AESEBU_TRANSMITTER:
374		if (phm->u.c.attribute == HPI_AESEBUTX_FORMAT)
375			phr->u.c.param1 = pC->u.aes3tx.format;
376		else
377			found = 0;
378		break;
379	case HPI_CONTROL_TONEDETECTOR:
380		if (phm->u.c.attribute == HPI_TONEDETECTOR_STATE)
381			phr->u.c.param1 = pC->u.tone.state;
382		else
383			found = 0;
384		break;
385	case HPI_CONTROL_SILENCEDETECTOR:
386		if (phm->u.c.attribute == HPI_SILENCEDETECTOR_STATE) {
387			phr->u.c.param1 = pC->u.silence.state;
388			phr->u.c.param2 = pC->u.silence.count;
389		} else
390			found = 0;
391		break;
392	case HPI_CONTROL_MICROPHONE:
393		if (phm->u.c.attribute == HPI_MICROPHONE_PHANTOM_POWER)
394			phr->u.c.param1 = pC->u.phantom_power.state;
395		else
396			found = 0;
397		break;
398	case HPI_CONTROL_SAMPLECLOCK:
399		if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE)
400			phr->u.c.param1 = pC->u.clk.source;
401		else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE_INDEX) {
402			if (pC->u.clk.source_index ==
403				HPI_ERROR_ILLEGAL_CACHE_VALUE) {
404				phr->u.c.param1 = 0;
405				phr->error =
406					HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
407			} else
408				phr->u.c.param1 = pC->u.clk.source_index;
409		} else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SAMPLERATE)
410			phr->u.c.param1 = pC->u.clk.sample_rate;
411		else
412			found = 0;
413		break;
414	case HPI_CONTROL_PAD:
415
416		if (!(p_pad->field_valid_flags & (1 <<
417					HPI_CTL_ATTR_INDEX(phm->u.c.
418						attribute)))) {
419			phr->error = HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
420			break;
421		}
422
423		if (phm->u.c.attribute == HPI_PAD_PROGRAM_ID)
424			phr->u.c.param1 = p_pad->pI;
425		else if (phm->u.c.attribute == HPI_PAD_PROGRAM_TYPE)
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 =
440					HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
441				break;
442			}
443
444			pad_string = ((char *)p_pad) + pad_desc[index].offset;
445			field_size = pad_desc[index].field_size;
446			/* Ensure null terminator */
447			pad_string[field_size - 1] = 0;
448
449			pad_string_len = strlen(pad_string) + 1;
450
451			if (offset > pad_string_len) {
452				phr->error = HPI_ERROR_INVALID_CONTROL_VALUE;
453				break;
454			}
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		}
469		break;
470	default:
471		found = 0;
472		break;
473	}
474
475	if (found)
476		HPI_DEBUG_LOG(VERBOSE,
477			"cached adap %d, ctl %d, type %d, attr %d\n",
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
486	if (found)
487		phr->size =
488			sizeof(struct hpi_response_header) +
489			sizeof(struct hpi_control_res);
490
491	return found;
492}
493
494/** Updates the cache with Set values.
495
496Only update if no error.
497Volume and Level return the limited values in the response, so use these
498Multiplexer does so use sent values
499*/
500void hpi_sync_control_cache(struct hpi_control_cache *p_cache,
501	struct hpi_message *phm, struct hpi_response *phr)
502{
503	u16 control_index;
504	struct hpi_control_cache_single *pC;
505	struct hpi_control_cache_info *pI;
506
507	if (phr->error)
508		return;
509
510	if (!find_control(phm, p_cache, &pI, &control_index))
511		return;
512
513	/* pC is the default cached control strucure.
514	   May be cast to something else in the following switch statement.
515	 */
516	pC = (struct hpi_control_cache_single *)pI;
517
518	switch (pI->control_type) {
519	case HPI_CONTROL_VOLUME:
520		if (phm->u.c.attribute == HPI_VOLUME_GAIN) {
521			pC->u.v.an_log[0] = phr->u.c.an_log_value[0];
522			pC->u.v.an_log[1] = phr->u.c.an_log_value[1];
523		}
524		break;
525	case HPI_CONTROL_MULTIPLEXER:
526		/* mux does not return its setting on Set command. */
527		if (phm->u.c.attribute == HPI_MULTIPLEXER_SOURCE) {
528			pC->u.x.source_node_type = (u16)phm->u.c.param1;
529			pC->u.x.source_node_index = (u16)phm->u.c.param2;
530		}
531		break;
532	case HPI_CONTROL_CHANNEL_MODE:
533		/* mode does not return its setting on Set command. */
534		if (phm->u.c.attribute == HPI_CHANNEL_MODE_MODE)
535			pC->u.m.mode = (u16)phm->u.c.param1;
536		break;
537	case HPI_CONTROL_LEVEL:
538		if (phm->u.c.attribute == HPI_LEVEL_GAIN) {
539			pC->u.v.an_log[0] = phr->u.c.an_log_value[0];
540			pC->u.v.an_log[1] = phr->u.c.an_log_value[1];
541		}
542		break;
543	case HPI_CONTROL_MICROPHONE:
544		if (phm->u.c.attribute == HPI_MICROPHONE_PHANTOM_POWER)
545			pC->u.phantom_power.state = (u16)phm->u.c.param1;
546		break;
547	case HPI_CONTROL_AESEBU_TRANSMITTER:
548		if (phm->u.c.attribute == HPI_AESEBUTX_FORMAT)
549			pC->u.aes3tx.format = phm->u.c.param1;
550		break;
551	case HPI_CONTROL_AESEBU_RECEIVER:
552		if (phm->u.c.attribute == HPI_AESEBURX_FORMAT)
553			pC->u.aes3rx.source = phm->u.c.param1;
554		break;
555	case HPI_CONTROL_SAMPLECLOCK:
556		if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE)
557			pC->u.clk.source = (u16)phm->u.c.param1;
558		else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE_INDEX)
559			pC->u.clk.source_index = (u16)phm->u.c.param1;
560		else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SAMPLERATE)
561			pC->u.clk.sample_rate = phm->u.c.param1;
562		break;
563	default:
564		break;
565	}
566}
567
568struct hpi_control_cache *hpi_alloc_control_cache(const u32
569	number_of_controls, const u32 size_in_bytes,
570	struct hpi_control_cache_info *pDSP_control_buffer)
571{
572	struct hpi_control_cache *p_cache =
573		kmalloc(sizeof(*p_cache), GFP_KERNEL);
574	p_cache->cache_size_in_bytes = size_in_bytes;
575	p_cache->control_count = number_of_controls;
576	p_cache->p_cache =
577		(struct hpi_control_cache_single *)pDSP_control_buffer;
578	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;
583}
584
585void hpi_free_control_cache(struct hpi_control_cache *p_cache)
586{
587	if (p_cache->init) {
588		kfree(p_cache->p_info);
589		p_cache->p_info = NULL;
590		p_cache->init = 0;
591		kfree(p_cache);
592	}
593}
594
595static void subsys_message(struct hpi_message *phm, struct hpi_response *phr)
596{
597
598	switch (phm->function) {
599	case HPI_SUBSYS_OPEN:
600	case HPI_SUBSYS_CLOSE:
601	case HPI_SUBSYS_DRIVER_UNLOAD:
602		phr->error = 0;
603		break;
604	case HPI_SUBSYS_DRIVER_LOAD:
605		wipe_adapter_list();
606		hpios_alistlock_init(&adapters);
607		phr->error = 0;
608		break;
609	case HPI_SUBSYS_GET_INFO:
610		subsys_get_adapters(phr);
611		break;
612	case HPI_SUBSYS_CREATE_ADAPTER:
613	case HPI_SUBSYS_DELETE_ADAPTER:
614		phr->error = 0;
615		break;
616	default:
617		phr->error = HPI_ERROR_INVALID_FUNC;
618		break;
619	}
620}
621
622void HPI_COMMON(struct hpi_message *phm, struct hpi_response *phr)
623{
624	switch (phm->type) {
625	case HPI_TYPE_MESSAGE:
626		switch (phm->object) {
627		case HPI_OBJ_SUBSYSTEM:
628			subsys_message(phm, phr);
629			break;
630		}
631		break;
632
633	default:
634		phr->error = HPI_ERROR_INVALID_TYPE;
635		break;
636	}
637}
638