18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/******************************************************************************
38c2ecf20Sopenharmony_ci
48c2ecf20Sopenharmony_ci    AudioScience HPI driver
58c2ecf20Sopenharmony_ci    Copyright (C) 1997-2014  AudioScience Inc. <support@audioscience.com>
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci\file hpicmn.c
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci Common functions used by hpixxxx.c modules
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_ci(C) Copyright AudioScience Inc. 1998-2003
138c2ecf20Sopenharmony_ci*******************************************************************************/
148c2ecf20Sopenharmony_ci#define SOURCEFILE_NAME "hpicmn.c"
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ci#include "hpi_internal.h"
178c2ecf20Sopenharmony_ci#include "hpidebug.h"
188c2ecf20Sopenharmony_ci#include "hpimsginit.h"
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_ci#include "hpicmn.h"
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_cistruct hpi_adapters_list {
238c2ecf20Sopenharmony_ci	struct hpios_spinlock list_lock;
248c2ecf20Sopenharmony_ci	struct hpi_adapter_obj adapter[HPI_MAX_ADAPTERS];
258c2ecf20Sopenharmony_ci	u16 gw_num_adapters;
268c2ecf20Sopenharmony_ci};
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_cistatic struct hpi_adapters_list adapters;
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_ci/**
318c2ecf20Sopenharmony_ci * hpi_validate_response - Given an HPI Message that was sent out and
328c2ecf20Sopenharmony_ci * a response that was received, validate that the response has the
338c2ecf20Sopenharmony_ci * correct fields filled in, i.e ObjectType, Function etc
348c2ecf20Sopenharmony_ci * @phm: message
358c2ecf20Sopenharmony_ci * @phr: response
368c2ecf20Sopenharmony_ci */
378c2ecf20Sopenharmony_ciu16 hpi_validate_response(struct hpi_message *phm, struct hpi_response *phr)
388c2ecf20Sopenharmony_ci{
398c2ecf20Sopenharmony_ci	if (phr->type != HPI_TYPE_RESPONSE) {
408c2ecf20Sopenharmony_ci		HPI_DEBUG_LOG(ERROR, "header type %d invalid\n", phr->type);
418c2ecf20Sopenharmony_ci		return HPI_ERROR_INVALID_RESPONSE;
428c2ecf20Sopenharmony_ci	}
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_ci	if (phr->object != phm->object) {
458c2ecf20Sopenharmony_ci		HPI_DEBUG_LOG(ERROR, "header object %d invalid\n",
468c2ecf20Sopenharmony_ci			phr->object);
478c2ecf20Sopenharmony_ci		return HPI_ERROR_INVALID_RESPONSE;
488c2ecf20Sopenharmony_ci	}
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_ci	if (phr->function != phm->function) {
518c2ecf20Sopenharmony_ci		HPI_DEBUG_LOG(ERROR, "header function %d invalid\n",
528c2ecf20Sopenharmony_ci			phr->function);
538c2ecf20Sopenharmony_ci		return HPI_ERROR_INVALID_RESPONSE;
548c2ecf20Sopenharmony_ci	}
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_ci	return 0;
578c2ecf20Sopenharmony_ci}
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_ciu16 hpi_add_adapter(struct hpi_adapter_obj *pao)
608c2ecf20Sopenharmony_ci{
618c2ecf20Sopenharmony_ci	u16 retval = 0;
628c2ecf20Sopenharmony_ci	/*HPI_ASSERT(pao->type); */
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_ci	hpios_alistlock_lock(&adapters);
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_ci	if (pao->index >= HPI_MAX_ADAPTERS) {
678c2ecf20Sopenharmony_ci		retval = HPI_ERROR_BAD_ADAPTER_NUMBER;
688c2ecf20Sopenharmony_ci		goto unlock;
698c2ecf20Sopenharmony_ci	}
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_ci	if (adapters.adapter[pao->index].type) {
728c2ecf20Sopenharmony_ci		int a;
738c2ecf20Sopenharmony_ci		for (a = HPI_MAX_ADAPTERS - 1; a >= 0; a--) {
748c2ecf20Sopenharmony_ci			if (!adapters.adapter[a].type) {
758c2ecf20Sopenharmony_ci				HPI_DEBUG_LOG(WARNING,
768c2ecf20Sopenharmony_ci					"ASI%X duplicate index %d moved to %d\n",
778c2ecf20Sopenharmony_ci					pao->type, pao->index, a);
788c2ecf20Sopenharmony_ci				pao->index = a;
798c2ecf20Sopenharmony_ci				break;
808c2ecf20Sopenharmony_ci			}
818c2ecf20Sopenharmony_ci		}
828c2ecf20Sopenharmony_ci		if (a < 0) {
838c2ecf20Sopenharmony_ci			retval = HPI_ERROR_DUPLICATE_ADAPTER_NUMBER;
848c2ecf20Sopenharmony_ci			goto unlock;
858c2ecf20Sopenharmony_ci		}
868c2ecf20Sopenharmony_ci	}
878c2ecf20Sopenharmony_ci	adapters.adapter[pao->index] = *pao;
888c2ecf20Sopenharmony_ci	hpios_dsplock_init(&adapters.adapter[pao->index]);
898c2ecf20Sopenharmony_ci	adapters.gw_num_adapters++;
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_ciunlock:
928c2ecf20Sopenharmony_ci	hpios_alistlock_unlock(&adapters);
938c2ecf20Sopenharmony_ci	return retval;
948c2ecf20Sopenharmony_ci}
958c2ecf20Sopenharmony_ci
968c2ecf20Sopenharmony_civoid hpi_delete_adapter(struct hpi_adapter_obj *pao)
978c2ecf20Sopenharmony_ci{
988c2ecf20Sopenharmony_ci	if (!pao->type) {
998c2ecf20Sopenharmony_ci		HPI_DEBUG_LOG(ERROR, "removing null adapter?\n");
1008c2ecf20Sopenharmony_ci		return;
1018c2ecf20Sopenharmony_ci	}
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_ci	hpios_alistlock_lock(&adapters);
1048c2ecf20Sopenharmony_ci	if (adapters.adapter[pao->index].type)
1058c2ecf20Sopenharmony_ci		adapters.gw_num_adapters--;
1068c2ecf20Sopenharmony_ci	memset(&adapters.adapter[pao->index], 0, sizeof(adapters.adapter[0]));
1078c2ecf20Sopenharmony_ci	hpios_alistlock_unlock(&adapters);
1088c2ecf20Sopenharmony_ci}
1098c2ecf20Sopenharmony_ci
1108c2ecf20Sopenharmony_ci/**
1118c2ecf20Sopenharmony_ci * hpi_find_adapter - FindAdapter returns a pointer to the struct
1128c2ecf20Sopenharmony_ci * hpi_adapter_obj with index wAdapterIndex in an HPI_ADAPTERS_LIST
1138c2ecf20Sopenharmony_ci * structure.
1148c2ecf20Sopenharmony_ci * @adapter_index: value in [0, HPI_MAX_ADAPTERS[
1158c2ecf20Sopenharmony_ci */
1168c2ecf20Sopenharmony_cistruct hpi_adapter_obj *hpi_find_adapter(u16 adapter_index)
1178c2ecf20Sopenharmony_ci{
1188c2ecf20Sopenharmony_ci	struct hpi_adapter_obj *pao = NULL;
1198c2ecf20Sopenharmony_ci
1208c2ecf20Sopenharmony_ci	if (adapter_index >= HPI_MAX_ADAPTERS) {
1218c2ecf20Sopenharmony_ci		HPI_DEBUG_LOG(VERBOSE, "find_adapter invalid index %d\n",
1228c2ecf20Sopenharmony_ci			adapter_index);
1238c2ecf20Sopenharmony_ci		return NULL;
1248c2ecf20Sopenharmony_ci	}
1258c2ecf20Sopenharmony_ci
1268c2ecf20Sopenharmony_ci	pao = &adapters.adapter[adapter_index];
1278c2ecf20Sopenharmony_ci	if (pao->type != 0) {
1288c2ecf20Sopenharmony_ci		/*
1298c2ecf20Sopenharmony_ci		   HPI_DEBUG_LOG(VERBOSE, "Found adapter index %d\n",
1308c2ecf20Sopenharmony_ci		   wAdapterIndex);
1318c2ecf20Sopenharmony_ci		 */
1328c2ecf20Sopenharmony_ci		return pao;
1338c2ecf20Sopenharmony_ci	} else {
1348c2ecf20Sopenharmony_ci		/*
1358c2ecf20Sopenharmony_ci		   HPI_DEBUG_LOG(VERBOSE, "No adapter index %d\n",
1368c2ecf20Sopenharmony_ci		   wAdapterIndex);
1378c2ecf20Sopenharmony_ci		 */
1388c2ecf20Sopenharmony_ci		return NULL;
1398c2ecf20Sopenharmony_ci	}
1408c2ecf20Sopenharmony_ci}
1418c2ecf20Sopenharmony_ci
1428c2ecf20Sopenharmony_ci/**
1438c2ecf20Sopenharmony_ci * wipe_adapter_list - wipe an HPI_ADAPTERS_LIST structure.
1448c2ecf20Sopenharmony_ci *
1458c2ecf20Sopenharmony_ci */
1468c2ecf20Sopenharmony_cistatic void wipe_adapter_list(void)
1478c2ecf20Sopenharmony_ci{
1488c2ecf20Sopenharmony_ci	memset(&adapters, 0, sizeof(adapters));
1498c2ecf20Sopenharmony_ci}
1508c2ecf20Sopenharmony_ci
1518c2ecf20Sopenharmony_cistatic void subsys_get_adapter(struct hpi_message *phm,
1528c2ecf20Sopenharmony_ci	struct hpi_response *phr)
1538c2ecf20Sopenharmony_ci{
1548c2ecf20Sopenharmony_ci	int count = phm->obj_index;
1558c2ecf20Sopenharmony_ci	u16 index = 0;
1568c2ecf20Sopenharmony_ci
1578c2ecf20Sopenharmony_ci	/* find the nCount'th nonzero adapter in array */
1588c2ecf20Sopenharmony_ci	for (index = 0; index < HPI_MAX_ADAPTERS; index++) {
1598c2ecf20Sopenharmony_ci		if (adapters.adapter[index].type) {
1608c2ecf20Sopenharmony_ci			if (!count)
1618c2ecf20Sopenharmony_ci				break;
1628c2ecf20Sopenharmony_ci			count--;
1638c2ecf20Sopenharmony_ci		}
1648c2ecf20Sopenharmony_ci	}
1658c2ecf20Sopenharmony_ci
1668c2ecf20Sopenharmony_ci	if (index < HPI_MAX_ADAPTERS) {
1678c2ecf20Sopenharmony_ci		phr->u.s.adapter_index = adapters.adapter[index].index;
1688c2ecf20Sopenharmony_ci		phr->u.s.adapter_type = adapters.adapter[index].type;
1698c2ecf20Sopenharmony_ci	} else {
1708c2ecf20Sopenharmony_ci		phr->u.s.adapter_index = 0;
1718c2ecf20Sopenharmony_ci		phr->u.s.adapter_type = 0;
1728c2ecf20Sopenharmony_ci		phr->error = HPI_ERROR_INVALID_OBJ_INDEX;
1738c2ecf20Sopenharmony_ci	}
1748c2ecf20Sopenharmony_ci}
1758c2ecf20Sopenharmony_ci
1768c2ecf20Sopenharmony_cistatic unsigned int control_cache_alloc_check(struct hpi_control_cache *pC)
1778c2ecf20Sopenharmony_ci{
1788c2ecf20Sopenharmony_ci	unsigned int i;
1798c2ecf20Sopenharmony_ci	int cached = 0;
1808c2ecf20Sopenharmony_ci	if (!pC)
1818c2ecf20Sopenharmony_ci		return 0;
1828c2ecf20Sopenharmony_ci
1838c2ecf20Sopenharmony_ci	if (pC->init)
1848c2ecf20Sopenharmony_ci		return pC->init;
1858c2ecf20Sopenharmony_ci
1868c2ecf20Sopenharmony_ci	if (!pC->p_cache)
1878c2ecf20Sopenharmony_ci		return 0;
1888c2ecf20Sopenharmony_ci
1898c2ecf20Sopenharmony_ci	if (pC->control_count && pC->cache_size_in_bytes) {
1908c2ecf20Sopenharmony_ci		char *p_master_cache;
1918c2ecf20Sopenharmony_ci		unsigned int byte_count = 0;
1928c2ecf20Sopenharmony_ci
1938c2ecf20Sopenharmony_ci		p_master_cache = (char *)pC->p_cache;
1948c2ecf20Sopenharmony_ci		HPI_DEBUG_LOG(DEBUG, "check %d controls\n",
1958c2ecf20Sopenharmony_ci			pC->control_count);
1968c2ecf20Sopenharmony_ci		for (i = 0; i < pC->control_count; i++) {
1978c2ecf20Sopenharmony_ci			struct hpi_control_cache_info *info =
1988c2ecf20Sopenharmony_ci				(struct hpi_control_cache_info *)
1998c2ecf20Sopenharmony_ci				&p_master_cache[byte_count];
2008c2ecf20Sopenharmony_ci			u16 control_index = info->control_index;
2018c2ecf20Sopenharmony_ci
2028c2ecf20Sopenharmony_ci			if (control_index >= pC->control_count) {
2038c2ecf20Sopenharmony_ci				HPI_DEBUG_LOG(INFO,
2048c2ecf20Sopenharmony_ci					"adap %d control index %d out of range, cache not ready?\n",
2058c2ecf20Sopenharmony_ci					pC->adap_idx, control_index);
2068c2ecf20Sopenharmony_ci				return 0;
2078c2ecf20Sopenharmony_ci			}
2088c2ecf20Sopenharmony_ci
2098c2ecf20Sopenharmony_ci			if (!info->size_in32bit_words) {
2108c2ecf20Sopenharmony_ci				if (!i) {
2118c2ecf20Sopenharmony_ci					HPI_DEBUG_LOG(INFO,
2128c2ecf20Sopenharmony_ci						"adap %d cache not ready?\n",
2138c2ecf20Sopenharmony_ci						pC->adap_idx);
2148c2ecf20Sopenharmony_ci					return 0;
2158c2ecf20Sopenharmony_ci				}
2168c2ecf20Sopenharmony_ci				/* The cache is invalid.
2178c2ecf20Sopenharmony_ci				 * Minimum valid entry size is
2188c2ecf20Sopenharmony_ci				 * sizeof(struct hpi_control_cache_info)
2198c2ecf20Sopenharmony_ci				 */
2208c2ecf20Sopenharmony_ci				HPI_DEBUG_LOG(ERROR,
2218c2ecf20Sopenharmony_ci					"adap %d zero size cache entry %d\n",
2228c2ecf20Sopenharmony_ci					pC->adap_idx, i);
2238c2ecf20Sopenharmony_ci				break;
2248c2ecf20Sopenharmony_ci			}
2258c2ecf20Sopenharmony_ci
2268c2ecf20Sopenharmony_ci			if (info->control_type) {
2278c2ecf20Sopenharmony_ci				pC->p_info[control_index] = info;
2288c2ecf20Sopenharmony_ci				cached++;
2298c2ecf20Sopenharmony_ci			} else {	/* dummy cache entry */
2308c2ecf20Sopenharmony_ci				pC->p_info[control_index] = NULL;
2318c2ecf20Sopenharmony_ci			}
2328c2ecf20Sopenharmony_ci
2338c2ecf20Sopenharmony_ci			byte_count += info->size_in32bit_words * 4;
2348c2ecf20Sopenharmony_ci
2358c2ecf20Sopenharmony_ci			HPI_DEBUG_LOG(VERBOSE,
2368c2ecf20Sopenharmony_ci				"cached %d, pinfo %p index %d type %d size %d\n",
2378c2ecf20Sopenharmony_ci				cached, pC->p_info[info->control_index],
2388c2ecf20Sopenharmony_ci				info->control_index, info->control_type,
2398c2ecf20Sopenharmony_ci				info->size_in32bit_words);
2408c2ecf20Sopenharmony_ci
2418c2ecf20Sopenharmony_ci			/* quit loop early if whole cache has been scanned.
2428c2ecf20Sopenharmony_ci			 * dwControlCount is the maximum possible entries
2438c2ecf20Sopenharmony_ci			 * but some may be absent from the cache
2448c2ecf20Sopenharmony_ci			 */
2458c2ecf20Sopenharmony_ci			if (byte_count >= pC->cache_size_in_bytes)
2468c2ecf20Sopenharmony_ci				break;
2478c2ecf20Sopenharmony_ci			/* have seen last control index */
2488c2ecf20Sopenharmony_ci			if (info->control_index == pC->control_count - 1)
2498c2ecf20Sopenharmony_ci				break;
2508c2ecf20Sopenharmony_ci		}
2518c2ecf20Sopenharmony_ci
2528c2ecf20Sopenharmony_ci		if (byte_count != pC->cache_size_in_bytes)
2538c2ecf20Sopenharmony_ci			HPI_DEBUG_LOG(WARNING,
2548c2ecf20Sopenharmony_ci				"adap %d bytecount %d != cache size %d\n",
2558c2ecf20Sopenharmony_ci				pC->adap_idx, byte_count,
2568c2ecf20Sopenharmony_ci				pC->cache_size_in_bytes);
2578c2ecf20Sopenharmony_ci		else
2588c2ecf20Sopenharmony_ci			HPI_DEBUG_LOG(DEBUG,
2598c2ecf20Sopenharmony_ci				"adap %d cache good, bytecount == cache size = %d\n",
2608c2ecf20Sopenharmony_ci				pC->adap_idx, byte_count);
2618c2ecf20Sopenharmony_ci
2628c2ecf20Sopenharmony_ci		pC->init = (u16)cached;
2638c2ecf20Sopenharmony_ci	}
2648c2ecf20Sopenharmony_ci	return pC->init;
2658c2ecf20Sopenharmony_ci}
2668c2ecf20Sopenharmony_ci
2678c2ecf20Sopenharmony_ci/** Find a control.
2688c2ecf20Sopenharmony_ci*/
2698c2ecf20Sopenharmony_cistatic short find_control(u16 control_index,
2708c2ecf20Sopenharmony_ci	struct hpi_control_cache *p_cache, struct hpi_control_cache_info **pI)
2718c2ecf20Sopenharmony_ci{
2728c2ecf20Sopenharmony_ci	if (!control_cache_alloc_check(p_cache)) {
2738c2ecf20Sopenharmony_ci		HPI_DEBUG_LOG(VERBOSE,
2748c2ecf20Sopenharmony_ci			"control_cache_alloc_check() failed %d\n",
2758c2ecf20Sopenharmony_ci			control_index);
2768c2ecf20Sopenharmony_ci		return 0;
2778c2ecf20Sopenharmony_ci	}
2788c2ecf20Sopenharmony_ci
2798c2ecf20Sopenharmony_ci	*pI = p_cache->p_info[control_index];
2808c2ecf20Sopenharmony_ci	if (!*pI) {
2818c2ecf20Sopenharmony_ci		HPI_DEBUG_LOG(VERBOSE, "Uncached Control %d\n",
2828c2ecf20Sopenharmony_ci			control_index);
2838c2ecf20Sopenharmony_ci		return 0;
2848c2ecf20Sopenharmony_ci	} else {
2858c2ecf20Sopenharmony_ci		HPI_DEBUG_LOG(VERBOSE, "find_control() type %d\n",
2868c2ecf20Sopenharmony_ci			(*pI)->control_type);
2878c2ecf20Sopenharmony_ci	}
2888c2ecf20Sopenharmony_ci	return 1;
2898c2ecf20Sopenharmony_ci}
2908c2ecf20Sopenharmony_ci
2918c2ecf20Sopenharmony_ci/* allow unified treatment of several string fields within struct */
2928c2ecf20Sopenharmony_ci#define HPICMN_PAD_OFS_AND_SIZE(m)  {\
2938c2ecf20Sopenharmony_ci	offsetof(struct hpi_control_cache_pad, m), \
2948c2ecf20Sopenharmony_ci	sizeof(((struct hpi_control_cache_pad *)(NULL))->m) }
2958c2ecf20Sopenharmony_ci
2968c2ecf20Sopenharmony_cistruct pad_ofs_size {
2978c2ecf20Sopenharmony_ci	unsigned int offset;
2988c2ecf20Sopenharmony_ci	unsigned int field_size;
2998c2ecf20Sopenharmony_ci};
3008c2ecf20Sopenharmony_ci
3018c2ecf20Sopenharmony_cistatic const struct pad_ofs_size pad_desc[] = {
3028c2ecf20Sopenharmony_ci	HPICMN_PAD_OFS_AND_SIZE(c_channel),	/* HPI_PAD_CHANNEL_NAME */
3038c2ecf20Sopenharmony_ci	HPICMN_PAD_OFS_AND_SIZE(c_artist),	/* HPI_PAD_ARTIST */
3048c2ecf20Sopenharmony_ci	HPICMN_PAD_OFS_AND_SIZE(c_title),	/* HPI_PAD_TITLE */
3058c2ecf20Sopenharmony_ci	HPICMN_PAD_OFS_AND_SIZE(c_comment),	/* HPI_PAD_COMMENT */
3068c2ecf20Sopenharmony_ci};
3078c2ecf20Sopenharmony_ci
3088c2ecf20Sopenharmony_ci/** CheckControlCache checks the cache and fills the struct hpi_response
3098c2ecf20Sopenharmony_ci * accordingly. It returns one if a cache hit occurred, zero otherwise.
3108c2ecf20Sopenharmony_ci */
3118c2ecf20Sopenharmony_cishort hpi_check_control_cache_single(struct hpi_control_cache_single *pC,
3128c2ecf20Sopenharmony_ci	struct hpi_message *phm, struct hpi_response *phr)
3138c2ecf20Sopenharmony_ci{
3148c2ecf20Sopenharmony_ci	size_t response_size;
3158c2ecf20Sopenharmony_ci	short found = 1;
3168c2ecf20Sopenharmony_ci
3178c2ecf20Sopenharmony_ci	/* set the default response size */
3188c2ecf20Sopenharmony_ci	response_size =
3198c2ecf20Sopenharmony_ci		sizeof(struct hpi_response_header) +
3208c2ecf20Sopenharmony_ci		sizeof(struct hpi_control_res);
3218c2ecf20Sopenharmony_ci
3228c2ecf20Sopenharmony_ci	switch (pC->u.i.control_type) {
3238c2ecf20Sopenharmony_ci
3248c2ecf20Sopenharmony_ci	case HPI_CONTROL_METER:
3258c2ecf20Sopenharmony_ci		if (phm->u.c.attribute == HPI_METER_PEAK) {
3268c2ecf20Sopenharmony_ci			phr->u.c.an_log_value[0] = pC->u.meter.an_log_peak[0];
3278c2ecf20Sopenharmony_ci			phr->u.c.an_log_value[1] = pC->u.meter.an_log_peak[1];
3288c2ecf20Sopenharmony_ci		} else if (phm->u.c.attribute == HPI_METER_RMS) {
3298c2ecf20Sopenharmony_ci			if (pC->u.meter.an_logRMS[0] ==
3308c2ecf20Sopenharmony_ci				HPI_CACHE_INVALID_SHORT) {
3318c2ecf20Sopenharmony_ci				phr->error =
3328c2ecf20Sopenharmony_ci					HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
3338c2ecf20Sopenharmony_ci				phr->u.c.an_log_value[0] = HPI_METER_MINIMUM;
3348c2ecf20Sopenharmony_ci				phr->u.c.an_log_value[1] = HPI_METER_MINIMUM;
3358c2ecf20Sopenharmony_ci			} else {
3368c2ecf20Sopenharmony_ci				phr->u.c.an_log_value[0] =
3378c2ecf20Sopenharmony_ci					pC->u.meter.an_logRMS[0];
3388c2ecf20Sopenharmony_ci				phr->u.c.an_log_value[1] =
3398c2ecf20Sopenharmony_ci					pC->u.meter.an_logRMS[1];
3408c2ecf20Sopenharmony_ci			}
3418c2ecf20Sopenharmony_ci		} else
3428c2ecf20Sopenharmony_ci			found = 0;
3438c2ecf20Sopenharmony_ci		break;
3448c2ecf20Sopenharmony_ci	case HPI_CONTROL_VOLUME:
3458c2ecf20Sopenharmony_ci		if (phm->u.c.attribute == HPI_VOLUME_GAIN) {
3468c2ecf20Sopenharmony_ci			phr->u.c.an_log_value[0] = pC->u.vol.an_log[0];
3478c2ecf20Sopenharmony_ci			phr->u.c.an_log_value[1] = pC->u.vol.an_log[1];
3488c2ecf20Sopenharmony_ci		} else if (phm->u.c.attribute == HPI_VOLUME_MUTE) {
3498c2ecf20Sopenharmony_ci			if (pC->u.vol.flags & HPI_VOLUME_FLAG_HAS_MUTE) {
3508c2ecf20Sopenharmony_ci				if (pC->u.vol.flags & HPI_VOLUME_FLAG_MUTED)
3518c2ecf20Sopenharmony_ci					phr->u.c.param1 =
3528c2ecf20Sopenharmony_ci						HPI_BITMASK_ALL_CHANNELS;
3538c2ecf20Sopenharmony_ci				else
3548c2ecf20Sopenharmony_ci					phr->u.c.param1 = 0;
3558c2ecf20Sopenharmony_ci			} else {
3568c2ecf20Sopenharmony_ci				phr->error =
3578c2ecf20Sopenharmony_ci					HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
3588c2ecf20Sopenharmony_ci				phr->u.c.param1 = 0;
3598c2ecf20Sopenharmony_ci			}
3608c2ecf20Sopenharmony_ci		} else {
3618c2ecf20Sopenharmony_ci			found = 0;
3628c2ecf20Sopenharmony_ci		}
3638c2ecf20Sopenharmony_ci		break;
3648c2ecf20Sopenharmony_ci	case HPI_CONTROL_MULTIPLEXER:
3658c2ecf20Sopenharmony_ci		if (phm->u.c.attribute == HPI_MULTIPLEXER_SOURCE) {
3668c2ecf20Sopenharmony_ci			phr->u.c.param1 = pC->u.mux.source_node_type;
3678c2ecf20Sopenharmony_ci			phr->u.c.param2 = pC->u.mux.source_node_index;
3688c2ecf20Sopenharmony_ci		} else {
3698c2ecf20Sopenharmony_ci			found = 0;
3708c2ecf20Sopenharmony_ci		}
3718c2ecf20Sopenharmony_ci		break;
3728c2ecf20Sopenharmony_ci	case HPI_CONTROL_CHANNEL_MODE:
3738c2ecf20Sopenharmony_ci		if (phm->u.c.attribute == HPI_CHANNEL_MODE_MODE)
3748c2ecf20Sopenharmony_ci			phr->u.c.param1 = pC->u.mode.mode;
3758c2ecf20Sopenharmony_ci		else
3768c2ecf20Sopenharmony_ci			found = 0;
3778c2ecf20Sopenharmony_ci		break;
3788c2ecf20Sopenharmony_ci	case HPI_CONTROL_LEVEL:
3798c2ecf20Sopenharmony_ci		if (phm->u.c.attribute == HPI_LEVEL_GAIN) {
3808c2ecf20Sopenharmony_ci			phr->u.c.an_log_value[0] = pC->u.level.an_log[0];
3818c2ecf20Sopenharmony_ci			phr->u.c.an_log_value[1] = pC->u.level.an_log[1];
3828c2ecf20Sopenharmony_ci		} else
3838c2ecf20Sopenharmony_ci			found = 0;
3848c2ecf20Sopenharmony_ci		break;
3858c2ecf20Sopenharmony_ci	case HPI_CONTROL_TUNER:
3868c2ecf20Sopenharmony_ci		if (phm->u.c.attribute == HPI_TUNER_FREQ)
3878c2ecf20Sopenharmony_ci			phr->u.c.param1 = pC->u.tuner.freq_ink_hz;
3888c2ecf20Sopenharmony_ci		else if (phm->u.c.attribute == HPI_TUNER_BAND)
3898c2ecf20Sopenharmony_ci			phr->u.c.param1 = pC->u.tuner.band;
3908c2ecf20Sopenharmony_ci		else if (phm->u.c.attribute == HPI_TUNER_LEVEL_AVG)
3918c2ecf20Sopenharmony_ci			if (pC->u.tuner.s_level_avg ==
3928c2ecf20Sopenharmony_ci				HPI_CACHE_INVALID_SHORT) {
3938c2ecf20Sopenharmony_ci				phr->u.cu.tuner.s_level = 0;
3948c2ecf20Sopenharmony_ci				phr->error =
3958c2ecf20Sopenharmony_ci					HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
3968c2ecf20Sopenharmony_ci			} else
3978c2ecf20Sopenharmony_ci				phr->u.cu.tuner.s_level =
3988c2ecf20Sopenharmony_ci					pC->u.tuner.s_level_avg;
3998c2ecf20Sopenharmony_ci		else
4008c2ecf20Sopenharmony_ci			found = 0;
4018c2ecf20Sopenharmony_ci		break;
4028c2ecf20Sopenharmony_ci	case HPI_CONTROL_AESEBU_RECEIVER:
4038c2ecf20Sopenharmony_ci		if (phm->u.c.attribute == HPI_AESEBURX_ERRORSTATUS)
4048c2ecf20Sopenharmony_ci			phr->u.c.param1 = pC->u.aes3rx.error_status;
4058c2ecf20Sopenharmony_ci		else if (phm->u.c.attribute == HPI_AESEBURX_FORMAT)
4068c2ecf20Sopenharmony_ci			phr->u.c.param1 = pC->u.aes3rx.format;
4078c2ecf20Sopenharmony_ci		else
4088c2ecf20Sopenharmony_ci			found = 0;
4098c2ecf20Sopenharmony_ci		break;
4108c2ecf20Sopenharmony_ci	case HPI_CONTROL_AESEBU_TRANSMITTER:
4118c2ecf20Sopenharmony_ci		if (phm->u.c.attribute == HPI_AESEBUTX_FORMAT)
4128c2ecf20Sopenharmony_ci			phr->u.c.param1 = pC->u.aes3tx.format;
4138c2ecf20Sopenharmony_ci		else
4148c2ecf20Sopenharmony_ci			found = 0;
4158c2ecf20Sopenharmony_ci		break;
4168c2ecf20Sopenharmony_ci	case HPI_CONTROL_TONEDETECTOR:
4178c2ecf20Sopenharmony_ci		if (phm->u.c.attribute == HPI_TONEDETECTOR_STATE)
4188c2ecf20Sopenharmony_ci			phr->u.c.param1 = pC->u.tone.state;
4198c2ecf20Sopenharmony_ci		else
4208c2ecf20Sopenharmony_ci			found = 0;
4218c2ecf20Sopenharmony_ci		break;
4228c2ecf20Sopenharmony_ci	case HPI_CONTROL_SILENCEDETECTOR:
4238c2ecf20Sopenharmony_ci		if (phm->u.c.attribute == HPI_SILENCEDETECTOR_STATE) {
4248c2ecf20Sopenharmony_ci			phr->u.c.param1 = pC->u.silence.state;
4258c2ecf20Sopenharmony_ci		} else
4268c2ecf20Sopenharmony_ci			found = 0;
4278c2ecf20Sopenharmony_ci		break;
4288c2ecf20Sopenharmony_ci	case HPI_CONTROL_MICROPHONE:
4298c2ecf20Sopenharmony_ci		if (phm->u.c.attribute == HPI_MICROPHONE_PHANTOM_POWER)
4308c2ecf20Sopenharmony_ci			phr->u.c.param1 = pC->u.microphone.phantom_state;
4318c2ecf20Sopenharmony_ci		else
4328c2ecf20Sopenharmony_ci			found = 0;
4338c2ecf20Sopenharmony_ci		break;
4348c2ecf20Sopenharmony_ci	case HPI_CONTROL_SAMPLECLOCK:
4358c2ecf20Sopenharmony_ci		if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE)
4368c2ecf20Sopenharmony_ci			phr->u.c.param1 = pC->u.clk.source;
4378c2ecf20Sopenharmony_ci		else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE_INDEX) {
4388c2ecf20Sopenharmony_ci			if (pC->u.clk.source_index ==
4398c2ecf20Sopenharmony_ci				HPI_CACHE_INVALID_UINT16) {
4408c2ecf20Sopenharmony_ci				phr->u.c.param1 = 0;
4418c2ecf20Sopenharmony_ci				phr->error =
4428c2ecf20Sopenharmony_ci					HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
4438c2ecf20Sopenharmony_ci			} else
4448c2ecf20Sopenharmony_ci				phr->u.c.param1 = pC->u.clk.source_index;
4458c2ecf20Sopenharmony_ci		} else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SAMPLERATE)
4468c2ecf20Sopenharmony_ci			phr->u.c.param1 = pC->u.clk.sample_rate;
4478c2ecf20Sopenharmony_ci		else
4488c2ecf20Sopenharmony_ci			found = 0;
4498c2ecf20Sopenharmony_ci		break;
4508c2ecf20Sopenharmony_ci	case HPI_CONTROL_PAD:{
4518c2ecf20Sopenharmony_ci			struct hpi_control_cache_pad *p_pad;
4528c2ecf20Sopenharmony_ci			p_pad = (struct hpi_control_cache_pad *)pC;
4538c2ecf20Sopenharmony_ci
4548c2ecf20Sopenharmony_ci			if (!(p_pad->field_valid_flags & (1 <<
4558c2ecf20Sopenharmony_ci						HPI_CTL_ATTR_INDEX(phm->u.c.
4568c2ecf20Sopenharmony_ci							attribute)))) {
4578c2ecf20Sopenharmony_ci				phr->error =
4588c2ecf20Sopenharmony_ci					HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
4598c2ecf20Sopenharmony_ci				break;
4608c2ecf20Sopenharmony_ci			}
4618c2ecf20Sopenharmony_ci
4628c2ecf20Sopenharmony_ci			if (phm->u.c.attribute == HPI_PAD_PROGRAM_ID)
4638c2ecf20Sopenharmony_ci				phr->u.c.param1 = p_pad->pI;
4648c2ecf20Sopenharmony_ci			else if (phm->u.c.attribute == HPI_PAD_PROGRAM_TYPE)
4658c2ecf20Sopenharmony_ci				phr->u.c.param1 = p_pad->pTY;
4668c2ecf20Sopenharmony_ci			else {
4678c2ecf20Sopenharmony_ci				unsigned int index =
4688c2ecf20Sopenharmony_ci					HPI_CTL_ATTR_INDEX(phm->u.c.
4698c2ecf20Sopenharmony_ci					attribute) - 1;
4708c2ecf20Sopenharmony_ci				unsigned int offset = phm->u.c.param1;
4718c2ecf20Sopenharmony_ci				unsigned int pad_string_len, field_size;
4728c2ecf20Sopenharmony_ci				char *pad_string;
4738c2ecf20Sopenharmony_ci				unsigned int tocopy;
4748c2ecf20Sopenharmony_ci
4758c2ecf20Sopenharmony_ci				if (index > ARRAY_SIZE(pad_desc) - 1) {
4768c2ecf20Sopenharmony_ci					phr->error =
4778c2ecf20Sopenharmony_ci						HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
4788c2ecf20Sopenharmony_ci					break;
4798c2ecf20Sopenharmony_ci				}
4808c2ecf20Sopenharmony_ci
4818c2ecf20Sopenharmony_ci				pad_string =
4828c2ecf20Sopenharmony_ci					((char *)p_pad) +
4838c2ecf20Sopenharmony_ci					pad_desc[index].offset;
4848c2ecf20Sopenharmony_ci				field_size = pad_desc[index].field_size;
4858c2ecf20Sopenharmony_ci				/* Ensure null terminator */
4868c2ecf20Sopenharmony_ci				pad_string[field_size - 1] = 0;
4878c2ecf20Sopenharmony_ci
4888c2ecf20Sopenharmony_ci				pad_string_len = strlen(pad_string) + 1;
4898c2ecf20Sopenharmony_ci
4908c2ecf20Sopenharmony_ci				if (offset > pad_string_len) {
4918c2ecf20Sopenharmony_ci					phr->error =
4928c2ecf20Sopenharmony_ci						HPI_ERROR_INVALID_CONTROL_VALUE;
4938c2ecf20Sopenharmony_ci					break;
4948c2ecf20Sopenharmony_ci				}
4958c2ecf20Sopenharmony_ci
4968c2ecf20Sopenharmony_ci				tocopy = pad_string_len - offset;
4978c2ecf20Sopenharmony_ci				if (tocopy > sizeof(phr->u.cu.chars8.sz_data))
4988c2ecf20Sopenharmony_ci					tocopy = sizeof(phr->u.cu.chars8.
4998c2ecf20Sopenharmony_ci						sz_data);
5008c2ecf20Sopenharmony_ci
5018c2ecf20Sopenharmony_ci				memcpy(phr->u.cu.chars8.sz_data,
5028c2ecf20Sopenharmony_ci					&pad_string[offset], tocopy);
5038c2ecf20Sopenharmony_ci
5048c2ecf20Sopenharmony_ci				phr->u.cu.chars8.remaining_chars =
5058c2ecf20Sopenharmony_ci					pad_string_len - offset - tocopy;
5068c2ecf20Sopenharmony_ci			}
5078c2ecf20Sopenharmony_ci		}
5088c2ecf20Sopenharmony_ci		break;
5098c2ecf20Sopenharmony_ci	default:
5108c2ecf20Sopenharmony_ci		found = 0;
5118c2ecf20Sopenharmony_ci		break;
5128c2ecf20Sopenharmony_ci	}
5138c2ecf20Sopenharmony_ci
5148c2ecf20Sopenharmony_ci	HPI_DEBUG_LOG(VERBOSE, "%s Adap %d, Ctl %d, Type %d, Attr %d\n",
5158c2ecf20Sopenharmony_ci		found ? "Cached" : "Uncached", phm->adapter_index,
5168c2ecf20Sopenharmony_ci		pC->u.i.control_index, pC->u.i.control_type,
5178c2ecf20Sopenharmony_ci		phm->u.c.attribute);
5188c2ecf20Sopenharmony_ci
5198c2ecf20Sopenharmony_ci	if (found) {
5208c2ecf20Sopenharmony_ci		phr->size = (u16)response_size;
5218c2ecf20Sopenharmony_ci		phr->type = HPI_TYPE_RESPONSE;
5228c2ecf20Sopenharmony_ci		phr->object = phm->object;
5238c2ecf20Sopenharmony_ci		phr->function = phm->function;
5248c2ecf20Sopenharmony_ci	}
5258c2ecf20Sopenharmony_ci
5268c2ecf20Sopenharmony_ci	return found;
5278c2ecf20Sopenharmony_ci}
5288c2ecf20Sopenharmony_ci
5298c2ecf20Sopenharmony_cishort hpi_check_control_cache(struct hpi_control_cache *p_cache,
5308c2ecf20Sopenharmony_ci	struct hpi_message *phm, struct hpi_response *phr)
5318c2ecf20Sopenharmony_ci{
5328c2ecf20Sopenharmony_ci	struct hpi_control_cache_info *pI;
5338c2ecf20Sopenharmony_ci
5348c2ecf20Sopenharmony_ci	if (!find_control(phm->obj_index, p_cache, &pI)) {
5358c2ecf20Sopenharmony_ci		HPI_DEBUG_LOG(VERBOSE,
5368c2ecf20Sopenharmony_ci			"HPICMN find_control() failed for adap %d\n",
5378c2ecf20Sopenharmony_ci			phm->adapter_index);
5388c2ecf20Sopenharmony_ci		return 0;
5398c2ecf20Sopenharmony_ci	}
5408c2ecf20Sopenharmony_ci
5418c2ecf20Sopenharmony_ci	phr->error = 0;
5428c2ecf20Sopenharmony_ci	phr->specific_error = 0;
5438c2ecf20Sopenharmony_ci	phr->version = 0;
5448c2ecf20Sopenharmony_ci
5458c2ecf20Sopenharmony_ci	return hpi_check_control_cache_single((struct hpi_control_cache_single
5468c2ecf20Sopenharmony_ci			*)pI, phm, phr);
5478c2ecf20Sopenharmony_ci}
5488c2ecf20Sopenharmony_ci
5498c2ecf20Sopenharmony_ci/** Updates the cache with Set values.
5508c2ecf20Sopenharmony_ci
5518c2ecf20Sopenharmony_ciOnly update if no error.
5528c2ecf20Sopenharmony_ciVolume and Level return the limited values in the response, so use these
5538c2ecf20Sopenharmony_ciMultiplexer does so use sent values
5548c2ecf20Sopenharmony_ci*/
5558c2ecf20Sopenharmony_civoid hpi_cmn_control_cache_sync_to_msg_single(struct hpi_control_cache_single
5568c2ecf20Sopenharmony_ci	*pC, struct hpi_message *phm, struct hpi_response *phr)
5578c2ecf20Sopenharmony_ci{
5588c2ecf20Sopenharmony_ci	switch (pC->u.i.control_type) {
5598c2ecf20Sopenharmony_ci	case HPI_CONTROL_VOLUME:
5608c2ecf20Sopenharmony_ci		if (phm->u.c.attribute == HPI_VOLUME_GAIN) {
5618c2ecf20Sopenharmony_ci			pC->u.vol.an_log[0] = phr->u.c.an_log_value[0];
5628c2ecf20Sopenharmony_ci			pC->u.vol.an_log[1] = phr->u.c.an_log_value[1];
5638c2ecf20Sopenharmony_ci		} else if (phm->u.c.attribute == HPI_VOLUME_MUTE) {
5648c2ecf20Sopenharmony_ci			if (phm->u.c.param1)
5658c2ecf20Sopenharmony_ci				pC->u.vol.flags |= HPI_VOLUME_FLAG_MUTED;
5668c2ecf20Sopenharmony_ci			else
5678c2ecf20Sopenharmony_ci				pC->u.vol.flags &= ~HPI_VOLUME_FLAG_MUTED;
5688c2ecf20Sopenharmony_ci		}
5698c2ecf20Sopenharmony_ci		break;
5708c2ecf20Sopenharmony_ci	case HPI_CONTROL_MULTIPLEXER:
5718c2ecf20Sopenharmony_ci		/* mux does not return its setting on Set command. */
5728c2ecf20Sopenharmony_ci		if (phm->u.c.attribute == HPI_MULTIPLEXER_SOURCE) {
5738c2ecf20Sopenharmony_ci			pC->u.mux.source_node_type = (u16)phm->u.c.param1;
5748c2ecf20Sopenharmony_ci			pC->u.mux.source_node_index = (u16)phm->u.c.param2;
5758c2ecf20Sopenharmony_ci		}
5768c2ecf20Sopenharmony_ci		break;
5778c2ecf20Sopenharmony_ci	case HPI_CONTROL_CHANNEL_MODE:
5788c2ecf20Sopenharmony_ci		/* mode does not return its setting on Set command. */
5798c2ecf20Sopenharmony_ci		if (phm->u.c.attribute == HPI_CHANNEL_MODE_MODE)
5808c2ecf20Sopenharmony_ci			pC->u.mode.mode = (u16)phm->u.c.param1;
5818c2ecf20Sopenharmony_ci		break;
5828c2ecf20Sopenharmony_ci	case HPI_CONTROL_LEVEL:
5838c2ecf20Sopenharmony_ci		if (phm->u.c.attribute == HPI_LEVEL_GAIN) {
5848c2ecf20Sopenharmony_ci			pC->u.vol.an_log[0] = phr->u.c.an_log_value[0];
5858c2ecf20Sopenharmony_ci			pC->u.vol.an_log[1] = phr->u.c.an_log_value[1];
5868c2ecf20Sopenharmony_ci		}
5878c2ecf20Sopenharmony_ci		break;
5888c2ecf20Sopenharmony_ci	case HPI_CONTROL_MICROPHONE:
5898c2ecf20Sopenharmony_ci		if (phm->u.c.attribute == HPI_MICROPHONE_PHANTOM_POWER)
5908c2ecf20Sopenharmony_ci			pC->u.microphone.phantom_state = (u16)phm->u.c.param1;
5918c2ecf20Sopenharmony_ci		break;
5928c2ecf20Sopenharmony_ci	case HPI_CONTROL_AESEBU_TRANSMITTER:
5938c2ecf20Sopenharmony_ci		if (phm->u.c.attribute == HPI_AESEBUTX_FORMAT)
5948c2ecf20Sopenharmony_ci			pC->u.aes3tx.format = phm->u.c.param1;
5958c2ecf20Sopenharmony_ci		break;
5968c2ecf20Sopenharmony_ci	case HPI_CONTROL_AESEBU_RECEIVER:
5978c2ecf20Sopenharmony_ci		if (phm->u.c.attribute == HPI_AESEBURX_FORMAT)
5988c2ecf20Sopenharmony_ci			pC->u.aes3rx.format = phm->u.c.param1;
5998c2ecf20Sopenharmony_ci		break;
6008c2ecf20Sopenharmony_ci	case HPI_CONTROL_SAMPLECLOCK:
6018c2ecf20Sopenharmony_ci		if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE)
6028c2ecf20Sopenharmony_ci			pC->u.clk.source = (u16)phm->u.c.param1;
6038c2ecf20Sopenharmony_ci		else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE_INDEX)
6048c2ecf20Sopenharmony_ci			pC->u.clk.source_index = (u16)phm->u.c.param1;
6058c2ecf20Sopenharmony_ci		else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SAMPLERATE)
6068c2ecf20Sopenharmony_ci			pC->u.clk.sample_rate = phm->u.c.param1;
6078c2ecf20Sopenharmony_ci		break;
6088c2ecf20Sopenharmony_ci	default:
6098c2ecf20Sopenharmony_ci		break;
6108c2ecf20Sopenharmony_ci	}
6118c2ecf20Sopenharmony_ci}
6128c2ecf20Sopenharmony_ci
6138c2ecf20Sopenharmony_civoid hpi_cmn_control_cache_sync_to_msg(struct hpi_control_cache *p_cache,
6148c2ecf20Sopenharmony_ci	struct hpi_message *phm, struct hpi_response *phr)
6158c2ecf20Sopenharmony_ci{
6168c2ecf20Sopenharmony_ci	struct hpi_control_cache_single *pC;
6178c2ecf20Sopenharmony_ci	struct hpi_control_cache_info *pI;
6188c2ecf20Sopenharmony_ci
6198c2ecf20Sopenharmony_ci	if (phr->error)
6208c2ecf20Sopenharmony_ci		return;
6218c2ecf20Sopenharmony_ci
6228c2ecf20Sopenharmony_ci	if (!find_control(phm->obj_index, p_cache, &pI)) {
6238c2ecf20Sopenharmony_ci		HPI_DEBUG_LOG(VERBOSE,
6248c2ecf20Sopenharmony_ci			"HPICMN find_control() failed for adap %d\n",
6258c2ecf20Sopenharmony_ci			phm->adapter_index);
6268c2ecf20Sopenharmony_ci		return;
6278c2ecf20Sopenharmony_ci	}
6288c2ecf20Sopenharmony_ci
6298c2ecf20Sopenharmony_ci	/* pC is the default cached control strucure.
6308c2ecf20Sopenharmony_ci	   May be cast to something else in the following switch statement.
6318c2ecf20Sopenharmony_ci	 */
6328c2ecf20Sopenharmony_ci	pC = (struct hpi_control_cache_single *)pI;
6338c2ecf20Sopenharmony_ci
6348c2ecf20Sopenharmony_ci	hpi_cmn_control_cache_sync_to_msg_single(pC, phm, phr);
6358c2ecf20Sopenharmony_ci}
6368c2ecf20Sopenharmony_ci
6378c2ecf20Sopenharmony_ci/** Allocate control cache.
6388c2ecf20Sopenharmony_ci
6398c2ecf20Sopenharmony_ci\return Cache pointer, or NULL if allocation fails.
6408c2ecf20Sopenharmony_ci*/
6418c2ecf20Sopenharmony_cistruct hpi_control_cache *hpi_alloc_control_cache(const u32 control_count,
6428c2ecf20Sopenharmony_ci	const u32 size_in_bytes, u8 *p_dsp_control_buffer)
6438c2ecf20Sopenharmony_ci{
6448c2ecf20Sopenharmony_ci	struct hpi_control_cache *p_cache =
6458c2ecf20Sopenharmony_ci		kmalloc(sizeof(*p_cache), GFP_KERNEL);
6468c2ecf20Sopenharmony_ci	if (!p_cache)
6478c2ecf20Sopenharmony_ci		return NULL;
6488c2ecf20Sopenharmony_ci
6498c2ecf20Sopenharmony_ci	p_cache->p_info =
6508c2ecf20Sopenharmony_ci		kcalloc(control_count, sizeof(*p_cache->p_info), GFP_KERNEL);
6518c2ecf20Sopenharmony_ci	if (!p_cache->p_info) {
6528c2ecf20Sopenharmony_ci		kfree(p_cache);
6538c2ecf20Sopenharmony_ci		return NULL;
6548c2ecf20Sopenharmony_ci	}
6558c2ecf20Sopenharmony_ci
6568c2ecf20Sopenharmony_ci	p_cache->cache_size_in_bytes = size_in_bytes;
6578c2ecf20Sopenharmony_ci	p_cache->control_count = control_count;
6588c2ecf20Sopenharmony_ci	p_cache->p_cache = p_dsp_control_buffer;
6598c2ecf20Sopenharmony_ci	p_cache->init = 0;
6608c2ecf20Sopenharmony_ci	return p_cache;
6618c2ecf20Sopenharmony_ci}
6628c2ecf20Sopenharmony_ci
6638c2ecf20Sopenharmony_civoid hpi_free_control_cache(struct hpi_control_cache *p_cache)
6648c2ecf20Sopenharmony_ci{
6658c2ecf20Sopenharmony_ci	if (p_cache) {
6668c2ecf20Sopenharmony_ci		kfree(p_cache->p_info);
6678c2ecf20Sopenharmony_ci		kfree(p_cache);
6688c2ecf20Sopenharmony_ci	}
6698c2ecf20Sopenharmony_ci}
6708c2ecf20Sopenharmony_ci
6718c2ecf20Sopenharmony_cistatic void subsys_message(struct hpi_message *phm, struct hpi_response *phr)
6728c2ecf20Sopenharmony_ci{
6738c2ecf20Sopenharmony_ci	hpi_init_response(phr, HPI_OBJ_SUBSYSTEM, phm->function, 0);
6748c2ecf20Sopenharmony_ci
6758c2ecf20Sopenharmony_ci	switch (phm->function) {
6768c2ecf20Sopenharmony_ci	case HPI_SUBSYS_OPEN:
6778c2ecf20Sopenharmony_ci	case HPI_SUBSYS_CLOSE:
6788c2ecf20Sopenharmony_ci	case HPI_SUBSYS_DRIVER_UNLOAD:
6798c2ecf20Sopenharmony_ci		break;
6808c2ecf20Sopenharmony_ci	case HPI_SUBSYS_DRIVER_LOAD:
6818c2ecf20Sopenharmony_ci		wipe_adapter_list();
6828c2ecf20Sopenharmony_ci		hpios_alistlock_init(&adapters);
6838c2ecf20Sopenharmony_ci		break;
6848c2ecf20Sopenharmony_ci	case HPI_SUBSYS_GET_ADAPTER:
6858c2ecf20Sopenharmony_ci		subsys_get_adapter(phm, phr);
6868c2ecf20Sopenharmony_ci		break;
6878c2ecf20Sopenharmony_ci	case HPI_SUBSYS_GET_NUM_ADAPTERS:
6888c2ecf20Sopenharmony_ci		phr->u.s.num_adapters = adapters.gw_num_adapters;
6898c2ecf20Sopenharmony_ci		break;
6908c2ecf20Sopenharmony_ci	case HPI_SUBSYS_CREATE_ADAPTER:
6918c2ecf20Sopenharmony_ci		break;
6928c2ecf20Sopenharmony_ci	default:
6938c2ecf20Sopenharmony_ci		phr->error = HPI_ERROR_INVALID_FUNC;
6948c2ecf20Sopenharmony_ci		break;
6958c2ecf20Sopenharmony_ci	}
6968c2ecf20Sopenharmony_ci}
6978c2ecf20Sopenharmony_ci
6988c2ecf20Sopenharmony_civoid HPI_COMMON(struct hpi_message *phm, struct hpi_response *phr)
6998c2ecf20Sopenharmony_ci{
7008c2ecf20Sopenharmony_ci	switch (phm->type) {
7018c2ecf20Sopenharmony_ci	case HPI_TYPE_REQUEST:
7028c2ecf20Sopenharmony_ci		switch (phm->object) {
7038c2ecf20Sopenharmony_ci		case HPI_OBJ_SUBSYSTEM:
7048c2ecf20Sopenharmony_ci			subsys_message(phm, phr);
7058c2ecf20Sopenharmony_ci			break;
7068c2ecf20Sopenharmony_ci		}
7078c2ecf20Sopenharmony_ci		break;
7088c2ecf20Sopenharmony_ci
7098c2ecf20Sopenharmony_ci	default:
7108c2ecf20Sopenharmony_ci		phr->error = HPI_ERROR_INVALID_TYPE;
7118c2ecf20Sopenharmony_ci		break;
7128c2ecf20Sopenharmony_ci	}
7138c2ecf20Sopenharmony_ci}
714