Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/djm/tmem
[pandora-kernel.git] / sound / pci / asihpi / hpicmn.c
1 /******************************************************************************
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"
29 #include "hpimsginit.h"
30
31 #include "hpicmn.h"
32
33 struct hpi_adapters_list {
34         struct hpios_spinlock list_lock;
35         struct hpi_adapter_obj adapter[HPI_MAX_ADAPTERS];
36         u16 gw_num_adapters;
37 };
38
39 static struct hpi_adapters_list adapters;
40
41 /**
42 * Given an HPI Message that was sent out and a response that was received,
43 * validate that the response has the correct fields filled in,
44 * i.e ObjectType, Function etc
45 **/
46 u16 hpi_validate_response(struct hpi_message *phm, struct hpi_response *phr)
47 {
48         if (phr->type != HPI_TYPE_RESPONSE) {
49                 HPI_DEBUG_LOG(ERROR, "header type %d invalid\n", phr->type);
50                 return HPI_ERROR_INVALID_RESPONSE;
51         }
52
53         if (phr->object != phm->object) {
54                 HPI_DEBUG_LOG(ERROR, "header object %d invalid\n",
55                         phr->object);
56                 return HPI_ERROR_INVALID_RESPONSE;
57         }
58
59         if (phr->function != phm->function) {
60                 HPI_DEBUG_LOG(ERROR, "header type %d invalid\n",
61                         phr->function);
62                 return HPI_ERROR_INVALID_RESPONSE;
63         }
64
65         return 0;
66 }
67
68 u16 hpi_add_adapter(struct hpi_adapter_obj *pao)
69 {
70         u16 retval = 0;
71         /*HPI_ASSERT(pao->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                 int a;
82                 for (a = HPI_MAX_ADAPTERS - 1; a >= 0; a--) {
83                         if (!adapters.adapter[a].adapter_type) {
84                                 HPI_DEBUG_LOG(WARNING,
85                                         "ASI%X duplicate index %d moved to %d\n",
86                                         pao->adapter_type, pao->index, a);
87                                 pao->index = a;
88                                 break;
89                         }
90                 }
91                 if (a < 0) {
92                         retval = HPI_ERROR_DUPLICATE_ADAPTER_NUMBER;
93                         goto unlock;
94                 }
95         }
96         adapters.adapter[pao->index] = *pao;
97         hpios_dsplock_init(&adapters.adapter[pao->index]);
98         adapters.gw_num_adapters++;
99
100 unlock:
101         hpios_alistlock_unlock(&adapters);
102         return retval;
103 }
104
105 void hpi_delete_adapter(struct hpi_adapter_obj *pao)
106 {
107         if (!pao->adapter_type) {
108                 HPI_DEBUG_LOG(ERROR, "removing null adapter?\n");
109                 return;
110         }
111
112         hpios_alistlock_lock(&adapters);
113         if (adapters.adapter[pao->index].adapter_type)
114                 adapters.gw_num_adapters--;
115         memset(&adapters.adapter[pao->index], 0, sizeof(adapters.adapter[0]));
116         hpios_alistlock_unlock(&adapters);
117 }
118
119 /**
120 * FindAdapter returns a pointer to the struct hpi_adapter_obj with
121 * index wAdapterIndex in an HPI_ADAPTERS_LIST structure.
122 *
123 */
124 struct hpi_adapter_obj *hpi_find_adapter(u16 adapter_index)
125 {
126         struct hpi_adapter_obj *pao = NULL;
127
128         if (adapter_index >= HPI_MAX_ADAPTERS) {
129                 HPI_DEBUG_LOG(VERBOSE, "find_adapter invalid index %d\n",
130                         adapter_index);
131                 return NULL;
132         }
133
134         pao = &adapters.adapter[adapter_index];
135         if (pao->adapter_type != 0) {
136                 /*
137                    HPI_DEBUG_LOG(VERBOSE, "Found adapter index %d\n",
138                    wAdapterIndex);
139                  */
140                 return pao;
141         } else {
142                 /*
143                    HPI_DEBUG_LOG(VERBOSE, "No adapter index %d\n",
144                    wAdapterIndex);
145                  */
146                 return NULL;
147         }
148 }
149
150 /**
151 *
152 * wipe an HPI_ADAPTERS_LIST structure.
153 *
154 **/
155 static void wipe_adapter_list(void)
156 {
157         memset(&adapters, 0, sizeof(adapters));
158 }
159
160 static void subsys_get_adapter(struct hpi_message *phm,
161         struct hpi_response *phr)
162 {
163         int count = phm->obj_index;
164         u16 index = 0;
165
166         /* find the nCount'th nonzero adapter in array */
167         for (index = 0; index < HPI_MAX_ADAPTERS; index++) {
168                 if (adapters.adapter[index].adapter_type) {
169                         if (!count)
170                                 break;
171                         count--;
172                 }
173         }
174
175         if (index < HPI_MAX_ADAPTERS) {
176                 phr->u.s.adapter_index = adapters.adapter[index].index;
177                 phr->u.s.adapter_type = adapters.adapter[index].adapter_type;
178         } else {
179                 phr->u.s.adapter_index = 0;
180                 phr->u.s.adapter_type = 0;
181                 phr->error = HPI_ERROR_BAD_ADAPTER_NUMBER;
182         }
183 }
184
185 static unsigned int control_cache_alloc_check(struct hpi_control_cache *pC)
186 {
187         unsigned int i;
188         int cached = 0;
189         if (!pC)
190                 return 0;
191
192         if (pC->init)
193                 return pC->init;
194
195         if (!pC->p_cache)
196                 return 0;
197
198         if (pC->control_count && pC->cache_size_in_bytes) {
199                 char *p_master_cache;
200                 unsigned int byte_count = 0;
201
202                 p_master_cache = (char *)pC->p_cache;
203                 HPI_DEBUG_LOG(DEBUG, "check %d controls\n",
204                         pC->control_count);
205                 for (i = 0; i < pC->control_count; i++) {
206                         struct hpi_control_cache_info *info =
207                                 (struct hpi_control_cache_info *)
208                                 &p_master_cache[byte_count];
209
210                         if (!info->size_in32bit_words) {
211                                 if (!i) {
212                                         HPI_DEBUG_LOG(INFO,
213                                                 "adap %d cache not ready?\n",
214                                                 pC->adap_idx);
215                                         return 0;
216                                 }
217                                 /* The cache is invalid.
218                                  * Minimum valid entry size is
219                                  * sizeof(struct hpi_control_cache_info)
220                                  */
221                                 HPI_DEBUG_LOG(ERROR,
222                                         "adap %d zero size cache entry %d\n",
223                                         pC->adap_idx, i);
224                                 break;
225                         }
226
227                         if (info->control_type) {
228                                 pC->p_info[info->control_index] = info;
229                                 cached++;
230                         } else {        /* dummy cache entry */
231                                 pC->p_info[info->control_index] = NULL;
232                         }
233
234                         byte_count += info->size_in32bit_words * 4;
235
236                         HPI_DEBUG_LOG(VERBOSE,
237                                 "cached %d, pinfo %p index %d type %d size %d\n",
238                                 cached, pC->p_info[info->control_index],
239                                 info->control_index, info->control_type,
240                                 info->size_in32bit_words);
241
242                         /* quit loop early if whole cache has been scanned.
243                          * dwControlCount is the maximum possible entries
244                          * but some may be absent from the cache
245                          */
246                         if (byte_count >= pC->cache_size_in_bytes)
247                                 break;
248                         /* have seen last control index */
249                         if (info->control_index == pC->control_count - 1)
250                                 break;
251                 }
252
253                 if (byte_count != pC->cache_size_in_bytes)
254                         HPI_DEBUG_LOG(WARNING,
255                                 "adap %d bytecount %d != cache size %d\n",
256                                 pC->adap_idx, byte_count,
257                                 pC->cache_size_in_bytes);
258                 else
259                         HPI_DEBUG_LOG(DEBUG,
260                                 "adap %d cache good, bytecount == cache size = %d\n",
261                                 pC->adap_idx, byte_count);
262
263                 pC->init = (u16)cached;
264         }
265         return pC->init;
266 }
267
268 /** Find a control.
269 */
270 static short find_control(u16 control_index,
271         struct hpi_control_cache *p_cache, struct hpi_control_cache_info **pI)
272 {
273         if (!control_cache_alloc_check(p_cache)) {
274                 HPI_DEBUG_LOG(VERBOSE,
275                         "control_cache_alloc_check() failed %d\n",
276                         control_index);
277                 return 0;
278         }
279
280         *pI = p_cache->p_info[control_index];
281         if (!*pI) {
282                 HPI_DEBUG_LOG(VERBOSE, "Uncached Control %d\n",
283                         control_index);
284                 return 0;
285         } else {
286                 HPI_DEBUG_LOG(VERBOSE, "find_control() type %d\n",
287                         (*pI)->control_type);
288         }
289         return 1;
290 }
291
292 /* allow unified treatment of several string fields within struct */
293 #define HPICMN_PAD_OFS_AND_SIZE(m)  {\
294         offsetof(struct hpi_control_cache_pad, m), \
295         sizeof(((struct hpi_control_cache_pad *)(NULL))->m) }
296
297 struct pad_ofs_size {
298         unsigned int offset;
299         unsigned int field_size;
300 };
301
302 static const struct pad_ofs_size pad_desc[] = {
303         HPICMN_PAD_OFS_AND_SIZE(c_channel),     /* HPI_PAD_CHANNEL_NAME */
304         HPICMN_PAD_OFS_AND_SIZE(c_artist),      /* HPI_PAD_ARTIST */
305         HPICMN_PAD_OFS_AND_SIZE(c_title),       /* HPI_PAD_TITLE */
306         HPICMN_PAD_OFS_AND_SIZE(c_comment),     /* HPI_PAD_COMMENT */
307 };
308
309 /** CheckControlCache checks the cache and fills the struct hpi_response
310  * accordingly. It returns one if a cache hit occurred, zero otherwise.
311  */
312 short hpi_check_control_cache(struct hpi_control_cache *p_cache,
313         struct hpi_message *phm, struct hpi_response *phr)
314 {
315         short found = 1;
316         struct hpi_control_cache_info *pI;
317         struct hpi_control_cache_single *pC;
318         struct hpi_control_cache_pad *p_pad;
319
320         if (!find_control(phm->obj_index, p_cache, &pI)) {
321                 HPI_DEBUG_LOG(VERBOSE,
322                         "HPICMN find_control() failed for adap %d\n",
323                         phm->adapter_index);
324                 return 0;
325         }
326
327         phr->error = 0;
328
329         /* pC is the default cached control strucure. May be cast to
330            something else in the following switch statement.
331          */
332         pC = (struct hpi_control_cache_single *)pI;
333         p_pad = (struct hpi_control_cache_pad *)pI;
334
335         switch (pI->control_type) {
336
337         case HPI_CONTROL_METER:
338                 if (phm->u.c.attribute == HPI_METER_PEAK) {
339                         phr->u.c.an_log_value[0] = pC->u.meter.an_log_peak[0];
340                         phr->u.c.an_log_value[1] = pC->u.meter.an_log_peak[1];
341                 } else if (phm->u.c.attribute == HPI_METER_RMS) {
342                         if (pC->u.meter.an_logRMS[0] ==
343                                 HPI_CACHE_INVALID_SHORT) {
344                                 phr->error =
345                                         HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
346                                 phr->u.c.an_log_value[0] = HPI_METER_MINIMUM;
347                                 phr->u.c.an_log_value[1] = HPI_METER_MINIMUM;
348                         } else {
349                                 phr->u.c.an_log_value[0] =
350                                         pC->u.meter.an_logRMS[0];
351                                 phr->u.c.an_log_value[1] =
352                                         pC->u.meter.an_logRMS[1];
353                         }
354                 } else
355                         found = 0;
356                 break;
357         case HPI_CONTROL_VOLUME:
358                 if (phm->u.c.attribute == HPI_VOLUME_GAIN) {
359                         phr->u.c.an_log_value[0] = pC->u.vol.an_log[0];
360                         phr->u.c.an_log_value[1] = pC->u.vol.an_log[1];
361                 } else if (phm->u.c.attribute == HPI_VOLUME_MUTE) {
362                         if (pC->u.vol.flags & HPI_VOLUME_FLAG_HAS_MUTE) {
363                                 if (pC->u.vol.flags & HPI_VOLUME_FLAG_MUTED)
364                                         phr->u.c.param1 =
365                                                 HPI_BITMASK_ALL_CHANNELS;
366                                 else
367                                         phr->u.c.param1 = 0;
368                         } else {
369                                 phr->error =
370                                         HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
371                                 phr->u.c.param1 = 0;
372                         }
373                 } else {
374                         found = 0;
375                 }
376                 break;
377         case HPI_CONTROL_MULTIPLEXER:
378                 if (phm->u.c.attribute == HPI_MULTIPLEXER_SOURCE) {
379                         phr->u.c.param1 = pC->u.mux.source_node_type;
380                         phr->u.c.param2 = pC->u.mux.source_node_index;
381                 } else {
382                         found = 0;
383                 }
384                 break;
385         case HPI_CONTROL_CHANNEL_MODE:
386                 if (phm->u.c.attribute == HPI_CHANNEL_MODE_MODE)
387                         phr->u.c.param1 = pC->u.mode.mode;
388                 else
389                         found = 0;
390                 break;
391         case HPI_CONTROL_LEVEL:
392                 if (phm->u.c.attribute == HPI_LEVEL_GAIN) {
393                         phr->u.c.an_log_value[0] = pC->u.level.an_log[0];
394                         phr->u.c.an_log_value[1] = pC->u.level.an_log[1];
395                 } else
396                         found = 0;
397                 break;
398         case HPI_CONTROL_TUNER:
399                 if (phm->u.c.attribute == HPI_TUNER_FREQ)
400                         phr->u.c.param1 = pC->u.tuner.freq_ink_hz;
401                 else if (phm->u.c.attribute == HPI_TUNER_BAND)
402                         phr->u.c.param1 = pC->u.tuner.band;
403                 else if (phm->u.c.attribute == HPI_TUNER_LEVEL_AVG)
404                         if (pC->u.tuner.s_level_avg ==
405                                 HPI_CACHE_INVALID_SHORT) {
406                                 phr->u.cu.tuner.s_level = 0;
407                                 phr->error =
408                                         HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
409                         } else
410                                 phr->u.cu.tuner.s_level =
411                                         pC->u.tuner.s_level_avg;
412                 else
413                         found = 0;
414                 break;
415         case HPI_CONTROL_AESEBU_RECEIVER:
416                 if (phm->u.c.attribute == HPI_AESEBURX_ERRORSTATUS)
417                         phr->u.c.param1 = pC->u.aes3rx.error_status;
418                 else if (phm->u.c.attribute == HPI_AESEBURX_FORMAT)
419                         phr->u.c.param1 = pC->u.aes3rx.format;
420                 else
421                         found = 0;
422                 break;
423         case HPI_CONTROL_AESEBU_TRANSMITTER:
424                 if (phm->u.c.attribute == HPI_AESEBUTX_FORMAT)
425                         phr->u.c.param1 = pC->u.aes3tx.format;
426                 else
427                         found = 0;
428                 break;
429         case HPI_CONTROL_TONEDETECTOR:
430                 if (phm->u.c.attribute == HPI_TONEDETECTOR_STATE)
431                         phr->u.c.param1 = pC->u.tone.state;
432                 else
433                         found = 0;
434                 break;
435         case HPI_CONTROL_SILENCEDETECTOR:
436                 if (phm->u.c.attribute == HPI_SILENCEDETECTOR_STATE) {
437                         phr->u.c.param1 = pC->u.silence.state;
438                 } else
439                         found = 0;
440                 break;
441         case HPI_CONTROL_MICROPHONE:
442                 if (phm->u.c.attribute == HPI_MICROPHONE_PHANTOM_POWER)
443                         phr->u.c.param1 = pC->u.microphone.phantom_state;
444                 else
445                         found = 0;
446                 break;
447         case HPI_CONTROL_SAMPLECLOCK:
448                 if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE)
449                         phr->u.c.param1 = pC->u.clk.source;
450                 else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE_INDEX) {
451                         if (pC->u.clk.source_index ==
452                                 HPI_CACHE_INVALID_UINT16) {
453                                 phr->u.c.param1 = 0;
454                                 phr->error =
455                                         HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
456                         } else
457                                 phr->u.c.param1 = pC->u.clk.source_index;
458                 } else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SAMPLERATE)
459                         phr->u.c.param1 = pC->u.clk.sample_rate;
460                 else
461                         found = 0;
462                 break;
463         case HPI_CONTROL_PAD:{
464                         struct hpi_control_cache_pad *p_pad;
465                         p_pad = (struct hpi_control_cache_pad *)pI;
466
467                         if (!(p_pad->field_valid_flags & (1 <<
468                                                 HPI_CTL_ATTR_INDEX(phm->u.c.
469                                                         attribute)))) {
470                                 phr->error =
471                                         HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
472                                 break;
473                         }
474
475                         if (phm->u.c.attribute == HPI_PAD_PROGRAM_ID)
476                                 phr->u.c.param1 = p_pad->pI;
477                         else if (phm->u.c.attribute == HPI_PAD_PROGRAM_TYPE)
478                                 phr->u.c.param1 = p_pad->pTY;
479                         else {
480                                 unsigned int index =
481                                         HPI_CTL_ATTR_INDEX(phm->u.c.
482                                         attribute) - 1;
483                                 unsigned int offset = phm->u.c.param1;
484                                 unsigned int pad_string_len, field_size;
485                                 char *pad_string;
486                                 unsigned int tocopy;
487
488                                 if (index > ARRAY_SIZE(pad_desc) - 1) {
489                                         phr->error =
490                                                 HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
491                                         break;
492                                 }
493
494                                 pad_string =
495                                         ((char *)p_pad) +
496                                         pad_desc[index].offset;
497                                 field_size = pad_desc[index].field_size;
498                                 /* Ensure null terminator */
499                                 pad_string[field_size - 1] = 0;
500
501                                 pad_string_len = strlen(pad_string) + 1;
502
503                                 if (offset > pad_string_len) {
504                                         phr->error =
505                                                 HPI_ERROR_INVALID_CONTROL_VALUE;
506                                         break;
507                                 }
508
509                                 tocopy = pad_string_len - offset;
510                                 if (tocopy > sizeof(phr->u.cu.chars8.sz_data))
511                                         tocopy = sizeof(phr->u.cu.chars8.
512                                                 sz_data);
513
514                                 memcpy(phr->u.cu.chars8.sz_data,
515                                         &pad_string[offset], tocopy);
516
517                                 phr->u.cu.chars8.remaining_chars =
518                                         pad_string_len - offset - tocopy;
519                         }
520                 }
521                 break;
522         default:
523                 found = 0;
524                 break;
525         }
526
527         HPI_DEBUG_LOG(VERBOSE, "%s Adap %d, Ctl %d, Type %d, Attr %d\n",
528                 found ? "Cached" : "Uncached", phm->adapter_index,
529                 pI->control_index, pI->control_type, phm->u.c.attribute);
530
531         if (found)
532                 phr->size =
533                         sizeof(struct hpi_response_header) +
534                         sizeof(struct hpi_control_res);
535
536         return found;
537 }
538
539 /** Updates the cache with Set values.
540
541 Only update if no error.
542 Volume and Level return the limited values in the response, so use these
543 Multiplexer does so use sent values
544 */
545 void hpi_cmn_control_cache_sync_to_msg(struct hpi_control_cache *p_cache,
546         struct hpi_message *phm, struct hpi_response *phr)
547 {
548         struct hpi_control_cache_single *pC;
549         struct hpi_control_cache_info *pI;
550
551         if (phr->error)
552                 return;
553
554         if (!find_control(phm->obj_index, p_cache, &pI)) {
555                 HPI_DEBUG_LOG(VERBOSE,
556                         "HPICMN find_control() failed for adap %d\n",
557                         phm->adapter_index);
558                 return;
559         }
560
561         /* pC is the default cached control strucure.
562            May be cast to something else in the following switch statement.
563          */
564         pC = (struct hpi_control_cache_single *)pI;
565
566         switch (pI->control_type) {
567         case HPI_CONTROL_VOLUME:
568                 if (phm->u.c.attribute == HPI_VOLUME_GAIN) {
569                         pC->u.vol.an_log[0] = phr->u.c.an_log_value[0];
570                         pC->u.vol.an_log[1] = phr->u.c.an_log_value[1];
571                 } else if (phm->u.c.attribute == HPI_VOLUME_MUTE) {
572                         if (phm->u.c.param1)
573                                 pC->u.vol.flags |= HPI_VOLUME_FLAG_MUTED;
574                         else
575                                 pC->u.vol.flags &= ~HPI_VOLUME_FLAG_MUTED;
576                 }
577                 break;
578         case HPI_CONTROL_MULTIPLEXER:
579                 /* mux does not return its setting on Set command. */
580                 if (phm->u.c.attribute == HPI_MULTIPLEXER_SOURCE) {
581                         pC->u.mux.source_node_type = (u16)phm->u.c.param1;
582                         pC->u.mux.source_node_index = (u16)phm->u.c.param2;
583                 }
584                 break;
585         case HPI_CONTROL_CHANNEL_MODE:
586                 /* mode does not return its setting on Set command. */
587                 if (phm->u.c.attribute == HPI_CHANNEL_MODE_MODE)
588                         pC->u.mode.mode = (u16)phm->u.c.param1;
589                 break;
590         case HPI_CONTROL_LEVEL:
591                 if (phm->u.c.attribute == HPI_LEVEL_GAIN) {
592                         pC->u.vol.an_log[0] = phr->u.c.an_log_value[0];
593                         pC->u.vol.an_log[1] = phr->u.c.an_log_value[1];
594                 }
595                 break;
596         case HPI_CONTROL_MICROPHONE:
597                 if (phm->u.c.attribute == HPI_MICROPHONE_PHANTOM_POWER)
598                         pC->u.microphone.phantom_state = (u16)phm->u.c.param1;
599                 break;
600         case HPI_CONTROL_AESEBU_TRANSMITTER:
601                 if (phm->u.c.attribute == HPI_AESEBUTX_FORMAT)
602                         pC->u.aes3tx.format = phm->u.c.param1;
603                 break;
604         case HPI_CONTROL_AESEBU_RECEIVER:
605                 if (phm->u.c.attribute == HPI_AESEBURX_FORMAT)
606                         pC->u.aes3rx.format = phm->u.c.param1;
607                 break;
608         case HPI_CONTROL_SAMPLECLOCK:
609                 if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE)
610                         pC->u.clk.source = (u16)phm->u.c.param1;
611                 else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE_INDEX)
612                         pC->u.clk.source_index = (u16)phm->u.c.param1;
613                 else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SAMPLERATE)
614                         pC->u.clk.sample_rate = phm->u.c.param1;
615                 break;
616         default:
617                 break;
618         }
619 }
620
621 /** Allocate control cache.
622
623 \return Cache pointer, or NULL if allocation fails.
624 */
625 struct hpi_control_cache *hpi_alloc_control_cache(const u32 control_count,
626         const u32 size_in_bytes, u8 *p_dsp_control_buffer)
627 {
628         struct hpi_control_cache *p_cache =
629                 kmalloc(sizeof(*p_cache), GFP_KERNEL);
630         if (!p_cache)
631                 return NULL;
632
633         p_cache->p_info =
634                 kmalloc(sizeof(*p_cache->p_info) * control_count, GFP_KERNEL);
635         if (!p_cache->p_info) {
636                 kfree(p_cache);
637                 return NULL;
638         }
639         memset(p_cache->p_info, 0, sizeof(*p_cache->p_info) * control_count);
640         p_cache->cache_size_in_bytes = size_in_bytes;
641         p_cache->control_count = control_count;
642         p_cache->p_cache = p_dsp_control_buffer;
643         p_cache->init = 0;
644         return p_cache;
645 }
646
647 void hpi_free_control_cache(struct hpi_control_cache *p_cache)
648 {
649         if (p_cache) {
650                 kfree(p_cache->p_info);
651                 kfree(p_cache);
652         }
653 }
654
655 static void subsys_message(struct hpi_message *phm, struct hpi_response *phr)
656 {
657         hpi_init_response(phr, HPI_OBJ_SUBSYSTEM, phm->function, 0);
658
659         switch (phm->function) {
660         case HPI_SUBSYS_OPEN:
661         case HPI_SUBSYS_CLOSE:
662         case HPI_SUBSYS_DRIVER_UNLOAD:
663                 break;
664         case HPI_SUBSYS_DRIVER_LOAD:
665                 wipe_adapter_list();
666                 hpios_alistlock_init(&adapters);
667                 break;
668         case HPI_SUBSYS_GET_ADAPTER:
669                 subsys_get_adapter(phm, phr);
670                 break;
671         case HPI_SUBSYS_GET_NUM_ADAPTERS:
672                 phr->u.s.num_adapters = adapters.gw_num_adapters;
673                 break;
674         case HPI_SUBSYS_CREATE_ADAPTER:
675                 break;
676         default:
677                 phr->error = HPI_ERROR_INVALID_FUNC;
678                 break;
679         }
680 }
681
682 void HPI_COMMON(struct hpi_message *phm, struct hpi_response *phr)
683 {
684         switch (phm->type) {
685         case HPI_TYPE_MESSAGE:
686                 switch (phm->object) {
687                 case HPI_OBJ_SUBSYSTEM:
688                         subsys_message(phm, phr);
689                         break;
690                 }
691                 break;
692
693         default:
694                 phr->error = HPI_ERROR_INVALID_TYPE;
695                 break;
696         }
697 }