2010-04-21 20:17:39 +04:00
/***********************************************************************/
2011-07-22 07:52:42 +04:00
/**
2010-04-21 20:17:39 +04:00
AudioScience HPI driver
2011-07-22 07:52:42 +04:00
Copyright ( C ) 1997 - 2011 AudioScience Inc . < support @ audioscience . com >
2010-04-21 20:17:39 +04:00
This program is free software ; you can redistribute it and / or modify
it under the terms of version 2 of the GNU General Public License as
published by the Free Software Foundation ;
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA
\ file
2011-07-22 07:52:42 +04:00
Functions for reading DSP code using
2010-04-21 20:17:39 +04:00
hotplug firmware loader from individual dsp code files
2011-07-22 07:52:42 +04:00
*/
2010-04-21 20:17:39 +04:00
/***********************************************************************/
# define SOURCEFILE_NAME "hpidspcd.c"
# include "hpidspcd.h"
# include "hpidebug.h"
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
} ;
# define HPI_VER_DECIMAL ((int)(HPI_VER_MAJOR(HPI_VER) * 10000 + \
HPI_VER_MINOR ( HPI_VER ) * 100 + HPI_VER_RELEASE ( HPI_VER ) ) )
/*-------------------------------------------------------------------*/
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 ] ;
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 ) {
dev_printk ( KERN_ERR , & dev - > dev ,
2011-02-10 07:25:54 +03:00
" %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 ) ) {
dev_printk ( KERN_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 ) ) {
dev_printk ( KERN_ERR , & dev - > dev , " Invalid firmware file \n " ) ;
2010-04-21 20:17:39 +04:00
goto error2 ;
}
2011-07-22 07:52:42 +04:00
if ( ( header . version / 100 & ~ 1 ) ! = ( HPI_VER_DECIMAL / 100 & ~ 1 ) ) {
dev_printk ( KERN_ERR , & dev - > dev ,
2011-02-10 07:26:19 +03:00
" Incompatible firmware version "
2011-02-10 07:25:54 +03:00
" DSP image %d != Driver %d \n " , header . version ,
2010-04-21 20:17:39 +04:00
HPI_VER_DECIMAL ) ;
goto error2 ;
}
if ( header . version ! = HPI_VER_DECIMAL ) {
2011-07-22 07:52:42 +04:00
dev_printk ( KERN_WARNING , & dev - > dev ,
2011-02-10 07:26:19 +03:00
" Firmware: release version mismatch DSP image %d != Driver %d \n " ,
2010-04-21 20:17:39 +04:00
header . version , HPI_VER_DECIMAL ) ;
}
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 ) ;
if ( ! dsp_code - > pvt )
return HPI_ERROR_MEMORY_ALLOC ;
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 ;
2010-04-21 20:17:39 +04:00
return HPI_ERROR_DSP_FILE_NOT_FOUND ;
}
/*-------------------------------------------------------------------*/
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-07-22 07:52:42 +04:00
if ( dsp_code - > pvt - > firmware ) {
2010-04-21 20:17:39 +04:00
HPI_DEBUG_LOG ( DEBUG , " dsp code closed \n " ) ;
2011-07-22 07:52:42 +04:00
release_firmware ( dsp_code - > pvt - > firmware ) ;
dsp_code - > pvt - > firmware = NULL ;
2010-04-21 20:17:39 +04:00
}
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 ;
}