linux/sound/pci/asihpi/hpicmn.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/******************************************************************************
   3
   4    AudioScience HPI driver
   5    Copyright (C) 1997-2014  AudioScience Inc. <support@audioscience.com>
   6
   7
   8\file hpicmn.c
   9
  10 Common functions used by hpixxxx.c modules
  11
  12(C) Copyright AudioScience Inc. 1998-2003
  13*******************************************************************************/
  14#define SOURCEFILE_NAME "hpicmn.c"
  15
  16#include "hpi_internal.h"
  17#include "hpidebug.h"
  18#include "hpimsginit.h"
  19
  20#include "hpicmn.h"
  21
  22struct hpi_adapters_list {
  23        struct hpios_spinlock list_lock;
  24        struct hpi_adapter_obj adapter[HPI_MAX_ADAPTERS];
  25        u16 gw_num_adapters;
  26};
  27
  28static struct hpi_adapters_list adapters;
  29
  30/**
  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
  34 * @phm: message
  35 * @phr: response
  36 */
  37u16 hpi_validate_response(struct hpi_message *phm, struct hpi_response *phr)
  38{
  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;
  42        }
  43
  44        if (phr->object != phm->object) {
  45                HPI_DEBUG_LOG(ERROR, "header object %d invalid\n",
  46                        phr->object);
  47                return HPI_ERROR_INVALID_RESPONSE;
  48        }
  49
  50        if (phr->function != phm->function) {
  51                HPI_DEBUG_LOG(ERROR, "header function %d invalid\n",
  52                        phr->function);
  53                return HPI_ERROR_INVALID_RESPONSE;
  54        }
  55
  56        return 0;
  57}
  58
  59u16 hpi_add_adapter(struct hpi_adapter_obj *pao)
  60{
  61        u16 retval = 0;
  62        /*HPI_ASSERT(pao->type); */
  63
  64        hpios_alistlock_lock(&adapters);
  65
  66        if (pao->index >= HPI_MAX_ADAPTERS) {
  67                retval = HPI_ERROR_BAD_ADAPTER_NUMBER;
  68                goto unlock;
  69        }
  70
  71        if (adapters.adapter[pao->index].type) {
  72                int a;
  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);
  78                                pao->index = a;
  79                                break;
  80                        }
  81                }
  82                if (a < 0) {
  83                        retval = HPI_ERROR_DUPLICATE_ADAPTER_NUMBER;
  84                        goto unlock;
  85                }
  86        }
  87        adapters.adapter[pao->index] = *pao;
  88        hpios_dsplock_init(&adapters.adapter[pao->index]);
  89        adapters.gw_num_adapters++;
  90
  91unlock:
  92        hpios_alistlock_unlock(&adapters);
  93        return retval;
  94}
  95
  96void hpi_delete_adapter(struct hpi_adapter_obj *pao)
  97{
  98        if (!pao->type) {
  99                HPI_DEBUG_LOG(ERROR, "removing null adapter?\n");
 100                return;
 101        }
 102
 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);
 108}
 109
 110/**
 111 * hpi_find_adapter - FindAdapter returns a pointer to the struct
 112 * hpi_adapter_obj with index wAdapterIndex in an HPI_ADAPTERS_LIST
 113 * structure.
 114 * @adapter_index: value in [0, HPI_MAX_ADAPTERS[
 115 */
 116struct hpi_adapter_obj *hpi_find_adapter(u16 adapter_index)
 117{
 118        struct hpi_adapter_obj *pao = NULL;
 119
 120        if (adapter_index >= HPI_MAX_ADAPTERS) {
 121                HPI_DEBUG_LOG(VERBOSE, "find_adapter invalid index %d\n",
 122                        adapter_index);
 123                return NULL;
 124        }
 125
 126        pao = &adapters.adapter[adapter_index];
 127        if (pao->type != 0) {
 128                /*
 129                   HPI_DEBUG_LOG(VERBOSE, "Found adapter index %d\n",
 130                   wAdapterIndex);
 131                 */
 132                return pao;
 133        } else {
 134                /*
 135                   HPI_DEBUG_LOG(VERBOSE, "No adapter index %d\n",
 136                   wAdapterIndex);
 137                 */
 138                return NULL;
 139        }
 140}
 141
 142/**
 143 * wipe_adapter_list - wipe an HPI_ADAPTERS_LIST structure.
 144 *
 145 */
 146static void wipe_adapter_list(void)
 147{
 148        memset(&adapters, 0, sizeof(adapters));
 149}
 150
 151static void subsys_get_adapter(struct hpi_message *phm,
 152        struct hpi_response *phr)
 153{
 154        int count = phm->obj_index;
 155        u16 index = 0;
 156
 157        /* find the nCount'th nonzero adapter in array */
 158        for (index = 0; index < HPI_MAX_ADAPTERS; index++) {
 159                if (adapters.adapter[index].type) {
 160                        if (!count)
 161                                break;
 162                        count--;
 163                }
 164        }
 165
 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;
 169        } else {
 170                phr->u.s.adapter_index = 0;
 171                phr->u.s.adapter_type = 0;
 172                phr->error = HPI_ERROR_INVALID_OBJ_INDEX;
 173        }
 174}
 175
 176static unsigned int control_cache_alloc_check(struct hpi_control_cache *pC)
 177{
 178        unsigned int i;
 179        int cached = 0;
 180        if (!pC)
 181                return 0;
 182
 183        if (pC->init)
 184                return pC->init;
 185
 186        if (!pC->p_cache)
 187                return 0;
 188
 189        if (pC->control_count && pC->cache_size_in_bytes) {
 190                char *p_master_cache;
 191                unsigned int byte_count = 0;
 192
 193                p_master_cache = (char *)pC->p_cache;
 194                HPI_DEBUG_LOG(DEBUG, "check %d controls\n",
 195                        pC->control_count);
 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;
 201
 202                        if (control_index >= pC->control_count) {
 203                                HPI_DEBUG_LOG(INFO,
 204                                        "adap %d control index %d out of range, cache not ready?\n",
 205                                        pC->adap_idx, control_index);
 206                                return 0;
 207                        }
 208
 209                        if (!info->size_in32bit_words) {
 210                                if (!i) {
 211                                        HPI_DEBUG_LOG(INFO,
 212                                                "adap %d cache not ready?\n",
 213                                                pC->adap_idx);
 214                                        return 0;
 215                                }
 216                                /* The cache is invalid.
 217                                 * Minimum valid entry size is
 218                                 * sizeof(struct hpi_control_cache_info)
 219                                 */
 220                                HPI_DEBUG_LOG(ERROR,
 221                                        "adap %d zero size cache entry %d\n",
 222                                        pC->adap_idx, i);
 223                                break;
 224                        }
 225
 226                        if (info->control_type) {
 227                                pC->p_info[control_index] = info;
 228                                cached++;
 229                        } else {        /* dummy cache entry */
 230                                pC->p_info[control_index] = NULL;
 231                        }
 232
 233                        byte_count += info->size_in32bit_words * 4;
 234
 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);
 240
 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
 244                         */
 245                        if (byte_count >= pC->cache_size_in_bytes)
 246                                break;
 247                        /* have seen last control index */
 248                        if (info->control_index == pC->control_count - 1)
 249                                break;
 250                }
 251
 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);
 257                else
 258                        HPI_DEBUG_LOG(DEBUG,
 259                                "adap %d cache good, bytecount == cache size = %d\n",
 260                                pC->adap_idx, byte_count);
 261
 262                pC->init = (u16)cached;
 263        }
 264        return pC->init;
 265}
 266
 267/** Find a control.
 268*/
 269static short find_control(u16 control_index,
 270        struct hpi_control_cache *p_cache, struct hpi_control_cache_info **pI)
 271{
 272        if (!control_cache_alloc_check(p_cache)) {
 273                HPI_DEBUG_LOG(VERBOSE,
 274                        "control_cache_alloc_check() failed %d\n",
 275                        control_index);
 276                return 0;
 277        }
 278
 279        *pI = p_cache->p_info[control_index];
 280        if (!*pI) {
 281                HPI_DEBUG_LOG(VERBOSE, "Uncached Control %d\n",
 282                        control_index);
 283                return 0;
 284        } else {
 285                HPI_DEBUG_LOG(VERBOSE, "find_control() type %d\n",
 286                        (*pI)->control_type);
 287        }
 288        return 1;
 289}
 290
 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) }
 295
 296struct pad_ofs_size {
 297        unsigned int offset;
 298        unsigned int field_size;
 299};
 300
 301static 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 */
 306};
 307
 308/** CheckControlCache checks the cache and fills the struct hpi_response
 309 * accordingly. It returns one if a cache hit occurred, zero otherwise.
 310 */
 311short hpi_check_control_cache_single(struct hpi_control_cache_single *pC,
 312        struct hpi_message *phm, struct hpi_response *phr)
 313{
 314        size_t response_size;
 315        short found = 1;
 316
 317        /* set the default response size */
 318        response_size =
 319                sizeof(struct hpi_response_header) +
 320                sizeof(struct hpi_control_res);
 321
 322        switch (pC->u.i.control_type) {
 323
 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) {
 331                                phr->error =
 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;
 335                        } else {
 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];
 340                        }
 341                } else
 342                        found = 0;
 343                break;
 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)
 351                                        phr->u.c.param1 =
 352                                                HPI_BITMASK_ALL_CHANNELS;
 353                                else
 354                                        phr->u.c.param1 = 0;
 355                        } else {
 356                                phr->error =
 357                                        HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
 358                                phr->u.c.param1 = 0;
 359                        }
 360                } else {
 361                        found = 0;
 362                }
 363                break;
 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;
 368                } else {
 369                        found = 0;
 370                }
 371                break;
 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;
 375                else
 376                        found = 0;
 377                break;
 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];
 382                } else
 383                        found = 0;
 384                break;
 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;
 394                                phr->error =
 395                                        HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
 396                        } else
 397                                phr->u.cu.tuner.s_level =
 398                                        pC->u.tuner.s_level_avg;
 399                else
 400                        found = 0;
 401                break;
 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;
 407                else
 408                        found = 0;
 409                break;
 410        case HPI_CONTROL_AESEBU_TRANSMITTER:
 411                if (phm->u.c.attribute == HPI_AESEBUTX_FORMAT)
 412                        phr->u.c.param1 = pC->u.aes3tx.format;
 413                else
 414                        found = 0;
 415                break;
 416        case HPI_CONTROL_TONEDETECTOR:
 417                if (phm->u.c.attribute == HPI_TONEDETECTOR_STATE)
 418                        phr->u.c.param1 = pC->u.tone.state;
 419                else
 420                        found = 0;
 421                break;
 422        case HPI_CONTROL_SILENCEDETECTOR:
 423                if (phm->u.c.attribute == HPI_SILENCEDETECTOR_STATE) {
 424                        phr->u.c.param1 = pC->u.silence.state;
 425                } else
 426                        found = 0;
 427                break;
 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;
 431                else
 432                        found = 0;
 433                break;
 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) {
 440                                phr->u.c.param1 = 0;
 441                                phr->error =
 442                                        HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
 443                        } else
 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;
 447                else
 448                        found = 0;
 449                break;
 450        case HPI_CONTROL_PAD:{
 451                        struct hpi_control_cache_pad *p_pad;
 452                        p_pad = (struct hpi_control_cache_pad *)pC;
 453
 454                        if (!(p_pad->field_valid_flags & (1 <<
 455                                                HPI_CTL_ATTR_INDEX(phm->u.c.
 456                                                        attribute)))) {
 457                                phr->error =
 458                                        HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
 459                                break;
 460                        }
 461
 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;
 466                        else {
 467                                unsigned int index =
 468                                        HPI_CTL_ATTR_INDEX(phm->u.c.
 469                                        attribute) - 1;
 470                                unsigned int offset = phm->u.c.param1;
 471                                unsigned int pad_string_len, field_size;
 472                                char *pad_string;
 473                                unsigned int tocopy;
 474
 475                                if (index > ARRAY_SIZE(pad_desc) - 1) {
 476                                        phr->error =
 477                                                HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
 478                                        break;
 479                                }
 480
 481                                pad_string =
 482                                        ((char *)p_pad) +
 483                                        pad_desc[index].offset;
 484                                field_size = pad_desc[index].field_size;
 485                                /* Ensure null terminator */
 486                                pad_string[field_size - 1] = 0;
 487
 488                                pad_string_len = strlen(pad_string) + 1;
 489
 490                                if (offset > pad_string_len) {
 491                                        phr->error =
 492                                                HPI_ERROR_INVALID_CONTROL_VALUE;
 493                                        break;
 494                                }
 495
 496                                tocopy = pad_string_len - offset;
 497                                if (tocopy > sizeof(phr->u.cu.chars8.sz_data))
 498                                        tocopy = sizeof(phr->u.cu.chars8.
 499                                                sz_data);
 500
 501                                memcpy(phr->u.cu.chars8.sz_data,
 502                                        &pad_string[offset], tocopy);
 503
 504                                phr->u.cu.chars8.remaining_chars =
 505                                        pad_string_len - offset - tocopy;
 506                        }
 507                }
 508                break;
 509        default:
 510                found = 0;
 511                break;
 512        }
 513
 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,
 517                phm->u.c.attribute);
 518
 519        if (found) {
 520                phr->size = (u16)response_size;
 521                phr->type = HPI_TYPE_RESPONSE;
 522                phr->object = phm->object;
 523                phr->function = phm->function;
 524        }
 525
 526        return found;
 527}
 528
 529short hpi_check_control_cache(struct hpi_control_cache *p_cache,
 530        struct hpi_message *phm, struct hpi_response *phr)
 531{
 532        struct hpi_control_cache_info *pI;
 533
 534        if (!find_control(phm->obj_index, p_cache, &pI)) {
 535                HPI_DEBUG_LOG(VERBOSE,
 536                        "HPICMN find_control() failed for adap %d\n",
 537                        phm->adapter_index);
 538                return 0;
 539        }
 540
 541        phr->error = 0;
 542        phr->specific_error = 0;
 543        phr->version = 0;
 544
 545        return hpi_check_control_cache_single((struct hpi_control_cache_single
 546                        *)pI, phm, phr);
 547}
 548
 549/** Updates the cache with Set values.
 550
 551Only update if no error.
 552Volume and Level return the limited values in the response, so use these
 553Multiplexer does so use sent values
 554*/
 555void hpi_cmn_control_cache_sync_to_msg_single(struct hpi_control_cache_single
 556        *pC, struct hpi_message *phm, struct hpi_response *phr)
 557{
 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) {
 564                        if (phm->u.c.param1)
 565                                pC->u.vol.flags |= HPI_VOLUME_FLAG_MUTED;
 566                        else
 567                                pC->u.vol.flags &= ~HPI_VOLUME_FLAG_MUTED;
 568                }
 569                break;
 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;
 575                }
 576                break;
 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;
 581                break;
 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];
 586                }
 587                break;
 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;
 591                break;
 592        case HPI_CONTROL_AESEBU_TRANSMITTER:
 593                if (phm->u.c.attribute == HPI_AESEBUTX_FORMAT)
 594                        pC->u.aes3tx.format = phm->u.c.param1;
 595                break;
 596        case HPI_CONTROL_AESEBU_RECEIVER:
 597                if (phm->u.c.attribute == HPI_AESEBURX_FORMAT)
 598                        pC->u.aes3rx.format = phm->u.c.param1;
 599                break;
 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;
 607                break;
 608        default:
 609                break;
 610        }
 611}
 612
 613void hpi_cmn_control_cache_sync_to_msg(struct hpi_control_cache *p_cache,
 614        struct hpi_message *phm, struct hpi_response *phr)
 615{
 616        struct hpi_control_cache_single *pC;
 617        struct hpi_control_cache_info *pI;
 618
 619        if (phr->error)
 620                return;
 621
 622        if (!find_control(phm->obj_index, p_cache, &pI)) {
 623                HPI_DEBUG_LOG(VERBOSE,
 624                        "HPICMN find_control() failed for adap %d\n",
 625                        phm->adapter_index);
 626                return;
 627        }
 628
 629        /* pC is the default cached control strucure.
 630           May be cast to something else in the following switch statement.
 631         */
 632        pC = (struct hpi_control_cache_single *)pI;
 633
 634        hpi_cmn_control_cache_sync_to_msg_single(pC, phm, phr);
 635}
 636
 637/** Allocate control cache.
 638
 639\return Cache pointer, or NULL if allocation fails.
 640*/
 641struct hpi_control_cache *hpi_alloc_control_cache(const u32 control_count,
 642        const u32 size_in_bytes, u8 *p_dsp_control_buffer)
 643{
 644        struct hpi_control_cache *p_cache =
 645                kmalloc(sizeof(*p_cache), GFP_KERNEL);
 646        if (!p_cache)
 647                return NULL;
 648
 649        p_cache->p_info =
 650                kcalloc(control_count, sizeof(*p_cache->p_info), GFP_KERNEL);
 651        if (!p_cache->p_info) {
 652                kfree(p_cache);
 653                return NULL;
 654        }
 655
 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;
 659        p_cache->init = 0;
 660        return p_cache;
 661}
 662
 663void hpi_free_control_cache(struct hpi_control_cache *p_cache)
 664{
 665        if (p_cache) {
 666                kfree(p_cache->p_info);
 667                kfree(p_cache);
 668        }
 669}
 670
 671static void subsys_message(struct hpi_message *phm, struct hpi_response *phr)
 672{
 673        hpi_init_response(phr, HPI_OBJ_SUBSYSTEM, phm->function, 0);
 674
 675        switch (phm->function) {
 676        case HPI_SUBSYS_OPEN:
 677        case HPI_SUBSYS_CLOSE:
 678        case HPI_SUBSYS_DRIVER_UNLOAD:
 679                break;
 680        case HPI_SUBSYS_DRIVER_LOAD:
 681                wipe_adapter_list();
 682                hpios_alistlock_init(&adapters);
 683                break;
 684        case HPI_SUBSYS_GET_ADAPTER:
 685                subsys_get_adapter(phm, phr);
 686                break;
 687        case HPI_SUBSYS_GET_NUM_ADAPTERS:
 688                phr->u.s.num_adapters = adapters.gw_num_adapters;
 689                break;
 690        case HPI_SUBSYS_CREATE_ADAPTER:
 691                break;
 692        default:
 693                phr->error = HPI_ERROR_INVALID_FUNC;
 694                break;
 695        }
 696}
 697
 698void HPI_COMMON(struct hpi_message *phm, struct hpi_response *phr)
 699{
 700        switch (phm->type) {
 701        case HPI_TYPE_REQUEST:
 702                switch (phm->object) {
 703                case HPI_OBJ_SUBSYSTEM:
 704                        subsys_message(phm, phr);
 705                        break;
 706                }
 707                break;
 708
 709        default:
 710                phr->error = HPI_ERROR_INVALID_TYPE;
 711                break;
 712        }
 713}
 714