blob: 4b3f4761cba573ec77826e0e0efd270eb8f2c057 [file] [log] [blame]
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001/******************************************************************************
2
3 AudioScience HPI driver
4 Copyright (C) 1997-2010 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"
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +130029#include "hpimsginit.h"
30
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +020031#include "hpicmn.h"
32
33struct 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
39static 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**/
46u16 hpi_validate_response(struct hpi_message *phm, struct hpi_response *phr)
47{
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +130048 if (phr->type != HPI_TYPE_RESPONSE) {
Eliot Blennerhassett1528fbb2011-02-10 17:26:02 +130049 HPI_DEBUG_LOG(ERROR, "header type %d invalid\n", phr->type);
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +130050 return HPI_ERROR_INVALID_RESPONSE;
51 }
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +020052
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +130053 if (phr->object != phm->object) {
Eliot Blennerhassett1528fbb2011-02-10 17:26:02 +130054 HPI_DEBUG_LOG(ERROR, "header object %d invalid\n",
55 phr->object);
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +130056 return HPI_ERROR_INVALID_RESPONSE;
57 }
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +020058
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +130059 if (phr->function != phm->function) {
Eliot Blennerhassett1528fbb2011-02-10 17:26:02 +130060 HPI_DEBUG_LOG(ERROR, "header type %d invalid\n",
61 phr->function);
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +130062 return HPI_ERROR_INVALID_RESPONSE;
63 }
64
65 return 0;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +020066}
67
68u16 hpi_add_adapter(struct hpi_adapter_obj *pao)
69{
70 u16 retval = 0;
71 /*HPI_ASSERT(pao->wAdapterType); */
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].adapter_type) {
81 {
82 retval = HPI_DUPLICATE_ADAPTER_NUMBER;
83 goto unlock;
84 }
85 }
86 adapters.adapter[pao->index] = *pao;
87 hpios_dsplock_init(&adapters.adapter[pao->index]);
88 adapters.gw_num_adapters++;
89
90unlock:
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +130091 hpios_alistlock_unlock(&adapters);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +020092 return retval;
93}
94
95void hpi_delete_adapter(struct hpi_adapter_obj *pao)
96{
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +130097 if (!pao->adapter_type) {
98 HPI_DEBUG_LOG(ERROR, "removing null adapter?\n");
99 return;
100 }
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200101
102 hpios_alistlock_lock(&adapters);
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300103 if (adapters.adapter[pao->index].adapter_type)
104 adapters.gw_num_adapters--;
105 memset(&adapters.adapter[pao->index], 0, sizeof(adapters.adapter[0]));
106 hpios_alistlock_unlock(&adapters);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200107}
108
109/**
110* FindAdapter returns a pointer to the struct hpi_adapter_obj with
111* index wAdapterIndex in an HPI_ADAPTERS_LIST structure.
112*
113*/
114struct hpi_adapter_obj *hpi_find_adapter(u16 adapter_index)
115{
116 struct hpi_adapter_obj *pao = NULL;
117
118 if (adapter_index >= HPI_MAX_ADAPTERS) {
Eliot Blennerhassett1528fbb2011-02-10 17:26:02 +1300119 HPI_DEBUG_LOG(VERBOSE, "find_adapter invalid index %d\n",
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200120 adapter_index);
121 return NULL;
122 }
123
124 pao = &adapters.adapter[adapter_index];
125 if (pao->adapter_type != 0) {
126 /*
127 HPI_DEBUG_LOG(VERBOSE, "Found adapter index %d\n",
128 wAdapterIndex);
129 */
130 return pao;
131 } else {
132 /*
133 HPI_DEBUG_LOG(VERBOSE, "No adapter index %d\n",
134 wAdapterIndex);
135 */
136 return NULL;
137 }
138}
139
140/**
141*
142* wipe an HPI_ADAPTERS_LIST structure.
143*
144**/
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300145static void wipe_adapter_list(void)
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200146{
147 memset(&adapters, 0, sizeof(adapters));
148}
149
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300150static void subsys_get_adapter(struct hpi_message *phm,
151 struct hpi_response *phr)
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200152{
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300153 int count = phm->obj_index;
154 u16 index = 0;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200155
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300156 /* find the nCount'th nonzero adapter in array */
157 for (index = 0; index < HPI_MAX_ADAPTERS; index++) {
158 if (adapters.adapter[index].adapter_type) {
Eliot Blennerhassett47049982011-02-10 17:26:06 +1300159 if (!count)
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300160 break;
161 count--;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200162 }
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200163 }
164
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300165 if (index < HPI_MAX_ADAPTERS) {
166 phr->u.s.adapter_index = adapters.adapter[index].index;
Eliot Blennerhassett2f918a62011-02-10 17:26:09 +1300167 phr->u.s.adapter_type = adapters.adapter[index].adapter_type;
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300168 } else {
169 phr->u.s.adapter_index = 0;
Eliot Blennerhassett2f918a62011-02-10 17:26:09 +1300170 phr->u.s.adapter_type = 0;
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300171 phr->error = HPI_ERROR_BAD_ADAPTER_NUMBER;
172 }
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200173}
174
175static unsigned int control_cache_alloc_check(struct hpi_control_cache *pC)
176{
177 unsigned int i;
178 int cached = 0;
179 if (!pC)
180 return 0;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200181
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300182 if (pC->init)
183 return pC->init;
184
185 if (!pC->p_cache)
186 return 0;
187
188 if (pC->control_count && pC->cache_size_in_bytes) {
189 char *p_master_cache;
190 unsigned int byte_count = 0;
191
192 p_master_cache = (char *)pC->p_cache;
193 HPI_DEBUG_LOG(DEBUG, "check %d controls\n",
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200194 pC->control_count);
195 for (i = 0; i < pC->control_count; i++) {
196 struct hpi_control_cache_info *info =
197 (struct hpi_control_cache_info *)
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300198 &p_master_cache[byte_count];
199
200 if (!info->size_in32bit_words) {
Eliot Blennerhassett47049982011-02-10 17:26:06 +1300201 if (!i) {
Eliot Blennerhassettffdb5782011-02-10 17:26:00 +1300202 HPI_DEBUG_LOG(INFO,
203 "adap %d cache not ready?\n",
204 pC->adap_idx);
205 return 0;
206 }
Eliot Blennerhassett1528fbb2011-02-10 17:26:02 +1300207 /* The cache is invalid.
208 * Minimum valid entry size is
209 * sizeof(struct hpi_control_cache_info)
210 */
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300211 HPI_DEBUG_LOG(ERROR,
Eliot Blennerhassettffdb5782011-02-10 17:26:00 +1300212 "adap %d zero size cache entry %d\n",
213 pC->adap_idx, i);
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300214 break;
215 }
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200216
217 if (info->control_type) {
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300218 pC->p_info[info->control_index] = info;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200219 cached++;
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300220 } else /* dummy cache entry */
221 pC->p_info[info->control_index] = NULL;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200222
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300223 byte_count += info->size_in32bit_words * 4;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200224
225 HPI_DEBUG_LOG(VERBOSE,
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300226 "cached %d, pinfo %p index %d type %d size %d\n",
227 cached, pC->p_info[info->control_index],
228 info->control_index, info->control_type,
229 info->size_in32bit_words);
230
Eliot Blennerhassett1528fbb2011-02-10 17:26:02 +1300231 /* quit loop early if whole cache has been scanned.
232 * dwControlCount is the maximum possible entries
233 * but some may be absent from the cache
234 */
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300235 if (byte_count >= pC->cache_size_in_bytes)
236 break;
237 /* have seen last control index */
238 if (info->control_index == pC->control_count - 1)
239 break;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200240 }
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300241
242 if (byte_count != pC->cache_size_in_bytes)
243 HPI_DEBUG_LOG(WARNING,
Eliot Blennerhassett1528fbb2011-02-10 17:26:02 +1300244 "adap %d bytecount %d != cache size %d\n",
Eliot Blennerhassettffdb5782011-02-10 17:26:00 +1300245 pC->adap_idx, byte_count,
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300246 pC->cache_size_in_bytes);
247 else
248 HPI_DEBUG_LOG(DEBUG,
Eliot Blennerhassett1528fbb2011-02-10 17:26:02 +1300249 "adap %d cache good, bytecount == cache size = %d\n",
Eliot Blennerhassettffdb5782011-02-10 17:26:00 +1300250 pC->adap_idx, byte_count);
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300251
Eliot Blennerhassett1528fbb2011-02-10 17:26:02 +1300252 pC->init = (u16)cached;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200253 }
254 return pC->init;
255}
256
257/** Find a control.
258*/
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300259static short find_control(u16 control_index,
260 struct hpi_control_cache *p_cache, struct hpi_control_cache_info **pI)
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200261{
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200262 if (!control_cache_alloc_check(p_cache)) {
263 HPI_DEBUG_LOG(VERBOSE,
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300264 "control_cache_alloc_check() failed %d\n",
265 control_index);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200266 return 0;
267 }
268
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300269 *pI = p_cache->p_info[control_index];
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200270 if (!*pI) {
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300271 HPI_DEBUG_LOG(VERBOSE, "Uncached Control %d\n",
272 control_index);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200273 return 0;
274 } else {
275 HPI_DEBUG_LOG(VERBOSE, "find_control() type %d\n",
276 (*pI)->control_type);
277 }
278 return 1;
279}
280
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200281/* allow unified treatment of several string fields within struct */
282#define HPICMN_PAD_OFS_AND_SIZE(m) {\
283 offsetof(struct hpi_control_cache_pad, m), \
284 sizeof(((struct hpi_control_cache_pad *)(NULL))->m) }
285
286struct pad_ofs_size {
287 unsigned int offset;
288 unsigned int field_size;
289};
290
291static struct pad_ofs_size pad_desc[] = {
292 HPICMN_PAD_OFS_AND_SIZE(c_channel), /* HPI_PAD_CHANNEL_NAME */
293 HPICMN_PAD_OFS_AND_SIZE(c_artist), /* HPI_PAD_ARTIST */
294 HPICMN_PAD_OFS_AND_SIZE(c_title), /* HPI_PAD_TITLE */
295 HPICMN_PAD_OFS_AND_SIZE(c_comment), /* HPI_PAD_COMMENT */
296};
297
298/** CheckControlCache checks the cache and fills the struct hpi_response
299 * accordingly. It returns one if a cache hit occurred, zero otherwise.
300 */
301short hpi_check_control_cache(struct hpi_control_cache *p_cache,
302 struct hpi_message *phm, struct hpi_response *phr)
303{
304 short found = 1;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200305 struct hpi_control_cache_info *pI;
306 struct hpi_control_cache_single *pC;
307 struct hpi_control_cache_pad *p_pad;
308
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300309 if (!find_control(phm->obj_index, p_cache, &pI)) {
310 HPI_DEBUG_LOG(VERBOSE,
311 "HPICMN find_control() failed for adap %d\n",
312 phm->adapter_index);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200313 return 0;
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300314 }
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200315
316 phr->error = 0;
317
318 /* pC is the default cached control strucure. May be cast to
319 something else in the following switch statement.
320 */
321 pC = (struct hpi_control_cache_single *)pI;
322 p_pad = (struct hpi_control_cache_pad *)pI;
323
324 switch (pI->control_type) {
325
326 case HPI_CONTROL_METER:
327 if (phm->u.c.attribute == HPI_METER_PEAK) {
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300328 phr->u.c.an_log_value[0] = pC->u.meter.an_log_peak[0];
329 phr->u.c.an_log_value[1] = pC->u.meter.an_log_peak[1];
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200330 } else if (phm->u.c.attribute == HPI_METER_RMS) {
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300331 if (pC->u.meter.an_logRMS[0] ==
332 HPI_CACHE_INVALID_SHORT) {
333 phr->error =
334 HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
335 phr->u.c.an_log_value[0] = HPI_METER_MINIMUM;
336 phr->u.c.an_log_value[1] = HPI_METER_MINIMUM;
337 } else {
338 phr->u.c.an_log_value[0] =
339 pC->u.meter.an_logRMS[0];
340 phr->u.c.an_log_value[1] =
341 pC->u.meter.an_logRMS[1];
342 }
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200343 } else
344 found = 0;
345 break;
346 case HPI_CONTROL_VOLUME:
347 if (phm->u.c.attribute == HPI_VOLUME_GAIN) {
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300348 phr->u.c.an_log_value[0] = pC->u.vol.an_log[0];
349 phr->u.c.an_log_value[1] = pC->u.vol.an_log[1];
Eliot Blennerhassettfc3a3992011-02-10 17:26:11 +1300350 } else if (phm->u.c.attribute == HPI_VOLUME_MUTE) {
351 if (pC->u.vol.flags & HPI_VOLUME_FLAG_HAS_MUTE) {
352 if (pC->u.vol.flags & HPI_VOLUME_FLAG_MUTED)
353 phr->u.c.param1 =
354 HPI_BITMASK_ALL_CHANNELS;
355 else
356 phr->u.c.param1 = 0;
357 } else {
358 phr->error =
359 HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
360 phr->u.c.param1 = 0;
361 }
362 } else {
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200363 found = 0;
Eliot Blennerhassettfc3a3992011-02-10 17:26:11 +1300364 }
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200365 break;
366 case HPI_CONTROL_MULTIPLEXER:
367 if (phm->u.c.attribute == HPI_MULTIPLEXER_SOURCE) {
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300368 phr->u.c.param1 = pC->u.mux.source_node_type;
369 phr->u.c.param2 = pC->u.mux.source_node_index;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200370 } else {
371 found = 0;
372 }
373 break;
374 case HPI_CONTROL_CHANNEL_MODE:
375 if (phm->u.c.attribute == HPI_CHANNEL_MODE_MODE)
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300376 phr->u.c.param1 = pC->u.mode.mode;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200377 else
378 found = 0;
379 break;
380 case HPI_CONTROL_LEVEL:
381 if (phm->u.c.attribute == HPI_LEVEL_GAIN) {
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300382 phr->u.c.an_log_value[0] = pC->u.level.an_log[0];
383 phr->u.c.an_log_value[1] = pC->u.level.an_log[1];
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200384 } else
385 found = 0;
386 break;
387 case HPI_CONTROL_TUNER:
Eliot Blennerhassett3ee317fe2010-05-27 17:53:55 +1200388 if (phm->u.c.attribute == HPI_TUNER_FREQ)
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300389 phr->u.c.param1 = pC->u.tuner.freq_ink_hz;
Eliot Blennerhassett3ee317fe2010-05-27 17:53:55 +1200390 else if (phm->u.c.attribute == HPI_TUNER_BAND)
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300391 phr->u.c.param1 = pC->u.tuner.band;
392 else if (phm->u.c.attribute == HPI_TUNER_LEVEL_AVG)
393 if (pC->u.tuner.s_level_avg ==
394 HPI_CACHE_INVALID_SHORT) {
395 phr->u.cu.tuner.s_level = 0;
Eliot Blennerhassett36ed8bd2010-07-06 08:37:10 +1200396 phr->error =
397 HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
398 } else
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300399 phr->u.cu.tuner.s_level =
400 pC->u.tuner.s_level_avg;
Eliot Blennerhassett3ee317fe2010-05-27 17:53:55 +1200401 else
402 found = 0;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200403 break;
404 case HPI_CONTROL_AESEBU_RECEIVER:
405 if (phm->u.c.attribute == HPI_AESEBURX_ERRORSTATUS)
406 phr->u.c.param1 = pC->u.aes3rx.error_status;
407 else if (phm->u.c.attribute == HPI_AESEBURX_FORMAT)
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300408 phr->u.c.param1 = pC->u.aes3rx.format;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200409 else
410 found = 0;
411 break;
412 case HPI_CONTROL_AESEBU_TRANSMITTER:
413 if (phm->u.c.attribute == HPI_AESEBUTX_FORMAT)
414 phr->u.c.param1 = pC->u.aes3tx.format;
415 else
416 found = 0;
417 break;
418 case HPI_CONTROL_TONEDETECTOR:
419 if (phm->u.c.attribute == HPI_TONEDETECTOR_STATE)
420 phr->u.c.param1 = pC->u.tone.state;
421 else
422 found = 0;
423 break;
424 case HPI_CONTROL_SILENCEDETECTOR:
425 if (phm->u.c.attribute == HPI_SILENCEDETECTOR_STATE) {
426 phr->u.c.param1 = pC->u.silence.state;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200427 } else
428 found = 0;
429 break;
430 case HPI_CONTROL_MICROPHONE:
431 if (phm->u.c.attribute == HPI_MICROPHONE_PHANTOM_POWER)
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300432 phr->u.c.param1 = pC->u.microphone.phantom_state;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200433 else
434 found = 0;
435 break;
436 case HPI_CONTROL_SAMPLECLOCK:
437 if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE)
438 phr->u.c.param1 = pC->u.clk.source;
439 else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE_INDEX) {
440 if (pC->u.clk.source_index ==
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300441 HPI_CACHE_INVALID_UINT16) {
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200442 phr->u.c.param1 = 0;
Eliot Blennerhassett36ed8bd2010-07-06 08:37:10 +1200443 phr->error =
444 HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200445 } else
446 phr->u.c.param1 = pC->u.clk.source_index;
447 } else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SAMPLERATE)
448 phr->u.c.param1 = pC->u.clk.sample_rate;
449 else
450 found = 0;
451 break;
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300452 case HPI_CONTROL_PAD:{
453 struct hpi_control_cache_pad *p_pad;
454 p_pad = (struct hpi_control_cache_pad *)pI;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200455
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300456 if (!(p_pad->field_valid_flags & (1 <<
457 HPI_CTL_ATTR_INDEX(phm->u.c.
458 attribute)))) {
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200459 phr->error =
460 HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
461 break;
462 }
463
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300464 if (phm->u.c.attribute == HPI_PAD_PROGRAM_ID)
465 phr->u.c.param1 = p_pad->pI;
466 else if (phm->u.c.attribute == HPI_PAD_PROGRAM_TYPE)
467 phr->u.c.param1 = p_pad->pTY;
468 else {
469 unsigned int index =
470 HPI_CTL_ATTR_INDEX(phm->u.c.
471 attribute) - 1;
472 unsigned int offset = phm->u.c.param1;
473 unsigned int pad_string_len, field_size;
474 char *pad_string;
475 unsigned int tocopy;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200476
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300477 if (index > ARRAY_SIZE(pad_desc) - 1) {
478 phr->error =
479 HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
480 break;
481 }
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200482
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300483 pad_string =
484 ((char *)p_pad) +
485 pad_desc[index].offset;
486 field_size = pad_desc[index].field_size;
487 /* Ensure null terminator */
488 pad_string[field_size - 1] = 0;
489
490 pad_string_len = strlen(pad_string) + 1;
491
492 if (offset > pad_string_len) {
493 phr->error =
494 HPI_ERROR_INVALID_CONTROL_VALUE;
495 break;
496 }
497
498 tocopy = pad_string_len - offset;
499 if (tocopy > sizeof(phr->u.cu.chars8.sz_data))
500 tocopy = sizeof(phr->u.cu.chars8.
501 sz_data);
502
503 memcpy(phr->u.cu.chars8.sz_data,
504 &pad_string[offset], tocopy);
505
506 phr->u.cu.chars8.remaining_chars =
507 pad_string_len - offset - tocopy;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200508 }
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200509 }
510 break;
511 default:
512 found = 0;
513 break;
514 }
515
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300516 HPI_DEBUG_LOG(VERBOSE, "%s Adap %d, Ctl %d, Type %d, Attr %d\n",
517 found ? "Cached" : "Uncached", phm->adapter_index,
518 pI->control_index, pI->control_type, phm->u.c.attribute);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200519
520 if (found)
521 phr->size =
522 sizeof(struct hpi_response_header) +
523 sizeof(struct hpi_control_res);
524
525 return found;
526}
527
528/** Updates the cache with Set values.
529
530Only update if no error.
531Volume and Level return the limited values in the response, so use these
532Multiplexer does so use sent values
533*/
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300534void hpi_cmn_control_cache_sync_to_msg(struct hpi_control_cache *p_cache,
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200535 struct hpi_message *phm, struct hpi_response *phr)
536{
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200537 struct hpi_control_cache_single *pC;
538 struct hpi_control_cache_info *pI;
539
Eliot Blennerhassett3ee317fe2010-05-27 17:53:55 +1200540 if (phr->error)
541 return;
542
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300543 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);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200547 return;
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300548 }
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200549
550 /* pC is the default cached control strucure.
551 May be cast to something else in the following switch statement.
552 */
553 pC = (struct hpi_control_cache_single *)pI;
554
555 switch (pI->control_type) {
556 case HPI_CONTROL_VOLUME:
557 if (phm->u.c.attribute == HPI_VOLUME_GAIN) {
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300558 pC->u.vol.an_log[0] = phr->u.c.an_log_value[0];
559 pC->u.vol.an_log[1] = phr->u.c.an_log_value[1];
Eliot Blennerhassettfc3a3992011-02-10 17:26:11 +1300560 } else if (phm->u.c.attribute == HPI_VOLUME_MUTE) {
561 if (phm->u.c.param1)
562 pC->u.vol.flags |= HPI_VOLUME_FLAG_MUTED;
563 else
564 pC->u.vol.flags &= ~HPI_VOLUME_FLAG_MUTED;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200565 }
566 break;
567 case HPI_CONTROL_MULTIPLEXER:
568 /* mux does not return its setting on Set command. */
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200569 if (phm->u.c.attribute == HPI_MULTIPLEXER_SOURCE) {
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300570 pC->u.mux.source_node_type = (u16)phm->u.c.param1;
571 pC->u.mux.source_node_index = (u16)phm->u.c.param2;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200572 }
573 break;
574 case HPI_CONTROL_CHANNEL_MODE:
575 /* mode does not return its setting on Set command. */
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200576 if (phm->u.c.attribute == HPI_CHANNEL_MODE_MODE)
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300577 pC->u.mode.mode = (u16)phm->u.c.param1;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200578 break;
579 case HPI_CONTROL_LEVEL:
580 if (phm->u.c.attribute == HPI_LEVEL_GAIN) {
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300581 pC->u.vol.an_log[0] = phr->u.c.an_log_value[0];
582 pC->u.vol.an_log[1] = phr->u.c.an_log_value[1];
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200583 }
584 break;
585 case HPI_CONTROL_MICROPHONE:
586 if (phm->u.c.attribute == HPI_MICROPHONE_PHANTOM_POWER)
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300587 pC->u.microphone.phantom_state = (u16)phm->u.c.param1;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200588 break;
589 case HPI_CONTROL_AESEBU_TRANSMITTER:
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200590 if (phm->u.c.attribute == HPI_AESEBUTX_FORMAT)
591 pC->u.aes3tx.format = phm->u.c.param1;
592 break;
593 case HPI_CONTROL_AESEBU_RECEIVER:
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200594 if (phm->u.c.attribute == HPI_AESEBURX_FORMAT)
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300595 pC->u.aes3rx.format = phm->u.c.param1;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200596 break;
597 case HPI_CONTROL_SAMPLECLOCK:
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200598 if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE)
599 pC->u.clk.source = (u16)phm->u.c.param1;
600 else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE_INDEX)
601 pC->u.clk.source_index = (u16)phm->u.c.param1;
602 else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SAMPLERATE)
603 pC->u.clk.sample_rate = phm->u.c.param1;
604 break;
605 default:
606 break;
607 }
608}
609
Eliot Blennerhassett47049982011-02-10 17:26:06 +1300610struct hpi_control_cache *hpi_alloc_control_cache(const u32 control_count,
611 const u32 size_in_bytes, u8 *p_dsp_control_buffer)
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200612{
613 struct hpi_control_cache *p_cache =
614 kmalloc(sizeof(*p_cache), GFP_KERNEL);
Jesper Juhlfd0977d2010-10-29 21:35:25 +0200615 if (!p_cache)
616 return NULL;
Eliot Blennerhassett47049982011-02-10 17:26:06 +1300617
Jesper Juhlfd0977d2010-10-29 21:35:25 +0200618 p_cache->p_info =
Eliot Blennerhassett47049982011-02-10 17:26:06 +1300619 kmalloc(sizeof(*p_cache->p_info) * control_count, GFP_KERNEL);
Jesper Juhlfd0977d2010-10-29 21:35:25 +0200620 if (!p_cache->p_info) {
621 kfree(p_cache);
622 return NULL;
623 }
Eliot Blennerhassett47049982011-02-10 17:26:06 +1300624 memset(p_cache->p_info, 0, sizeof(*p_cache->p_info) * control_count);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200625 p_cache->cache_size_in_bytes = size_in_bytes;
Eliot Blennerhassett47049982011-02-10 17:26:06 +1300626 p_cache->control_count = control_count;
627 p_cache->p_cache = p_dsp_control_buffer;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200628 p_cache->init = 0;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200629 return p_cache;
630}
631
632void hpi_free_control_cache(struct hpi_control_cache *p_cache)
633{
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300634 if (p_cache) {
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200635 kfree(p_cache->p_info);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200636 kfree(p_cache);
637 }
638}
639
640static void subsys_message(struct hpi_message *phm, struct hpi_response *phr)
641{
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300642 hpi_init_response(phr, HPI_OBJ_SUBSYSTEM, phm->function, 0);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200643
644 switch (phm->function) {
645 case HPI_SUBSYS_OPEN:
646 case HPI_SUBSYS_CLOSE:
647 case HPI_SUBSYS_DRIVER_UNLOAD:
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200648 break;
649 case HPI_SUBSYS_DRIVER_LOAD:
650 wipe_adapter_list();
651 hpios_alistlock_init(&adapters);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200652 break;
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300653 case HPI_SUBSYS_GET_ADAPTER:
654 subsys_get_adapter(phm, phr);
655 break;
656 case HPI_SUBSYS_GET_NUM_ADAPTERS:
657 phr->u.s.num_adapters = adapters.gw_num_adapters;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200658 break;
659 case HPI_SUBSYS_CREATE_ADAPTER:
660 case HPI_SUBSYS_DELETE_ADAPTER:
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200661 break;
662 default:
663 phr->error = HPI_ERROR_INVALID_FUNC;
664 break;
665 }
666}
667
668void HPI_COMMON(struct hpi_message *phm, struct hpi_response *phr)
669{
670 switch (phm->type) {
671 case HPI_TYPE_MESSAGE:
672 switch (phm->object) {
673 case HPI_OBJ_SUBSYSTEM:
674 subsys_message(phm, phr);
675 break;
676 }
677 break;
678
679 default:
680 phr->error = HPI_ERROR_INVALID_TYPE;
681 break;
682 }
683}