linux/sound/pci/asihpi/hpicmn.c
<<
>>
Prefs
   1/******************************************************************************
   2
   3    AudioScience HPI driver
   4    Copyright (C) 1997-2014  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
  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{
  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 function %d invalid\n",
  61                        phr->function);
  62                return HPI_ERROR_INVALID_RESPONSE;
  63        }
  64
  65        return 0;
  66}
  67
  68u16 hpi_add_adapter(struct hpi_adapter_obj *pao)
  69{
  70        u16 retval = 0;
  71        /*HPI_ASSERT(pao->type); */
  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].type) {
  81                int a;
  82                for (a = HPI_MAX_ADAPTERS - 1; a >= 0; a--) {
  83                        if (!adapters.adapter[a].type) {
  84                                HPI_DEBUG_LOG(WARNING,
  85                                        "ASI%X duplicate index %d moved to %d\n",
  86                                        pao->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
 100unlock:
 101        hpios_alistlock_unlock(&adapters);
 102        return retval;
 103}
 104
 105void hpi_delete_adapter(struct hpi_adapter_obj *pao)
 106{
 107        if (!pao->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].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*/
 124struct 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->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**/
 155static void wipe_adapter_list(void)
 156{
 157        memset(&adapters, 0, sizeof(adapters));
 158}
 159
 160static 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].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].type;
 178        } else {
 179                phr->u.s.adapter_index = 0;
 180                phr->u.s.adapter_type = 0;
 181                phr->error = HPI_ERROR_INVALID_OBJ_INDEX;
 182        }
 183}
 184
 185static 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                        u16 control_index = info->control_index;
 210
 211                        if (control_index >= pC->control_count) {
 212                                HPI_DEBUG_LOG(INFO,
 213                                        "adap %d control index %d out of range, cache not ready?\n",
 214                                        pC->adap_idx, control_index);
 215                                return 0;
 216                        }
 217
 218                        if (!info->size_in32bit_words) {
 219                                if (!i) {
 220                                        HPI_DEBUG_LOG(INFO,
 221                                                "adap %d cache not ready?\n",
 222                                                pC->adap_idx);
 223                                        return 0;
 224                                }
 225                                /* The cache is invalid.
 226                                 * Minimum valid entry size is
 227                                 * sizeof(struct hpi_control_cache_info)
 228                                 */
 229                                HPI_DEBUG_LOG(ERROR,
 230                                        "adap %d zero size cache entry %d\n",
 231                                        pC->adap_idx, i);
 232                                break;
 233                        }
 234
 235                        if (info->control_type) {
 236                                pC->p_info[control_index] = info;
 237                                cached++;
 238                        } else {        /* dummy cache entry */
 239                                pC->p_info[control_index] = NULL;
 240                        }
 241
 242                        byte_count += info->size_in32bit_words * 4;
 243
 244                        HPI_DEBUG_LOG(VERBOSE,
 245                                "cached %d, pinfo %p index %d type %d size %d\n",
 246                                cached, pC->p_info[info->control_index],
 247                                info->control_index, info->control_type,
 248                                info->size_in32bit_words);
 249
 250                        /* quit loop early if whole cache has been scanned.
 251                         * dwControlCount is the maximum possible entries
 252                         * but some may be absent from the cache
 253                         */
 254                        if (byte_count >= pC->cache_size_in_bytes)
 255                                break;
 256                        /* have seen last control index */
 257                        if (info->control_index == pC->control_count - 1)
 258                                break;
 259                }
 260
 261                if (byte_count != pC->cache_size_in_bytes)
 262                        HPI_DEBUG_LOG(WARNING,
 263                                "adap %d bytecount %d != cache size %d\n",
 264                                pC->adap_idx, byte_count,
 265                                pC->cache_size_in_bytes);
 266                else
 267                        HPI_DEBUG_LOG(DEBUG,
 268                                "adap %d cache good, bytecount == cache size = %d\n",
 269                                pC->adap_idx, byte_count);
 270
 271                pC->init = (u16)cached;
 272        }
 273        return pC->init;
 274}
 275
 276/** Find a control.
 277*/
 278static short find_control(u16 control_index,
 279        struct hpi_control_cache *p_cache, struct hpi_control_cache_info **pI)
 280{
 281        if (!control_cache_alloc_check(p_cache)) {
 282                HPI_DEBUG_LOG(VERBOSE,
 283                        "control_cache_alloc_check() failed %d\n",
 284                        control_index);
 285                return 0;
 286        }
 287
 288        *pI = p_cache->p_info[control_index];
 289        if (!*pI) {
 290                HPI_DEBUG_LOG(VERBOSE, "Uncached Control %d\n",
 291                        control_index);
 292                return 0;
 293        } else {
 294                HPI_DEBUG_LOG(VERBOSE, "find_control() type %d\n",
 295                        (*pI)->control_type);
 296        }
 297        return 1;
 298}
 299
 300/* allow unified treatment of several string fields within struct */
 301#define HPICMN_PAD_OFS_AND_SIZE(m)  {\
 302        offsetof(struct hpi_control_cache_pad, m), \
 303        sizeof(((struct hpi_control_cache_pad *)(NULL))->m) }
 304
 305struct pad_ofs_size {
 306        unsigned int offset;
 307        unsigned int field_size;
 308};
 309
 310static const struct pad_ofs_size pad_desc[] = {
 311        HPICMN_PAD_OFS_AND_SIZE(c_channel),     /* HPI_PAD_CHANNEL_NAME */
 312        HPICMN_PAD_OFS_AND_SIZE(c_artist),      /* HPI_PAD_ARTIST */
 313        HPICMN_PAD_OFS_AND_SIZE(c_title),       /* HPI_PAD_TITLE */
 314        HPICMN_PAD_OFS_AND_SIZE(c_comment),     /* HPI_PAD_COMMENT */
 315};
 316
 317/** CheckControlCache checks the cache and fills the struct hpi_response
 318 * accordingly. It returns one if a cache hit occurred, zero otherwise.
 319 */
 320short hpi_check_control_cache_single(struct hpi_control_cache_single *pC,
 321        struct hpi_message *phm, struct hpi_response *phr)
 322{
 323        size_t response_size;
 324        short found = 1;
 325
 326        /* set the default response size */
 327        response_size =
 328                sizeof(struct hpi_response_header) +
 329                sizeof(struct hpi_control_res);
 330
 331        switch (pC->u.i.control_type) {
 332
 333        case HPI_CONTROL_METER:
 334                if (phm->u.c.attribute == HPI_METER_PEAK) {
 335                        phr->u.c.an_log_value[0] = pC->u.meter.an_log_peak[0];
 336                        phr->u.c.an_log_value[1] = pC->u.meter.an_log_peak[1];
 337                } else if (phm->u.c.attribute == HPI_METER_RMS) {
 338                        if (pC->u.meter.an_logRMS[0] ==
 339                                HPI_CACHE_INVALID_SHORT) {
 340                                phr->error =
 341                                        HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
 342                                phr->u.c.an_log_value[0] = HPI_METER_MINIMUM;
 343                                phr->u.c.an_log_value[1] = HPI_METER_MINIMUM;
 344                        } else {
 345                                phr->u.c.an_log_value[0] =
 346                                        pC->u.meter.an_logRMS[0];
 347                                phr->u.c.an_log_value[1] =
 348                                        pC->u.meter.an_logRMS[1];
 349                        }
 350                } else
 351                        found = 0;
 352                break;
 353        case HPI_CONTROL_VOLUME:
 354                if (phm->u.c.attribute == HPI_VOLUME_GAIN) {
 355                        phr->u.c.an_log_value[0] = pC->u.vol.an_log[0];
 356                        phr->u.c.an_log_value[1] = pC->u.vol.an_log[1];
 357                } else if (phm->u.c.attribute == HPI_VOLUME_MUTE) {
 358                        if (pC->u.vol.flags & HPI_VOLUME_FLAG_HAS_MUTE) {
 359                                if (pC->u.vol.flags & HPI_VOLUME_FLAG_MUTED)
 360                                        phr->u.c.param1 =
 361                                                HPI_BITMASK_ALL_CHANNELS;
 362                                else
 363                                        phr->u.c.param1 = 0;
 364                        } else {
 365                                phr->error =
 366                                        HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
 367                                phr->u.c.param1 = 0;
 368                        }
 369                } else {
 370                        found = 0;
 371                }
 372                break;
 373        case HPI_CONTROL_MULTIPLEXER:
 374                if (phm->u.c.attribute == HPI_MULTIPLEXER_SOURCE) {
 375                        phr->u.c.param1 = pC->u.mux.source_node_type;
 376                        phr->u.c.param2 = pC->u.mux.source_node_index;
 377                } else {
 378                        found = 0;
 379                }
 380                break;
 381        case HPI_CONTROL_CHANNEL_MODE:
 382                if (phm->u.c.attribute == HPI_CHANNEL_MODE_MODE)
 383                        phr->u.c.param1 = pC->u.mode.mode;
 384                else
 385                        found = 0;
 386                break;
 387        case HPI_CONTROL_LEVEL:
 388                if (phm->u.c.attribute == HPI_LEVEL_GAIN) {
 389                        phr->u.c.an_log_value[0] = pC->u.level.an_log[0];
 390                        phr->u.c.an_log_value[1] = pC->u.level.an_log[1];
 391                } else
 392                        found = 0;
 393                break;
 394        case HPI_CONTROL_TUNER:
 395                if (phm->u.c.attribute == HPI_TUNER_FREQ)
 396                        phr->u.c.param1 = pC->u.tuner.freq_ink_hz;
 397                else if (phm->u.c.attribute == HPI_TUNER_BAND)
 398                        phr->u.c.param1 = pC->u.tuner.band;
 399                else if (phm->u.c.attribute == HPI_TUNER_LEVEL_AVG)
 400                        if (pC->u.tuner.s_level_avg ==
 401                                HPI_CACHE_INVALID_SHORT) {
 402                                phr->u.cu.tuner.s_level = 0;
 403                                phr->error =
 404                                        HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
 405                        } else
 406                                phr->u.cu.tuner.s_level =
 407                                        pC->u.tuner.s_level_avg;
 408                else
 409                        found = 0;
 410                break;
 411        case HPI_CONTROL_AESEBU_RECEIVER:
 412                if (phm->u.c.attribute == HPI_AESEBURX_ERRORSTATUS)
 413                        phr->u.c.param1 = pC->u.aes3rx.error_status;
 414                else if (phm->u.c.attribute == HPI_AESEBURX_FORMAT)
 415                        phr->u.c.param1 = pC->u.aes3rx.format;
 416                else
 417                        found = 0;
 418                break;
 419        case HPI_CONTROL_AESEBU_TRANSMITTER:
 420                if (phm->u.c.attribute == HPI_AESEBUTX_FORMAT)
 421                        phr->u.c.param1 = pC->u.aes3tx.format;
 422                else
 423                        found = 0;
 424                break;
 425        case HPI_CONTROL_TONEDETECTOR:
 426                if (phm->u.c.attribute == HPI_TONEDETECTOR_STATE)
 427                        phr->u.c.param1 = pC->u.tone.state;
 428                else
 429                        found = 0;
 430                break;
 431        case HPI_CONTROL_SILENCEDETECTOR:
 432                if (phm->u.c.attribute == HPI_SILENCEDETECTOR_STATE) {
 433                        phr->u.c.param1 = pC->u.silence.state;
 434                } else
 435                        found = 0;
 436                break;
 437        case HPI_CONTROL_MICROPHONE:
 438                if (phm->u.c.attribute == HPI_MICROPHONE_PHANTOM_POWER)
 439                        phr->u.c.param1 = pC->u.microphone.phantom_state;
 440                else
 441                        found = 0;
 442                break;
 443        case HPI_CONTROL_SAMPLECLOCK:
 444                if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE)
 445                        phr->u.c.param1 = pC->u.clk.source;
 446                else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE_INDEX) {
 447                        if (pC->u.clk.source_index ==
 448                                HPI_CACHE_INVALID_UINT16) {
 449                                phr->u.c.param1 = 0;
 450                                phr->error =
 451                                        HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
 452                        } else
 453                                phr->u.c.param1 = pC->u.clk.source_index;
 454                } else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SAMPLERATE)
 455                        phr->u.c.param1 = pC->u.clk.sample_rate;
 456                else
 457                        found = 0;
 458                break;
 459        case HPI_CONTROL_PAD:{
 460                        struct hpi_control_cache_pad *p_pad;
 461                        p_pad = (struct hpi_control_cache_pad *)pC;
 462
 463                        if (!(p_pad->field_valid_flags & (1 <<
 464                                                HPI_CTL_ATTR_INDEX(phm->u.c.
 465                                                        attribute)))) {
 466                                phr->error =
 467                                        HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
 468                                break;
 469                        }
 470
 471                        if (phm->u.c.attribute == HPI_PAD_PROGRAM_ID)
 472                                phr->u.c.param1 = p_pad->pI;
 473                        else if (phm->u.c.attribute == HPI_PAD_PROGRAM_TYPE)
 474                                phr->u.c.param1 = p_pad->pTY;
 475                        else {
 476                                unsigned int index =
 477                                        HPI_CTL_ATTR_INDEX(phm->u.c.
 478                                        attribute) - 1;
 479                                unsigned int offset = phm->u.c.param1;
 480                                unsigned int pad_string_len, field_size;
 481                                char *pad_string;
 482                                unsigned int tocopy;
 483
 484                                if (index > ARRAY_SIZE(pad_desc) - 1) {
 485                                        phr->error =
 486                                                HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
 487                                        break;
 488                                }
 489
 490                                pad_string =
 491                                        ((char *)p_pad) +
 492                                        pad_desc[index].offset;
 493                                field_size = pad_desc[index].field_size;
 494                                /* Ensure null terminator */
 495                                pad_string[field_size - 1] = 0;
 496
 497                                pad_string_len = strlen(pad_string) + 1;
 498
 499                                if (offset > pad_string_len) {
 500                                        phr->error =
 501                                                HPI_ERROR_INVALID_CONTROL_VALUE;
 502                                        break;
 503                                }
 504
 505                                tocopy = pad_string_len - offset;
 506                                if (tocopy > sizeof(phr->u.cu.chars8.sz_data))
 507                                        tocopy = sizeof(phr->u.cu.chars8.
 508                                                sz_data);
 509
 510                                memcpy(phr->u.cu.chars8.sz_data,
 511                                        &pad_string[offset], tocopy);
 512
 513                                phr->u.cu.chars8.remaining_chars =
 514                                        pad_string_len - offset - tocopy;
 515                        }
 516                }
 517                break;
 518        default:
 519                found = 0;
 520                break;
 521        }
 522
 523        HPI_DEBUG_LOG(VERBOSE, "%s Adap %d, Ctl %d, Type %d, Attr %d\n",
 524                found ? "Cached" : "Uncached", phm->adapter_index,
 525                pC->u.i.control_index, pC->u.i.control_type,
 526                phm->u.c.attribute);
 527
 528        if (found) {
 529                phr->size = (u16)response_size;
 530                phr->type = HPI_TYPE_RESPONSE;
 531                phr->object = phm->object;
 532                phr->function = phm->function;
 533        }
 534
 535        return found;
 536}
 537
 538short hpi_check_control_cache(struct hpi_control_cache *p_cache,
 539        struct hpi_message *phm, struct hpi_response *phr)
 540{
 541        struct hpi_control_cache_info *pI;
 542
 543        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);
 547                return 0;
 548        }
 549
 550        phr->error = 0;
 551        phr->specific_error = 0;
 552        phr->version = 0;
 553
 554        return hpi_check_control_cache_single((struct hpi_control_cache_single
 555                        *)pI, phm, phr);
 556}
 557
 558/** Updates the cache with Set values.
 559
 560Only update if no error.
 561Volume and Level return the limited values in the response, so use these
 562Multiplexer does so use sent values
 563*/
 564void hpi_cmn_control_cache_sync_to_msg_single(struct hpi_control_cache_single
 565        *pC, struct hpi_message *phm, struct hpi_response *phr)
 566{
 567        switch (pC->u.i.control_type) {
 568        case HPI_CONTROL_VOLUME:
 569                if (phm->u.c.attribute == HPI_VOLUME_GAIN) {
 570                        pC->u.vol.an_log[0] = phr->u.c.an_log_value[0];
 571                        pC->u.vol.an_log[1] = phr->u.c.an_log_value[1];
 572                } else if (phm->u.c.attribute == HPI_VOLUME_MUTE) {
 573                        if (phm->u.c.param1)
 574                                pC->u.vol.flags |= HPI_VOLUME_FLAG_MUTED;
 575                        else
 576                                pC->u.vol.flags &= ~HPI_VOLUME_FLAG_MUTED;
 577                }
 578                break;
 579        case HPI_CONTROL_MULTIPLEXER:
 580                /* mux does not return its setting on Set command. */
 581                if (phm->u.c.attribute == HPI_MULTIPLEXER_SOURCE) {
 582                        pC->u.mux.source_node_type = (u16)phm->u.c.param1;
 583                        pC->u.mux.source_node_index = (u16)phm->u.c.param2;
 584                }
 585                break;
 586        case HPI_CONTROL_CHANNEL_MODE:
 587                /* mode does not return its setting on Set command. */
 588                if (phm->u.c.attribute == HPI_CHANNEL_MODE_MODE)
 589                        pC->u.mode.mode = (u16)phm->u.c.param1;
 590                break;
 591        case HPI_CONTROL_LEVEL:
 592                if (phm->u.c.attribute == HPI_LEVEL_GAIN) {
 593                        pC->u.vol.an_log[0] = phr->u.c.an_log_value[0];
 594                        pC->u.vol.an_log[1] = phr->u.c.an_log_value[1];
 595                }
 596                break;
 597        case HPI_CONTROL_MICROPHONE:
 598                if (phm->u.c.attribute == HPI_MICROPHONE_PHANTOM_POWER)
 599                        pC->u.microphone.phantom_state = (u16)phm->u.c.param1;
 600                break;
 601        case HPI_CONTROL_AESEBU_TRANSMITTER:
 602                if (phm->u.c.attribute == HPI_AESEBUTX_FORMAT)
 603                        pC->u.aes3tx.format = phm->u.c.param1;
 604                break;
 605        case HPI_CONTROL_AESEBU_RECEIVER:
 606                if (phm->u.c.attribute == HPI_AESEBURX_FORMAT)
 607                        pC->u.aes3rx.format = phm->u.c.param1;
 608                break;
 609        case HPI_CONTROL_SAMPLECLOCK:
 610                if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE)
 611                        pC->u.clk.source = (u16)phm->u.c.param1;
 612                else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE_INDEX)
 613                        pC->u.clk.source_index = (u16)phm->u.c.param1;
 614                else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SAMPLERATE)
 615                        pC->u.clk.sample_rate = phm->u.c.param1;
 616                break;
 617        default:
 618                break;
 619        }
 620}
 621
 622void hpi_cmn_control_cache_sync_to_msg(struct hpi_control_cache *p_cache,
 623        struct hpi_message *phm, struct hpi_response *phr)
 624{
 625        struct hpi_control_cache_single *pC;
 626        struct hpi_control_cache_info *pI;
 627
 628        if (phr->error)
 629                return;
 630
 631        if (!find_control(phm->obj_index, p_cache, &pI)) {
 632                HPI_DEBUG_LOG(VERBOSE,
 633                        "HPICMN find_control() failed for adap %d\n",
 634                        phm->adapter_index);
 635                return;
 636        }
 637
 638        /* pC is the default cached control strucure.
 639           May be cast to something else in the following switch statement.
 640         */
 641        pC = (struct hpi_control_cache_single *)pI;
 642
 643        hpi_cmn_control_cache_sync_to_msg_single(pC, phm, phr);
 644}
 645
 646/** Allocate control cache.
 647
 648\return Cache pointer, or NULL if allocation fails.
 649*/
 650struct hpi_control_cache *hpi_alloc_control_cache(const u32 control_count,
 651        const u32 size_in_bytes, u8 *p_dsp_control_buffer)
 652{
 653        struct hpi_control_cache *p_cache =
 654                kmalloc(sizeof(*p_cache), GFP_KERNEL);
 655        if (!p_cache)
 656                return NULL;
 657
 658        p_cache->p_info =
 659                kcalloc(control_count, sizeof(*p_cache->p_info), GFP_KERNEL);
 660        if (!p_cache->p_info) {
 661                kfree(p_cache);
 662                return NULL;
 663        }
 664
 665        p_cache->cache_size_in_bytes = size_in_bytes;
 666        p_cache->control_count = control_count;
 667        p_cache->p_cache = p_dsp_control_buffer;
 668        p_cache->init = 0;
 669        return p_cache;
 670}
 671
 672void hpi_free_control_cache(struct hpi_control_cache *p_cache)
 673{
 674        if (p_cache) {
 675                kfree(p_cache->p_info);
 676                kfree(p_cache);
 677        }
 678}
 679
 680static void subsys_message(struct hpi_message *phm, struct hpi_response *phr)
 681{
 682        hpi_init_response(phr, HPI_OBJ_SUBSYSTEM, phm->function, 0);
 683
 684        switch (phm->function) {
 685        case HPI_SUBSYS_OPEN:
 686        case HPI_SUBSYS_CLOSE:
 687        case HPI_SUBSYS_DRIVER_UNLOAD:
 688                break;
 689        case HPI_SUBSYS_DRIVER_LOAD:
 690                wipe_adapter_list();
 691                hpios_alistlock_init(&adapters);
 692                break;
 693        case HPI_SUBSYS_GET_ADAPTER:
 694                subsys_get_adapter(phm, phr);
 695                break;
 696        case HPI_SUBSYS_GET_NUM_ADAPTERS:
 697                phr->u.s.num_adapters = adapters.gw_num_adapters;
 698                break;
 699        case HPI_SUBSYS_CREATE_ADAPTER:
 700                break;
 701        default:
 702                phr->error = HPI_ERROR_INVALID_FUNC;
 703                break;
 704        }
 705}
 706
 707void HPI_COMMON(struct hpi_message *phm, struct hpi_response *phr)
 708{
 709        switch (phm->type) {
 710        case HPI_TYPE_REQUEST:
 711                switch (phm->object) {
 712                case HPI_OBJ_SUBSYSTEM:
 713                        subsys_message(phm, phr);
 714                        break;
 715                }
 716                break;
 717
 718        default:
 719                phr->error = HPI_ERROR_INVALID_TYPE;
 720                break;
 721        }
 722}
 723