xref: /openbmc/linux/sound/pci/asihpi/hpicmn.c (revision b34e08d5)
1 /******************************************************************************
2 
3     AudioScience HPI driver
4     Copyright (C) 1997-2011  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->type); */
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].type) {
81 		int a;
82 		for (a = HPI_MAX_ADAPTERS - 1; a >= 0; a--) {
83 			if (!adapters.adapter[a].type) {
84 				HPI_DEBUG_LOG(WARNING,
85 					"ASI%X duplicate index %d moved to %d\n",
86 					pao->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->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].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->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].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].type;
178 	} else {
179 		phr->u.s.adapter_index = 0;
180 		phr->u.s.adapter_type = 0;
181 		phr->error = HPI_ERROR_INVALID_OBJ_INDEX;
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 	phr->specific_error = 0;
328 	phr->version = 0;
329 
330 	/* set the default response size */
331 	response_size =
332 		sizeof(struct hpi_response_header) +
333 		sizeof(struct hpi_control_res);
334 
335 	/* pC is the default cached control strucure. May be cast to
336 	   something else in the following switch statement.
337 	 */
338 	pC = (struct hpi_control_cache_single *)pI;
339 
340 	switch (pI->control_type) {
341 
342 	case HPI_CONTROL_METER:
343 		if (phm->u.c.attribute == HPI_METER_PEAK) {
344 			phr->u.c.an_log_value[0] = pC->u.meter.an_log_peak[0];
345 			phr->u.c.an_log_value[1] = pC->u.meter.an_log_peak[1];
346 		} else if (phm->u.c.attribute == HPI_METER_RMS) {
347 			if (pC->u.meter.an_logRMS[0] ==
348 				HPI_CACHE_INVALID_SHORT) {
349 				phr->error =
350 					HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
351 				phr->u.c.an_log_value[0] = HPI_METER_MINIMUM;
352 				phr->u.c.an_log_value[1] = HPI_METER_MINIMUM;
353 			} else {
354 				phr->u.c.an_log_value[0] =
355 					pC->u.meter.an_logRMS[0];
356 				phr->u.c.an_log_value[1] =
357 					pC->u.meter.an_logRMS[1];
358 			}
359 		} else
360 			found = 0;
361 		break;
362 	case HPI_CONTROL_VOLUME:
363 		if (phm->u.c.attribute == HPI_VOLUME_GAIN) {
364 			phr->u.c.an_log_value[0] = pC->u.vol.an_log[0];
365 			phr->u.c.an_log_value[1] = pC->u.vol.an_log[1];
366 		} else if (phm->u.c.attribute == HPI_VOLUME_MUTE) {
367 			if (pC->u.vol.flags & HPI_VOLUME_FLAG_HAS_MUTE) {
368 				if (pC->u.vol.flags & HPI_VOLUME_FLAG_MUTED)
369 					phr->u.c.param1 =
370 						HPI_BITMASK_ALL_CHANNELS;
371 				else
372 					phr->u.c.param1 = 0;
373 			} else {
374 				phr->error =
375 					HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
376 				phr->u.c.param1 = 0;
377 			}
378 		} else {
379 			found = 0;
380 		}
381 		break;
382 	case HPI_CONTROL_MULTIPLEXER:
383 		if (phm->u.c.attribute == HPI_MULTIPLEXER_SOURCE) {
384 			phr->u.c.param1 = pC->u.mux.source_node_type;
385 			phr->u.c.param2 = pC->u.mux.source_node_index;
386 		} else {
387 			found = 0;
388 		}
389 		break;
390 	case HPI_CONTROL_CHANNEL_MODE:
391 		if (phm->u.c.attribute == HPI_CHANNEL_MODE_MODE)
392 			phr->u.c.param1 = pC->u.mode.mode;
393 		else
394 			found = 0;
395 		break;
396 	case HPI_CONTROL_LEVEL:
397 		if (phm->u.c.attribute == HPI_LEVEL_GAIN) {
398 			phr->u.c.an_log_value[0] = pC->u.level.an_log[0];
399 			phr->u.c.an_log_value[1] = pC->u.level.an_log[1];
400 		} else
401 			found = 0;
402 		break;
403 	case HPI_CONTROL_TUNER:
404 		if (phm->u.c.attribute == HPI_TUNER_FREQ)
405 			phr->u.c.param1 = pC->u.tuner.freq_ink_hz;
406 		else if (phm->u.c.attribute == HPI_TUNER_BAND)
407 			phr->u.c.param1 = pC->u.tuner.band;
408 		else if (phm->u.c.attribute == HPI_TUNER_LEVEL_AVG)
409 			if (pC->u.tuner.s_level_avg ==
410 				HPI_CACHE_INVALID_SHORT) {
411 				phr->u.cu.tuner.s_level = 0;
412 				phr->error =
413 					HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
414 			} else
415 				phr->u.cu.tuner.s_level =
416 					pC->u.tuner.s_level_avg;
417 		else
418 			found = 0;
419 		break;
420 	case HPI_CONTROL_AESEBU_RECEIVER:
421 		if (phm->u.c.attribute == HPI_AESEBURX_ERRORSTATUS)
422 			phr->u.c.param1 = pC->u.aes3rx.error_status;
423 		else if (phm->u.c.attribute == HPI_AESEBURX_FORMAT)
424 			phr->u.c.param1 = pC->u.aes3rx.format;
425 		else
426 			found = 0;
427 		break;
428 	case HPI_CONTROL_AESEBU_TRANSMITTER:
429 		if (phm->u.c.attribute == HPI_AESEBUTX_FORMAT)
430 			phr->u.c.param1 = pC->u.aes3tx.format;
431 		else
432 			found = 0;
433 		break;
434 	case HPI_CONTROL_TONEDETECTOR:
435 		if (phm->u.c.attribute == HPI_TONEDETECTOR_STATE)
436 			phr->u.c.param1 = pC->u.tone.state;
437 		else
438 			found = 0;
439 		break;
440 	case HPI_CONTROL_SILENCEDETECTOR:
441 		if (phm->u.c.attribute == HPI_SILENCEDETECTOR_STATE) {
442 			phr->u.c.param1 = pC->u.silence.state;
443 		} else
444 			found = 0;
445 		break;
446 	case HPI_CONTROL_MICROPHONE:
447 		if (phm->u.c.attribute == HPI_MICROPHONE_PHANTOM_POWER)
448 			phr->u.c.param1 = pC->u.microphone.phantom_state;
449 		else
450 			found = 0;
451 		break;
452 	case HPI_CONTROL_SAMPLECLOCK:
453 		if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE)
454 			phr->u.c.param1 = pC->u.clk.source;
455 		else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE_INDEX) {
456 			if (pC->u.clk.source_index ==
457 				HPI_CACHE_INVALID_UINT16) {
458 				phr->u.c.param1 = 0;
459 				phr->error =
460 					HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
461 			} else
462 				phr->u.c.param1 = pC->u.clk.source_index;
463 		} else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SAMPLERATE)
464 			phr->u.c.param1 = pC->u.clk.sample_rate;
465 		else
466 			found = 0;
467 		break;
468 	case HPI_CONTROL_PAD:{
469 			struct hpi_control_cache_pad *p_pad;
470 			p_pad = (struct hpi_control_cache_pad *)pI;
471 
472 			if (!(p_pad->field_valid_flags & (1 <<
473 						HPI_CTL_ATTR_INDEX(phm->u.c.
474 							attribute)))) {
475 				phr->error =
476 					HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
477 				break;
478 			}
479 
480 			if (phm->u.c.attribute == HPI_PAD_PROGRAM_ID)
481 				phr->u.c.param1 = p_pad->pI;
482 			else if (phm->u.c.attribute == HPI_PAD_PROGRAM_TYPE)
483 				phr->u.c.param1 = p_pad->pTY;
484 			else {
485 				unsigned int index =
486 					HPI_CTL_ATTR_INDEX(phm->u.c.
487 					attribute) - 1;
488 				unsigned int offset = phm->u.c.param1;
489 				unsigned int pad_string_len, field_size;
490 				char *pad_string;
491 				unsigned int tocopy;
492 
493 				if (index > ARRAY_SIZE(pad_desc) - 1) {
494 					phr->error =
495 						HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
496 					break;
497 				}
498 
499 				pad_string =
500 					((char *)p_pad) +
501 					pad_desc[index].offset;
502 				field_size = pad_desc[index].field_size;
503 				/* Ensure null terminator */
504 				pad_string[field_size - 1] = 0;
505 
506 				pad_string_len = strlen(pad_string) + 1;
507 
508 				if (offset > pad_string_len) {
509 					phr->error =
510 						HPI_ERROR_INVALID_CONTROL_VALUE;
511 					break;
512 				}
513 
514 				tocopy = pad_string_len - offset;
515 				if (tocopy > sizeof(phr->u.cu.chars8.sz_data))
516 					tocopy = sizeof(phr->u.cu.chars8.
517 						sz_data);
518 
519 				memcpy(phr->u.cu.chars8.sz_data,
520 					&pad_string[offset], tocopy);
521 
522 				phr->u.cu.chars8.remaining_chars =
523 					pad_string_len - offset - tocopy;
524 			}
525 		}
526 		break;
527 	default:
528 		found = 0;
529 		break;
530 	}
531 
532 	HPI_DEBUG_LOG(VERBOSE, "%s Adap %d, Ctl %d, Type %d, Attr %d\n",
533 		found ? "Cached" : "Uncached", phm->adapter_index,
534 		pI->control_index, pI->control_type, phm->u.c.attribute);
535 
536 	if (found) {
537 		phr->size = (u16)response_size;
538 		phr->type = HPI_TYPE_RESPONSE;
539 		phr->object = phm->object;
540 		phr->function = phm->function;
541 	}
542 
543 	return found;
544 }
545 
546 /** Updates the cache with Set values.
547 
548 Only update if no error.
549 Volume and Level return the limited values in the response, so use these
550 Multiplexer does so use sent values
551 */
552 void hpi_cmn_control_cache_sync_to_msg(struct hpi_control_cache *p_cache,
553 	struct hpi_message *phm, struct hpi_response *phr)
554 {
555 	struct hpi_control_cache_single *pC;
556 	struct hpi_control_cache_info *pI;
557 
558 	if (phr->error)
559 		return;
560 
561 	if (!find_control(phm->obj_index, p_cache, &pI)) {
562 		HPI_DEBUG_LOG(VERBOSE,
563 			"HPICMN find_control() failed for adap %d\n",
564 			phm->adapter_index);
565 		return;
566 	}
567 
568 	/* pC is the default cached control strucure.
569 	   May be cast to something else in the following switch statement.
570 	 */
571 	pC = (struct hpi_control_cache_single *)pI;
572 
573 	switch (pI->control_type) {
574 	case HPI_CONTROL_VOLUME:
575 		if (phm->u.c.attribute == HPI_VOLUME_GAIN) {
576 			pC->u.vol.an_log[0] = phr->u.c.an_log_value[0];
577 			pC->u.vol.an_log[1] = phr->u.c.an_log_value[1];
578 		} else if (phm->u.c.attribute == HPI_VOLUME_MUTE) {
579 			if (phm->u.c.param1)
580 				pC->u.vol.flags |= HPI_VOLUME_FLAG_MUTED;
581 			else
582 				pC->u.vol.flags &= ~HPI_VOLUME_FLAG_MUTED;
583 		}
584 		break;
585 	case HPI_CONTROL_MULTIPLEXER:
586 		/* mux does not return its setting on Set command. */
587 		if (phm->u.c.attribute == HPI_MULTIPLEXER_SOURCE) {
588 			pC->u.mux.source_node_type = (u16)phm->u.c.param1;
589 			pC->u.mux.source_node_index = (u16)phm->u.c.param2;
590 		}
591 		break;
592 	case HPI_CONTROL_CHANNEL_MODE:
593 		/* mode does not return its setting on Set command. */
594 		if (phm->u.c.attribute == HPI_CHANNEL_MODE_MODE)
595 			pC->u.mode.mode = (u16)phm->u.c.param1;
596 		break;
597 	case HPI_CONTROL_LEVEL:
598 		if (phm->u.c.attribute == HPI_LEVEL_GAIN) {
599 			pC->u.vol.an_log[0] = phr->u.c.an_log_value[0];
600 			pC->u.vol.an_log[1] = phr->u.c.an_log_value[1];
601 		}
602 		break;
603 	case HPI_CONTROL_MICROPHONE:
604 		if (phm->u.c.attribute == HPI_MICROPHONE_PHANTOM_POWER)
605 			pC->u.microphone.phantom_state = (u16)phm->u.c.param1;
606 		break;
607 	case HPI_CONTROL_AESEBU_TRANSMITTER:
608 		if (phm->u.c.attribute == HPI_AESEBUTX_FORMAT)
609 			pC->u.aes3tx.format = phm->u.c.param1;
610 		break;
611 	case HPI_CONTROL_AESEBU_RECEIVER:
612 		if (phm->u.c.attribute == HPI_AESEBURX_FORMAT)
613 			pC->u.aes3rx.format = phm->u.c.param1;
614 		break;
615 	case HPI_CONTROL_SAMPLECLOCK:
616 		if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE)
617 			pC->u.clk.source = (u16)phm->u.c.param1;
618 		else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE_INDEX)
619 			pC->u.clk.source_index = (u16)phm->u.c.param1;
620 		else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SAMPLERATE)
621 			pC->u.clk.sample_rate = phm->u.c.param1;
622 		break;
623 	default:
624 		break;
625 	}
626 }
627 
628 /** Allocate control cache.
629 
630 \return Cache pointer, or NULL if allocation fails.
631 */
632 struct hpi_control_cache *hpi_alloc_control_cache(const u32 control_count,
633 	const u32 size_in_bytes, u8 *p_dsp_control_buffer)
634 {
635 	struct hpi_control_cache *p_cache =
636 		kmalloc(sizeof(*p_cache), GFP_KERNEL);
637 	if (!p_cache)
638 		return NULL;
639 
640 	p_cache->p_info = kcalloc(control_count, sizeof(*p_cache->p_info),
641 				  GFP_KERNEL);
642 	if (!p_cache->p_info) {
643 		kfree(p_cache);
644 		return NULL;
645 	}
646 	p_cache->cache_size_in_bytes = size_in_bytes;
647 	p_cache->control_count = control_count;
648 	p_cache->p_cache = p_dsp_control_buffer;
649 	p_cache->init = 0;
650 	return p_cache;
651 }
652 
653 void hpi_free_control_cache(struct hpi_control_cache *p_cache)
654 {
655 	if (p_cache) {
656 		kfree(p_cache->p_info);
657 		kfree(p_cache);
658 	}
659 }
660 
661 static void subsys_message(struct hpi_message *phm, struct hpi_response *phr)
662 {
663 	hpi_init_response(phr, HPI_OBJ_SUBSYSTEM, phm->function, 0);
664 
665 	switch (phm->function) {
666 	case HPI_SUBSYS_OPEN:
667 	case HPI_SUBSYS_CLOSE:
668 	case HPI_SUBSYS_DRIVER_UNLOAD:
669 		break;
670 	case HPI_SUBSYS_DRIVER_LOAD:
671 		wipe_adapter_list();
672 		hpios_alistlock_init(&adapters);
673 		break;
674 	case HPI_SUBSYS_GET_ADAPTER:
675 		subsys_get_adapter(phm, phr);
676 		break;
677 	case HPI_SUBSYS_GET_NUM_ADAPTERS:
678 		phr->u.s.num_adapters = adapters.gw_num_adapters;
679 		break;
680 	case HPI_SUBSYS_CREATE_ADAPTER:
681 		break;
682 	default:
683 		phr->error = HPI_ERROR_INVALID_FUNC;
684 		break;
685 	}
686 }
687 
688 void HPI_COMMON(struct hpi_message *phm, struct hpi_response *phr)
689 {
690 	switch (phm->type) {
691 	case HPI_TYPE_REQUEST:
692 		switch (phm->object) {
693 		case HPI_OBJ_SUBSYSTEM:
694 			subsys_message(phm, phr);
695 			break;
696 		}
697 		break;
698 
699 	default:
700 		phr->error = HPI_ERROR_INVALID_TYPE;
701 		break;
702 	}
703 }
704