3636#include "tas2783.h"
3737
3838#define TIMEOUT_FW_DL_MS (3000)
39- #define FW_DL_OFFSET 36
40- #define FW_FL_HDR 12
39+ #define FW_DL_OFFSET 84 /* binary file information */
40+ #define FW_FL_HDR 20 /* minimum number of bytes in one chunk */
4141#define TAS2783_PROBE_TIMEOUT 5000
4242#define TAS2783_CALI_GUID EFI_GUID(0x1f52d2a1, 0xbb3a, 0x457d, 0xbc, \
4343 0x09, 0x43, 0xa3, 0xf4, 0x31, 0x0a, 0x92)
@@ -51,11 +51,22 @@ static const u32 tas2783_cali_reg[] = {
5151 TAS2783_CAL_TLIM ,
5252};
5353
54- struct bin_header_t {
55- u16 vendor_id ;
56- u16 version ;
54+ struct tas_fw_hdr {
55+ u32 size ;
56+ u32 version_offset ;
57+ u32 plt_id ;
58+ u32 ppc3_ver ;
59+ u32 timestamp ;
60+ u8 ddc_name [64 ];
61+ };
62+
63+ struct tas_fw_file {
64+ u32 vendor_id ;
5765 u32 file_id ;
66+ u32 version ;
5867 u32 length ;
68+ u32 dest_addr ;
69+ u8 * fw_data ;
5970};
6071
6172struct raw_init_data {
@@ -90,7 +101,7 @@ struct tas2783_prv {
90101 wait_queue_head_t fw_wait ;
91102 bool fw_dl_task_done ;
92103 bool fw_dl_success ;
93- struct reg_sequence * init_data ;
104+ const struct reg_sequence * init_data ;
94105 int num_init_data ;
95106};
96107
@@ -744,79 +755,98 @@ static s32 tas2783_update_calibdata(struct tas2783_prv *tas_dev)
744755 return ret ;
745756}
746757
747- static s32 read_header (const u8 * data , struct bin_header_t * hdr )
758+
759+ static s32 tas_fw_read_hdr (const u8 * data , struct tas_fw_hdr * hdr )
748760{
749- hdr -> vendor_id = get_unaligned_le16 (& data [0 ]);
750- hdr -> file_id = get_unaligned_le32 (& data [2 ]);
751- hdr -> version = get_unaligned_le16 (& data [6 ]);
752- hdr -> length = get_unaligned_le32 (& data [8 ]);
753- return 12 ;
761+ hdr -> size = get_unaligned_le32 (data );
762+ hdr -> version_offset = get_unaligned_le32 (& data [4 ]);
763+ hdr -> plt_id = get_unaligned_le32 (& data [8 ]);
764+ hdr -> ppc3_ver = get_unaligned_le32 (& data [12 ]);
765+ memcpy (hdr -> ddc_name , & data [16 ], 64 );
766+ hdr -> timestamp = get_unaligned_le32 (& data [80 ]);
767+
768+ return 84 ;
769+ }
770+
771+ static s32 tas_fw_get_next_file (const u8 * data , struct tas_fw_file * file )
772+ {
773+ file -> vendor_id = get_unaligned_le32 (& data [0 ]);
774+ file -> file_id = get_unaligned_le32 (& data [4 ]);
775+ file -> version = get_unaligned_le32 (& data [8 ]);
776+ file -> length = get_unaligned_le32 (& data [12 ]);
777+ file -> dest_addr = get_unaligned_le32 (& data [16 ]);
778+ file -> fw_data = (u8 * )& data [20 ];
779+
780+ return file -> length + sizeof (u32 ) * 5 ;
754781}
755782
756783static void tas2783_fw_ready (const struct firmware * fmw , void * context )
757784{
758785 struct tas2783_prv * tas_dev =
759786 (struct tas2783_prv * )context ;
760787 const u8 * buf = NULL ;
761- s32 offset = 0 , img_sz , file_blk_size , ret ;
762- struct bin_header_t hdr ;
788+ s32 img_sz , ret , cur_file ;
789+ s32 offset = 0 ;
790+
791+ struct tas_fw_hdr * hdr __free (kfree ) = kzalloc (sizeof (* hdr ), GFP_KERNEL );
792+ struct tas_fw_file * file __free (kfree ) = kzalloc (sizeof (* file ), GFP_KERNEL );
793+ if (!file || !hdr ) {
794+ ret = - ENOMEM ;
795+ goto out ;
796+ }
763797
764798 if (!fmw || !fmw -> data ) {
765- /* No firmware binary, devices will work in ROM mode. */
799+ /* firmware binary not found */
766800 dev_err (tas_dev -> dev ,
767- "Failed to read %s, no side-effect on driver running \n" ,
801+ "Failed to read fw binary %s \n" ,
768802 tas_dev -> rca_binaryname );
769803 ret = - EINVAL ;
770804 goto out ;
771805 }
772806
773- mutex_lock (& tas_dev -> pde_lock );
774807 img_sz = fmw -> size ;
775808 buf = fmw -> data ;
776- offset += FW_DL_OFFSET ;
777- while (offset < (img_sz - FW_FL_HDR )) {
778- memset (& hdr , 0 , sizeof (hdr ));
779- offset += read_header (& buf [offset ], & hdr );
780- dev_dbg (tas_dev -> dev ,
781- "vndr=%d, file=%d, version=%d, len=%d, off=%d\n" ,
782- hdr .vendor_id , hdr .file_id , hdr .version ,
783- hdr .length , offset );
784- /* size also includes the header */
785- file_blk_size = hdr .length - FW_FL_HDR ;
786-
787- switch (hdr .file_id ) {
788- case 0 :
789- ret = sdw_nwrite_no_pm (tas_dev -> sdw_peripheral ,
790- PRAM_ADDR_START , file_blk_size ,
791- & buf [offset ]);
792- if (ret < 0 )
793- dev_err (tas_dev -> dev ,
794- "PRAM update failed: %d" , ret );
795- break ;
796-
797- case 1 :
798- ret = sdw_nwrite_no_pm (tas_dev -> sdw_peripheral ,
799- YRAM_ADDR_START , file_blk_size ,
800- & buf [offset ]);
801- if (ret < 0 )
802- dev_err (tas_dev -> dev ,
803- "YRAM update failed: %d" , ret );
809+ offset += tas_fw_read_hdr (buf , hdr );
810+ if (hdr -> size != img_sz ) {
811+ ret = - EINVAL ;
812+ dev_dbg (tas_dev -> dev , "firmware size mismatch with header" );
813+ goto out ;
814+ }
804815
805- break ;
816+ if (img_sz < FW_DL_OFFSET ) {
817+ ret = - EINVAL ;
818+ dev_err (tas_dev -> dev , "unexpected size, size is too small" );
819+ goto out ;
820+ }
806821
807- default :
808- ret = - EINVAL ;
809- dev_err (tas_dev -> dev , "Unsupported file" );
822+ mutex_lock (& tas_dev -> pde_lock );
823+ while (offset < (img_sz - FW_FL_HDR )) {
824+ offset += tas_fw_get_next_file (& buf [offset ], file );
825+ dev_dbg (tas_dev -> dev ,
826+ "v=%d, fid=%d, ver=%d, len=%d, daddr=0x%x, fw=%p" ,
827+ file -> vendor_id , file -> file_id ,
828+ file -> version , file -> length ,
829+ file -> dest_addr , file -> fw_data );
830+
831+ ret = sdw_nwrite_no_pm (tas_dev -> sdw_peripheral ,
832+ file -> dest_addr ,
833+ file -> length ,
834+ file -> fw_data );
835+ if (ret < 0 ) {
836+ dev_err (tas_dev -> dev ,
837+ "FW download failed: %d" , ret );
810838 break ;
811839 }
812-
813- if (ret == 0 )
814- offset += file_blk_size ;
815- else
816- break ;
840+ cur_file ++ ;
817841 }
818842 mutex_unlock (& tas_dev -> pde_lock );
819- tas2783_update_calibdata (tas_dev );
843+
844+ if (cur_file == 0 ) {
845+ dev_err (tas_dev -> dev , "fw with no files" );
846+ ret = - EINVAL ;
847+ } else {
848+ tas2783_update_calibdata (tas_dev );
849+ }
820850
821851out :
822852 if (!ret )
0 commit comments