2019-05-29 17:12:47 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2014-12-18 07:57:13 +03:00
/***********************************************************************
2010-04-21 20:17:39 +04:00
AudioScience HPI driver
2014-12-18 07:57:13 +03:00
Functions for reading DSP code using hotplug firmware loader
Copyright ( C ) 1997 - 2014 AudioScience Inc . < support @ audioscience . com >
2010-04-21 20:17:39 +04:00
2014-12-18 07:57:13 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2010-04-21 20:17:39 +04:00
# define SOURCEFILE_NAME "hpidspcd.c"
# include "hpidspcd.h"
# include "hpidebug.h"
2011-12-22 04:38:31 +04:00
# include "hpi_version.h"
2010-04-21 20:17:39 +04:00
2011-07-22 07:52:42 +04:00
struct dsp_code_private {
/** Firmware descriptor */
const struct firmware * firmware ;
struct pci_dev * dev ;
2010-04-21 20:17:39 +04:00
} ;
/*-------------------------------------------------------------------*/
2011-07-22 07:52:42 +04:00
short hpi_dsp_code_open ( u32 adapter , void * os_data , struct dsp_code * dsp_code ,
u32 * os_error_code )
2010-04-21 20:17:39 +04:00
{
2011-07-22 07:52:42 +04:00
const struct firmware * firmware ;
struct pci_dev * dev = os_data ;
2010-04-21 20:17:39 +04:00
struct code_header header ;
char fw_name [ 20 ] ;
2011-08-01 01:16:43 +04:00
short err_ret = HPI_ERROR_DSP_FILE_NOT_FOUND ;
2010-04-21 20:17:39 +04:00
int err ;
sprintf ( fw_name , " asihpi/dsp%04x.bin " , adapter ) ;
2011-07-22 07:52:42 +04:00
err = request_firmware ( & firmware , fw_name , & dev - > dev ) ;
2011-02-10 07:25:54 +03:00
2011-07-22 07:52:42 +04:00
if ( err | | ! firmware ) {
2012-10-28 12:05:54 +04:00
dev_err ( & dev - > dev , " %d, request_firmware failed for %s \n " ,
err , fw_name ) ;
2010-04-21 20:17:39 +04:00
goto error1 ;
}
2011-07-22 07:52:42 +04:00
if ( firmware - > size < sizeof ( header ) ) {
2012-10-28 12:05:54 +04:00
dev_err ( & dev - > dev , " Header size too small %s \n " , fw_name ) ;
2010-04-21 20:17:39 +04:00
goto error2 ;
}
2011-07-22 07:52:42 +04:00
memcpy ( & header , firmware - > data , sizeof ( header ) ) ;
if ( ( header . type ! = 0x45444F43 ) | | /* "CODE" */
( header . adapter ! = adapter )
| | ( header . size ! = firmware - > size ) ) {
2012-10-28 12:05:54 +04:00
dev_err ( & dev - > dev ,
2011-12-22 04:38:31 +04:00
" Invalid firmware header size %d != file %zd \n " ,
header . size , firmware - > size ) ;
2010-04-21 20:17:39 +04:00
goto error2 ;
}
2014-12-18 07:57:13 +03:00
if ( HPI_VER_MAJOR ( header . version ) ! = HPI_VER_MAJOR ( HPI_VER ) ) {
/* Major version change probably means Host-DSP protocol change */
dev_err ( & dev - > dev ,
" Incompatible firmware version DSP image %X != Driver %X \n " ,
2012-10-28 12:05:54 +04:00
header . version , HPI_VER ) ;
2010-04-21 20:17:39 +04:00
goto error2 ;
}
2011-12-22 04:38:31 +04:00
if ( header . version ! = HPI_VER ) {
2014-12-18 07:57:13 +03:00
dev_warn ( & dev - > dev ,
" Firmware version mismatch: DSP image %X != Driver %X \n " ,
header . version , HPI_VER ) ;
2010-04-21 20:17:39 +04:00
}
2011-02-10 07:25:54 +03:00
HPI_DEBUG_LOG ( DEBUG , " dsp code %s opened \n " , fw_name ) ;
2011-07-22 07:52:42 +04:00
dsp_code - > pvt = kmalloc ( sizeof ( * dsp_code - > pvt ) , GFP_KERNEL ) ;
2011-08-01 01:16:43 +04:00
if ( ! dsp_code - > pvt ) {
err_ret = HPI_ERROR_MEMORY_ALLOC ;
goto error2 ;
}
2011-07-22 07:52:42 +04:00
dsp_code - > pvt - > dev = dev ;
dsp_code - > pvt - > firmware = firmware ;
dsp_code - > header = header ;
dsp_code - > block_length = header . size / sizeof ( u32 ) ;
dsp_code - > word_count = sizeof ( header ) / sizeof ( u32 ) ;
2010-04-21 20:17:39 +04:00
return 0 ;
error2 :
2011-07-22 07:52:42 +04:00
release_firmware ( firmware ) ;
2010-04-21 20:17:39 +04:00
error1 :
2011-07-22 07:52:42 +04:00
dsp_code - > block_length = 0 ;
2011-08-01 01:16:43 +04:00
return err_ret ;
2010-04-21 20:17:39 +04:00
}
/*-------------------------------------------------------------------*/
2011-07-22 07:52:42 +04:00
void hpi_dsp_code_close ( struct dsp_code * dsp_code )
2010-04-21 20:17:39 +04:00
{
2011-12-22 04:38:44 +04:00
HPI_DEBUG_LOG ( DEBUG , " dsp code closed \n " ) ;
release_firmware ( dsp_code - > pvt - > firmware ) ;
2011-07-22 07:52:42 +04:00
kfree ( dsp_code - > pvt ) ;
2010-04-21 20:17:39 +04:00
}
/*-------------------------------------------------------------------*/
2011-07-22 07:52:42 +04:00
void hpi_dsp_code_rewind ( struct dsp_code * dsp_code )
2010-04-21 20:17:39 +04:00
{
/* Go back to start of data, after header */
2011-07-22 07:52:42 +04:00
dsp_code - > word_count = sizeof ( struct code_header ) / sizeof ( u32 ) ;
2010-04-21 20:17:39 +04:00
}
/*-------------------------------------------------------------------*/
2011-07-22 07:52:42 +04:00
short hpi_dsp_code_read_word ( struct dsp_code * dsp_code , u32 * pword )
2010-04-21 20:17:39 +04:00
{
2011-07-22 07:52:42 +04:00
if ( dsp_code - > word_count + 1 > dsp_code - > block_length )
2011-02-10 07:25:54 +03:00
return HPI_ERROR_DSP_FILE_FORMAT ;
2010-04-21 20:17:39 +04:00
2011-07-22 07:52:42 +04:00
* pword = ( ( u32 * ) ( dsp_code - > pvt - > firmware - > data ) ) [ dsp_code - >
2010-04-21 20:17:39 +04:00
word_count ] ;
2011-07-22 07:52:42 +04:00
dsp_code - > word_count + + ;
2010-04-21 20:17:39 +04:00
return 0 ;
}
/*-------------------------------------------------------------------*/
short hpi_dsp_code_read_block ( size_t words_requested ,
2011-07-22 07:52:42 +04:00
struct dsp_code * dsp_code , u32 * * ppblock )
2010-04-21 20:17:39 +04:00
{
2011-07-22 07:52:42 +04:00
if ( dsp_code - > word_count + words_requested > dsp_code - > block_length )
2010-04-21 20:17:39 +04:00
return HPI_ERROR_DSP_FILE_FORMAT ;
* ppblock =
2011-07-22 07:52:42 +04:00
( ( u32 * ) ( dsp_code - > pvt - > firmware - > data ) ) +
dsp_code - > word_count ;
dsp_code - > word_count + = words_requested ;
2010-04-21 20:17:39 +04:00
return 0 ;
}