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