Skip to content

Commit 069c229

Browse files
committed
ASoC: tas2783A: use custom fw binary parsing logic
Use fw binary parsing logic same as windows. Signed-off-by: Niranjan H Y <niranjan.hy@ti.com>
1 parent 79dba34 commit 069c229

1 file changed

Lines changed: 85 additions & 55 deletions

File tree

sound/soc/codecs/tas2783-sdw.c

Lines changed: 85 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@
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

6172
struct 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

756783
static 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

821851
out:
822852
if (!ret)

0 commit comments

Comments
 (0)