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