Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /***********************************************************************
0003 
0004     AudioScience HPI driver
0005     Functions for reading DSP code using hotplug firmware loader
0006 
0007     Copyright (C) 1997-2014  AudioScience Inc. <support@audioscience.com>
0008 
0009 
0010 ***********************************************************************/
0011 #define SOURCEFILE_NAME "hpidspcd.c"
0012 #include "hpidspcd.h"
0013 #include "hpidebug.h"
0014 #include "hpi_version.h"
0015 
0016 struct dsp_code_private {
0017     /**  Firmware descriptor */
0018     const struct firmware *firmware;
0019     struct pci_dev *dev;
0020 };
0021 
0022 /*-------------------------------------------------------------------*/
0023 short hpi_dsp_code_open(u32 adapter, void *os_data, struct dsp_code *dsp_code,
0024     u32 *os_error_code)
0025 {
0026     const struct firmware *firmware;
0027     struct pci_dev *dev = os_data;
0028     struct code_header header;
0029     char fw_name[20];
0030     short err_ret = HPI_ERROR_DSP_FILE_NOT_FOUND;
0031     int err;
0032 
0033     sprintf(fw_name, "asihpi/dsp%04x.bin", adapter);
0034 
0035     err = request_firmware(&firmware, fw_name, &dev->dev);
0036 
0037     if (err || !firmware) {
0038         dev_err(&dev->dev, "%d, request_firmware failed for %s\n",
0039             err, fw_name);
0040         goto error1;
0041     }
0042     if (firmware->size < sizeof(header)) {
0043         dev_err(&dev->dev, "Header size too small %s\n", fw_name);
0044         goto error2;
0045     }
0046     memcpy(&header, firmware->data, sizeof(header));
0047 
0048     if ((header.type != 0x45444F43) ||  /* "CODE" */
0049         (header.adapter != adapter)
0050         || (header.size != firmware->size)) {
0051         dev_err(&dev->dev,
0052             "Invalid firmware header size %d != file %zd\n",
0053             header.size, firmware->size);
0054         goto error2;
0055     }
0056 
0057     if (HPI_VER_MAJOR(header.version) != HPI_VER_MAJOR(HPI_VER)) {
0058         /* Major version change probably means Host-DSP protocol change */
0059         dev_err(&dev->dev,
0060             "Incompatible firmware version DSP image %X != Driver %X\n",
0061             header.version, HPI_VER);
0062         goto error2;
0063     }
0064 
0065     if (header.version != HPI_VER) {
0066         dev_warn(&dev->dev,
0067             "Firmware version mismatch: DSP image %X != Driver %X\n",
0068             header.version, HPI_VER);
0069     }
0070 
0071     HPI_DEBUG_LOG(DEBUG, "dsp code %s opened\n", fw_name);
0072     dsp_code->pvt = kmalloc(sizeof(*dsp_code->pvt), GFP_KERNEL);
0073     if (!dsp_code->pvt) {
0074         err_ret = HPI_ERROR_MEMORY_ALLOC;
0075         goto error2;
0076     }
0077 
0078     dsp_code->pvt->dev = dev;
0079     dsp_code->pvt->firmware = firmware;
0080     dsp_code->header = header;
0081     dsp_code->block_length = header.size / sizeof(u32);
0082     dsp_code->word_count = sizeof(header) / sizeof(u32);
0083     return 0;
0084 
0085 error2:
0086     release_firmware(firmware);
0087 error1:
0088     dsp_code->block_length = 0;
0089     return err_ret;
0090 }
0091 
0092 /*-------------------------------------------------------------------*/
0093 void hpi_dsp_code_close(struct dsp_code *dsp_code)
0094 {
0095     HPI_DEBUG_LOG(DEBUG, "dsp code closed\n");
0096     release_firmware(dsp_code->pvt->firmware);
0097     kfree(dsp_code->pvt);
0098 }
0099 
0100 /*-------------------------------------------------------------------*/
0101 void hpi_dsp_code_rewind(struct dsp_code *dsp_code)
0102 {
0103     /* Go back to start of  data, after header */
0104     dsp_code->word_count = sizeof(struct code_header) / sizeof(u32);
0105 }
0106 
0107 /*-------------------------------------------------------------------*/
0108 short hpi_dsp_code_read_word(struct dsp_code *dsp_code, u32 *pword)
0109 {
0110     if (dsp_code->word_count + 1 > dsp_code->block_length)
0111         return HPI_ERROR_DSP_FILE_FORMAT;
0112 
0113     *pword = ((u32 *)(dsp_code->pvt->firmware->data))[dsp_code->
0114         word_count];
0115     dsp_code->word_count++;
0116     return 0;
0117 }
0118 
0119 /*-------------------------------------------------------------------*/
0120 short hpi_dsp_code_read_block(size_t words_requested,
0121     struct dsp_code *dsp_code, u32 **ppblock)
0122 {
0123     if (dsp_code->word_count + words_requested > dsp_code->block_length)
0124         return HPI_ERROR_DSP_FILE_FORMAT;
0125 
0126     *ppblock =
0127         ((u32 *)(dsp_code->pvt->firmware->data)) +
0128         dsp_code->word_count;
0129     dsp_code->word_count += words_requested;
0130     return 0;
0131 }