xref: /openbmc/linux/sound/pci/asihpi/hpicmn.c (revision 565d76cb)
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 type %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 			byte_count += info->size_in32bit_words * 4;
234 
235 			HPI_DEBUG_LOG(VERBOSE,
236 				"cached %d, pinfo %p index %d type %d size %d\n",
237 				cached, pC->p_info[info->control_index],
238 				info->control_index, info->control_type,
239 				info->size_in32bit_words);
240 
241 			/* quit loop early if whole cache has been scanned.
242 			 * dwControlCount is the maximum possible entries
243 			 * but some may be absent from the cache
244 			 */
245 			if (byte_count >= pC->cache_size_in_bytes)
246 				break;
247 			/* have seen last control index */
248 			if (info->control_index == pC->control_count - 1)
249 				break;
250 		}
251 
252 		if (byte_count != pC->cache_size_in_bytes)
253 			HPI_DEBUG_LOG(WARNING,
254 				"adap %d bytecount %d != cache size %d\n",
255 				pC->adap_idx, byte_count,
256 				pC->cache_size_in_bytes);
257 		else
258 			HPI_DEBUG_LOG(DEBUG,
259 				"adap %d cache good, bytecount == cache size = %d\n",
260 				pC->adap_idx, byte_count);
261 
262 		pC->init = (u16)cached;
263 	}
264 	return pC->init;
265 }
266 
267 /** Find a control.
268 */
269 static short find_control(u16 control_index,
270 	struct hpi_control_cache *p_cache, struct hpi_control_cache_info **pI)
271 {
272 	if (!control_cache_alloc_check(p_cache)) {
273 		HPI_DEBUG_LOG(VERBOSE,
274 			"control_cache_alloc_check() failed %d\n",
275 			control_index);
276 		return 0;
277 	}
278 
279 	*pI = p_cache->p_info[control_index];
280 	if (!*pI) {
281 		HPI_DEBUG_LOG(VERBOSE, "Uncached Control %d\n",
282 			control_index);
283 		return 0;
284 	} else {
285 		HPI_DEBUG_LOG(VERBOSE, "find_control() type %d\n",
286 			(*pI)->control_type);
287 	}
288 	return 1;
289 }
290 
291 /* allow unified treatment of several string fields within struct */
292 #define HPICMN_PAD_OFS_AND_SIZE(m)  {\
293 	offsetof(struct hpi_control_cache_pad, m), \
294 	sizeof(((struct hpi_control_cache_pad *)(NULL))->m) }
295 
296 struct pad_ofs_size {
297 	unsigned int offset;
298 	unsigned int field_size;
299 };
300 
301 static struct pad_ofs_size pad_desc[] = {
302 	HPICMN_PAD_OFS_AND_SIZE(c_channel),	/* HPI_PAD_CHANNEL_NAME */
303 	HPICMN_PAD_OFS_AND_SIZE(c_artist),	/* HPI_PAD_ARTIST */
304 	HPICMN_PAD_OFS_AND_SIZE(c_title),	/* HPI_PAD_TITLE */
305 	HPICMN_PAD_OFS_AND_SIZE(c_comment),	/* HPI_PAD_COMMENT */
306 };
307 
308 /** CheckControlCache checks the cache and fills the struct hpi_response
309  * accordingly. It returns one if a cache hit occurred, zero otherwise.
310  */
311 short hpi_check_control_cache(struct hpi_control_cache *p_cache,
312 	struct hpi_message *phm, struct hpi_response *phr)
313 {
314 	short found = 1;
315 	struct hpi_control_cache_info *pI;
316 	struct hpi_control_cache_single *pC;
317 	struct hpi_control_cache_pad *p_pad;
318 
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 	/* pC is the default cached control strucure. May be cast to
329 	   something else in the following switch statement.
330 	 */
331 	pC = (struct hpi_control_cache_single *)pI;
332 	p_pad = (struct hpi_control_cache_pad *)pI;
333 
334 	switch (pI->control_type) {
335 
336 	case HPI_CONTROL_METER:
337 		if (phm->u.c.attribute == HPI_METER_PEAK) {
338 			phr->u.c.an_log_value[0] = pC->u.meter.an_log_peak[0];
339 			phr->u.c.an_log_value[1] = pC->u.meter.an_log_peak[1];
340 		} else if (phm->u.c.attribute == HPI_METER_RMS) {
341 			if (pC->u.meter.an_logRMS[0] ==
342 				HPI_CACHE_INVALID_SHORT) {
343 				phr->error =
344 					HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
345 				phr->u.c.an_log_value[0] = HPI_METER_MINIMUM;
346 				phr->u.c.an_log_value[1] = HPI_METER_MINIMUM;
347 			} else {
348 				phr->u.c.an_log_value[0] =
349 					pC->u.meter.an_logRMS[0];
350 				phr->u.c.an_log_value[1] =
351 					pC->u.meter.an_logRMS[1];
352 			}
353 		} else
354 			found = 0;
355 		break;
356 	case HPI_CONTROL_VOLUME:
357 		if (phm->u.c.attribute == HPI_VOLUME_GAIN) {
358 			phr->u.c.an_log_value[0] = pC->u.vol.an_log[0];
359 			phr->u.c.an_log_value[1] = pC->u.vol.an_log[1];
360 		} else if (phm->u.c.attribute == HPI_VOLUME_MUTE) {
361 			if (pC->u.vol.flags & HPI_VOLUME_FLAG_HAS_MUTE) {
362 				if (pC->u.vol.flags & HPI_VOLUME_FLAG_MUTED)
363 					phr->u.c.param1 =
364 						HPI_BITMASK_ALL_CHANNELS;
365 				else
366 					phr->u.c.param1 = 0;
367 			} else {
368 				phr->error =
369 					HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
370 				phr->u.c.param1 = 0;
371 			}
372 		} else {
373 			found = 0;
374 		}
375 		break;
376 	case HPI_CONTROL_MULTIPLEXER:
377 		if (phm->u.c.attribute == HPI_MULTIPLEXER_SOURCE) {
378 			phr->u.c.param1 = pC->u.mux.source_node_type;
379 			phr->u.c.param2 = pC->u.mux.source_node_index;
380 		} else {
381 			found = 0;
382 		}
383 		break;
384 	case HPI_CONTROL_CHANNEL_MODE:
385 		if (phm->u.c.attribute == HPI_CHANNEL_MODE_MODE)
386 			phr->u.c.param1 = pC->u.mode.mode;
387 		else
388 			found = 0;
389 		break;
390 	case HPI_CONTROL_LEVEL:
391 		if (phm->u.c.attribute == HPI_LEVEL_GAIN) {
392 			phr->u.c.an_log_value[0] = pC->u.level.an_log[0];
393 			phr->u.c.an_log_value[1] = pC->u.level.an_log[1];
394 		} else
395 			found = 0;
396 		break;
397 	case HPI_CONTROL_TUNER:
398 		if (phm->u.c.attribute == HPI_TUNER_FREQ)
399 			phr->u.c.param1 = pC->u.tuner.freq_ink_hz;
400 		else if (phm->u.c.attribute == HPI_TUNER_BAND)
401 			phr->u.c.param1 = pC->u.tuner.band;
402 		else if (phm->u.c.attribute == HPI_TUNER_LEVEL_AVG)
403 			if (pC->u.tuner.s_level_avg ==
404 				HPI_CACHE_INVALID_SHORT) {
405 				phr->u.cu.tuner.s_level = 0;
406 				phr->error =
407 					HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
408 			} else
409 				phr->u.cu.tuner.s_level =
410 					pC->u.tuner.s_level_avg;
411 		else
412 			found = 0;
413 		break;
414 	case HPI_CONTROL_AESEBU_RECEIVER:
415 		if (phm->u.c.attribute == HPI_AESEBURX_ERRORSTATUS)
416 			phr->u.c.param1 = pC->u.aes3rx.error_status;
417 		else if (phm->u.c.attribute == HPI_AESEBURX_FORMAT)
418 			phr->u.c.param1 = pC->u.aes3rx.format;
419 		else
420 			found = 0;
421 		break;
422 	case HPI_CONTROL_AESEBU_TRANSMITTER:
423 		if (phm->u.c.attribute == HPI_AESEBUTX_FORMAT)
424 			phr->u.c.param1 = pC->u.aes3tx.format;
425 		else
426 			found = 0;
427 		break;
428 	case HPI_CONTROL_TONEDETECTOR:
429 		if (phm->u.c.attribute == HPI_TONEDETECTOR_STATE)
430 			phr->u.c.param1 = pC->u.tone.state;
431 		else
432 			found = 0;
433 		break;
434 	case HPI_CONTROL_SILENCEDETECTOR:
435 		if (phm->u.c.attribute == HPI_SILENCEDETECTOR_STATE) {
436 			phr->u.c.param1 = pC->u.silence.state;
437 		} else
438 			found = 0;
439 		break;
440 	case HPI_CONTROL_MICROPHONE:
441 		if (phm->u.c.attribute == HPI_MICROPHONE_PHANTOM_POWER)
442 			phr->u.c.param1 = pC->u.microphone.phantom_state;
443 		else
444 			found = 0;
445 		break;
446 	case HPI_CONTROL_SAMPLECLOCK:
447 		if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE)
448 			phr->u.c.param1 = pC->u.clk.source;
449 		else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE_INDEX) {
450 			if (pC->u.clk.source_index ==
451 				HPI_CACHE_INVALID_UINT16) {
452 				phr->u.c.param1 = 0;
453 				phr->error =
454 					HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
455 			} else
456 				phr->u.c.param1 = pC->u.clk.source_index;
457 		} else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SAMPLERATE)
458 			phr->u.c.param1 = pC->u.clk.sample_rate;
459 		else
460 			found = 0;
461 		break;
462 	case HPI_CONTROL_PAD:{
463 			struct hpi_control_cache_pad *p_pad;
464 			p_pad = (struct hpi_control_cache_pad *)pI;
465 
466 			if (!(p_pad->field_valid_flags & (1 <<
467 						HPI_CTL_ATTR_INDEX(phm->u.c.
468 							attribute)))) {
469 				phr->error =
470 					HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
471 				break;
472 			}
473 
474 			if (phm->u.c.attribute == HPI_PAD_PROGRAM_ID)
475 				phr->u.c.param1 = p_pad->pI;
476 			else if (phm->u.c.attribute == HPI_PAD_PROGRAM_TYPE)
477 				phr->u.c.param1 = p_pad->pTY;
478 			else {
479 				unsigned int index =
480 					HPI_CTL_ATTR_INDEX(phm->u.c.
481 					attribute) - 1;
482 				unsigned int offset = phm->u.c.param1;
483 				unsigned int pad_string_len, field_size;
484 				char *pad_string;
485 				unsigned int tocopy;
486 
487 				if (index > ARRAY_SIZE(pad_desc) - 1) {
488 					phr->error =
489 						HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
490 					break;
491 				}
492 
493 				pad_string =
494 					((char *)p_pad) +
495 					pad_desc[index].offset;
496 				field_size = pad_desc[index].field_size;
497 				/* Ensure null terminator */
498 				pad_string[field_size - 1] = 0;
499 
500 				pad_string_len = strlen(pad_string) + 1;
501 
502 				if (offset > pad_string_len) {
503 					phr->error =
504 						HPI_ERROR_INVALID_CONTROL_VALUE;
505 					break;
506 				}
507 
508 				tocopy = pad_string_len - offset;
509 				if (tocopy > sizeof(phr->u.cu.chars8.sz_data))
510 					tocopy = sizeof(phr->u.cu.chars8.
511 						sz_data);
512 
513 				memcpy(phr->u.cu.chars8.sz_data,
514 					&pad_string[offset], tocopy);
515 
516 				phr->u.cu.chars8.remaining_chars =
517 					pad_string_len - offset - tocopy;
518 			}
519 		}
520 		break;
521 	default:
522 		found = 0;
523 		break;
524 	}
525 
526 	HPI_DEBUG_LOG(VERBOSE, "%s Adap %d, Ctl %d, Type %d, Attr %d\n",
527 		found ? "Cached" : "Uncached", phm->adapter_index,
528 		pI->control_index, pI->control_type, phm->u.c.attribute);
529 
530 	if (found)
531 		phr->size =
532 			sizeof(struct hpi_response_header) +
533 			sizeof(struct hpi_control_res);
534 
535 	return found;
536 }
537 
538 /** Updates the cache with Set values.
539 
540 Only update if no error.
541 Volume and Level return the limited values in the response, so use these
542 Multiplexer does so use sent values
543 */
544 void hpi_cmn_control_cache_sync_to_msg(struct hpi_control_cache *p_cache,
545 	struct hpi_message *phm, struct hpi_response *phr)
546 {
547 	struct hpi_control_cache_single *pC;
548 	struct hpi_control_cache_info *pI;
549 
550 	if (phr->error)
551 		return;
552 
553 	if (!find_control(phm->obj_index, p_cache, &pI)) {
554 		HPI_DEBUG_LOG(VERBOSE,
555 			"HPICMN find_control() failed for adap %d\n",
556 			phm->adapter_index);
557 		return;
558 	}
559 
560 	/* pC is the default cached control strucure.
561 	   May be cast to something else in the following switch statement.
562 	 */
563 	pC = (struct hpi_control_cache_single *)pI;
564 
565 	switch (pI->control_type) {
566 	case HPI_CONTROL_VOLUME:
567 		if (phm->u.c.attribute == HPI_VOLUME_GAIN) {
568 			pC->u.vol.an_log[0] = phr->u.c.an_log_value[0];
569 			pC->u.vol.an_log[1] = phr->u.c.an_log_value[1];
570 		} else if (phm->u.c.attribute == HPI_VOLUME_MUTE) {
571 			if (phm->u.c.param1)
572 				pC->u.vol.flags |= HPI_VOLUME_FLAG_MUTED;
573 			else
574 				pC->u.vol.flags &= ~HPI_VOLUME_FLAG_MUTED;
575 		}
576 		break;
577 	case HPI_CONTROL_MULTIPLEXER:
578 		/* mux does not return its setting on Set command. */
579 		if (phm->u.c.attribute == HPI_MULTIPLEXER_SOURCE) {
580 			pC->u.mux.source_node_type = (u16)phm->u.c.param1;
581 			pC->u.mux.source_node_index = (u16)phm->u.c.param2;
582 		}
583 		break;
584 	case HPI_CONTROL_CHANNEL_MODE:
585 		/* mode does not return its setting on Set command. */
586 		if (phm->u.c.attribute == HPI_CHANNEL_MODE_MODE)
587 			pC->u.mode.mode = (u16)phm->u.c.param1;
588 		break;
589 	case HPI_CONTROL_LEVEL:
590 		if (phm->u.c.attribute == HPI_LEVEL_GAIN) {
591 			pC->u.vol.an_log[0] = phr->u.c.an_log_value[0];
592 			pC->u.vol.an_log[1] = phr->u.c.an_log_value[1];
593 		}
594 		break;
595 	case HPI_CONTROL_MICROPHONE:
596 		if (phm->u.c.attribute == HPI_MICROPHONE_PHANTOM_POWER)
597 			pC->u.microphone.phantom_state = (u16)phm->u.c.param1;
598 		break;
599 	case HPI_CONTROL_AESEBU_TRANSMITTER:
600 		if (phm->u.c.attribute == HPI_AESEBUTX_FORMAT)
601 			pC->u.aes3tx.format = phm->u.c.param1;
602 		break;
603 	case HPI_CONTROL_AESEBU_RECEIVER:
604 		if (phm->u.c.attribute == HPI_AESEBURX_FORMAT)
605 			pC->u.aes3rx.format = phm->u.c.param1;
606 		break;
607 	case HPI_CONTROL_SAMPLECLOCK:
608 		if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE)
609 			pC->u.clk.source = (u16)phm->u.c.param1;
610 		else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE_INDEX)
611 			pC->u.clk.source_index = (u16)phm->u.c.param1;
612 		else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SAMPLERATE)
613 			pC->u.clk.sample_rate = phm->u.c.param1;
614 		break;
615 	default:
616 		break;
617 	}
618 }
619 
620 struct hpi_control_cache *hpi_alloc_control_cache(const u32 control_count,
621 	const u32 size_in_bytes, u8 *p_dsp_control_buffer)
622 {
623 	struct hpi_control_cache *p_cache =
624 		kmalloc(sizeof(*p_cache), GFP_KERNEL);
625 	if (!p_cache)
626 		return NULL;
627 
628 	p_cache->p_info =
629 		kmalloc(sizeof(*p_cache->p_info) * control_count, GFP_KERNEL);
630 	if (!p_cache->p_info) {
631 		kfree(p_cache);
632 		return NULL;
633 	}
634 	memset(p_cache->p_info, 0, sizeof(*p_cache->p_info) * control_count);
635 	p_cache->cache_size_in_bytes = size_in_bytes;
636 	p_cache->control_count = control_count;
637 	p_cache->p_cache = p_dsp_control_buffer;
638 	p_cache->init = 0;
639 	return p_cache;
640 }
641 
642 void hpi_free_control_cache(struct hpi_control_cache *p_cache)
643 {
644 	if (p_cache) {
645 		kfree(p_cache->p_info);
646 		kfree(p_cache);
647 	}
648 }
649 
650 static void subsys_message(struct hpi_message *phm, struct hpi_response *phr)
651 {
652 	hpi_init_response(phr, HPI_OBJ_SUBSYSTEM, phm->function, 0);
653 
654 	switch (phm->function) {
655 	case HPI_SUBSYS_OPEN:
656 	case HPI_SUBSYS_CLOSE:
657 	case HPI_SUBSYS_DRIVER_UNLOAD:
658 		break;
659 	case HPI_SUBSYS_DRIVER_LOAD:
660 		wipe_adapter_list();
661 		hpios_alistlock_init(&adapters);
662 		break;
663 	case HPI_SUBSYS_GET_ADAPTER:
664 		subsys_get_adapter(phm, phr);
665 		break;
666 	case HPI_SUBSYS_GET_NUM_ADAPTERS:
667 		phr->u.s.num_adapters = adapters.gw_num_adapters;
668 		break;
669 	case HPI_SUBSYS_CREATE_ADAPTER:
670 	case HPI_SUBSYS_DELETE_ADAPTER:
671 		break;
672 	default:
673 		phr->error = HPI_ERROR_INVALID_FUNC;
674 		break;
675 	}
676 }
677 
678 void HPI_COMMON(struct hpi_message *phm, struct hpi_response *phr)
679 {
680 	switch (phm->type) {
681 	case HPI_TYPE_MESSAGE:
682 		switch (phm->object) {
683 		case HPI_OBJ_SUBSYSTEM:
684 			subsys_message(phm, phr);
685 			break;
686 		}
687 		break;
688 
689 	default:
690 		phr->error = HPI_ERROR_INVALID_TYPE;
691 		break;
692 	}
693 }
694