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