linux/sound/pci/asihpi/hpidspcd.c
<<
>>
Prefs
   1/***********************************************************************/
   2/**
   3
   4    AudioScience HPI driver
   5    Copyright (C) 1997-2011  AudioScience Inc. <support@audioscience.com>
   6
   7    This program is free software; you can redistribute it and/or modify
   8    it under the terms of version 2 of the GNU General Public License as
   9    published by the Free Software Foundation;
  10
  11    This program is distributed in the hope that it will be useful,
  12    but WITHOUT ANY WARRANTY; without even the implied warranty of
  13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14    GNU General Public License for more details.
  15
  16    You should have received a copy of the GNU General Public License
  17    along with this program; if not, write to the Free Software
  18    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  19
  20\file
  21Functions for reading DSP code using
  22hotplug firmware loader from individual dsp code files
  23*/
  24/***********************************************************************/
  25#define SOURCEFILE_NAME "hpidspcd.c"
  26#include "hpidspcd.h"
  27#include "hpidebug.h"
  28#include "hpi_version.h"
  29
  30struct dsp_code_private {
  31        /**  Firmware descriptor */
  32        const struct firmware *firmware;
  33        struct pci_dev *dev;
  34};
  35
  36/*-------------------------------------------------------------------*/
  37short hpi_dsp_code_open(u32 adapter, void *os_data, struct dsp_code *dsp_code,
  38        u32 *os_error_code)
  39{
  40        const struct firmware *firmware;
  41        struct pci_dev *dev = os_data;
  42        struct code_header header;
  43        char fw_name[20];
  44        short err_ret = HPI_ERROR_DSP_FILE_NOT_FOUND;
  45        int err;
  46
  47        sprintf(fw_name, "asihpi/dsp%04x.bin", adapter);
  48
  49        err = request_firmware(&firmware, fw_name, &dev->dev);
  50
  51        if (err || !firmware) {
  52                dev_err(&dev->dev, "%d, request_firmware failed for %s\n",
  53                        err, fw_name);
  54                goto error1;
  55        }
  56        if (firmware->size < sizeof(header)) {
  57                dev_err(&dev->dev, "Header size too small %s\n", fw_name);
  58                goto error2;
  59        }
  60        memcpy(&header, firmware->data, sizeof(header));
  61
  62        if ((header.type != 0x45444F43) ||      /* "CODE" */
  63                (header.adapter != adapter)
  64                || (header.size != firmware->size)) {
  65                dev_err(&dev->dev,
  66                        "Invalid firmware header size %d != file %zd\n",
  67                        header.size, firmware->size);
  68                goto error2;
  69        }
  70
  71        if ((header.version >> 9) != (HPI_VER >> 9)) {
  72                /* Consider even and subsequent odd minor versions to be compatible */
  73                dev_err(&dev->dev, "Incompatible firmware version DSP image %X != Driver %X\n",
  74                        header.version, HPI_VER);
  75                goto error2;
  76        }
  77
  78        if (header.version != HPI_VER) {
  79                dev_info(&dev->dev,
  80                         "Firmware: release version mismatch  DSP image %X != Driver %X\n",
  81                         header.version, HPI_VER);
  82        }
  83
  84        HPI_DEBUG_LOG(DEBUG, "dsp code %s opened\n", fw_name);
  85        dsp_code->pvt = kmalloc(sizeof(*dsp_code->pvt), GFP_KERNEL);
  86        if (!dsp_code->pvt) {
  87                err_ret = HPI_ERROR_MEMORY_ALLOC;
  88                goto error2;
  89        }
  90
  91        dsp_code->pvt->dev = dev;
  92        dsp_code->pvt->firmware = firmware;
  93        dsp_code->header = header;
  94        dsp_code->block_length = header.size / sizeof(u32);
  95        dsp_code->word_count = sizeof(header) / sizeof(u32);
  96        return 0;
  97
  98error2:
  99        release_firmware(firmware);
 100error1:
 101        dsp_code->block_length = 0;
 102        return err_ret;
 103}
 104
 105/*-------------------------------------------------------------------*/
 106void hpi_dsp_code_close(struct dsp_code *dsp_code)
 107{
 108        HPI_DEBUG_LOG(DEBUG, "dsp code closed\n");
 109        release_firmware(dsp_code->pvt->firmware);
 110        kfree(dsp_code->pvt);
 111}
 112
 113/*-------------------------------------------------------------------*/
 114void hpi_dsp_code_rewind(struct dsp_code *dsp_code)
 115{
 116        /* Go back to start of  data, after header */
 117        dsp_code->word_count = sizeof(struct code_header) / sizeof(u32);
 118}
 119
 120/*-------------------------------------------------------------------*/
 121short hpi_dsp_code_read_word(struct dsp_code *dsp_code, u32 *pword)
 122{
 123        if (dsp_code->word_count + 1 > dsp_code->block_length)
 124                return HPI_ERROR_DSP_FILE_FORMAT;
 125
 126        *pword = ((u32 *)(dsp_code->pvt->firmware->data))[dsp_code->
 127                word_count];
 128        dsp_code->word_count++;
 129        return 0;
 130}
 131
 132/*-------------------------------------------------------------------*/
 133short hpi_dsp_code_read_block(size_t words_requested,
 134        struct dsp_code *dsp_code, u32 **ppblock)
 135{
 136        if (dsp_code->word_count + words_requested > dsp_code->block_length)
 137                return HPI_ERROR_DSP_FILE_FORMAT;
 138
 139        *ppblock =
 140                ((u32 *)(dsp_code->pvt->firmware->data)) +
 141                dsp_code->word_count;
 142        dsp_code->word_count += words_requested;
 143        return 0;
 144}
 145