xref: /linux/sound/soc/codecs/tas2783-sdw.c (revision 48a710760e10a4f36e11233a21860796ba204b1e)
14cc9bd8dSNiranjan H Y // SPDX-License-Identifier: GPL-2.0
24cc9bd8dSNiranjan H Y //
34cc9bd8dSNiranjan H Y // ALSA SoC Texas Instruments TAS2783 Audio Smart Amplifier
44cc9bd8dSNiranjan H Y //
54cc9bd8dSNiranjan H Y // Copyright (C) 2025 Texas Instruments Incorporated
64cc9bd8dSNiranjan H Y // https://www.ti.com
74cc9bd8dSNiranjan H Y //
84cc9bd8dSNiranjan H Y // The TAS2783 driver implements a flexible and configurable
94cc9bd8dSNiranjan H Y // algo coefficient setting for single TAS2783 chips.
104cc9bd8dSNiranjan H Y //
114cc9bd8dSNiranjan H Y // Author: Niranjan H Y <niranjanhy@ti.com>
124cc9bd8dSNiranjan H Y // Author: Baojun Xu <baojun.xu@ti.com>
134cc9bd8dSNiranjan H Y // Author: Kevin Lu <kevin-lu@ti.com>
144cc9bd8dSNiranjan H Y 
154cc9bd8dSNiranjan H Y #include <linux/unaligned.h>
164cc9bd8dSNiranjan H Y #include <linux/crc32.h>
174cc9bd8dSNiranjan H Y #include <linux/efi.h>
184cc9bd8dSNiranjan H Y #include <linux/err.h>
194cc9bd8dSNiranjan H Y #include <linux/firmware.h>
204cc9bd8dSNiranjan H Y #include <linux/init.h>
214cc9bd8dSNiranjan H Y #include <linux/module.h>
224cc9bd8dSNiranjan H Y #include <sound/pcm_params.h>
234cc9bd8dSNiranjan H Y #include <linux/pm.h>
244cc9bd8dSNiranjan H Y #include <linux/pm_runtime.h>
254cc9bd8dSNiranjan H Y #include <linux/regmap.h>
264cc9bd8dSNiranjan H Y #include <linux/wait.h>
274cc9bd8dSNiranjan H Y #include <linux/soundwire/sdw.h>
284cc9bd8dSNiranjan H Y #include <linux/soundwire/sdw_registers.h>
294cc9bd8dSNiranjan H Y #include <linux/soundwire/sdw_type.h>
304cc9bd8dSNiranjan H Y #include <sound/sdw.h>
314cc9bd8dSNiranjan H Y #include <sound/soc.h>
324cc9bd8dSNiranjan H Y #include <sound/tlv.h>
334cc9bd8dSNiranjan H Y #include <sound/tas2781-tlv.h>
344cc9bd8dSNiranjan H Y 
354cc9bd8dSNiranjan H Y #include "tas2783.h"
364cc9bd8dSNiranjan H Y 
374cc9bd8dSNiranjan H Y #define TIMEOUT_FW_DL_MS (3000)
384cc9bd8dSNiranjan H Y #define FW_DL_OFFSET	36
394cc9bd8dSNiranjan H Y #define FW_FL_HDR	12
404cc9bd8dSNiranjan H Y #define TAS2783_PROBE_TIMEOUT 5000
414cc9bd8dSNiranjan H Y #define TAS2783_CALI_GUID EFI_GUID(0x1f52d2a1, 0xbb3a, 0x457d, 0xbc, \
424cc9bd8dSNiranjan H Y 				   0x09, 0x43, 0xa3, 0xf4, 0x31, 0x0a, 0x92)
434cc9bd8dSNiranjan H Y 
444cc9bd8dSNiranjan H Y static const u32 tas2783_cali_reg[] = {
454cc9bd8dSNiranjan H Y 	TAS2783_CAL_R0,
464cc9bd8dSNiranjan H Y 	TAS2783_CAL_INVR0,
474cc9bd8dSNiranjan H Y 	TAS2783_CAL_R0LOW,
484cc9bd8dSNiranjan H Y 	TAS2783_CAL_POWER,
494cc9bd8dSNiranjan H Y 	TAS2783_CAL_TLIM,
504cc9bd8dSNiranjan H Y };
514cc9bd8dSNiranjan H Y 
524cc9bd8dSNiranjan H Y struct bin_header_t {
534cc9bd8dSNiranjan H Y 	u16 vendor_id;
544cc9bd8dSNiranjan H Y 	u16 version;
554cc9bd8dSNiranjan H Y 	u32 file_id;
564cc9bd8dSNiranjan H Y 	u32 length;
574cc9bd8dSNiranjan H Y };
584cc9bd8dSNiranjan H Y 
594cc9bd8dSNiranjan H Y struct calibration_data {
604cc9bd8dSNiranjan H Y 	u32 is_valid;
614cc9bd8dSNiranjan H Y 	unsigned long read_sz;
624cc9bd8dSNiranjan H Y 	u8 data[TAS2783_CALIB_DATA_SZ];
634cc9bd8dSNiranjan H Y };
644cc9bd8dSNiranjan H Y 
654cc9bd8dSNiranjan H Y struct tas2783_prv {
664cc9bd8dSNiranjan H Y 	struct snd_soc_component *component;
674cc9bd8dSNiranjan H Y 	struct calibration_data cali_data;
684cc9bd8dSNiranjan H Y 	struct sdw_slave *sdw_peripheral;
694cc9bd8dSNiranjan H Y 	enum sdw_slave_status status;
704cc9bd8dSNiranjan H Y 	/* calibration */
714cc9bd8dSNiranjan H Y 	struct mutex calib_lock;
724cc9bd8dSNiranjan H Y 	/* pde and firmware download */
734cc9bd8dSNiranjan H Y 	struct mutex pde_lock;
744cc9bd8dSNiranjan H Y 	struct regmap *regmap;
754cc9bd8dSNiranjan H Y 	struct device *dev;
764cc9bd8dSNiranjan H Y 	struct class *class;
774cc9bd8dSNiranjan H Y 	struct attribute_group *cal_attr_groups;
784cc9bd8dSNiranjan H Y 	struct tm tm;
794cc9bd8dSNiranjan H Y 	u8 rca_binaryname[64];
804cc9bd8dSNiranjan H Y 	u8 dev_name[32];
814cc9bd8dSNiranjan H Y 	bool hw_init;
824cc9bd8dSNiranjan H Y 	/* wq for firmware download */
834cc9bd8dSNiranjan H Y 	wait_queue_head_t fw_wait;
844cc9bd8dSNiranjan H Y 	bool fw_dl_task_done;
854cc9bd8dSNiranjan H Y 	bool fw_dl_success;
864cc9bd8dSNiranjan H Y };
874cc9bd8dSNiranjan H Y 
884cc9bd8dSNiranjan H Y static const struct reg_default tas2783_reg_default[] = {
894cc9bd8dSNiranjan H Y 	{TAS2783_AMP_LEVEL, 0x28},
904cc9bd8dSNiranjan H Y 	{TASDEV_REG_SDW(0, 0, 0x03), 0x28},
914cc9bd8dSNiranjan H Y 	{TASDEV_REG_SDW(0, 0, 0x04), 0x21},
924cc9bd8dSNiranjan H Y 	{TASDEV_REG_SDW(0, 0, 0x05), 0x41},
934cc9bd8dSNiranjan H Y 	{TASDEV_REG_SDW(0, 0, 0x06), 0x00},
944cc9bd8dSNiranjan H Y 	{TASDEV_REG_SDW(0, 0, 0x07), 0x20},
954cc9bd8dSNiranjan H Y 	{TASDEV_REG_SDW(0, 0, 0x08), 0x09},
964cc9bd8dSNiranjan H Y 	{TASDEV_REG_SDW(0, 0, 0x09), 0x02},
974cc9bd8dSNiranjan H Y 	{TASDEV_REG_SDW(0, 0, 0x0a), 0x0a},
984cc9bd8dSNiranjan H Y 	{TASDEV_REG_SDW(0, 0, 0x0c), 0x10},
994cc9bd8dSNiranjan H Y 	{TASDEV_REG_SDW(0, 0, 0x0d), 0x13},
1004cc9bd8dSNiranjan H Y 	{TASDEV_REG_SDW(0, 0, 0x0e), 0xc2},
1014cc9bd8dSNiranjan H Y 	{TASDEV_REG_SDW(0, 0, 0x0f), 0x40},
1024cc9bd8dSNiranjan H Y 	{TASDEV_REG_SDW(0, 0, 0x10), 0x04},
1034cc9bd8dSNiranjan H Y 	{TASDEV_REG_SDW(0, 0, 0x13), 0x13},
1044cc9bd8dSNiranjan H Y 	{TASDEV_REG_SDW(0, 0, 0x14), 0x12},
1054cc9bd8dSNiranjan H Y 	{TASDEV_REG_SDW(0, 0, 0x15), 0x00},
1064cc9bd8dSNiranjan H Y 	{TASDEV_REG_SDW(0, 0, 0x16), 0x12},
1074cc9bd8dSNiranjan H Y 	{TASDEV_REG_SDW(0, 0, 0x17), 0x80},
1084cc9bd8dSNiranjan H Y 	{TAS2783_DVC_LVL, 0x00},
1094cc9bd8dSNiranjan H Y 	{TASDEV_REG_SDW(0, 0, 0x1b), 0x61},
1104cc9bd8dSNiranjan H Y 	{TASDEV_REG_SDW(0, 0, 0x1c), 0x36},
1114cc9bd8dSNiranjan H Y 	{TASDEV_REG_SDW(0, 0, 0x1d), 0x00},
1124cc9bd8dSNiranjan H Y 	{TASDEV_REG_SDW(0, 0, 0x1f), 0x01},
1134cc9bd8dSNiranjan H Y 	{TASDEV_REG_SDW(0, 0, 0x20), 0x2e},
1144cc9bd8dSNiranjan H Y 	{TASDEV_REG_SDW(0, 0, 0x21), 0x00},
1154cc9bd8dSNiranjan H Y 	{TASDEV_REG_SDW(0, 0, 0x34), 0x06},
1164cc9bd8dSNiranjan H Y 	{TASDEV_REG_SDW(0, 0, 0x35), 0xbd},
1174cc9bd8dSNiranjan H Y 	{TASDEV_REG_SDW(0, 0, 0x36), 0xad},
1184cc9bd8dSNiranjan H Y 	{TASDEV_REG_SDW(0, 0, 0x37), 0xa8},
1194cc9bd8dSNiranjan H Y 	{TASDEV_REG_SDW(0, 0, 0x38), 0x00},
1204cc9bd8dSNiranjan H Y 	{TASDEV_REG_SDW(0, 0, 0x3b), 0xfc},
1214cc9bd8dSNiranjan H Y 	{TASDEV_REG_SDW(0, 0, 0x3d), 0xdd},
1224cc9bd8dSNiranjan H Y 	{TASDEV_REG_SDW(0, 0, 0x40), 0xf6},
1234cc9bd8dSNiranjan H Y 	{TASDEV_REG_SDW(0, 0, 0x41), 0x14},
1244cc9bd8dSNiranjan H Y 	{TASDEV_REG_SDW(0, 0, 0x5c), 0x19},
1254cc9bd8dSNiranjan H Y 	{TASDEV_REG_SDW(0, 0, 0x5d), 0x80},
1264cc9bd8dSNiranjan H Y 	{TASDEV_REG_SDW(0, 0, 0x63), 0x48},
1274cc9bd8dSNiranjan H Y 	{TASDEV_REG_SDW(0, 0, 0x65), 0x08},
1284cc9bd8dSNiranjan H Y 	{TASDEV_REG_SDW(0, 0, 0x66), 0xb2},
1294cc9bd8dSNiranjan H Y 	{TASDEV_REG_SDW(0, 0, 0x67), 0x00},
1304cc9bd8dSNiranjan H Y 	{TASDEV_REG_SDW(0, 0, 0x6a), 0x12},
1314cc9bd8dSNiranjan H Y 	{TASDEV_REG_SDW(0, 0, 0x6b), 0xfb},
1324cc9bd8dSNiranjan H Y 	{TASDEV_REG_SDW(0, 0, 0x6c), 0x00},
1334cc9bd8dSNiranjan H Y 	{TASDEV_REG_SDW(0, 0, 0x6d), 0x00},
1344cc9bd8dSNiranjan H Y 	{TASDEV_REG_SDW(0, 0, 0x6e), 0x1a},
1354cc9bd8dSNiranjan H Y 	{TASDEV_REG_SDW(0, 0, 0x6f), 0x00},
1364cc9bd8dSNiranjan H Y 	{TASDEV_REG_SDW(0, 0, 0x70), 0x96},
1374cc9bd8dSNiranjan H Y 	{TASDEV_REG_SDW(0, 0, 0x71), 0x02},
1384cc9bd8dSNiranjan H Y 	{TASDEV_REG_SDW(0, 0, 0x73), 0x08},
1394cc9bd8dSNiranjan H Y 	{TASDEV_REG_SDW(0, 0, 0x75), 0xe0},
1404cc9bd8dSNiranjan H Y 	{TASDEV_REG_SDW(0, 0, 0x7a), 0x60},
1414cc9bd8dSNiranjan H Y 	{TASDEV_REG_SDW(0, 0, 0x60), 0x21},
1424cc9bd8dSNiranjan H Y 	{TASDEV_REG_SDW(0, 1, 0x02), 0x00},
1434cc9bd8dSNiranjan H Y 	{TASDEV_REG_SDW(0, 1, 0x17), 0xc0},
1444cc9bd8dSNiranjan H Y 	{TASDEV_REG_SDW(0, 1, 0x19), 0x60},
1454cc9bd8dSNiranjan H Y 	{TASDEV_REG_SDW(0, 1, 0x35), 0x75},
1464cc9bd8dSNiranjan H Y 	{TASDEV_REG_SDW(0, 1, 0x3d), 0x00},
1474cc9bd8dSNiranjan H Y 	{TASDEV_REG_SDW(0, 1, 0x3e), 0x00},
1484cc9bd8dSNiranjan H Y 	{TASDEV_REG_SDW(0, 1, 0x3f), 0x00},
1494cc9bd8dSNiranjan H Y 	{TASDEV_REG_SDW(0, 1, 0x40), 0x00},
1504cc9bd8dSNiranjan H Y 	{TASDEV_REG_SDW(0, 1, 0x41), 0x00},
1514cc9bd8dSNiranjan H Y 	{TASDEV_REG_SDW(0, 1, 0x42), 0x00},
1524cc9bd8dSNiranjan H Y 	{TASDEV_REG_SDW(0, 1, 0x43), 0x00},
1534cc9bd8dSNiranjan H Y 	{TASDEV_REG_SDW(0, 1, 0x44), 0x00},
1544cc9bd8dSNiranjan H Y 	{TASDEV_REG_SDW(0, 1, 0x45), 0x00},
1554cc9bd8dSNiranjan H Y 	{TASDEV_REG_SDW(0, 1, 0x47), 0xab},
1564cc9bd8dSNiranjan H Y 	{TASDEV_REG_SDW(0, 0xfd, 0x0d), 0x0d},
1574cc9bd8dSNiranjan H Y 	{TASDEV_REG_SDW(0, 0xfd, 0x39), 0x00},
1584cc9bd8dSNiranjan H Y 	{TASDEV_REG_SDW(0, 0xfd, 0x3e), 0x00},
1594cc9bd8dSNiranjan H Y 	{TASDEV_REG_SDW(0, 0xfd, 0x45), 0x00},
1604cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_CS21, 0x02, 0), 0x0},
1614cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_CS21, 0x10, 0), 0x0},
1624cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_CS24, 0x02, 0), 0x0},
1634cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_CS24, 0x10, 0), 0x0},
1644cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_CS26, 0x02, 0), 0x0},
1654cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_CS26, 0x10, 0), 0x0},
1664cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_CS28, 0x02, 0), 0x0},
1674cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_CS28, 0x10, 0), 0x0},
1684cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_CS127, 0x02, 0), 0x0},
1694cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_CS127, 0x10, 0), 0x0},
1704cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU21, 0x01, 1), 0x1},
1714cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU21, 0x02, 1), 0x9c00},
1724cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU23, 0x01, 0), 0x1},
1734cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU23, 0x01, 1), 0x1},
1744cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU23, 0x0b, 1), 0x0},
1754cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU23, 0x10, 0), 0x0},
1764cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU26, 0x01, 1), 0x1},
1774cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU26, 0x01, 0), 0x1},
1784cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU26, 0x0b, 1), 0x0},
1794cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU26, 0x10, 0), 0x0},
1804cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU127, 0x01, 0), 0x1},
1814cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU127, 0x01, 1), 0x1},
1824cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU127, 0x01, 2), 0x1},
1834cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU127, 0x0b, 0), 0x0},
1844cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU127, 0x0b, 1), 0x0},
1854cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU127, 0x0b, 2), 0x0},
1864cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU127, 0x10, 0), 0x0},
1874cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT21, 0x04, 0), 0x0},
1884cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT21, 0x08, 0), 0x0},
1894cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT21, 0x10, 0), 0x0},
1904cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT21, 0x11, 0), 0x0},
1914cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT26, 0x04, 0), 0x0},
1924cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT26, 0x08, 0), 0x0},
1934cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT26, 0x10, 0), 0x0},
1944cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT26, 0x11, 0), 0x0},
1954cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT28, 0x04, 0), 0x0},
1964cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT28, 0x08, 0), 0x0},
1974cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT28, 0x10, 0), 0x0},
1984cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT28, 0x11, 0), 0x0},
1994cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT29, 0x04, 0), 0x0},
2004cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT29, 0x08, 0), 0x0},
2014cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT29, 0x10, 0), 0x0},
2024cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT29, 0x11, 0), 0x0},
2034cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MFPU21, 0x01, 0), 0x0},
2044cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MFPU21, 0x04, 0), 0x0},
2054cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MFPU21, 0x05, 0), 0x1},
2064cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MFPU21, 0x08, 0), 0x0},
2074cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MFPU21, 0x10, 0), 0x0},
2084cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MFPU21, 0x11, 0), 0x0},
2094cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MFPU21, 0x12, 0), 0x0},
2104cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MFPU26, 0x01, 0), 0x0},
2114cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MFPU26, 0x04, 0), 0x0},
2124cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MFPU26, 0x05, 0), 0x1},
2134cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MFPU26, 0x08, 0), 0x0},
2144cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MFPU26, 0x10, 0), 0x0},
2154cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MFPU26, 0x11, 0), 0x0},
2164cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MFPU26, 0x12, 0), 0x0},
2174cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MU26, 0x01, 0), 0x0},
2184cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MU26, 0x01, 1), 0x0},
2194cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MU26, 0x01, 2), 0x0},
2204cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MU26, 0x01, 3), 0x0},
2214cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MU26, 0x01, 4), 0x0},
2224cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MU26, 0x01, 5), 0x0},
2234cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MU26, 0x01, 6), 0x0},
2244cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MU26, 0x01, 7), 0x0},
2254cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MU26, 0x06, 0), 0x0},
2264cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT23, 0x04, 0), 0x0},
2274cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT23, 0x08, 0), 0x0},
2284cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT24, 0x04, 0), 0x0},
2294cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT24, 0x08, 0), 0x0},
2304cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT24, 0x11, 0), 0x0},
2314cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT25, 0x04, 0), 0x0},
2324cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT25, 0x08, 0), 0x0},
2334cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT25, 0x11, 0), 0x0},
2344cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT28, 0x04, 0), 0x0},
2354cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT28, 0x08, 0), 0x0},
2364cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT28, 0x11, 0), 0x0},
2374cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x04, 0), 0x0},
2384cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x08, 0), 0x0},
2394cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x11, 0), 0x0},
2404cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 0), 0x0},
2414cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 1), 0x0},
2424cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 2), 0x0},
2434cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 3), 0x0},
2444cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 4), 0x0},
2454cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 5), 0x0},
2464cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 6), 0x0},
2474cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 7), 0x0},
2484cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 8), 0x0},
2494cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 9), 0x0},
2504cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 0xa), 0x0},
2514cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 0xb), 0x0},
2524cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 0xc), 0x0},
2534cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 0xd), 0x0},
2544cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 0xe), 0x0},
2554cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 0xf), 0x0},
2564cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PDE23, 0x1, 0), 0x3},
2574cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PDE23, 0x10, 0), 0x3},
2584cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PPU21, 0x06, 0), 0x0},
2594cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PPU21, 0x10, 0), 0x0},
2604cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PPU21, 0x11, 0), 0x0},
2614cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PPU21, 0x12, 0), 0x0},
2624cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PPU21, 0x13, 0), 0x0},
2634cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PPU26, 0x06, 0), 0x0},
2644cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PPU26, 0x10, 0), 0x0},
2654cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PPU26, 0x11, 0), 0x0},
2664cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PPU26, 0x12, 0), 0x0},
2674cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PPU26, 0x13, 0), 0x0},
2684cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_SAPU29, 0x05, 0), 0x0},
2694cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_SAPU29, 0x10, 0), 0x1},
2704cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_SAPU29, 0x11, 0), 0x0},
2714cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_SAPU29, 0x12, 0), 0x0},
2724cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_TG23, 0x10, 0), 0x0},
2734cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_XU22, 0x01, 0), 0x1},
2744cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_XU22, 0x06, 0), 0x0},
2754cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_XU22, 0x07, 0), 0x0},
2764cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_XU22, 0x08, 0), 0x0},
2774cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_XU22, 0x09, 0), 0x0},
2784cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_XU22, 0x0a, 0), 0x0},
2794cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_XU22, 0x10, 0), 0x1},
2804cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_XU22, 0x12, 0), 0x0},
2814cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_XU22, 0x13, 0), 0x0},
2824cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_XU22, 0x14, 0), 0x0},
2834cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_XU22, 0x15, 0), 0x0},
2844cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_XU22, 0x16, 0), 0x0},
2854cc9bd8dSNiranjan H Y 	{SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_UDMPU23, 0x10, 0), 0x0},
2864cc9bd8dSNiranjan H Y };
2874cc9bd8dSNiranjan H Y 
2884cc9bd8dSNiranjan H Y static const struct reg_sequence tas2783_init_seq[] = {
2894cc9bd8dSNiranjan H Y 	REG_SEQ0(SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PPU21, 0x10, 0x00), 0x04),
2904cc9bd8dSNiranjan H Y 	REG_SEQ0(0x00800418, 0x00),
2914cc9bd8dSNiranjan H Y 	REG_SEQ0(0x00800419, 0x00),
2924cc9bd8dSNiranjan H Y 	REG_SEQ0(0x0080041a, 0x00),
2934cc9bd8dSNiranjan H Y 	REG_SEQ0(0x0080041b, 0x00),
2944cc9bd8dSNiranjan H Y 	REG_SEQ0(0x00800428, 0x40),
2954cc9bd8dSNiranjan H Y 	REG_SEQ0(0x00800429, 0x00),
2964cc9bd8dSNiranjan H Y 	REG_SEQ0(0x0080042a, 0x00),
2974cc9bd8dSNiranjan H Y 	REG_SEQ0(0x0080042b, 0x00),
2984cc9bd8dSNiranjan H Y 	REG_SEQ0(SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU23, 0x1, 0x00), 0x00),
2994cc9bd8dSNiranjan H Y 	REG_SEQ0(0x0080005c, 0xD9),
3004cc9bd8dSNiranjan H Y 	REG_SEQ0(0x00800082, 0x20),
3014cc9bd8dSNiranjan H Y 	REG_SEQ0(0x008000a1, 0x00),
3024cc9bd8dSNiranjan H Y 	REG_SEQ0(0x00800097, 0xc8),
3034cc9bd8dSNiranjan H Y 	REG_SEQ0(0x00800099, 0x20),
3044cc9bd8dSNiranjan H Y 	REG_SEQ0(0x008000c7, 0xaa),
3054cc9bd8dSNiranjan H Y 	REG_SEQ0(0x008000b5, 0x74),
3064cc9bd8dSNiranjan H Y 	REG_SEQ0(0x00800082, 0x20),
3074cc9bd8dSNiranjan H Y 	REG_SEQ0(0x00807e8d, 0x0d),
3084cc9bd8dSNiranjan H Y 	REG_SEQ0(0x00807eb9, 0x53),
3094cc9bd8dSNiranjan H Y 	REG_SEQ0(0x00807ebe, 0x42),
3104cc9bd8dSNiranjan H Y 	REG_SEQ0(0x00807ec5, 0x37),
3114cc9bd8dSNiranjan H Y 	REG_SEQ0(0x00800066, 0x92),
3124cc9bd8dSNiranjan H Y 	REG_SEQ0(0x00800003, 0x28),
3134cc9bd8dSNiranjan H Y 	REG_SEQ0(0x00800004, 0x21),
3144cc9bd8dSNiranjan H Y 	REG_SEQ0(0x00800005, 0x41),
3154cc9bd8dSNiranjan H Y 	REG_SEQ0(0x00800006, 0x00),
3164cc9bd8dSNiranjan H Y 	REG_SEQ0(0x00800007, 0x20),
3174cc9bd8dSNiranjan H Y 	REG_SEQ0(0x0080000c, 0x10),
3184cc9bd8dSNiranjan H Y 	REG_SEQ0(0x00800013, 0x08),
3194cc9bd8dSNiranjan H Y 	REG_SEQ0(0x00800015, 0x00),
3204cc9bd8dSNiranjan H Y 	REG_SEQ0(0x00800017, 0x80),
3214cc9bd8dSNiranjan H Y 	REG_SEQ0(0x0080001a, 0x00),
3224cc9bd8dSNiranjan H Y 	REG_SEQ0(0x0080001b, 0x22),
3234cc9bd8dSNiranjan H Y 	REG_SEQ0(0x0080001c, 0x36),
3244cc9bd8dSNiranjan H Y 	REG_SEQ0(0x0080001d, 0x01),
3254cc9bd8dSNiranjan H Y 	REG_SEQ0(0x0080001f, 0x00),
3264cc9bd8dSNiranjan H Y 	REG_SEQ0(0x00800020, 0x2e),
3274cc9bd8dSNiranjan H Y 	REG_SEQ0(0x00800034, 0x06),
3284cc9bd8dSNiranjan H Y 	REG_SEQ0(0x00800035, 0xb9),
3294cc9bd8dSNiranjan H Y 	REG_SEQ0(0x00800036, 0xad),
3304cc9bd8dSNiranjan H Y 	REG_SEQ0(0x00800037, 0xa8),
3314cc9bd8dSNiranjan H Y 	REG_SEQ0(0x00800038, 0x00),
3324cc9bd8dSNiranjan H Y 	REG_SEQ0(0x0080003b, 0xfc),
3334cc9bd8dSNiranjan H Y 	REG_SEQ0(0x0080003d, 0xdd),
3344cc9bd8dSNiranjan H Y 	REG_SEQ0(0x00800040, 0xf6),
3354cc9bd8dSNiranjan H Y 	REG_SEQ0(0x00800041, 0x14),
3364cc9bd8dSNiranjan H Y 	REG_SEQ0(0x0080005c, 0x19),
3374cc9bd8dSNiranjan H Y 	REG_SEQ0(0x0080005d, 0x80),
3384cc9bd8dSNiranjan H Y 	REG_SEQ0(0x00800063, 0x48),
3394cc9bd8dSNiranjan H Y 	REG_SEQ0(0x00800065, 0x08),
3404cc9bd8dSNiranjan H Y 	REG_SEQ0(0x00800067, 0x00),
3414cc9bd8dSNiranjan H Y 	REG_SEQ0(0x0080006a, 0x12),
3424cc9bd8dSNiranjan H Y 	REG_SEQ0(0x0080006b, 0x7b),
3434cc9bd8dSNiranjan H Y 	REG_SEQ0(0x0080006c, 0x00),
3444cc9bd8dSNiranjan H Y 	REG_SEQ0(0x0080006d, 0x00),
3454cc9bd8dSNiranjan H Y 	REG_SEQ0(0x0080006e, 0x1a),
3464cc9bd8dSNiranjan H Y 	REG_SEQ0(0x0080006f, 0x00),
3474cc9bd8dSNiranjan H Y 	REG_SEQ0(0x00800070, 0x96),
3484cc9bd8dSNiranjan H Y 	REG_SEQ0(0x00800071, 0x02),
3494cc9bd8dSNiranjan H Y 	REG_SEQ0(0x00800073, 0x08),
3504cc9bd8dSNiranjan H Y 	REG_SEQ0(0x00800075, 0xe0),
3514cc9bd8dSNiranjan H Y 	REG_SEQ0(0x0080007a, 0x60),
3524cc9bd8dSNiranjan H Y 	REG_SEQ0(0x008000bd, 0x00),
3534cc9bd8dSNiranjan H Y 	REG_SEQ0(0x008000be, 0x00),
3544cc9bd8dSNiranjan H Y 	REG_SEQ0(0x008000bf, 0x00),
3554cc9bd8dSNiranjan H Y 	REG_SEQ0(0x008000c0, 0x00),
3564cc9bd8dSNiranjan H Y 	REG_SEQ0(0x008000c1, 0x00),
3574cc9bd8dSNiranjan H Y 	REG_SEQ0(0x008000c2, 0x00),
3584cc9bd8dSNiranjan H Y 	REG_SEQ0(0x008000c3, 0x00),
3594cc9bd8dSNiranjan H Y 	REG_SEQ0(0x008000c4, 0x00),
3604cc9bd8dSNiranjan H Y 	REG_SEQ0(0x008000c5, 0x00),
3614cc9bd8dSNiranjan H Y 	REG_SEQ0(0x00800008, 0x49),
3624cc9bd8dSNiranjan H Y 	REG_SEQ0(0x00800009, 0x02),
3634cc9bd8dSNiranjan H Y 	REG_SEQ0(0x0080000a, 0x1a),
3644cc9bd8dSNiranjan H Y 	REG_SEQ0(0x0080000d, 0x93),
3654cc9bd8dSNiranjan H Y 	REG_SEQ0(0x0080000e, 0x82),
3664cc9bd8dSNiranjan H Y 	REG_SEQ0(0x0080000f, 0x42),
3674cc9bd8dSNiranjan H Y 	REG_SEQ0(0x00800010, 0x84),
3684cc9bd8dSNiranjan H Y 	REG_SEQ0(0x00800014, 0x0a),
3694cc9bd8dSNiranjan H Y 	REG_SEQ0(0x00800016, 0x00),
3704cc9bd8dSNiranjan H Y 	REG_SEQ0(0x00800060, 0x21),
3714cc9bd8dSNiranjan H Y };
3724cc9bd8dSNiranjan H Y 
3734cc9bd8dSNiranjan H Y static int tas2783_sdca_mbq_size(struct device *dev, u32 reg)
3744cc9bd8dSNiranjan H Y {
3754cc9bd8dSNiranjan H Y 	switch (reg) {
3764cc9bd8dSNiranjan H Y 	case 0x000 ... 0x080: /* Data port 0. */
3774cc9bd8dSNiranjan H Y 	case 0x100 ... 0x140: /* Data port 1. */
3784cc9bd8dSNiranjan H Y 	case 0x200 ... 0x240: /* Data port 2. */
3794cc9bd8dSNiranjan H Y 	case 0x300 ... 0x340: /* Data port 3. */
3804cc9bd8dSNiranjan H Y 	case 0x400 ... 0x440: /* Data port 4. */
3814cc9bd8dSNiranjan H Y 	case 0x500 ... 0x540: /* Data port 5. */
3824cc9bd8dSNiranjan H Y 	case 0x800000 ... 0x803fff: /* Page 0 ~ 127. */
3834cc9bd8dSNiranjan H Y 	case 0x807e80 ... 0x807eff: /* Page 253. */
3844cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_UDMPU23,
3854cc9bd8dSNiranjan H Y 			  TAS2783_SDCA_CTL_UDMPU_CLUSTER, 0):
3864cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU21, TAS2783_SDCA_CTL_FU_MUTE,
3874cc9bd8dSNiranjan H Y 			  TAS2783_DEVICE_CHANNEL_LEFT):
3884cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PDE23, 0x1, 0):
3894cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PDE23, 0x10, 0):
3904cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT21, 0x04, 0):
3914cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_SAPU29, 0x10, 0):
3924cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_SAPU29, 0x11, 0):
3934cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_SAPU29, 0x12, 0):
3944cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PPU21, 0x10, 0):
3954cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PPU21, 0x11, 0):
3964cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PPU26, 0x10, 0):
3974cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PPU26, 0x11, 0):
3984cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_TG23, 0x10, 0):
3994cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_XU22, 0x01, 0):
4004cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_XU22, 0x08, 0):
4014cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_XU22, 0x0a, 0):
4024cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_XU22, 0x10, 0):
4034cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_XU22, 0x14, 0):
4044cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_XU22, 0x15, 0):
4054cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_XU22, 0x16, 0):
4064cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT26, 0x04, 0):
4074cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT28, 0x04, 0):
4084cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT29, 0x04, 0):
4094cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT23, 0x04, 0):
4104cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT24, 0x04, 0):
4114cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT28, 0x04, 0):
4124cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x04, 0):
4134cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 0):
4144cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 1):
4154cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 2):
4164cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 3):
4174cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 4):
4184cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 5):
4194cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 6):
4204cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 7):
4214cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 8):
4224cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 9):
4234cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 0xa):
4244cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 0xb):
4254cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 0xc):
4264cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 0xd):
4274cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 0xe):
4284cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 0xf):
4294cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_CS21, 0x02, 0):
4304cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_CS21, 0x10, 0):
4314cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_CS24, 0x02, 0):
4324cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_CS24, 0x10, 0):
4334cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_CS25, 0x02, 0):
4344cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_CS25, 0x10, 0):
4354cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_CS127, 0x02, 0):
4364cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_CS127, 0x10, 0):
4374cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_CS26, 0x02, 0):
4384cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_CS26, 0x10, 0):
4394cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_CS28, 0x02, 0):
4404cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_CS28, 0x10, 0):
4414cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MFPU21, 0x01, 0):
4424cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MFPU21, 0x04, 0):
4434cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MFPU21, 0x05, 0):
4444cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MFPU21, 0x10, 0):
4454cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MFPU21, 0x11, 0):
4464cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU127, 0x01, 1):
4474cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU127, 0x01, 2):
4484cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU127, 0x01, 0):
4494cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU26, 0x01, 1):
4504cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU26, 0x01, 0):
4514cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MFPU26, 0x01, 0):
4524cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MFPU26, 0x04, 0):
4534cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MFPU26, 0x05, 0):
4544cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MFPU26, 0x10, 0):
4554cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MFPU26, 0x11, 0):
4564cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU23, 0x01, 0):
4574cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU23, 0x01, 1):
4584cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT25, 0x04, 0):
4594cc9bd8dSNiranjan H Y 		return 1;
4604cc9bd8dSNiranjan H Y 
4614cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT26, 0x10, 0):
4624cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT26, 0x11, 0):
4634cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT28, 0x10, 0):
4644cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT28, 0x11, 0):
4654cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT29, 0x10, 0):
4664cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT29, 0x11, 0):
4674cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT24, 0x11, 0):
4684cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT25, 0x11, 0):
4694cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT28, 0x11, 0):
4704cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x11, 0):
4714cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MU26, 0x01, 0):
4724cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MU26, 0x01, 1):
4734cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MU26, 0x01, 2):
4744cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MU26, 0x01, 3):
4754cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MU26, 0x01, 4):
4764cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MU26, 0x01, 5):
4774cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MU26, 0x01, 6):
4784cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MU26, 0x01, 7):
4794cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU21, 0x02, 1):
4804cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU23, 0x0b, 1):
4814cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU127, 0x0b, 1):
4824cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU127, 0x0b, 2):
4834cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU127, 0x0b, 0):
4844cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU26, 0x0b, 0):
4854cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU26, 0x0b, 1):
4864cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_XU22, 0x07, 0):
4874cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_XU22, 0x09, 0):
4884cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MFPU21, 0x12, 0):
4894cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MFPU26, 0x12, 0):
4904cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PPU21, 0x12, 0):
4914cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PPU21, 0x13, 0):
4924cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PPU26, 0x12, 0):
4934cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PPU26, 0x13, 0):
4944cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT21, 0x10, 0):
4954cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT21, 0x11, 0):
4964cc9bd8dSNiranjan H Y 		return 2;
4974cc9bd8dSNiranjan H Y 
4984cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU23, 0x10, 0):
4994cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT21, 0x08, 0):
5004cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT26, 0x08, 0):
5014cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT28, 0x08, 0):
5024cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT29, 0x08, 0):
5034cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT23, 0x08, 0):
5044cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT24, 0x08, 0):
5054cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT25, 0x08, 0):
5064cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT28, 0x08, 0):
5074cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x08, 0):
5084cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MU26, 0x06, 0):
5094cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU127, 0x10, 0):
5104cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU26, 0x10, 0):
5114cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_XU22, 0x06, 0):
5124cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_XU22, 0x12, 0):
5134cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_XU22, 0x13, 0):
5144cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MFPU21, 0x08, 0):
5154cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MFPU26, 0x08, 0):
5164cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_SAPU29, 0x05, 0):
5174cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PPU21, 0x06, 0):
5184cc9bd8dSNiranjan H Y 	case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PPU26, 0x06, 0):
5194cc9bd8dSNiranjan H Y 		return 4;
5204cc9bd8dSNiranjan H Y 
5214cc9bd8dSNiranjan H Y 	default:
5224cc9bd8dSNiranjan H Y 		return 0;
5234cc9bd8dSNiranjan H Y 	}
5244cc9bd8dSNiranjan H Y }
5254cc9bd8dSNiranjan H Y 
5264cc9bd8dSNiranjan H Y static bool tas2783_readable_register(struct device *dev, unsigned int reg)
5274cc9bd8dSNiranjan H Y {
5284cc9bd8dSNiranjan H Y 	return tas2783_sdca_mbq_size(dev, reg) > 0;
5294cc9bd8dSNiranjan H Y }
5304cc9bd8dSNiranjan H Y 
5314cc9bd8dSNiranjan H Y static bool tas2783_volatile_register(struct device *dev, u32 reg)
5324cc9bd8dSNiranjan H Y {
5334cc9bd8dSNiranjan H Y 	switch (reg) {
5344cc9bd8dSNiranjan H Y 	case 0x000 ... 0x080: /* Data port 0. */
5354cc9bd8dSNiranjan H Y 	case 0x100 ... 0x140: /* Data port 1. */
5364cc9bd8dSNiranjan H Y 	case 0x200 ... 0x240: /* Data port 2. */
5374cc9bd8dSNiranjan H Y 	case 0x300 ... 0x340: /* Data port 3. */
5384cc9bd8dSNiranjan H Y 	case 0x400 ... 0x440: /* Data port 4. */
5394cc9bd8dSNiranjan H Y 	case 0x500 ... 0x540: /* Data port 5. */
5404cc9bd8dSNiranjan H Y 	case 0x800001:
5414cc9bd8dSNiranjan H Y 		return true;
5424cc9bd8dSNiranjan H Y 
5434cc9bd8dSNiranjan H Y 	default:
5444cc9bd8dSNiranjan H Y 		return false;
5454cc9bd8dSNiranjan H Y 	}
5464cc9bd8dSNiranjan H Y }
5474cc9bd8dSNiranjan H Y 
5484cc9bd8dSNiranjan H Y static const struct regmap_config tas_regmap = {
5494cc9bd8dSNiranjan H Y 	.reg_bits = 32,
5504cc9bd8dSNiranjan H Y 	.val_bits = 8,
5514cc9bd8dSNiranjan H Y 	.readable_reg = tas2783_readable_register,
5524cc9bd8dSNiranjan H Y 	.volatile_reg = tas2783_volatile_register,
5534cc9bd8dSNiranjan H Y 	.reg_defaults = tas2783_reg_default,
5544cc9bd8dSNiranjan H Y 	.num_reg_defaults = ARRAY_SIZE(tas2783_reg_default),
5554cc9bd8dSNiranjan H Y 	.max_register = 0x41008000 + TASDEV_REG_SDW(0xa1, 0x60, 0x7f),
5564cc9bd8dSNiranjan H Y 	.cache_type = REGCACHE_MAPLE,
5574cc9bd8dSNiranjan H Y 	.use_single_read = true,
5584cc9bd8dSNiranjan H Y 	.use_single_write = true,
5594cc9bd8dSNiranjan H Y };
5604cc9bd8dSNiranjan H Y 
5614cc9bd8dSNiranjan H Y static const struct regmap_sdw_mbq_cfg tas2783_mbq_cfg = {
5624cc9bd8dSNiranjan H Y 	.mbq_size = tas2783_sdca_mbq_size,
5634cc9bd8dSNiranjan H Y };
5644cc9bd8dSNiranjan H Y 
5654cc9bd8dSNiranjan H Y static s32 tas2783_digital_getvol(struct snd_kcontrol *kcontrol,
5664cc9bd8dSNiranjan H Y 				  struct snd_ctl_elem_value *ucontrol)
5674cc9bd8dSNiranjan H Y {
5684cc9bd8dSNiranjan H Y 	return snd_soc_get_volsw(kcontrol, ucontrol);
5694cc9bd8dSNiranjan H Y }
5704cc9bd8dSNiranjan H Y 
5714cc9bd8dSNiranjan H Y static s32 tas2783_digital_putvol(struct snd_kcontrol *kcontrol,
5724cc9bd8dSNiranjan H Y 				  struct snd_ctl_elem_value *ucontrol)
5734cc9bd8dSNiranjan H Y {
5744cc9bd8dSNiranjan H Y 	return snd_soc_put_volsw(kcontrol, ucontrol);
5754cc9bd8dSNiranjan H Y }
5764cc9bd8dSNiranjan H Y 
5774cc9bd8dSNiranjan H Y static s32 tas2783_amp_getvol(struct snd_kcontrol *kcontrol,
5784cc9bd8dSNiranjan H Y 			      struct snd_ctl_elem_value *ucontrol)
5794cc9bd8dSNiranjan H Y {
5804cc9bd8dSNiranjan H Y 	return snd_soc_get_volsw(kcontrol, ucontrol);
5814cc9bd8dSNiranjan H Y }
5824cc9bd8dSNiranjan H Y 
5834cc9bd8dSNiranjan H Y static s32 tas2783_amp_putvol(struct snd_kcontrol *kcontrol,
5844cc9bd8dSNiranjan H Y 			      struct snd_ctl_elem_value *ucontrol)
5854cc9bd8dSNiranjan H Y {
5864cc9bd8dSNiranjan H Y 	return snd_soc_put_volsw(kcontrol, ucontrol);
5874cc9bd8dSNiranjan H Y }
5884cc9bd8dSNiranjan H Y 
5894cc9bd8dSNiranjan H Y static const struct snd_kcontrol_new tas2783_snd_controls[] = {
5904cc9bd8dSNiranjan H Y 	SOC_SINGLE_RANGE_EXT_TLV("Amp Volume", TAS2783_AMP_LEVEL,
5914cc9bd8dSNiranjan H Y 				 1, 0, 20, 0, tas2783_amp_getvol,
5924cc9bd8dSNiranjan H Y 				 tas2783_amp_putvol, tas2781_amp_tlv),
5934cc9bd8dSNiranjan H Y 	SOC_SINGLE_RANGE_EXT_TLV("Speaker Volume", TAS2783_DVC_LVL,
5944cc9bd8dSNiranjan H Y 				 0, 0, 200, 1, tas2783_digital_getvol,
5954cc9bd8dSNiranjan H Y 				 tas2783_digital_putvol, tas2781_dvc_tlv),
5964cc9bd8dSNiranjan H Y };
5974cc9bd8dSNiranjan H Y 
5984cc9bd8dSNiranjan H Y static s32 tas2783_validate_calibdata(struct tas2783_prv *tas_dev,
5994cc9bd8dSNiranjan H Y 				      u8 *data, u32 size)
6004cc9bd8dSNiranjan H Y {
6014cc9bd8dSNiranjan H Y 	u32 ts, spk_count, size_calculated;
6024cc9bd8dSNiranjan H Y 	u32 crc_calculated, crc_read, i;
6034cc9bd8dSNiranjan H Y 	u32 *tmp_val;
6044cc9bd8dSNiranjan H Y 	struct tm tm;
6054cc9bd8dSNiranjan H Y 
6064cc9bd8dSNiranjan H Y 	i = 0;
6074cc9bd8dSNiranjan H Y 	tmp_val = (u32 *)data;
6084cc9bd8dSNiranjan H Y 	if (tmp_val[i++] != 2783) {
6094cc9bd8dSNiranjan H Y 		dev_err(tas_dev->dev, "cal data magic number mismatch");
6104cc9bd8dSNiranjan H Y 		return -EINVAL;
6114cc9bd8dSNiranjan H Y 	}
6124cc9bd8dSNiranjan H Y 
6134cc9bd8dSNiranjan H Y 	spk_count = tmp_val[i++];
6144cc9bd8dSNiranjan H Y 	if (spk_count > TAS2783_CALIB_MAX_SPK_COUNT) {
6154cc9bd8dSNiranjan H Y 		dev_err(tas_dev->dev, "cal data spk_count too large");
6164cc9bd8dSNiranjan H Y 		return -EINVAL;
6174cc9bd8dSNiranjan H Y 	}
6184cc9bd8dSNiranjan H Y 
6194cc9bd8dSNiranjan H Y 	ts = tmp_val[i++];
6204cc9bd8dSNiranjan H Y 	time64_to_tm(ts, 0, &tm);
6214cc9bd8dSNiranjan H Y 	dev_dbg(tas_dev->dev, "cal data timestamp: %ld-%d-%d %d:%d:%d",
6224cc9bd8dSNiranjan H Y 		tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
6234cc9bd8dSNiranjan H Y 		tm.tm_hour, tm.tm_min, tm.tm_sec);
6244cc9bd8dSNiranjan H Y 
6254cc9bd8dSNiranjan H Y 	size_calculated =
6264cc9bd8dSNiranjan H Y 		(spk_count * TAS2783_CALIB_PARAMS * sizeof(u32)) +
6274cc9bd8dSNiranjan H Y 		TAS2783_CALIB_HDR_SZ + TAS2783_CALIB_CRC_SZ;
6284cc9bd8dSNiranjan H Y 	if (size_calculated > TAS2783_CALIB_DATA_SZ) {
6294cc9bd8dSNiranjan H Y 		dev_err(tas_dev->dev, "cali data sz too large");
6304cc9bd8dSNiranjan H Y 		return -EINVAL;
6314cc9bd8dSNiranjan H Y 	} else if (size < size_calculated) {
6324cc9bd8dSNiranjan H Y 		dev_err(tas_dev->dev, "cali data size mismatch calc=%u vs %d\n",
6334cc9bd8dSNiranjan H Y 			size, size_calculated);
6344cc9bd8dSNiranjan H Y 		return -EINVAL;
6354cc9bd8dSNiranjan H Y 	}
6364cc9bd8dSNiranjan H Y 
6374cc9bd8dSNiranjan H Y 	crc_calculated = crc32(~0, data,
6384cc9bd8dSNiranjan H Y 			       size_calculated - TAS2783_CALIB_CRC_SZ) ^ ~0;
6394cc9bd8dSNiranjan H Y 	crc_read = tmp_val[(size_calculated - TAS2783_CALIB_CRC_SZ) / sizeof(u32)];
6404cc9bd8dSNiranjan H Y 	if (crc_calculated != crc_read) {
6414cc9bd8dSNiranjan H Y 		dev_err(tas_dev->dev,
6424cc9bd8dSNiranjan H Y 			"calib data integrity check fail, 0x%08x vs 0x%08x\n",
6434cc9bd8dSNiranjan H Y 			crc_calculated, crc_read);
6444cc9bd8dSNiranjan H Y 		return -EINVAL;
6454cc9bd8dSNiranjan H Y 	}
6464cc9bd8dSNiranjan H Y 
6474cc9bd8dSNiranjan H Y 	return 0;
6484cc9bd8dSNiranjan H Y }
6494cc9bd8dSNiranjan H Y 
6504cc9bd8dSNiranjan H Y static void tas2783_set_calib_params_to_device(struct tas2783_prv *tas_dev, u32 *cali_data)
6514cc9bd8dSNiranjan H Y {
6524cc9bd8dSNiranjan H Y 	u32 dev_count, offset, i, device_num;
6534cc9bd8dSNiranjan H Y 	u32 reg_value;
6544cc9bd8dSNiranjan H Y 	u8 buf[4];
6554cc9bd8dSNiranjan H Y 
6564cc9bd8dSNiranjan H Y 	dev_count = cali_data[1];
6574cc9bd8dSNiranjan H Y 	offset = 3;
6584cc9bd8dSNiranjan H Y 
6594cc9bd8dSNiranjan H Y 	for (device_num = 0; device_num < dev_count; device_num++) {
6604cc9bd8dSNiranjan H Y 		if (cali_data[offset] != tas_dev->sdw_peripheral->id.unique_id) {
6614cc9bd8dSNiranjan H Y 			offset += TAS2783_CALIB_PARAMS;
6624cc9bd8dSNiranjan H Y 			continue;
6634cc9bd8dSNiranjan H Y 		}
6644cc9bd8dSNiranjan H Y 		offset++;
6654cc9bd8dSNiranjan H Y 
6664cc9bd8dSNiranjan H Y 		for (i = 0; i < ARRAY_SIZE(tas2783_cali_reg); i++) {
6674cc9bd8dSNiranjan H Y 			reg_value = cali_data[offset + i];
6684cc9bd8dSNiranjan H Y 			buf[0] = reg_value >> 24;
6694cc9bd8dSNiranjan H Y 			buf[1] = reg_value >> 16;
6704cc9bd8dSNiranjan H Y 			buf[2] = reg_value >> 8;
6714cc9bd8dSNiranjan H Y 			buf[3] = reg_value & 0xff;
6724cc9bd8dSNiranjan H Y 			regmap_bulk_write(tas_dev->regmap, tas2783_cali_reg[i],
6734cc9bd8dSNiranjan H Y 					  buf, sizeof(u32));
6744cc9bd8dSNiranjan H Y 		}
6754cc9bd8dSNiranjan H Y 		break;
6764cc9bd8dSNiranjan H Y 	}
6774cc9bd8dSNiranjan H Y 
6784cc9bd8dSNiranjan H Y 	if (device_num == dev_count)
6794cc9bd8dSNiranjan H Y 		dev_err(tas_dev->dev, "device not found\n");
6804cc9bd8dSNiranjan H Y 	else
6814cc9bd8dSNiranjan H Y 		dev_dbg(tas_dev->dev, "calib data update done\n");
6824cc9bd8dSNiranjan H Y }
6834cc9bd8dSNiranjan H Y 
6844cc9bd8dSNiranjan H Y static s32 tas2783_update_calibdata(struct tas2783_prv *tas_dev)
6854cc9bd8dSNiranjan H Y {
6864cc9bd8dSNiranjan H Y 	efi_guid_t efi_guid = TAS2783_CALI_GUID;
6874cc9bd8dSNiranjan H Y 	u32 attr, i, *tmp_val;
6884cc9bd8dSNiranjan H Y 	unsigned long size;
6894cc9bd8dSNiranjan H Y 	s32 ret;
6904cc9bd8dSNiranjan H Y 	efi_status_t status;
6914cc9bd8dSNiranjan H Y 	static efi_char16_t efi_names[][32] = {
6924cc9bd8dSNiranjan H Y 		L"SmartAmpCalibrationData", L"CALI_DATA"};
6934cc9bd8dSNiranjan H Y 
6944cc9bd8dSNiranjan H Y 	tmp_val = (u32 *)tas_dev->cali_data.data;
6954cc9bd8dSNiranjan H Y 	attr = 0;
6964cc9bd8dSNiranjan H Y 	i = 0;
6974cc9bd8dSNiranjan H Y 
6984cc9bd8dSNiranjan H Y 	/*
6994cc9bd8dSNiranjan H Y 	 * In some cases, the calibration is performed in Windows,
7004cc9bd8dSNiranjan H Y 	 * and data was saved in UEFI. Linux can access it.
7014cc9bd8dSNiranjan H Y 	 */
7024cc9bd8dSNiranjan H Y 	for (i = 0; i < ARRAY_SIZE(efi_names); i++) {
7034cc9bd8dSNiranjan H Y 		size = 0;
7044cc9bd8dSNiranjan H Y 		status = efi.get_variable(efi_names[i], &efi_guid, &attr,
7054cc9bd8dSNiranjan H Y 					  &size, NULL);
7064cc9bd8dSNiranjan H Y 		if (size > TAS2783_CALIB_DATA_SZ) {
7074cc9bd8dSNiranjan H Y 			dev_err(tas_dev->dev, "cali data too large\n");
7084cc9bd8dSNiranjan H Y 			break;
7094cc9bd8dSNiranjan H Y 		}
7104cc9bd8dSNiranjan H Y 
7114cc9bd8dSNiranjan H Y 		tas_dev->cali_data.read_sz = size;
7124cc9bd8dSNiranjan H Y 		if (status == EFI_BUFFER_TOO_SMALL) {
7134cc9bd8dSNiranjan H Y 			status = efi.get_variable(efi_names[i], &efi_guid, &attr,
7144cc9bd8dSNiranjan H Y 							&tas_dev->cali_data.read_sz,
7154cc9bd8dSNiranjan H Y 							tas_dev->cali_data.data);
7164cc9bd8dSNiranjan H Y 			dev_dbg(tas_dev->dev, "cali get %lu bytes result:%ld\n",
7174cc9bd8dSNiranjan H Y 				tas_dev->cali_data.read_sz, status);
7184cc9bd8dSNiranjan H Y 		}
7194cc9bd8dSNiranjan H Y 		if (status == EFI_SUCCESS)
7204cc9bd8dSNiranjan H Y 			break;
7214cc9bd8dSNiranjan H Y 	}
7224cc9bd8dSNiranjan H Y 
7234cc9bd8dSNiranjan H Y 	if (status != EFI_SUCCESS) {
7244cc9bd8dSNiranjan H Y 		/* Failed got calibration data from EFI. */
7254cc9bd8dSNiranjan H Y 		dev_dbg(tas_dev->dev, "No calibration data in UEFI.");
7264cc9bd8dSNiranjan H Y 		return 0;
7274cc9bd8dSNiranjan H Y 	}
7284cc9bd8dSNiranjan H Y 
7294cc9bd8dSNiranjan H Y 	mutex_lock(&tas_dev->calib_lock);
7304cc9bd8dSNiranjan H Y 	ret = tas2783_validate_calibdata(tas_dev, tas_dev->cali_data.data,
7314cc9bd8dSNiranjan H Y 					 tas_dev->cali_data.read_sz);
7324cc9bd8dSNiranjan H Y 	if (!ret)
7334cc9bd8dSNiranjan H Y 		tas2783_set_calib_params_to_device(tas_dev, tmp_val);
7344cc9bd8dSNiranjan H Y 	mutex_unlock(&tas_dev->calib_lock);
7354cc9bd8dSNiranjan H Y 
7364cc9bd8dSNiranjan H Y 	return ret;
7374cc9bd8dSNiranjan H Y }
7384cc9bd8dSNiranjan H Y 
7394cc9bd8dSNiranjan H Y static s32 read_header(const u8 *data, struct bin_header_t *hdr)
7404cc9bd8dSNiranjan H Y {
7414cc9bd8dSNiranjan H Y 	hdr->vendor_id = get_unaligned_le16(&data[0]);
7424cc9bd8dSNiranjan H Y 	hdr->file_id = get_unaligned_le32(&data[2]);
7434cc9bd8dSNiranjan H Y 	hdr->version = get_unaligned_le16(&data[6]);
7444cc9bd8dSNiranjan H Y 	hdr->length = get_unaligned_le32(&data[8]);
7454cc9bd8dSNiranjan H Y 	return 12;
7464cc9bd8dSNiranjan H Y }
7474cc9bd8dSNiranjan H Y 
7484cc9bd8dSNiranjan H Y static void tas2783_fw_ready(const struct firmware *fmw, void *context)
7494cc9bd8dSNiranjan H Y {
7504cc9bd8dSNiranjan H Y 	struct tas2783_prv *tas_dev =
7514cc9bd8dSNiranjan H Y 		(struct tas2783_prv *)context;
7524cc9bd8dSNiranjan H Y 	const u8 *buf = NULL;
7534cc9bd8dSNiranjan H Y 	s32 offset = 0, img_sz, file_blk_size, ret;
7544cc9bd8dSNiranjan H Y 	struct bin_header_t hdr;
7554cc9bd8dSNiranjan H Y 
7564cc9bd8dSNiranjan H Y 	if (!fmw || !fmw->data) {
7574cc9bd8dSNiranjan H Y 		/* No firmware binary, devices will work in ROM mode. */
7584cc9bd8dSNiranjan H Y 		dev_err(tas_dev->dev,
7594cc9bd8dSNiranjan H Y 			"Failed to read %s, no side-effect on driver running\n",
7604cc9bd8dSNiranjan H Y 			tas_dev->rca_binaryname);
7614cc9bd8dSNiranjan H Y 		ret = -EINVAL;
7624cc9bd8dSNiranjan H Y 		goto out;
7634cc9bd8dSNiranjan H Y 	}
7644cc9bd8dSNiranjan H Y 
7654cc9bd8dSNiranjan H Y 	mutex_lock(&tas_dev->pde_lock);
7664cc9bd8dSNiranjan H Y 	img_sz = fmw->size;
7674cc9bd8dSNiranjan H Y 	buf = fmw->data;
7684cc9bd8dSNiranjan H Y 	offset += FW_DL_OFFSET;
7694cc9bd8dSNiranjan H Y 	while (offset < (img_sz - FW_FL_HDR)) {
7704cc9bd8dSNiranjan H Y 		memset(&hdr, 0, sizeof(hdr));
7714cc9bd8dSNiranjan H Y 		offset += read_header(&buf[offset], &hdr);
7724cc9bd8dSNiranjan H Y 		dev_dbg(tas_dev->dev,
7734cc9bd8dSNiranjan H Y 			"vndr=%d, file=%d, version=%d, len=%d, off=%d\n",
7744cc9bd8dSNiranjan H Y 			hdr.vendor_id, hdr.file_id, hdr.version,
7754cc9bd8dSNiranjan H Y 			hdr.length, offset);
7764cc9bd8dSNiranjan H Y 		/* size also includes the header */
7774cc9bd8dSNiranjan H Y 		file_blk_size = hdr.length - FW_FL_HDR;
7784cc9bd8dSNiranjan H Y 
7794cc9bd8dSNiranjan H Y 		switch (hdr.file_id) {
7804cc9bd8dSNiranjan H Y 		case 0:
7814cc9bd8dSNiranjan H Y 			ret = sdw_nwrite_no_pm(tas_dev->sdw_peripheral,
7824cc9bd8dSNiranjan H Y 					       PRAM_ADDR_START, file_blk_size,
7834cc9bd8dSNiranjan H Y 					       &buf[offset]);
7844cc9bd8dSNiranjan H Y 			if (ret < 0)
7854cc9bd8dSNiranjan H Y 				dev_err(tas_dev->dev,
7864cc9bd8dSNiranjan H Y 					"PRAM update failed: %d", ret);
7874cc9bd8dSNiranjan H Y 			break;
7884cc9bd8dSNiranjan H Y 
7894cc9bd8dSNiranjan H Y 		case 1:
7904cc9bd8dSNiranjan H Y 			ret = sdw_nwrite_no_pm(tas_dev->sdw_peripheral,
7914cc9bd8dSNiranjan H Y 					       YRAM_ADDR_START, file_blk_size,
7924cc9bd8dSNiranjan H Y 					       &buf[offset]);
7934cc9bd8dSNiranjan H Y 			if (ret < 0)
7944cc9bd8dSNiranjan H Y 				dev_err(tas_dev->dev,
7954cc9bd8dSNiranjan H Y 					"YRAM update failed: %d", ret);
7964cc9bd8dSNiranjan H Y 
7974cc9bd8dSNiranjan H Y 			break;
7984cc9bd8dSNiranjan H Y 
7994cc9bd8dSNiranjan H Y 		default:
8004cc9bd8dSNiranjan H Y 			ret = -EINVAL;
8014cc9bd8dSNiranjan H Y 			dev_err(tas_dev->dev, "Unsupported file");
8024cc9bd8dSNiranjan H Y 			break;
8034cc9bd8dSNiranjan H Y 		}
8044cc9bd8dSNiranjan H Y 
8054cc9bd8dSNiranjan H Y 		if (ret == 0)
8064cc9bd8dSNiranjan H Y 			offset += file_blk_size;
8074cc9bd8dSNiranjan H Y 		else
8084cc9bd8dSNiranjan H Y 			break;
80970a0bcdeSChen Ni 	}
8104cc9bd8dSNiranjan H Y 	mutex_unlock(&tas_dev->pde_lock);
8114cc9bd8dSNiranjan H Y 	tas2783_update_calibdata(tas_dev);
8124cc9bd8dSNiranjan H Y 
8134cc9bd8dSNiranjan H Y out:
8144cc9bd8dSNiranjan H Y 	if (!ret)
8154cc9bd8dSNiranjan H Y 		tas_dev->fw_dl_success = true;
8164cc9bd8dSNiranjan H Y 	tas_dev->fw_dl_task_done = true;
8174cc9bd8dSNiranjan H Y 	wake_up(&tas_dev->fw_wait);
8184cc9bd8dSNiranjan H Y 	if (fmw)
8194cc9bd8dSNiranjan H Y 		release_firmware(fmw);
8204cc9bd8dSNiranjan H Y }
8214cc9bd8dSNiranjan H Y 
8224cc9bd8dSNiranjan H Y static inline s32 tas_clear_latch(struct tas2783_prv *priv)
8234cc9bd8dSNiranjan H Y {
8244cc9bd8dSNiranjan H Y 	return regmap_update_bits(priv->regmap,
8254cc9bd8dSNiranjan H Y 				  TASDEV_REG_SDW(0, 0, 0x5c),
8264cc9bd8dSNiranjan H Y 				  0x04, 0x04);
8274cc9bd8dSNiranjan H Y }
8284cc9bd8dSNiranjan H Y 
8294cc9bd8dSNiranjan H Y static s32 tas_fu21_event(struct snd_soc_dapm_widget *w,
8304cc9bd8dSNiranjan H Y 			  struct snd_kcontrol *k, s32 event)
8314cc9bd8dSNiranjan H Y {
8324cc9bd8dSNiranjan H Y 	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
8334cc9bd8dSNiranjan H Y 	struct tas2783_prv *tas_dev = snd_soc_component_get_drvdata(component);
8344cc9bd8dSNiranjan H Y 	s32 mute;
8354cc9bd8dSNiranjan H Y 
8364cc9bd8dSNiranjan H Y 	switch (event) {
8374cc9bd8dSNiranjan H Y 	case SND_SOC_DAPM_POST_PMU:
8384cc9bd8dSNiranjan H Y 		mute = 0;
8394cc9bd8dSNiranjan H Y 		break;
8404cc9bd8dSNiranjan H Y 
8414cc9bd8dSNiranjan H Y 	case SND_SOC_DAPM_PRE_PMD:
8424cc9bd8dSNiranjan H Y 		mute = 1;
8434cc9bd8dSNiranjan H Y 		break;
8444cc9bd8dSNiranjan H Y 	}
8454cc9bd8dSNiranjan H Y 
8464cc9bd8dSNiranjan H Y 	return sdw_write_no_pm(tas_dev->sdw_peripheral,
8474cc9bd8dSNiranjan H Y 			       SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU21,
8484cc9bd8dSNiranjan H Y 					    TAS2783_SDCA_CTL_FU_MUTE, 1), mute);
8494cc9bd8dSNiranjan H Y }
8504cc9bd8dSNiranjan H Y 
8514cc9bd8dSNiranjan H Y static s32 tas_fu23_event(struct snd_soc_dapm_widget *w,
8524cc9bd8dSNiranjan H Y 			  struct snd_kcontrol *k, s32 event)
8534cc9bd8dSNiranjan H Y {
8544cc9bd8dSNiranjan H Y 	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
8554cc9bd8dSNiranjan H Y 	struct tas2783_prv *tas_dev = snd_soc_component_get_drvdata(component);
8564cc9bd8dSNiranjan H Y 	s32 mute;
8574cc9bd8dSNiranjan H Y 
8584cc9bd8dSNiranjan H Y 	switch (event) {
8594cc9bd8dSNiranjan H Y 	case SND_SOC_DAPM_POST_PMU:
8604cc9bd8dSNiranjan H Y 		mute = 0;
8614cc9bd8dSNiranjan H Y 		break;
8624cc9bd8dSNiranjan H Y 
8634cc9bd8dSNiranjan H Y 	case SND_SOC_DAPM_PRE_PMD:
8644cc9bd8dSNiranjan H Y 		mute = 1;
8654cc9bd8dSNiranjan H Y 		break;
8664cc9bd8dSNiranjan H Y 	}
8674cc9bd8dSNiranjan H Y 
8684cc9bd8dSNiranjan H Y 	return sdw_write_no_pm(tas_dev->sdw_peripheral,
8694cc9bd8dSNiranjan H Y 			       SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU23,
8704cc9bd8dSNiranjan H Y 					    TAS2783_SDCA_CTL_FU_MUTE, 1), mute);
8714cc9bd8dSNiranjan H Y }
8724cc9bd8dSNiranjan H Y 
8734cc9bd8dSNiranjan H Y static const struct snd_soc_dapm_widget tas_dapm_widgets[] = {
8744cc9bd8dSNiranjan H Y 	SND_SOC_DAPM_AIF_IN("ASI", "ASI Playback", 0, SND_SOC_NOPM, 0, 0),
8754cc9bd8dSNiranjan H Y 	SND_SOC_DAPM_AIF_OUT("ASI OUT", "ASI Capture", 0, SND_SOC_NOPM,
8764cc9bd8dSNiranjan H Y 			     0, 0),
8774cc9bd8dSNiranjan H Y 	SND_SOC_DAPM_DAC_E("FU21", NULL, SND_SOC_NOPM, 0, 0, tas_fu21_event,
8784cc9bd8dSNiranjan H Y 			   SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
8794cc9bd8dSNiranjan H Y 	SND_SOC_DAPM_DAC_E("FU23", NULL, SND_SOC_NOPM, 0, 0, tas_fu23_event,
8804cc9bd8dSNiranjan H Y 			   SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
8814cc9bd8dSNiranjan H Y 	SND_SOC_DAPM_OUTPUT("SPK"),
8824cc9bd8dSNiranjan H Y 	SND_SOC_DAPM_INPUT("DMIC"),
8834cc9bd8dSNiranjan H Y };
8844cc9bd8dSNiranjan H Y 
8854cc9bd8dSNiranjan H Y static const struct snd_soc_dapm_route tas_audio_map[] = {
8864cc9bd8dSNiranjan H Y 	{"FU21", NULL, "ASI"},
8874cc9bd8dSNiranjan H Y 	{"SPK", NULL, "FU21"},
8884cc9bd8dSNiranjan H Y 	{"FU23", NULL, "ASI"},
8894cc9bd8dSNiranjan H Y 	{"SPK", NULL, "FU23"},
8904cc9bd8dSNiranjan H Y 	{"ASI OUT", NULL, "DMIC"},
8914cc9bd8dSNiranjan H Y };
8924cc9bd8dSNiranjan H Y 
8934cc9bd8dSNiranjan H Y static s32 tas_set_sdw_stream(struct snd_soc_dai *dai,
8944cc9bd8dSNiranjan H Y 			      void *sdw_stream, s32 direction)
8954cc9bd8dSNiranjan H Y {
8964cc9bd8dSNiranjan H Y 	if (!sdw_stream)
8974cc9bd8dSNiranjan H Y 		return 0;
8984cc9bd8dSNiranjan H Y 
8994cc9bd8dSNiranjan H Y 	snd_soc_dai_dma_data_set(dai, direction, sdw_stream);
9004cc9bd8dSNiranjan H Y 
9014cc9bd8dSNiranjan H Y 	return 0;
9024cc9bd8dSNiranjan H Y }
9034cc9bd8dSNiranjan H Y 
9044cc9bd8dSNiranjan H Y static void tas_sdw_shutdown(struct snd_pcm_substream *substream,
9054cc9bd8dSNiranjan H Y 			     struct snd_soc_dai *dai)
9064cc9bd8dSNiranjan H Y {
9074cc9bd8dSNiranjan H Y 	snd_soc_dai_set_dma_data(dai, substream, NULL);
9084cc9bd8dSNiranjan H Y }
9094cc9bd8dSNiranjan H Y 
9104cc9bd8dSNiranjan H Y static s32 tas_sdw_hw_params(struct snd_pcm_substream *substream,
9114cc9bd8dSNiranjan H Y 			     struct snd_pcm_hw_params *params,
9124cc9bd8dSNiranjan H Y 			     struct snd_soc_dai *dai)
9134cc9bd8dSNiranjan H Y {
9144cc9bd8dSNiranjan H Y 	struct snd_soc_component *component = dai->component;
9154cc9bd8dSNiranjan H Y 	struct tas2783_prv *tas_dev =
9164cc9bd8dSNiranjan H Y 		snd_soc_component_get_drvdata(component);
9174cc9bd8dSNiranjan H Y 	struct sdw_stream_config stream_config = {0};
9184cc9bd8dSNiranjan H Y 	struct sdw_port_config port_config = {0};
9194cc9bd8dSNiranjan H Y 	struct sdw_stream_runtime *sdw_stream;
9204cc9bd8dSNiranjan H Y 	struct sdw_slave *sdw_peripheral = tas_dev->sdw_peripheral;
9214cc9bd8dSNiranjan H Y 	s32 ret, retry = 3;
9224cc9bd8dSNiranjan H Y 
9234cc9bd8dSNiranjan H Y 	if (!tas_dev->fw_dl_success) {
9244cc9bd8dSNiranjan H Y 		dev_err(tas_dev->dev, "error playback without fw download");
9254cc9bd8dSNiranjan H Y 		return -EINVAL;
9264cc9bd8dSNiranjan H Y 	}
9274cc9bd8dSNiranjan H Y 
9284cc9bd8dSNiranjan H Y 	sdw_stream = snd_soc_dai_get_dma_data(dai, substream);
9294cc9bd8dSNiranjan H Y 	if (!sdw_stream)
9304cc9bd8dSNiranjan H Y 		return -EINVAL;
9314cc9bd8dSNiranjan H Y 
9324cc9bd8dSNiranjan H Y 	ret = tas_clear_latch(tas_dev);
9334cc9bd8dSNiranjan H Y 	if (ret)
9344cc9bd8dSNiranjan H Y 		dev_err(tas_dev->dev,
9354cc9bd8dSNiranjan H Y 			"clear latch failed, err=%d", ret);
9364cc9bd8dSNiranjan H Y 
9374cc9bd8dSNiranjan H Y 	mutex_lock(&tas_dev->pde_lock);
9384cc9bd8dSNiranjan H Y 	/*
9394cc9bd8dSNiranjan H Y 	 * Sometimes, there is error returned during power on.
9404cc9bd8dSNiranjan H Y 	 * So added retry logic to ensure power on so that
9414cc9bd8dSNiranjan H Y 	 * port prepare succeeds
9424cc9bd8dSNiranjan H Y 	 */
9434cc9bd8dSNiranjan H Y 	do {
9444cc9bd8dSNiranjan H Y 		ret = regmap_write(tas_dev->regmap,
9454cc9bd8dSNiranjan H Y 				   SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PDE23,
9464cc9bd8dSNiranjan H Y 						TAS2783_SDCA_CTL_REQ_POW_STATE, 0),
9474cc9bd8dSNiranjan H Y 						TAS2783_SDCA_POW_STATE_ON);
9484cc9bd8dSNiranjan H Y 		if (!ret)
9494cc9bd8dSNiranjan H Y 			break;
9504cc9bd8dSNiranjan H Y 		usleep_range(2000, 2200);
9514cc9bd8dSNiranjan H Y 	} while (retry--);
9524cc9bd8dSNiranjan H Y 	mutex_unlock(&tas_dev->pde_lock);
9534cc9bd8dSNiranjan H Y 	if (ret)
9544cc9bd8dSNiranjan H Y 		return ret;
9554cc9bd8dSNiranjan H Y 
9564cc9bd8dSNiranjan H Y 	/* SoundWire specific configuration */
9574cc9bd8dSNiranjan H Y 	snd_sdw_params_to_config(substream, params,
9584cc9bd8dSNiranjan H Y 				 &stream_config, &port_config);
9594cc9bd8dSNiranjan H Y 	/* port 1 for playback */
9604cc9bd8dSNiranjan H Y 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
9614cc9bd8dSNiranjan H Y 		port_config.num = 1;
9624cc9bd8dSNiranjan H Y 	else
9634cc9bd8dSNiranjan H Y 		port_config.num = 2;
9644cc9bd8dSNiranjan H Y 
9654cc9bd8dSNiranjan H Y 	ret = sdw_stream_add_slave(sdw_peripheral,
9664cc9bd8dSNiranjan H Y 				   &stream_config, &port_config, 1, sdw_stream);
9674cc9bd8dSNiranjan H Y 	if (ret)
9684cc9bd8dSNiranjan H Y 		dev_err(dai->dev, "Unable to configure port\n");
9694cc9bd8dSNiranjan H Y 
9704cc9bd8dSNiranjan H Y 	return ret;
9714cc9bd8dSNiranjan H Y }
9724cc9bd8dSNiranjan H Y 
9734cc9bd8dSNiranjan H Y static s32 tas_sdw_pcm_hw_free(struct snd_pcm_substream *substream,
9744cc9bd8dSNiranjan H Y 			       struct snd_soc_dai *dai)
9754cc9bd8dSNiranjan H Y {
9764cc9bd8dSNiranjan H Y 	s32 ret;
9774cc9bd8dSNiranjan H Y 	struct snd_soc_component *component = dai->component;
9784cc9bd8dSNiranjan H Y 	struct tas2783_prv *tas_dev =
9794cc9bd8dSNiranjan H Y 		snd_soc_component_get_drvdata(component);
9804cc9bd8dSNiranjan H Y 	struct sdw_stream_runtime *sdw_stream =
9814cc9bd8dSNiranjan H Y 		snd_soc_dai_get_dma_data(dai, substream);
9824cc9bd8dSNiranjan H Y 
9834cc9bd8dSNiranjan H Y 	sdw_stream_remove_slave(tas_dev->sdw_peripheral, sdw_stream);
9844cc9bd8dSNiranjan H Y 
9854cc9bd8dSNiranjan H Y 	mutex_lock(&tas_dev->pde_lock);
9864cc9bd8dSNiranjan H Y 	ret = regmap_write(tas_dev->regmap,
9874cc9bd8dSNiranjan H Y 			   SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PDE23,
9884cc9bd8dSNiranjan H Y 					TAS2783_SDCA_CTL_REQ_POW_STATE, 0),
9894cc9bd8dSNiranjan H Y 			   TAS2783_SDCA_POW_STATE_OFF);
9904cc9bd8dSNiranjan H Y 	mutex_unlock(&tas_dev->pde_lock);
9914cc9bd8dSNiranjan H Y 
9924cc9bd8dSNiranjan H Y 	return ret;
9934cc9bd8dSNiranjan H Y }
9944cc9bd8dSNiranjan H Y 
9954cc9bd8dSNiranjan H Y static const struct snd_soc_dai_ops tas_dai_ops = {
9964cc9bd8dSNiranjan H Y 	.hw_params	= tas_sdw_hw_params,
9974cc9bd8dSNiranjan H Y 	.hw_free	= tas_sdw_pcm_hw_free,
9984cc9bd8dSNiranjan H Y 	.set_stream	= tas_set_sdw_stream,
9994cc9bd8dSNiranjan H Y 	.shutdown	= tas_sdw_shutdown,
10004cc9bd8dSNiranjan H Y };
10014cc9bd8dSNiranjan H Y 
10024cc9bd8dSNiranjan H Y static struct snd_soc_dai_driver tas_dai_driver[] = {
10034cc9bd8dSNiranjan H Y 	{
10044cc9bd8dSNiranjan H Y 		.name = "tas2783-codec",
10054cc9bd8dSNiranjan H Y 		.id = 0,
10064cc9bd8dSNiranjan H Y 		.playback = {
10074cc9bd8dSNiranjan H Y 			.stream_name	= "Playback",
10084cc9bd8dSNiranjan H Y 			.channels_min	= 1,
10094cc9bd8dSNiranjan H Y 			.channels_max	= 4,
10104cc9bd8dSNiranjan H Y 			.rates		= TAS2783_DEVICE_RATES,
10114cc9bd8dSNiranjan H Y 			.formats	= TAS2783_DEVICE_FORMATS,
10124cc9bd8dSNiranjan H Y 		},
10134cc9bd8dSNiranjan H Y 		.capture = {
10144cc9bd8dSNiranjan H Y 			.stream_name	= "Capture",
10154cc9bd8dSNiranjan H Y 			.channels_min	= 1,
10164cc9bd8dSNiranjan H Y 			.channels_max	= 4,
10174cc9bd8dSNiranjan H Y 			.rates		= TAS2783_DEVICE_RATES,
10184cc9bd8dSNiranjan H Y 			.formats	= TAS2783_DEVICE_FORMATS,
10194cc9bd8dSNiranjan H Y 		},
10204cc9bd8dSNiranjan H Y 		.ops = &tas_dai_ops,
10214cc9bd8dSNiranjan H Y 		.symmetric_rate = 1,
10224cc9bd8dSNiranjan H Y 	},
10234cc9bd8dSNiranjan H Y };
10244cc9bd8dSNiranjan H Y 
10254cc9bd8dSNiranjan H Y static s32 tas_component_probe(struct snd_soc_component *component)
10264cc9bd8dSNiranjan H Y {
10274cc9bd8dSNiranjan H Y 	struct tas2783_prv *tas_dev =
10284cc9bd8dSNiranjan H Y 		snd_soc_component_get_drvdata(component);
10294cc9bd8dSNiranjan H Y 
10304cc9bd8dSNiranjan H Y 	tas_dev->component = component;
10314cc9bd8dSNiranjan H Y 	tas25xx_register_misc(tas_dev->sdw_peripheral);
10324cc9bd8dSNiranjan H Y 
10334cc9bd8dSNiranjan H Y 	return 0;
10344cc9bd8dSNiranjan H Y }
10354cc9bd8dSNiranjan H Y 
10364cc9bd8dSNiranjan H Y static void tas_component_remove(struct snd_soc_component *codec)
10374cc9bd8dSNiranjan H Y {
10384cc9bd8dSNiranjan H Y 	struct tas2783_prv *tas_dev =
10394cc9bd8dSNiranjan H Y 			snd_soc_component_get_drvdata(codec);
10404cc9bd8dSNiranjan H Y 	tas25xx_deregister_misc();
10414cc9bd8dSNiranjan H Y 	tas_dev->component = NULL;
10424cc9bd8dSNiranjan H Y }
10434cc9bd8dSNiranjan H Y 
10444cc9bd8dSNiranjan H Y static const struct snd_soc_component_driver soc_codec_driver_tasdevice = {
10454cc9bd8dSNiranjan H Y 	.probe = tas_component_probe,
10464cc9bd8dSNiranjan H Y 	.remove = tas_component_remove,
10474cc9bd8dSNiranjan H Y 	.controls = tas2783_snd_controls,
10484cc9bd8dSNiranjan H Y 	.num_controls = ARRAY_SIZE(tas2783_snd_controls),
10494cc9bd8dSNiranjan H Y 	.dapm_widgets = tas_dapm_widgets,
10504cc9bd8dSNiranjan H Y 	.num_dapm_widgets = ARRAY_SIZE(tas_dapm_widgets),
10514cc9bd8dSNiranjan H Y 	.dapm_routes = tas_audio_map,
10524cc9bd8dSNiranjan H Y 	.num_dapm_routes = ARRAY_SIZE(tas_audio_map),
10534cc9bd8dSNiranjan H Y 	.idle_bias_on = 1,
10544cc9bd8dSNiranjan H Y 	.endianness = 1,
10554cc9bd8dSNiranjan H Y };
10564cc9bd8dSNiranjan H Y 
10574cc9bd8dSNiranjan H Y static s32 tas_init(struct tas2783_prv *tas_dev)
10584cc9bd8dSNiranjan H Y {
10594cc9bd8dSNiranjan H Y 	s32 ret;
10604cc9bd8dSNiranjan H Y 
10614cc9bd8dSNiranjan H Y 	dev_set_drvdata(tas_dev->dev, tas_dev);
10624cc9bd8dSNiranjan H Y 	ret = devm_snd_soc_register_component(tas_dev->dev,
10634cc9bd8dSNiranjan H Y 					      &soc_codec_driver_tasdevice,
10644cc9bd8dSNiranjan H Y 					      tas_dai_driver,
10654cc9bd8dSNiranjan H Y 					      ARRAY_SIZE(tas_dai_driver));
10664cc9bd8dSNiranjan H Y 	if (ret) {
10674cc9bd8dSNiranjan H Y 		dev_err(tas_dev->dev, "%s: codec register error:%d.\n",
10684cc9bd8dSNiranjan H Y 			__func__, ret);
10694cc9bd8dSNiranjan H Y 		return ret;
10704cc9bd8dSNiranjan H Y 	}
10714cc9bd8dSNiranjan H Y 
10724cc9bd8dSNiranjan H Y 	/* set autosuspend parameters */
10734cc9bd8dSNiranjan H Y 	pm_runtime_set_autosuspend_delay(tas_dev->dev, 3000);
10744cc9bd8dSNiranjan H Y 	pm_runtime_use_autosuspend(tas_dev->dev);
10754cc9bd8dSNiranjan H Y 	/* make sure the device does not suspend immediately */
10764cc9bd8dSNiranjan H Y 	pm_runtime_mark_last_busy(tas_dev->dev);
10774cc9bd8dSNiranjan H Y 	pm_runtime_enable(tas_dev->dev);
10784cc9bd8dSNiranjan H Y 
10794cc9bd8dSNiranjan H Y 	return ret;
10804cc9bd8dSNiranjan H Y }
10814cc9bd8dSNiranjan H Y 
10824cc9bd8dSNiranjan H Y static s32 tas_read_prop(struct sdw_slave *slave)
10834cc9bd8dSNiranjan H Y {
10844cc9bd8dSNiranjan H Y 	struct sdw_slave_prop *prop = &slave->prop;
10854cc9bd8dSNiranjan H Y 	s32 nval;
10864cc9bd8dSNiranjan H Y 	s32 i, j;
10874cc9bd8dSNiranjan H Y 	u32 bit;
10884cc9bd8dSNiranjan H Y 	unsigned long addr;
10894cc9bd8dSNiranjan H Y 	struct sdw_dpn_prop *dpn;
10904cc9bd8dSNiranjan H Y 
10914cc9bd8dSNiranjan H Y 	prop->scp_int1_mask =
10924cc9bd8dSNiranjan H Y 		SDW_SCP_INT1_BUS_CLASH | SDW_SCP_INT1_PARITY;
10934cc9bd8dSNiranjan H Y 	prop->quirks = SDW_SLAVE_QUIRKS_INVALID_INITIAL_PARITY;
10944cc9bd8dSNiranjan H Y 
10954cc9bd8dSNiranjan H Y 	prop->paging_support = true;
10964cc9bd8dSNiranjan H Y 
10974cc9bd8dSNiranjan H Y 	/* first we need to allocate memory for set bits in port lists */
10984cc9bd8dSNiranjan H Y 	prop->source_ports = 0x04; /* BITMAP: 00000100 */
10994cc9bd8dSNiranjan H Y 	prop->sink_ports = 0x2; /* BITMAP:  00000010 */
11004cc9bd8dSNiranjan H Y 
11014cc9bd8dSNiranjan H Y 	nval = hweight32(prop->source_ports);
11024cc9bd8dSNiranjan H Y 	prop->src_dpn_prop = devm_kcalloc(&slave->dev, nval,
11034cc9bd8dSNiranjan H Y 					  sizeof(*prop->src_dpn_prop), GFP_KERNEL);
11044cc9bd8dSNiranjan H Y 	if (!prop->src_dpn_prop)
11054cc9bd8dSNiranjan H Y 		return -ENOMEM;
11064cc9bd8dSNiranjan H Y 
11074cc9bd8dSNiranjan H Y 	i = 0;
11084cc9bd8dSNiranjan H Y 	dpn = prop->src_dpn_prop;
11094cc9bd8dSNiranjan H Y 	addr = prop->source_ports;
11104cc9bd8dSNiranjan H Y 	for_each_set_bit(bit, &addr, 32) {
11114cc9bd8dSNiranjan H Y 		dpn[i].num = bit;
11124cc9bd8dSNiranjan H Y 		dpn[i].type = SDW_DPN_FULL;
11134cc9bd8dSNiranjan H Y 		dpn[i].simple_ch_prep_sm = false;
11144cc9bd8dSNiranjan H Y 		dpn[i].ch_prep_timeout = 10;
11154cc9bd8dSNiranjan H Y 		i++;
11164cc9bd8dSNiranjan H Y 	}
11174cc9bd8dSNiranjan H Y 
11184cc9bd8dSNiranjan H Y 	/* do this again for sink now */
11194cc9bd8dSNiranjan H Y 	nval = hweight32(prop->sink_ports);
11204cc9bd8dSNiranjan H Y 	prop->sink_dpn_prop = devm_kcalloc(&slave->dev, nval,
11214cc9bd8dSNiranjan H Y 					   sizeof(*prop->sink_dpn_prop), GFP_KERNEL);
11224cc9bd8dSNiranjan H Y 	if (!prop->sink_dpn_prop)
11234cc9bd8dSNiranjan H Y 		return -ENOMEM;
11244cc9bd8dSNiranjan H Y 
11254cc9bd8dSNiranjan H Y 	j = 0;
11264cc9bd8dSNiranjan H Y 	dpn = prop->sink_dpn_prop;
11274cc9bd8dSNiranjan H Y 	addr = prop->sink_ports;
11284cc9bd8dSNiranjan H Y 	for_each_set_bit(bit, &addr, 32) {
11294cc9bd8dSNiranjan H Y 		dpn[j].num = bit;
11304cc9bd8dSNiranjan H Y 		dpn[j].type = SDW_DPN_FULL;
11314cc9bd8dSNiranjan H Y 		dpn[j].simple_ch_prep_sm = false;
11324cc9bd8dSNiranjan H Y 		dpn[j].ch_prep_timeout = 10;
11334cc9bd8dSNiranjan H Y 		j++;
11344cc9bd8dSNiranjan H Y 	}
11354cc9bd8dSNiranjan H Y 
11364cc9bd8dSNiranjan H Y 	/* set the timeout values */
11374cc9bd8dSNiranjan H Y 	prop->clk_stop_timeout = 200;
11384cc9bd8dSNiranjan H Y 
11394cc9bd8dSNiranjan H Y 	return 0;
11404cc9bd8dSNiranjan H Y }
11414cc9bd8dSNiranjan H Y 
11424cc9bd8dSNiranjan H Y static s32 tas2783_sdca_dev_suspend(struct device *dev)
11434cc9bd8dSNiranjan H Y {
11444cc9bd8dSNiranjan H Y 	struct tas2783_prv *tas_dev = dev_get_drvdata(dev);
11454cc9bd8dSNiranjan H Y 
11464cc9bd8dSNiranjan H Y 	if (!tas_dev->hw_init)
11474cc9bd8dSNiranjan H Y 		return 0;
11484cc9bd8dSNiranjan H Y 
11494cc9bd8dSNiranjan H Y 	regcache_cache_only(tas_dev->regmap, true);
11504cc9bd8dSNiranjan H Y 	return 0;
11514cc9bd8dSNiranjan H Y }
11524cc9bd8dSNiranjan H Y 
11534cc9bd8dSNiranjan H Y static s32 tas2783_sdca_dev_system_suspend(struct device *dev)
11544cc9bd8dSNiranjan H Y {
11554cc9bd8dSNiranjan H Y 	return tas2783_sdca_dev_suspend(dev);
11564cc9bd8dSNiranjan H Y }
11574cc9bd8dSNiranjan H Y 
11584cc9bd8dSNiranjan H Y static s32 tas2783_sdca_dev_resume(struct device *dev)
11594cc9bd8dSNiranjan H Y {
11604cc9bd8dSNiranjan H Y 	struct sdw_slave *slave = dev_to_sdw_dev(dev);
11614cc9bd8dSNiranjan H Y 	struct tas2783_prv *tas_dev = dev_get_drvdata(dev);
11624cc9bd8dSNiranjan H Y 	unsigned long t;
11634cc9bd8dSNiranjan H Y 
11644cc9bd8dSNiranjan H Y 	if (!slave->unattach_request)
11654cc9bd8dSNiranjan H Y 		goto regmap_sync;
11664cc9bd8dSNiranjan H Y 
11674cc9bd8dSNiranjan H Y 	t = wait_for_completion_timeout(&slave->initialization_complete,
11684cc9bd8dSNiranjan H Y 					msecs_to_jiffies(TAS2783_PROBE_TIMEOUT));
11694cc9bd8dSNiranjan H Y 	if (!t) {
11704cc9bd8dSNiranjan H Y 		dev_err(&slave->dev, "resume: initialization timed out\n");
11714cc9bd8dSNiranjan H Y 		sdw_show_ping_status(slave->bus, true);
11724cc9bd8dSNiranjan H Y 		return -ETIMEDOUT;
11734cc9bd8dSNiranjan H Y 	}
11744cc9bd8dSNiranjan H Y 
11754cc9bd8dSNiranjan H Y 	slave->unattach_request = 0;
11764cc9bd8dSNiranjan H Y 
11774cc9bd8dSNiranjan H Y regmap_sync:
11784cc9bd8dSNiranjan H Y 	regcache_cache_only(tas_dev->regmap, false);
11794cc9bd8dSNiranjan H Y 	regcache_sync(tas_dev->regmap);
11804cc9bd8dSNiranjan H Y 	return 0;
11814cc9bd8dSNiranjan H Y }
11824cc9bd8dSNiranjan H Y 
11834cc9bd8dSNiranjan H Y static const struct dev_pm_ops tas2783_sdca_pm = {
11844cc9bd8dSNiranjan H Y 	SYSTEM_SLEEP_PM_OPS(tas2783_sdca_dev_system_suspend, tas2783_sdca_dev_resume)
11854cc9bd8dSNiranjan H Y 	RUNTIME_PM_OPS(tas2783_sdca_dev_suspend, tas2783_sdca_dev_resume, NULL)
11864cc9bd8dSNiranjan H Y };
11874cc9bd8dSNiranjan H Y 
11884cc9bd8dSNiranjan H Y static s32 tas_io_init(struct device *dev, struct sdw_slave *slave)
11894cc9bd8dSNiranjan H Y {
11904cc9bd8dSNiranjan H Y 	struct tas2783_prv *tas_dev = dev_get_drvdata(dev);
11914cc9bd8dSNiranjan H Y 	s32 ret;
11924cc9bd8dSNiranjan H Y 	u8 unique_id = tas_dev->sdw_peripheral->id.unique_id;
11934cc9bd8dSNiranjan H Y 
11944cc9bd8dSNiranjan H Y 	if (tas_dev->hw_init)
11954cc9bd8dSNiranjan H Y 		return 0;
11964cc9bd8dSNiranjan H Y 
11974cc9bd8dSNiranjan H Y 	tas_dev->fw_dl_task_done = false;
11984cc9bd8dSNiranjan H Y 	tas_dev->fw_dl_success = false;
11994cc9bd8dSNiranjan H Y 	scnprintf(tas_dev->rca_binaryname, sizeof(tas_dev->rca_binaryname),
12004cc9bd8dSNiranjan H Y 		  "tas2783-%01x.bin", unique_id);
12014cc9bd8dSNiranjan H Y 
12024cc9bd8dSNiranjan H Y 	ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_UEVENT,
12034cc9bd8dSNiranjan H Y 				      tas_dev->rca_binaryname, tas_dev->dev,
12044cc9bd8dSNiranjan H Y 				      GFP_KERNEL, tas_dev, tas2783_fw_ready);
12054cc9bd8dSNiranjan H Y 	if (ret) {
12064cc9bd8dSNiranjan H Y 		dev_err(tas_dev->dev,
12074cc9bd8dSNiranjan H Y 			"firmware request failed for uid=%d, ret=%d\n",
12084cc9bd8dSNiranjan H Y 			unique_id, ret);
12094cc9bd8dSNiranjan H Y 		return ret;
12104cc9bd8dSNiranjan H Y 	}
12114cc9bd8dSNiranjan H Y 
12124cc9bd8dSNiranjan H Y 	ret = wait_event_timeout(tas_dev->fw_wait, tas_dev->fw_dl_task_done,
12134cc9bd8dSNiranjan H Y 				 msecs_to_jiffies(TIMEOUT_FW_DL_MS));
12144cc9bd8dSNiranjan H Y 	if (!ret) {
12154cc9bd8dSNiranjan H Y 		dev_err(tas_dev->dev, "fw request, wait_event timeout\n");
12164cc9bd8dSNiranjan H Y 		ret = -EAGAIN;
12174cc9bd8dSNiranjan H Y 	} else {
12184cc9bd8dSNiranjan H Y 		ret = regmap_multi_reg_write(tas_dev->regmap, tas2783_init_seq,
12194cc9bd8dSNiranjan H Y 					     ARRAY_SIZE(tas2783_init_seq));
12204cc9bd8dSNiranjan H Y 		tas_dev->hw_init = true;
12214cc9bd8dSNiranjan H Y 	}
12224cc9bd8dSNiranjan H Y 
12234cc9bd8dSNiranjan H Y 	return ret;
12244cc9bd8dSNiranjan H Y }
12254cc9bd8dSNiranjan H Y 
12264cc9bd8dSNiranjan H Y static s32 tas_update_status(struct sdw_slave *slave,
12274cc9bd8dSNiranjan H Y 			     enum sdw_slave_status status)
12284cc9bd8dSNiranjan H Y {
12294cc9bd8dSNiranjan H Y 	struct tas2783_prv *tas_dev = dev_get_drvdata(&slave->dev);
12304cc9bd8dSNiranjan H Y 	struct device *dev = &slave->dev;
12314cc9bd8dSNiranjan H Y 
12326be98866SColin Ian King 	dev_dbg(dev, "Peripheral status = %s",
12334cc9bd8dSNiranjan H Y 		status == SDW_SLAVE_UNATTACHED ? "unattached" :
12344cc9bd8dSNiranjan H Y 		 status == SDW_SLAVE_ATTACHED ? "attached" : "alert");
12354cc9bd8dSNiranjan H Y 
12364cc9bd8dSNiranjan H Y 	tas_dev->status = status;
12374cc9bd8dSNiranjan H Y 	if (status == SDW_SLAVE_UNATTACHED)
12384cc9bd8dSNiranjan H Y 		tas_dev->hw_init = false;
12394cc9bd8dSNiranjan H Y 
12404cc9bd8dSNiranjan H Y 	/* Perform initialization only if slave status
12414cc9bd8dSNiranjan H Y 	 * is present and hw_init flag is false
12424cc9bd8dSNiranjan H Y 	 */
12434cc9bd8dSNiranjan H Y 	if (tas_dev->hw_init || tas_dev->status != SDW_SLAVE_ATTACHED)
12444cc9bd8dSNiranjan H Y 		return 0;
12454cc9bd8dSNiranjan H Y 
12464cc9bd8dSNiranjan H Y 	/* updated the cache data to device */
12474cc9bd8dSNiranjan H Y 	regcache_cache_only(tas_dev->regmap, false);
12484cc9bd8dSNiranjan H Y 	regcache_sync(tas_dev->regmap);
12494cc9bd8dSNiranjan H Y 
12504cc9bd8dSNiranjan H Y 	/* perform I/O transfers required for Slave initialization */
12514cc9bd8dSNiranjan H Y 	return tas_io_init(&slave->dev, slave);
12524cc9bd8dSNiranjan H Y }
12534cc9bd8dSNiranjan H Y 
12544cc9bd8dSNiranjan H Y static const struct sdw_slave_ops tas_sdw_ops = {
12554cc9bd8dSNiranjan H Y 	.read_prop	= tas_read_prop,
12564cc9bd8dSNiranjan H Y 	.update_status	= tas_update_status,
12574cc9bd8dSNiranjan H Y };
12584cc9bd8dSNiranjan H Y 
12594cc9bd8dSNiranjan H Y static void tas_remove(struct tas2783_prv *tas_dev)
12604cc9bd8dSNiranjan H Y {
12614cc9bd8dSNiranjan H Y 	snd_soc_unregister_component(tas_dev->dev);
12624cc9bd8dSNiranjan H Y }
12634cc9bd8dSNiranjan H Y 
12644cc9bd8dSNiranjan H Y static s32 tas_sdw_probe(struct sdw_slave *peripheral,
12654cc9bd8dSNiranjan H Y 			 const struct sdw_device_id *id)
12664cc9bd8dSNiranjan H Y {
12674cc9bd8dSNiranjan H Y 	struct regmap *regmap;
12684cc9bd8dSNiranjan H Y 	struct device *dev = &peripheral->dev;
12694cc9bd8dSNiranjan H Y 	struct tas2783_prv *tas_dev;
12704cc9bd8dSNiranjan H Y 
12714cc9bd8dSNiranjan H Y 	tas_dev = devm_kzalloc(dev, sizeof(*tas_dev), GFP_KERNEL);
12724cc9bd8dSNiranjan H Y 	if (!tas_dev)
12734cc9bd8dSNiranjan H Y 		return dev_err_probe(dev, -ENOMEM,
12744cc9bd8dSNiranjan H Y 				     "Failed devm_kzalloc");
12754cc9bd8dSNiranjan H Y 
12764cc9bd8dSNiranjan H Y 	tas_dev->dev = dev;
12774cc9bd8dSNiranjan H Y 	tas_dev->sdw_peripheral = peripheral;
12784cc9bd8dSNiranjan H Y 	tas_dev->hw_init = false;
12794cc9bd8dSNiranjan H Y 	mutex_init(&tas_dev->calib_lock);
12804cc9bd8dSNiranjan H Y 	mutex_init(&tas_dev->pde_lock);
12814cc9bd8dSNiranjan H Y 
12824cc9bd8dSNiranjan H Y 	init_waitqueue_head(&tas_dev->fw_wait);
12834cc9bd8dSNiranjan H Y 	dev_set_drvdata(dev, tas_dev);
12844cc9bd8dSNiranjan H Y 	regmap = devm_regmap_init_sdw_mbq_cfg(peripheral,
12854cc9bd8dSNiranjan H Y 					      &tas_regmap,
12864cc9bd8dSNiranjan H Y 					      &tas2783_mbq_cfg);
12874cc9bd8dSNiranjan H Y 	if (IS_ERR(regmap))
1288*f8b9c819SDan Carpenter 		return dev_err_probe(dev, PTR_ERR(regmap),
12894cc9bd8dSNiranjan H Y 				     "Failed devm_regmap_init_sdw.");
12904cc9bd8dSNiranjan H Y 
12914cc9bd8dSNiranjan H Y 	/* keep in cache until the device is fully initialized */
12924cc9bd8dSNiranjan H Y 	regcache_cache_only(regmap, true);
12934cc9bd8dSNiranjan H Y 	tas_dev->regmap = regmap;
12944cc9bd8dSNiranjan H Y 	return tas_init(tas_dev);
12954cc9bd8dSNiranjan H Y }
12964cc9bd8dSNiranjan H Y 
12974cc9bd8dSNiranjan H Y static s32 tas_sdw_remove(struct sdw_slave *peripheral)
12984cc9bd8dSNiranjan H Y {
12994cc9bd8dSNiranjan H Y 	struct tas2783_prv *tas_dev = dev_get_drvdata(&peripheral->dev);
13004cc9bd8dSNiranjan H Y 
13014cc9bd8dSNiranjan H Y 	pm_runtime_disable(tas_dev->dev);
13024cc9bd8dSNiranjan H Y 	tas_remove(tas_dev);
13034cc9bd8dSNiranjan H Y 	mutex_destroy(&tas_dev->calib_lock);
13044cc9bd8dSNiranjan H Y 	mutex_destroy(&tas_dev->pde_lock);
13054cc9bd8dSNiranjan H Y 	dev_set_drvdata(&peripheral->dev, NULL);
13064cc9bd8dSNiranjan H Y 
13074cc9bd8dSNiranjan H Y 	return 0;
13084cc9bd8dSNiranjan H Y }
13094cc9bd8dSNiranjan H Y 
13104cc9bd8dSNiranjan H Y static const struct sdw_device_id tas_sdw_id[] = {
13114cc9bd8dSNiranjan H Y 	/* chipid for the TAS2783 is 0x0000 */
13124cc9bd8dSNiranjan H Y 	SDW_SLAVE_ENTRY(0x0102, 0x0000, 0),
13134cc9bd8dSNiranjan H Y 	{},
13144cc9bd8dSNiranjan H Y };
13154cc9bd8dSNiranjan H Y MODULE_DEVICE_TABLE(sdw, tas_sdw_id);
13164cc9bd8dSNiranjan H Y 
13174cc9bd8dSNiranjan H Y static struct sdw_driver tas_sdw_driver = {
13184cc9bd8dSNiranjan H Y 	.driver = {
13194cc9bd8dSNiranjan H Y 		.name = "slave-tas2783",
13204cc9bd8dSNiranjan H Y 		.pm = pm_ptr(&tas2783_sdca_pm),
13214cc9bd8dSNiranjan H Y 	},
13224cc9bd8dSNiranjan H Y 	.probe = tas_sdw_probe,
13234cc9bd8dSNiranjan H Y 	.remove = tas_sdw_remove,
13244cc9bd8dSNiranjan H Y 	.ops = &tas_sdw_ops,
13254cc9bd8dSNiranjan H Y 	.id_table = tas_sdw_id,
13264cc9bd8dSNiranjan H Y };
13274cc9bd8dSNiranjan H Y module_sdw_driver(tas_sdw_driver);
13284cc9bd8dSNiranjan H Y 
13294cc9bd8dSNiranjan H Y MODULE_AUTHOR("Texas Instruments Inc.");
13304cc9bd8dSNiranjan H Y MODULE_DESCRIPTION("ASoC TAS2783 SoundWire Driver");
13314cc9bd8dSNiranjan H Y MODULE_LICENSE("GPL");
1332