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