Skip to content

Commit ed73984

Browse files
committed
ASoC: tas2783A: use custom fw binary parsing logic
Use fw binary parsing logic same as windows as same the same will be used in Linux Signed-off-by: Niranjan H Y <niranjan.hy@ti.com> --- v2: - convert dbg to err log for firmware size mimatch issue - checkpatch error fix for logs - remove unwanted empty line - add software reset before fw download ASoC: tas2783A: add sw reset for firmware download
1 parent 6f0b47b commit ed73984

2 files changed

Lines changed: 93 additions & 55 deletions

File tree

sound/soc/codecs/tas2783-sdw.c

Lines changed: 92 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,97 @@ 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+
static s32 tas_fw_read_hdr(const u8 *data, struct tas_fw_hdr *hdr)
759+
{
760+
hdr->size = get_unaligned_le32(data);
761+
hdr->version_offset = get_unaligned_le32(&data[4]);
762+
hdr->plt_id = get_unaligned_le32(&data[8]);
763+
hdr->ppc3_ver = get_unaligned_le32(&data[12]);
764+
memcpy(hdr->ddc_name, &data[16], 64);
765+
hdr->timestamp = get_unaligned_le32(&data[80]);
766+
767+
return 84;
768+
}
769+
770+
static s32 tas_fw_get_next_file(const u8 *data, struct tas_fw_file *file)
748771
{
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;
772+
file->vendor_id = get_unaligned_le32(&data[0]);
773+
file->file_id = get_unaligned_le32(&data[4]);
774+
file->version = get_unaligned_le32(&data[8]);
775+
file->length = get_unaligned_le32(&data[12]);
776+
file->dest_addr = get_unaligned_le32(&data[16]);
777+
file->fw_data = (u8 *)&data[20];
778+
779+
return file->length + sizeof(u32) * 5;
754780
}
755781

756782
static void tas2783_fw_ready(const struct firmware *fmw, void *context)
757783
{
758784
struct tas2783_prv *tas_dev =
759785
(struct tas2783_prv *)context;
760786
const u8 *buf = NULL;
761-
s32 offset = 0, img_sz, file_blk_size, ret;
762-
struct bin_header_t hdr;
787+
s32 img_sz, ret, cur_file;
788+
s32 offset = 0;
789+
790+
struct tas_fw_hdr *hdr __free(kfree) = kzalloc(sizeof(*hdr), GFP_KERNEL);
791+
struct tas_fw_file *file __free(kfree) = kzalloc(sizeof(*file), GFP_KERNEL);
792+
if (!file || !hdr) {
793+
ret = -ENOMEM;
794+
goto out;
795+
}
763796

764797
if (!fmw || !fmw->data) {
765-
/* No firmware binary, devices will work in ROM mode. */
798+
/* firmware binary not found*/
766799
dev_err(tas_dev->dev,
767-
"Failed to read %s, no side-effect on driver running\n",
800+
"Failed to read fw binary %s\n",
768801
tas_dev->rca_binaryname);
769802
ret = -EINVAL;
770803
goto out;
771804
}
772805

773-
mutex_lock(&tas_dev->pde_lock);
774806
img_sz = fmw->size;
775807
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);
808+
offset += tas_fw_read_hdr(buf, hdr);
809+
if (hdr->size != img_sz) {
810+
ret = -EINVAL;
811+
dev_err(tas_dev->dev, "firmware size mismatch with header");
812+
goto out;
813+
}
804814

805-
break;
815+
if (img_sz < FW_DL_OFFSET) {
816+
ret = -EINVAL;
817+
dev_err(tas_dev->dev, "unexpected size, size is too small");
818+
goto out;
819+
}
806820

807-
default:
808-
ret = -EINVAL;
809-
dev_err(tas_dev->dev, "Unsupported file");
821+
mutex_lock(&tas_dev->pde_lock);
822+
while (offset < (img_sz - FW_FL_HDR)) {
823+
offset += tas_fw_get_next_file(&buf[offset], file);
824+
dev_dbg(tas_dev->dev,
825+
"v=%d, fid=%d, ver=%d, len=%d, daddr=0x%x, fw=%p",
826+
file->vendor_id, file->file_id,
827+
file->version, file->length,
828+
file->dest_addr, file->fw_data);
829+
830+
ret = sdw_nwrite_no_pm(tas_dev->sdw_peripheral,
831+
file->dest_addr,
832+
file->length,
833+
file->fw_data);
834+
if (ret < 0) {
835+
dev_err(tas_dev->dev,
836+
"FW download failed: %d", ret);
810837
break;
811838
}
812-
813-
if (ret == 0)
814-
offset += file_blk_size;
815-
else
816-
break;
839+
cur_file++;
817840
}
818841
mutex_unlock(&tas_dev->pde_lock);
819-
tas2783_update_calibdata(tas_dev);
842+
843+
if (cur_file == 0) {
844+
dev_err(tas_dev->dev, "fw with no files");
845+
ret = -EINVAL;
846+
} else {
847+
tas2783_update_calibdata(tas_dev);
848+
}
820849

821850
out:
822851
if (!ret)
@@ -1204,6 +1233,14 @@ static s32 tas_io_init(struct device *dev, struct sdw_slave *slave)
12041233

12051234
tas_dev->fw_dl_task_done = false;
12061235
tas_dev->fw_dl_success = false;
1236+
1237+
ret = regmap_write(tas_dev->regmap, TAS2783_SW_RESET, 0x1);
1238+
if (ret) {
1239+
dev_err(dev, "sw reset failed, err=%d", ret);
1240+
return ret;
1241+
}
1242+
usleep_range(2000, 2200);
1243+
12071244
scnprintf(tas_dev->rca_binaryname, sizeof(tas_dev->rca_binaryname),
12081245
"tas2783-%01x.bin", unique_id);
12091246

sound/soc/codecs/tas2783.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#define TASDEV_REG_SDW(book, page, reg) (((book) * 256 * 128) + \
2929
0x800000 + ((page) * 128) + (reg))
3030

31+
#define TAS2783_SW_RESET TASDEV_REG_SDW(0x0, 0x00, 0x01)
3132
/* Volume control */
3233
#define TAS2783_DVC_LVL TASDEV_REG_SDW(0x0, 0x00, 0x1A)
3334
#define TAS2783_AMP_LEVEL TASDEV_REG_SDW(0x0, 0x00, 0x03)

0 commit comments

Comments
 (0)