1 // SPDX-License-Identifier: GPL-2.0-only
2 /******************************************************************************
4 AudioScience HPI driver
5 Copyright (C) 1997-2014 AudioScience Inc. <support@audioscience.com>
10 Common functions used by hpixxxx.c modules
12 (C) Copyright AudioScience Inc. 1998-2003
13 *******************************************************************************/
14 #define SOURCEFILE_NAME "hpicmn.c"
16 #include "hpi_internal.h"
18 #include "hpimsginit.h"
22 struct hpi_adapters_list
{
23 struct hpios_spinlock list_lock
;
24 struct hpi_adapter_obj adapter
[HPI_MAX_ADAPTERS
];
28 static struct hpi_adapters_list adapters
;
31 * hpi_validate_response - Given an HPI Message that was sent out and
32 * a response that was received, validate that the response has the
33 * correct fields filled in, i.e ObjectType, Function etc
37 u16
hpi_validate_response(struct hpi_message
*phm
, struct hpi_response
*phr
)
39 if (phr
->type
!= HPI_TYPE_RESPONSE
) {
40 HPI_DEBUG_LOG(ERROR
, "header type %d invalid\n", phr
->type
);
41 return HPI_ERROR_INVALID_RESPONSE
;
44 if (phr
->object
!= phm
->object
) {
45 HPI_DEBUG_LOG(ERROR
, "header object %d invalid\n",
47 return HPI_ERROR_INVALID_RESPONSE
;
50 if (phr
->function
!= phm
->function
) {
51 HPI_DEBUG_LOG(ERROR
, "header function %d invalid\n",
53 return HPI_ERROR_INVALID_RESPONSE
;
59 u16
hpi_add_adapter(struct hpi_adapter_obj
*pao
)
62 /*HPI_ASSERT(pao->type); */
64 hpios_alistlock_lock(&adapters
);
66 if (pao
->index
>= HPI_MAX_ADAPTERS
) {
67 retval
= HPI_ERROR_BAD_ADAPTER_NUMBER
;
71 if (adapters
.adapter
[pao
->index
].type
) {
73 for (a
= HPI_MAX_ADAPTERS
- 1; a
>= 0; a
--) {
74 if (!adapters
.adapter
[a
].type
) {
75 HPI_DEBUG_LOG(WARNING
,
76 "ASI%X duplicate index %d moved to %d\n",
77 pao
->type
, pao
->index
, a
);
83 retval
= HPI_ERROR_DUPLICATE_ADAPTER_NUMBER
;
87 adapters
.adapter
[pao
->index
] = *pao
;
88 hpios_dsplock_init(&adapters
.adapter
[pao
->index
]);
89 adapters
.gw_num_adapters
++;
92 hpios_alistlock_unlock(&adapters
);
96 void hpi_delete_adapter(struct hpi_adapter_obj
*pao
)
99 HPI_DEBUG_LOG(ERROR
, "removing null adapter?\n");
103 hpios_alistlock_lock(&adapters
);
104 if (adapters
.adapter
[pao
->index
].type
)
105 adapters
.gw_num_adapters
--;
106 memset(&adapters
.adapter
[pao
->index
], 0, sizeof(adapters
.adapter
[0]));
107 hpios_alistlock_unlock(&adapters
);
111 * hpi_find_adapter - FindAdapter returns a pointer to the struct
112 * hpi_adapter_obj with index wAdapterIndex in an HPI_ADAPTERS_LIST
114 * @adapter_index: value in [0, HPI_MAX_ADAPTERS[
116 struct hpi_adapter_obj
*hpi_find_adapter(u16 adapter_index
)
118 struct hpi_adapter_obj
*pao
= NULL
;
120 if (adapter_index
>= HPI_MAX_ADAPTERS
) {
121 HPI_DEBUG_LOG(VERBOSE
, "find_adapter invalid index %d\n",
126 pao
= &adapters
.adapter
[adapter_index
];
127 if (pao
->type
!= 0) {
129 HPI_DEBUG_LOG(VERBOSE, "Found adapter index %d\n",
135 HPI_DEBUG_LOG(VERBOSE, "No adapter index %d\n",
143 * wipe_adapter_list - wipe an HPI_ADAPTERS_LIST structure.
146 static void wipe_adapter_list(void)
148 memset(&adapters
, 0, sizeof(adapters
));
151 static void subsys_get_adapter(struct hpi_message
*phm
,
152 struct hpi_response
*phr
)
154 int count
= phm
->obj_index
;
157 /* find the nCount'th nonzero adapter in array */
158 for (index
= 0; index
< HPI_MAX_ADAPTERS
; index
++) {
159 if (adapters
.adapter
[index
].type
) {
166 if (index
< HPI_MAX_ADAPTERS
) {
167 phr
->u
.s
.adapter_index
= adapters
.adapter
[index
].index
;
168 phr
->u
.s
.adapter_type
= adapters
.adapter
[index
].type
;
170 phr
->u
.s
.adapter_index
= 0;
171 phr
->u
.s
.adapter_type
= 0;
172 phr
->error
= HPI_ERROR_INVALID_OBJ_INDEX
;
176 static unsigned int control_cache_alloc_check(struct hpi_control_cache
*pC
)
189 if (pC
->control_count
&& pC
->cache_size_in_bytes
) {
190 char *p_master_cache
;
191 unsigned int byte_count
= 0;
193 p_master_cache
= (char *)pC
->p_cache
;
194 HPI_DEBUG_LOG(DEBUG
, "check %d controls\n",
196 for (i
= 0; i
< pC
->control_count
; i
++) {
197 struct hpi_control_cache_info
*info
=
198 (struct hpi_control_cache_info
*)
199 &p_master_cache
[byte_count
];
200 u16 control_index
= info
->control_index
;
202 if (control_index
>= pC
->control_count
) {
204 "adap %d control index %d out of range, cache not ready?\n",
205 pC
->adap_idx
, control_index
);
209 if (!info
->size_in32bit_words
) {
212 "adap %d cache not ready?\n",
216 /* The cache is invalid.
217 * Minimum valid entry size is
218 * sizeof(struct hpi_control_cache_info)
221 "adap %d zero size cache entry %d\n",
226 if (info
->control_type
) {
227 pC
->p_info
[control_index
] = info
;
229 } else { /* dummy cache entry */
230 pC
->p_info
[control_index
] = NULL
;
233 byte_count
+= info
->size_in32bit_words
* 4;
235 HPI_DEBUG_LOG(VERBOSE
,
236 "cached %d, pinfo %p index %d type %d size %d\n",
237 cached
, pC
->p_info
[info
->control_index
],
238 info
->control_index
, info
->control_type
,
239 info
->size_in32bit_words
);
241 /* quit loop early if whole cache has been scanned.
242 * dwControlCount is the maximum possible entries
243 * but some may be absent from the cache
245 if (byte_count
>= pC
->cache_size_in_bytes
)
247 /* have seen last control index */
248 if (info
->control_index
== pC
->control_count
- 1)
252 if (byte_count
!= pC
->cache_size_in_bytes
)
253 HPI_DEBUG_LOG(WARNING
,
254 "adap %d bytecount %d != cache size %d\n",
255 pC
->adap_idx
, byte_count
,
256 pC
->cache_size_in_bytes
);
259 "adap %d cache good, bytecount == cache size = %d\n",
260 pC
->adap_idx
, byte_count
);
262 pC
->init
= (u16
)cached
;
269 static short find_control(u16 control_index
,
270 struct hpi_control_cache
*p_cache
, struct hpi_control_cache_info
**pI
)
272 if (!control_cache_alloc_check(p_cache
)) {
273 HPI_DEBUG_LOG(VERBOSE
,
274 "control_cache_alloc_check() failed %d\n",
279 *pI
= p_cache
->p_info
[control_index
];
281 HPI_DEBUG_LOG(VERBOSE
, "Uncached Control %d\n",
285 HPI_DEBUG_LOG(VERBOSE
, "find_control() type %d\n",
286 (*pI
)->control_type
);
291 /* allow unified treatment of several string fields within struct */
292 #define HPICMN_PAD_OFS_AND_SIZE(m) {\
293 offsetof(struct hpi_control_cache_pad, m), \
294 sizeof(((struct hpi_control_cache_pad *)(NULL))->m) }
296 struct pad_ofs_size
{
298 unsigned int field_size
;
301 static const struct pad_ofs_size pad_desc
[] = {
302 HPICMN_PAD_OFS_AND_SIZE(c_channel
), /* HPI_PAD_CHANNEL_NAME */
303 HPICMN_PAD_OFS_AND_SIZE(c_artist
), /* HPI_PAD_ARTIST */
304 HPICMN_PAD_OFS_AND_SIZE(c_title
), /* HPI_PAD_TITLE */
305 HPICMN_PAD_OFS_AND_SIZE(c_comment
), /* HPI_PAD_COMMENT */
308 /** CheckControlCache checks the cache and fills the struct hpi_response
309 * accordingly. It returns one if a cache hit occurred, zero otherwise.
311 short hpi_check_control_cache_single(struct hpi_control_cache_single
*pC
,
312 struct hpi_message
*phm
, struct hpi_response
*phr
)
314 size_t response_size
;
317 /* set the default response size */
319 sizeof(struct hpi_response_header
) +
320 sizeof(struct hpi_control_res
);
322 switch (pC
->u
.i
.control_type
) {
324 case HPI_CONTROL_METER
:
325 if (phm
->u
.c
.attribute
== HPI_METER_PEAK
) {
326 phr
->u
.c
.an_log_value
[0] = pC
->u
.meter
.an_log_peak
[0];
327 phr
->u
.c
.an_log_value
[1] = pC
->u
.meter
.an_log_peak
[1];
328 } else if (phm
->u
.c
.attribute
== HPI_METER_RMS
) {
329 if (pC
->u
.meter
.an_logRMS
[0] ==
330 HPI_CACHE_INVALID_SHORT
) {
332 HPI_ERROR_INVALID_CONTROL_ATTRIBUTE
;
333 phr
->u
.c
.an_log_value
[0] = HPI_METER_MINIMUM
;
334 phr
->u
.c
.an_log_value
[1] = HPI_METER_MINIMUM
;
336 phr
->u
.c
.an_log_value
[0] =
337 pC
->u
.meter
.an_logRMS
[0];
338 phr
->u
.c
.an_log_value
[1] =
339 pC
->u
.meter
.an_logRMS
[1];
344 case HPI_CONTROL_VOLUME
:
345 if (phm
->u
.c
.attribute
== HPI_VOLUME_GAIN
) {
346 phr
->u
.c
.an_log_value
[0] = pC
->u
.vol
.an_log
[0];
347 phr
->u
.c
.an_log_value
[1] = pC
->u
.vol
.an_log
[1];
348 } else if (phm
->u
.c
.attribute
== HPI_VOLUME_MUTE
) {
349 if (pC
->u
.vol
.flags
& HPI_VOLUME_FLAG_HAS_MUTE
) {
350 if (pC
->u
.vol
.flags
& HPI_VOLUME_FLAG_MUTED
)
352 HPI_BITMASK_ALL_CHANNELS
;
357 HPI_ERROR_INVALID_CONTROL_ATTRIBUTE
;
364 case HPI_CONTROL_MULTIPLEXER
:
365 if (phm
->u
.c
.attribute
== HPI_MULTIPLEXER_SOURCE
) {
366 phr
->u
.c
.param1
= pC
->u
.mux
.source_node_type
;
367 phr
->u
.c
.param2
= pC
->u
.mux
.source_node_index
;
372 case HPI_CONTROL_CHANNEL_MODE
:
373 if (phm
->u
.c
.attribute
== HPI_CHANNEL_MODE_MODE
)
374 phr
->u
.c
.param1
= pC
->u
.mode
.mode
;
378 case HPI_CONTROL_LEVEL
:
379 if (phm
->u
.c
.attribute
== HPI_LEVEL_GAIN
) {
380 phr
->u
.c
.an_log_value
[0] = pC
->u
.level
.an_log
[0];
381 phr
->u
.c
.an_log_value
[1] = pC
->u
.level
.an_log
[1];
385 case HPI_CONTROL_TUNER
:
386 if (phm
->u
.c
.attribute
== HPI_TUNER_FREQ
)
387 phr
->u
.c
.param1
= pC
->u
.tuner
.freq_ink_hz
;
388 else if (phm
->u
.c
.attribute
== HPI_TUNER_BAND
)
389 phr
->u
.c
.param1
= pC
->u
.tuner
.band
;
390 else if (phm
->u
.c
.attribute
== HPI_TUNER_LEVEL_AVG
)
391 if (pC
->u
.tuner
.s_level_avg
==
392 HPI_CACHE_INVALID_SHORT
) {
393 phr
->u
.cu
.tuner
.s_level
= 0;
395 HPI_ERROR_INVALID_CONTROL_ATTRIBUTE
;
397 phr
->u
.cu
.tuner
.s_level
=
398 pC
->u
.tuner
.s_level_avg
;
402 case HPI_CONTROL_AESEBU_RECEIVER
:
403 if (phm
->u
.c
.attribute
== HPI_AESEBURX_ERRORSTATUS
)
404 phr
->u
.c
.param1
= pC
->u
.aes3rx
.error_status
;
405 else if (phm
->u
.c
.attribute
== HPI_AESEBURX_FORMAT
)
406 phr
->u
.c
.param1
= pC
->u
.aes3rx
.format
;
410 case HPI_CONTROL_AESEBU_TRANSMITTER
:
411 if (phm
->u
.c
.attribute
== HPI_AESEBUTX_FORMAT
)
412 phr
->u
.c
.param1
= pC
->u
.aes3tx
.format
;
416 case HPI_CONTROL_TONEDETECTOR
:
417 if (phm
->u
.c
.attribute
== HPI_TONEDETECTOR_STATE
)
418 phr
->u
.c
.param1
= pC
->u
.tone
.state
;
422 case HPI_CONTROL_SILENCEDETECTOR
:
423 if (phm
->u
.c
.attribute
== HPI_SILENCEDETECTOR_STATE
) {
424 phr
->u
.c
.param1
= pC
->u
.silence
.state
;
428 case HPI_CONTROL_MICROPHONE
:
429 if (phm
->u
.c
.attribute
== HPI_MICROPHONE_PHANTOM_POWER
)
430 phr
->u
.c
.param1
= pC
->u
.microphone
.phantom_state
;
434 case HPI_CONTROL_SAMPLECLOCK
:
435 if (phm
->u
.c
.attribute
== HPI_SAMPLECLOCK_SOURCE
)
436 phr
->u
.c
.param1
= pC
->u
.clk
.source
;
437 else if (phm
->u
.c
.attribute
== HPI_SAMPLECLOCK_SOURCE_INDEX
) {
438 if (pC
->u
.clk
.source_index
==
439 HPI_CACHE_INVALID_UINT16
) {
442 HPI_ERROR_INVALID_CONTROL_ATTRIBUTE
;
444 phr
->u
.c
.param1
= pC
->u
.clk
.source_index
;
445 } else if (phm
->u
.c
.attribute
== HPI_SAMPLECLOCK_SAMPLERATE
)
446 phr
->u
.c
.param1
= pC
->u
.clk
.sample_rate
;
450 case HPI_CONTROL_PAD
:{
451 struct hpi_control_cache_pad
*p_pad
;
452 p_pad
= (struct hpi_control_cache_pad
*)pC
;
454 if (!(p_pad
->field_valid_flags
& (1 <<
455 HPI_CTL_ATTR_INDEX(phm
->u
.c
.
458 HPI_ERROR_INVALID_CONTROL_ATTRIBUTE
;
462 if (phm
->u
.c
.attribute
== HPI_PAD_PROGRAM_ID
)
463 phr
->u
.c
.param1
= p_pad
->pI
;
464 else if (phm
->u
.c
.attribute
== HPI_PAD_PROGRAM_TYPE
)
465 phr
->u
.c
.param1
= p_pad
->pTY
;
468 HPI_CTL_ATTR_INDEX(phm
->u
.c
.
470 unsigned int offset
= phm
->u
.c
.param1
;
471 unsigned int pad_string_len
, field_size
;
475 if (index
> ARRAY_SIZE(pad_desc
) - 1) {
477 HPI_ERROR_INVALID_CONTROL_ATTRIBUTE
;
483 pad_desc
[index
].offset
;
484 field_size
= pad_desc
[index
].field_size
;
485 /* Ensure null terminator */
486 pad_string
[field_size
- 1] = 0;
488 pad_string_len
= strlen(pad_string
) + 1;
490 if (offset
> pad_string_len
) {
492 HPI_ERROR_INVALID_CONTROL_VALUE
;
496 tocopy
= pad_string_len
- offset
;
497 if (tocopy
> sizeof(phr
->u
.cu
.chars8
.sz_data
))
498 tocopy
= sizeof(phr
->u
.cu
.chars8
.
501 memcpy(phr
->u
.cu
.chars8
.sz_data
,
502 &pad_string
[offset
], tocopy
);
504 phr
->u
.cu
.chars8
.remaining_chars
=
505 pad_string_len
- offset
- tocopy
;
514 HPI_DEBUG_LOG(VERBOSE
, "%s Adap %d, Ctl %d, Type %d, Attr %d\n",
515 found
? "Cached" : "Uncached", phm
->adapter_index
,
516 pC
->u
.i
.control_index
, pC
->u
.i
.control_type
,
520 phr
->size
= (u16
)response_size
;
521 phr
->type
= HPI_TYPE_RESPONSE
;
522 phr
->object
= phm
->object
;
523 phr
->function
= phm
->function
;
529 short hpi_check_control_cache(struct hpi_control_cache
*p_cache
,
530 struct hpi_message
*phm
, struct hpi_response
*phr
)
532 struct hpi_control_cache_info
*pI
;
534 if (!find_control(phm
->obj_index
, p_cache
, &pI
)) {
535 HPI_DEBUG_LOG(VERBOSE
,
536 "HPICMN find_control() failed for adap %d\n",
542 phr
->specific_error
= 0;
545 return hpi_check_control_cache_single((struct hpi_control_cache_single
549 /** Updates the cache with Set values.
551 Only update if no error.
552 Volume and Level return the limited values in the response, so use these
553 Multiplexer does so use sent values
555 void hpi_cmn_control_cache_sync_to_msg_single(struct hpi_control_cache_single
556 *pC
, struct hpi_message
*phm
, struct hpi_response
*phr
)
558 switch (pC
->u
.i
.control_type
) {
559 case HPI_CONTROL_VOLUME
:
560 if (phm
->u
.c
.attribute
== HPI_VOLUME_GAIN
) {
561 pC
->u
.vol
.an_log
[0] = phr
->u
.c
.an_log_value
[0];
562 pC
->u
.vol
.an_log
[1] = phr
->u
.c
.an_log_value
[1];
563 } else if (phm
->u
.c
.attribute
== HPI_VOLUME_MUTE
) {
565 pC
->u
.vol
.flags
|= HPI_VOLUME_FLAG_MUTED
;
567 pC
->u
.vol
.flags
&= ~HPI_VOLUME_FLAG_MUTED
;
570 case HPI_CONTROL_MULTIPLEXER
:
571 /* mux does not return its setting on Set command. */
572 if (phm
->u
.c
.attribute
== HPI_MULTIPLEXER_SOURCE
) {
573 pC
->u
.mux
.source_node_type
= (u16
)phm
->u
.c
.param1
;
574 pC
->u
.mux
.source_node_index
= (u16
)phm
->u
.c
.param2
;
577 case HPI_CONTROL_CHANNEL_MODE
:
578 /* mode does not return its setting on Set command. */
579 if (phm
->u
.c
.attribute
== HPI_CHANNEL_MODE_MODE
)
580 pC
->u
.mode
.mode
= (u16
)phm
->u
.c
.param1
;
582 case HPI_CONTROL_LEVEL
:
583 if (phm
->u
.c
.attribute
== HPI_LEVEL_GAIN
) {
584 pC
->u
.vol
.an_log
[0] = phr
->u
.c
.an_log_value
[0];
585 pC
->u
.vol
.an_log
[1] = phr
->u
.c
.an_log_value
[1];
588 case HPI_CONTROL_MICROPHONE
:
589 if (phm
->u
.c
.attribute
== HPI_MICROPHONE_PHANTOM_POWER
)
590 pC
->u
.microphone
.phantom_state
= (u16
)phm
->u
.c
.param1
;
592 case HPI_CONTROL_AESEBU_TRANSMITTER
:
593 if (phm
->u
.c
.attribute
== HPI_AESEBUTX_FORMAT
)
594 pC
->u
.aes3tx
.format
= phm
->u
.c
.param1
;
596 case HPI_CONTROL_AESEBU_RECEIVER
:
597 if (phm
->u
.c
.attribute
== HPI_AESEBURX_FORMAT
)
598 pC
->u
.aes3rx
.format
= phm
->u
.c
.param1
;
600 case HPI_CONTROL_SAMPLECLOCK
:
601 if (phm
->u
.c
.attribute
== HPI_SAMPLECLOCK_SOURCE
)
602 pC
->u
.clk
.source
= (u16
)phm
->u
.c
.param1
;
603 else if (phm
->u
.c
.attribute
== HPI_SAMPLECLOCK_SOURCE_INDEX
)
604 pC
->u
.clk
.source_index
= (u16
)phm
->u
.c
.param1
;
605 else if (phm
->u
.c
.attribute
== HPI_SAMPLECLOCK_SAMPLERATE
)
606 pC
->u
.clk
.sample_rate
= phm
->u
.c
.param1
;
613 void hpi_cmn_control_cache_sync_to_msg(struct hpi_control_cache
*p_cache
,
614 struct hpi_message
*phm
, struct hpi_response
*phr
)
616 struct hpi_control_cache_single
*pC
;
617 struct hpi_control_cache_info
*pI
;
622 if (!find_control(phm
->obj_index
, p_cache
, &pI
)) {
623 HPI_DEBUG_LOG(VERBOSE
,
624 "HPICMN find_control() failed for adap %d\n",
629 /* pC is the default cached control strucure.
630 May be cast to something else in the following switch statement.
632 pC
= (struct hpi_control_cache_single
*)pI
;
634 hpi_cmn_control_cache_sync_to_msg_single(pC
, phm
, phr
);
637 /** Allocate control cache.
639 \return Cache pointer, or NULL if allocation fails.
641 struct hpi_control_cache
*hpi_alloc_control_cache(const u32 control_count
,
642 const u32 size_in_bytes
, u8
*p_dsp_control_buffer
)
644 struct hpi_control_cache
*p_cache
=
645 kmalloc(sizeof(*p_cache
), GFP_KERNEL
);
650 kcalloc(control_count
, sizeof(*p_cache
->p_info
), GFP_KERNEL
);
651 if (!p_cache
->p_info
) {
656 p_cache
->cache_size_in_bytes
= size_in_bytes
;
657 p_cache
->control_count
= control_count
;
658 p_cache
->p_cache
= p_dsp_control_buffer
;
663 void hpi_free_control_cache(struct hpi_control_cache
*p_cache
)
666 kfree(p_cache
->p_info
);
671 static void subsys_message(struct hpi_message
*phm
, struct hpi_response
*phr
)
673 hpi_init_response(phr
, HPI_OBJ_SUBSYSTEM
, phm
->function
, 0);
675 switch (phm
->function
) {
676 case HPI_SUBSYS_OPEN
:
677 case HPI_SUBSYS_CLOSE
:
678 case HPI_SUBSYS_DRIVER_UNLOAD
:
680 case HPI_SUBSYS_DRIVER_LOAD
:
682 hpios_alistlock_init(&adapters
);
684 case HPI_SUBSYS_GET_ADAPTER
:
685 subsys_get_adapter(phm
, phr
);
687 case HPI_SUBSYS_GET_NUM_ADAPTERS
:
688 phr
->u
.s
.num_adapters
= adapters
.gw_num_adapters
;
690 case HPI_SUBSYS_CREATE_ADAPTER
:
693 phr
->error
= HPI_ERROR_INVALID_FUNC
;
698 void HPI_COMMON(struct hpi_message
*phm
, struct hpi_response
*phr
)
701 case HPI_TYPE_REQUEST
:
702 switch (phm
->object
) {
703 case HPI_OBJ_SUBSYSTEM
:
704 subsys_message(phm
, phr
);
710 phr
->error
= HPI_ERROR_INVALID_TYPE
;