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