xref: /linux/sound/pci/asihpi/hpicmn.c (revision 60e13231561b3a4c5269bfa1ef6c0569ad6f28ec)
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 "hpimsginit.h"
30 
31 #include "hpicmn.h"
32 
33 struct hpi_adapters_list {
34 	struct hpios_spinlock list_lock;
35 	struct hpi_adapter_obj adapter[HPI_MAX_ADAPTERS];
36 	u16 gw_num_adapters;
37 };
38 
39 static struct hpi_adapters_list adapters;
40 
41 /**
42 * Given an HPI Message that was sent out and a response that was received,
43 * validate that the response has the correct fields filled in,
44 * i.e ObjectType, Function etc
45 **/
46 u16 hpi_validate_response(struct hpi_message *phm, struct hpi_response *phr)
47 {
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 	}
58 
59 	if (phr->function != phm->function) {
60 		HPI_DEBUG_LOG(ERROR, "header function %d invalid\n",
61 			phr->function);
62 		return HPI_ERROR_INVALID_RESPONSE;
63 	}
64 
65 	return 0;
66 }
67 
68 u16 hpi_add_adapter(struct hpi_adapter_obj *pao)
69 {
70 	u16 retval = 0;
71 	/*HPI_ASSERT(pao->wAdapterType); */
72 
73 	hpios_alistlock_lock(&adapters);
74 
75 	if (pao->index >= HPI_MAX_ADAPTERS) {
76 		retval = HPI_ERROR_BAD_ADAPTER_NUMBER;
77 		goto unlock;
78 	}
79 
80 	if (adapters.adapter[pao->index].adapter_type) {
81 		int a;
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;
93 			goto unlock;
94 		}
95 	}
96 	adapters.adapter[pao->index] = *pao;
97 	hpios_dsplock_init(&adapters.adapter[pao->index]);
98 	adapters.gw_num_adapters++;
99 
100 unlock:
101 	hpios_alistlock_unlock(&adapters);
102 	return retval;
103 }
104 
105 void hpi_delete_adapter(struct hpi_adapter_obj *pao)
106 {
107 	if (!pao->adapter_type) {
108 		HPI_DEBUG_LOG(ERROR, "removing null adapter?\n");
109 		return;
110 	}
111 
112 	hpios_alistlock_lock(&adapters);
113 	if (adapters.adapter[pao->index].adapter_type)
114 		adapters.gw_num_adapters--;
115 	memset(&adapters.adapter[pao->index], 0, sizeof(adapters.adapter[0]));
116 	hpios_alistlock_unlock(&adapters);
117 }
118 
119 /**
120 * FindAdapter returns a pointer to the struct hpi_adapter_obj with
121 * index wAdapterIndex in an HPI_ADAPTERS_LIST structure.
122 *
123 */
124 struct hpi_adapter_obj *hpi_find_adapter(u16 adapter_index)
125 {
126 	struct hpi_adapter_obj *pao = NULL;
127 
128 	if (adapter_index >= HPI_MAX_ADAPTERS) {
129 		HPI_DEBUG_LOG(VERBOSE, "find_adapter invalid index %d\n",
130 			adapter_index);
131 		return NULL;
132 	}
133 
134 	pao = &adapters.adapter[adapter_index];
135 	if (pao->adapter_type != 0) {
136 		/*
137 		   HPI_DEBUG_LOG(VERBOSE, "Found adapter index %d\n",
138 		   wAdapterIndex);
139 		 */
140 		return pao;
141 	} else {
142 		/*
143 		   HPI_DEBUG_LOG(VERBOSE, "No adapter index %d\n",
144 		   wAdapterIndex);
145 		 */
146 		return NULL;
147 	}
148 }
149 
150 /**
151 *
152 * wipe an HPI_ADAPTERS_LIST structure.
153 *
154 **/
155 static void wipe_adapter_list(void)
156 {
157 	memset(&adapters, 0, sizeof(adapters));
158 }
159 
160 static void subsys_get_adapter(struct hpi_message *phm,
161 	struct hpi_response *phr)
162 {
163 	int count = phm->obj_index;
164 	u16 index = 0;
165 
166 	/* find the nCount'th nonzero adapter in array */
167 	for (index = 0; index < HPI_MAX_ADAPTERS; index++) {
168 		if (adapters.adapter[index].adapter_type) {
169 			if (!count)
170 				break;
171 			count--;
172 		}
173 	}
174 
175 	if (index < HPI_MAX_ADAPTERS) {
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 	}
183 }
184 
185 static unsigned int control_cache_alloc_check(struct hpi_control_cache *pC)
186 {
187 	unsigned int i;
188 	int cached = 0;
189 	if (!pC)
190 		return 0;
191 
192 	if (pC->init)
193 		return pC->init;
194 
195 	if (!pC->p_cache)
196 		return 0;
197 
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",
204 			pC->control_count);
205 		for (i = 0; i < pC->control_count; i++) {
206 			struct hpi_control_cache_info *info =
207 				(struct hpi_control_cache_info *)
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 			}
226 
227 			if (info->control_type) {
228 				pC->p_info[info->control_index] = info;
229 				cached++;
230 			} else {	/* dummy cache entry */
231 				pC->p_info[info->control_index] = NULL;
232 			}
233 
234 			byte_count += info->size_in32bit_words * 4;
235 
236 			HPI_DEBUG_LOG(VERBOSE,
237 				"cached %d, pinfo %p index %d type %d size %d\n",
238 				cached, pC->p_info[info->control_index],
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;
251 		}
252 
253 		if (byte_count != pC->cache_size_in_bytes)
254 			HPI_DEBUG_LOG(WARNING,
255 				"adap %d bytecount %d != cache size %d\n",
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;
264 	}
265 	return pC->init;
266 }
267 
268 /** Find a control.
269 */
270 static short find_control(u16 control_index,
271 	struct hpi_control_cache *p_cache, struct hpi_control_cache_info **pI)
272 {
273 	if (!control_cache_alloc_check(p_cache)) {
274 		HPI_DEBUG_LOG(VERBOSE,
275 			"control_cache_alloc_check() failed %d\n",
276 			control_index);
277 		return 0;
278 	}
279 
280 	*pI = p_cache->p_info[control_index];
281 	if (!*pI) {
282 		HPI_DEBUG_LOG(VERBOSE, "Uncached Control %d\n",
283 			control_index);
284 		return 0;
285 	} else {
286 		HPI_DEBUG_LOG(VERBOSE, "find_control() type %d\n",
287 			(*pI)->control_type);
288 	}
289 	return 1;
290 }
291 
292 /* allow unified treatment of several string fields within struct */
293 #define HPICMN_PAD_OFS_AND_SIZE(m)  {\
294 	offsetof(struct hpi_control_cache_pad, m), \
295 	sizeof(((struct hpi_control_cache_pad *)(NULL))->m) }
296 
297 struct pad_ofs_size {
298 	unsigned int offset;
299 	unsigned int field_size;
300 };
301 
302 static const struct pad_ofs_size pad_desc[] = {
303 	HPICMN_PAD_OFS_AND_SIZE(c_channel),	/* HPI_PAD_CHANNEL_NAME */
304 	HPICMN_PAD_OFS_AND_SIZE(c_artist),	/* HPI_PAD_ARTIST */
305 	HPICMN_PAD_OFS_AND_SIZE(c_title),	/* HPI_PAD_TITLE */
306 	HPICMN_PAD_OFS_AND_SIZE(c_comment),	/* HPI_PAD_COMMENT */
307 };
308 
309 /** CheckControlCache checks the cache and fills the struct hpi_response
310  * accordingly. It returns one if a cache hit occurred, zero otherwise.
311  */
312 short hpi_check_control_cache(struct hpi_control_cache *p_cache,
313 	struct hpi_message *phm, struct hpi_response *phr)
314 {
315 	short found = 1;
316 	struct hpi_control_cache_info *pI;
317 	struct hpi_control_cache_single *pC;
318 	size_t response_size;
319 	if (!find_control(phm->obj_index, p_cache, &pI)) {
320 		HPI_DEBUG_LOG(VERBOSE,
321 			"HPICMN find_control() failed for adap %d\n",
322 			phm->adapter_index);
323 		return 0;
324 	}
325 
326 	phr->error = 0;
327 
328 	/* set the default response size */
329 	response_size =
330 		sizeof(struct hpi_response_header) +
331 		sizeof(struct hpi_control_res);
332 
333 	/* pC is the default cached control strucure. May be cast to
334 	   something else in the following switch statement.
335 	 */
336 	pC = (struct hpi_control_cache_single *)pI;
337 
338 	switch (pI->control_type) {
339 
340 	case HPI_CONTROL_METER:
341 		if (phm->u.c.attribute == HPI_METER_PEAK) {
342 			phr->u.c.an_log_value[0] = pC->u.meter.an_log_peak[0];
343 			phr->u.c.an_log_value[1] = pC->u.meter.an_log_peak[1];
344 		} else if (phm->u.c.attribute == HPI_METER_RMS) {
345 			if (pC->u.meter.an_logRMS[0] ==
346 				HPI_CACHE_INVALID_SHORT) {
347 				phr->error =
348 					HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
349 				phr->u.c.an_log_value[0] = HPI_METER_MINIMUM;
350 				phr->u.c.an_log_value[1] = HPI_METER_MINIMUM;
351 			} else {
352 				phr->u.c.an_log_value[0] =
353 					pC->u.meter.an_logRMS[0];
354 				phr->u.c.an_log_value[1] =
355 					pC->u.meter.an_logRMS[1];
356 			}
357 		} else
358 			found = 0;
359 		break;
360 	case HPI_CONTROL_VOLUME:
361 		if (phm->u.c.attribute == HPI_VOLUME_GAIN) {
362 			phr->u.c.an_log_value[0] = pC->u.vol.an_log[0];
363 			phr->u.c.an_log_value[1] = pC->u.vol.an_log[1];
364 		} else if (phm->u.c.attribute == HPI_VOLUME_MUTE) {
365 			if (pC->u.vol.flags & HPI_VOLUME_FLAG_HAS_MUTE) {
366 				if (pC->u.vol.flags & HPI_VOLUME_FLAG_MUTED)
367 					phr->u.c.param1 =
368 						HPI_BITMASK_ALL_CHANNELS;
369 				else
370 					phr->u.c.param1 = 0;
371 			} else {
372 				phr->error =
373 					HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
374 				phr->u.c.param1 = 0;
375 			}
376 		} else {
377 			found = 0;
378 		}
379 		break;
380 	case HPI_CONTROL_MULTIPLEXER:
381 		if (phm->u.c.attribute == HPI_MULTIPLEXER_SOURCE) {
382 			phr->u.c.param1 = pC->u.mux.source_node_type;
383 			phr->u.c.param2 = pC->u.mux.source_node_index;
384 		} else {
385 			found = 0;
386 		}
387 		break;
388 	case HPI_CONTROL_CHANNEL_MODE:
389 		if (phm->u.c.attribute == HPI_CHANNEL_MODE_MODE)
390 			phr->u.c.param1 = pC->u.mode.mode;
391 		else
392 			found = 0;
393 		break;
394 	case HPI_CONTROL_LEVEL:
395 		if (phm->u.c.attribute == HPI_LEVEL_GAIN) {
396 			phr->u.c.an_log_value[0] = pC->u.level.an_log[0];
397 			phr->u.c.an_log_value[1] = pC->u.level.an_log[1];
398 		} else
399 			found = 0;
400 		break;
401 	case HPI_CONTROL_TUNER:
402 		if (phm->u.c.attribute == HPI_TUNER_FREQ)
403 			phr->u.c.param1 = pC->u.tuner.freq_ink_hz;
404 		else if (phm->u.c.attribute == HPI_TUNER_BAND)
405 			phr->u.c.param1 = pC->u.tuner.band;
406 		else if (phm->u.c.attribute == HPI_TUNER_LEVEL_AVG)
407 			if (pC->u.tuner.s_level_avg ==
408 				HPI_CACHE_INVALID_SHORT) {
409 				phr->u.cu.tuner.s_level = 0;
410 				phr->error =
411 					HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
412 			} else
413 				phr->u.cu.tuner.s_level =
414 					pC->u.tuner.s_level_avg;
415 		else
416 			found = 0;
417 		break;
418 	case HPI_CONTROL_AESEBU_RECEIVER:
419 		if (phm->u.c.attribute == HPI_AESEBURX_ERRORSTATUS)
420 			phr->u.c.param1 = pC->u.aes3rx.error_status;
421 		else if (phm->u.c.attribute == HPI_AESEBURX_FORMAT)
422 			phr->u.c.param1 = pC->u.aes3rx.format;
423 		else
424 			found = 0;
425 		break;
426 	case HPI_CONTROL_AESEBU_TRANSMITTER:
427 		if (phm->u.c.attribute == HPI_AESEBUTX_FORMAT)
428 			phr->u.c.param1 = pC->u.aes3tx.format;
429 		else
430 			found = 0;
431 		break;
432 	case HPI_CONTROL_TONEDETECTOR:
433 		if (phm->u.c.attribute == HPI_TONEDETECTOR_STATE)
434 			phr->u.c.param1 = pC->u.tone.state;
435 		else
436 			found = 0;
437 		break;
438 	case HPI_CONTROL_SILENCEDETECTOR:
439 		if (phm->u.c.attribute == HPI_SILENCEDETECTOR_STATE) {
440 			phr->u.c.param1 = pC->u.silence.state;
441 		} else
442 			found = 0;
443 		break;
444 	case HPI_CONTROL_MICROPHONE:
445 		if (phm->u.c.attribute == HPI_MICROPHONE_PHANTOM_POWER)
446 			phr->u.c.param1 = pC->u.microphone.phantom_state;
447 		else
448 			found = 0;
449 		break;
450 	case HPI_CONTROL_SAMPLECLOCK:
451 		if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE)
452 			phr->u.c.param1 = pC->u.clk.source;
453 		else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE_INDEX) {
454 			if (pC->u.clk.source_index ==
455 				HPI_CACHE_INVALID_UINT16) {
456 				phr->u.c.param1 = 0;
457 				phr->error =
458 					HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
459 			} else
460 				phr->u.c.param1 = pC->u.clk.source_index;
461 		} else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SAMPLERATE)
462 			phr->u.c.param1 = pC->u.clk.sample_rate;
463 		else
464 			found = 0;
465 		break;
466 	case HPI_CONTROL_PAD:{
467 			struct hpi_control_cache_pad *p_pad;
468 			p_pad = (struct hpi_control_cache_pad *)pI;
469 
470 			if (!(p_pad->field_valid_flags & (1 <<
471 						HPI_CTL_ATTR_INDEX(phm->u.c.
472 							attribute)))) {
473 				phr->error =
474 					HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
475 				break;
476 			}
477 
478 			if (phm->u.c.attribute == HPI_PAD_PROGRAM_ID)
479 				phr->u.c.param1 = p_pad->pI;
480 			else if (phm->u.c.attribute == HPI_PAD_PROGRAM_TYPE)
481 				phr->u.c.param1 = p_pad->pTY;
482 			else {
483 				unsigned int index =
484 					HPI_CTL_ATTR_INDEX(phm->u.c.
485 					attribute) - 1;
486 				unsigned int offset = phm->u.c.param1;
487 				unsigned int pad_string_len, field_size;
488 				char *pad_string;
489 				unsigned int tocopy;
490 
491 				if (index > ARRAY_SIZE(pad_desc) - 1) {
492 					phr->error =
493 						HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
494 					break;
495 				}
496 
497 				pad_string =
498 					((char *)p_pad) +
499 					pad_desc[index].offset;
500 				field_size = pad_desc[index].field_size;
501 				/* Ensure null terminator */
502 				pad_string[field_size - 1] = 0;
503 
504 				pad_string_len = strlen(pad_string) + 1;
505 
506 				if (offset > pad_string_len) {
507 					phr->error =
508 						HPI_ERROR_INVALID_CONTROL_VALUE;
509 					break;
510 				}
511 
512 				tocopy = pad_string_len - offset;
513 				if (tocopy > sizeof(phr->u.cu.chars8.sz_data))
514 					tocopy = sizeof(phr->u.cu.chars8.
515 						sz_data);
516 
517 				memcpy(phr->u.cu.chars8.sz_data,
518 					&pad_string[offset], tocopy);
519 
520 				phr->u.cu.chars8.remaining_chars =
521 					pad_string_len - offset - tocopy;
522 			}
523 		}
524 		break;
525 	default:
526 		found = 0;
527 		break;
528 	}
529 
530 	HPI_DEBUG_LOG(VERBOSE, "%s Adap %d, Ctl %d, Type %d, Attr %d\n",
531 		found ? "Cached" : "Uncached", phm->adapter_index,
532 		pI->control_index, pI->control_type, phm->u.c.attribute);
533 
534 	if (found)
535 		phr->size = (u16)response_size;
536 
537 	return found;
538 }
539 
540 /** Updates the cache with Set values.
541 
542 Only update if no error.
543 Volume and Level return the limited values in the response, so use these
544 Multiplexer does so use sent values
545 */
546 void hpi_cmn_control_cache_sync_to_msg(struct hpi_control_cache *p_cache,
547 	struct hpi_message *phm, struct hpi_response *phr)
548 {
549 	struct hpi_control_cache_single *pC;
550 	struct hpi_control_cache_info *pI;
551 
552 	if (phr->error)
553 		return;
554 
555 	if (!find_control(phm->obj_index, p_cache, &pI)) {
556 		HPI_DEBUG_LOG(VERBOSE,
557 			"HPICMN find_control() failed for adap %d\n",
558 			phm->adapter_index);
559 		return;
560 	}
561 
562 	/* pC is the default cached control strucure.
563 	   May be cast to something else in the following switch statement.
564 	 */
565 	pC = (struct hpi_control_cache_single *)pI;
566 
567 	switch (pI->control_type) {
568 	case HPI_CONTROL_VOLUME:
569 		if (phm->u.c.attribute == HPI_VOLUME_GAIN) {
570 			pC->u.vol.an_log[0] = phr->u.c.an_log_value[0];
571 			pC->u.vol.an_log[1] = phr->u.c.an_log_value[1];
572 		} else if (phm->u.c.attribute == HPI_VOLUME_MUTE) {
573 			if (phm->u.c.param1)
574 				pC->u.vol.flags |= HPI_VOLUME_FLAG_MUTED;
575 			else
576 				pC->u.vol.flags &= ~HPI_VOLUME_FLAG_MUTED;
577 		}
578 		break;
579 	case HPI_CONTROL_MULTIPLEXER:
580 		/* mux does not return its setting on Set command. */
581 		if (phm->u.c.attribute == HPI_MULTIPLEXER_SOURCE) {
582 			pC->u.mux.source_node_type = (u16)phm->u.c.param1;
583 			pC->u.mux.source_node_index = (u16)phm->u.c.param2;
584 		}
585 		break;
586 	case HPI_CONTROL_CHANNEL_MODE:
587 		/* mode does not return its setting on Set command. */
588 		if (phm->u.c.attribute == HPI_CHANNEL_MODE_MODE)
589 			pC->u.mode.mode = (u16)phm->u.c.param1;
590 		break;
591 	case HPI_CONTROL_LEVEL:
592 		if (phm->u.c.attribute == HPI_LEVEL_GAIN) {
593 			pC->u.vol.an_log[0] = phr->u.c.an_log_value[0];
594 			pC->u.vol.an_log[1] = phr->u.c.an_log_value[1];
595 		}
596 		break;
597 	case HPI_CONTROL_MICROPHONE:
598 		if (phm->u.c.attribute == HPI_MICROPHONE_PHANTOM_POWER)
599 			pC->u.microphone.phantom_state = (u16)phm->u.c.param1;
600 		break;
601 	case HPI_CONTROL_AESEBU_TRANSMITTER:
602 		if (phm->u.c.attribute == HPI_AESEBUTX_FORMAT)
603 			pC->u.aes3tx.format = phm->u.c.param1;
604 		break;
605 	case HPI_CONTROL_AESEBU_RECEIVER:
606 		if (phm->u.c.attribute == HPI_AESEBURX_FORMAT)
607 			pC->u.aes3rx.format = phm->u.c.param1;
608 		break;
609 	case HPI_CONTROL_SAMPLECLOCK:
610 		if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE)
611 			pC->u.clk.source = (u16)phm->u.c.param1;
612 		else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE_INDEX)
613 			pC->u.clk.source_index = (u16)phm->u.c.param1;
614 		else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SAMPLERATE)
615 			pC->u.clk.sample_rate = phm->u.c.param1;
616 		break;
617 	default:
618 		break;
619 	}
620 }
621 
622 /** Allocate control cache.
623 
624 \return Cache pointer, or NULL if allocation fails.
625 */
626 struct hpi_control_cache *hpi_alloc_control_cache(const u32 control_count,
627 	const u32 size_in_bytes, u8 *p_dsp_control_buffer)
628 {
629 	struct hpi_control_cache *p_cache =
630 		kmalloc(sizeof(*p_cache), GFP_KERNEL);
631 	if (!p_cache)
632 		return NULL;
633 
634 	p_cache->p_info = kzalloc(sizeof(*p_cache->p_info) * control_count,
635 				  GFP_KERNEL);
636 	if (!p_cache->p_info) {
637 		kfree(p_cache);
638 		return NULL;
639 	}
640 	p_cache->cache_size_in_bytes = size_in_bytes;
641 	p_cache->control_count = control_count;
642 	p_cache->p_cache = p_dsp_control_buffer;
643 	p_cache->init = 0;
644 	return p_cache;
645 }
646 
647 void hpi_free_control_cache(struct hpi_control_cache *p_cache)
648 {
649 	if (p_cache) {
650 		kfree(p_cache->p_info);
651 		kfree(p_cache);
652 	}
653 }
654 
655 static void subsys_message(struct hpi_message *phm, struct hpi_response *phr)
656 {
657 	hpi_init_response(phr, HPI_OBJ_SUBSYSTEM, phm->function, 0);
658 
659 	switch (phm->function) {
660 	case HPI_SUBSYS_OPEN:
661 	case HPI_SUBSYS_CLOSE:
662 	case HPI_SUBSYS_DRIVER_UNLOAD:
663 		break;
664 	case HPI_SUBSYS_DRIVER_LOAD:
665 		wipe_adapter_list();
666 		hpios_alistlock_init(&adapters);
667 		break;
668 	case HPI_SUBSYS_GET_ADAPTER:
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;
673 		break;
674 	case HPI_SUBSYS_CREATE_ADAPTER:
675 		break;
676 	default:
677 		phr->error = HPI_ERROR_INVALID_FUNC;
678 		break;
679 	}
680 }
681 
682 void HPI_COMMON(struct hpi_message *phm, struct hpi_response *phr)
683 {
684 	switch (phm->type) {
685 	case HPI_TYPE_REQUEST:
686 		switch (phm->object) {
687 		case HPI_OBJ_SUBSYSTEM:
688 			subsys_message(phm, phr);
689 			break;
690 		}
691 		break;
692 
693 	default:
694 		phr->error = HPI_ERROR_INVALID_TYPE;
695 		break;
696 	}
697 }
698