1 // SPDX-License-Identifier: GPL-2.0-only 2 /*********************************************************************** 3 4 AudioScience HPI driver 5 Functions for reading DSP code using hotplug firmware loader 6 7 Copyright (C) 1997-2014 AudioScience Inc. <support@audioscience.com> 8 9 10 ***********************************************************************/ 11 #define SOURCEFILE_NAME "hpidspcd.c" 12 #include "hpidspcd.h" 13 #include "hpidebug.h" 14 #include "hpi_version.h" 15 16 struct dsp_code_private { 17 /** Firmware descriptor */ 18 const struct firmware *firmware; 19 struct pci_dev *dev; 20 }; 21 22 /*-------------------------------------------------------------------*/ 23 short hpi_dsp_code_open(u32 adapter, void *os_data, struct dsp_code *dsp_code, 24 u32 *os_error_code) 25 { 26 const struct firmware *firmware; 27 struct pci_dev *dev = os_data; 28 struct code_header header; 29 char fw_name[20]; 30 short err_ret = HPI_ERROR_DSP_FILE_NOT_FOUND; 31 int err; 32 33 sprintf(fw_name, "asihpi/dsp%04x.bin", adapter); 34 35 err = request_firmware(&firmware, fw_name, &dev->dev); 36 37 if (err || !firmware) { 38 dev_err(&dev->dev, "%d, request_firmware failed for %s\n", 39 err, fw_name); 40 goto error1; 41 } 42 if (firmware->size < sizeof(header)) { 43 dev_err(&dev->dev, "Header size too small %s\n", fw_name); 44 goto error2; 45 } 46 memcpy(&header, firmware->data, sizeof(header)); 47 48 if ((header.type != 0x45444F43) || /* "CODE" */ 49 (header.adapter != adapter) 50 || (header.size != firmware->size)) { 51 dev_err(&dev->dev, 52 "Invalid firmware header size %d != file %zd\n", 53 header.size, firmware->size); 54 goto error2; 55 } 56 57 if (HPI_VER_MAJOR(header.version) != HPI_VER_MAJOR(HPI_VER)) { 58 /* Major version change probably means Host-DSP protocol change */ 59 dev_err(&dev->dev, 60 "Incompatible firmware version DSP image %X != Driver %X\n", 61 header.version, HPI_VER); 62 goto error2; 63 } 64 65 if (header.version != HPI_VER) { 66 dev_warn(&dev->dev, 67 "Firmware version mismatch: DSP image %X != Driver %X\n", 68 header.version, HPI_VER); 69 } 70 71 HPI_DEBUG_LOG(DEBUG, "dsp code %s opened\n", fw_name); 72 dsp_code->pvt = kmalloc(sizeof(*dsp_code->pvt), GFP_KERNEL); 73 if (!dsp_code->pvt) { 74 err_ret = HPI_ERROR_MEMORY_ALLOC; 75 goto error2; 76 } 77 78 dsp_code->pvt->dev = dev; 79 dsp_code->pvt->firmware = firmware; 80 dsp_code->header = header; 81 dsp_code->block_length = header.size / sizeof(u32); 82 dsp_code->word_count = sizeof(header) / sizeof(u32); 83 return 0; 84 85 error2: 86 release_firmware(firmware); 87 error1: 88 dsp_code->block_length = 0; 89 return err_ret; 90 } 91 92 /*-------------------------------------------------------------------*/ 93 void hpi_dsp_code_close(struct dsp_code *dsp_code) 94 { 95 HPI_DEBUG_LOG(DEBUG, "dsp code closed\n"); 96 release_firmware(dsp_code->pvt->firmware); 97 kfree(dsp_code->pvt); 98 } 99 100 /*-------------------------------------------------------------------*/ 101 void hpi_dsp_code_rewind(struct dsp_code *dsp_code) 102 { 103 /* Go back to start of data, after header */ 104 dsp_code->word_count = sizeof(struct code_header) / sizeof(u32); 105 } 106 107 /*-------------------------------------------------------------------*/ 108 short hpi_dsp_code_read_word(struct dsp_code *dsp_code, u32 *pword) 109 { 110 if (dsp_code->word_count + 1 > dsp_code->block_length) 111 return HPI_ERROR_DSP_FILE_FORMAT; 112 113 *pword = ((u32 *)(dsp_code->pvt->firmware->data))[dsp_code-> 114 word_count]; 115 dsp_code->word_count++; 116 return 0; 117 } 118 119 /*-------------------------------------------------------------------*/ 120 short hpi_dsp_code_read_block(size_t words_requested, 121 struct dsp_code *dsp_code, u32 **ppblock) 122 { 123 if (dsp_code->word_count + words_requested > dsp_code->block_length) 124 return HPI_ERROR_DSP_FILE_FORMAT; 125 126 *ppblock = 127 ((u32 *)(dsp_code->pvt->firmware->data)) + 128 dsp_code->word_count; 129 dsp_code->word_count += words_requested; 130 return 0; 131 } 132