xref: /linux/sound/soc/codecs/tac5xx2-sdw.c (revision fab183d632628381b466a41479489541ac0e29a0)
138c89fedSNiranjan H Y // SPDX-License-Identifier: GPL-2.0
238c89fedSNiranjan H Y //
338c89fedSNiranjan H Y // ALSA SoC Texas Instruments TAC5XX2 Audio Smart Amplifier
438c89fedSNiranjan H Y //
538c89fedSNiranjan H Y // Copyright (C) 2025 Texas Instruments Incorporated
638c89fedSNiranjan H Y // https://www.ti.com
738c89fedSNiranjan H Y //
838c89fedSNiranjan H Y // Author: Niranjan H Y <niranjan.hy@ti.com>
938c89fedSNiranjan H Y 
1038c89fedSNiranjan H Y #include <linux/err.h>
1138c89fedSNiranjan H Y #include <linux/firmware.h>
1238c89fedSNiranjan H Y #include <linux/init.h>
1338c89fedSNiranjan H Y #include <linux/module.h>
1438c89fedSNiranjan H Y #include <linux/pci.h>
1538c89fedSNiranjan H Y #include <linux/pm.h>
1638c89fedSNiranjan H Y #include <linux/pm_runtime.h>
1738c89fedSNiranjan H Y #include <linux/regmap.h>
1838c89fedSNiranjan H Y #include <linux/soundwire/sdw.h>
1938c89fedSNiranjan H Y #include <linux/soundwire/sdw_registers.h>
2038c89fedSNiranjan H Y #include <linux/soundwire/sdw_type.h>
2138c89fedSNiranjan H Y #include <linux/time.h>
2238c89fedSNiranjan H Y #include <linux/unaligned.h>
2338c89fedSNiranjan H Y #include <sound/pcm_params.h>
2438c89fedSNiranjan H Y #include <sound/sdw.h>
2538c89fedSNiranjan H Y #include <sound/soc.h>
2638c89fedSNiranjan H Y #include <sound/tlv.h>
2738c89fedSNiranjan H Y #include <sound/sdca_asoc.h>
2838c89fedSNiranjan H Y #include <sound/sdca_function.h>
2938c89fedSNiranjan H Y #include <sound/sdca_regmap.h>
3038c89fedSNiranjan H Y #include <sound/jack.h>
3138c89fedSNiranjan H Y 
3238c89fedSNiranjan H Y #include "tac5xx2.h"
3338c89fedSNiranjan H Y 
3438c89fedSNiranjan H Y #define TAC5XX2_PROBE_TIMEOUT_MS 3000
3538c89fedSNiranjan H Y #define TAC5XX2_FW_CACHE_TIMEOUT_MS 300
3638c89fedSNiranjan H Y 
3738c89fedSNiranjan H Y #define TAC5XX2_DEVICE_RATES (SNDRV_PCM_RATE_44100 | \
3838c89fedSNiranjan H Y 			      SNDRV_PCM_RATE_48000 | \
3938c89fedSNiranjan H Y 			      SNDRV_PCM_RATE_96000 | \
4038c89fedSNiranjan H Y 			      SNDRV_PCM_RATE_88200)
4138c89fedSNiranjan H Y #define TAC5XX2_DEVICE_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
4238c89fedSNiranjan H Y 				SNDRV_PCM_FMTBIT_S24_LE | \
4338c89fedSNiranjan H Y 				SNDRV_PCM_FMTBIT_S32_LE)
4438c89fedSNiranjan H Y /* Define channel constants */
4538c89fedSNiranjan H Y #define TAC_CHANNEL_LEFT	1
4638c89fedSNiranjan H Y #define TAC_CHANNEL_RIGHT	2
4738c89fedSNiranjan H Y #define TAC_JACK_MONO_CS	2
4838c89fedSNiranjan H Y 
4938c89fedSNiranjan H Y #define TAC_MUTE_REG(func, fu, ch) \
5038c89fedSNiranjan H Y 	SDW_SDCA_CTL(TAC_FUNCTION_ID_##func, TAC_SDCA_ENT_##fu, \
5138c89fedSNiranjan H Y 		     TAC_SDCA_CHANNEL_MUTE, TAC_CHANNEL_##ch)
5238c89fedSNiranjan H Y #define TAC_USAGE_REG(func, ent) \
5338c89fedSNiranjan H Y 	SDW_SDCA_CTL(TAC_FUNCTION_ID_##func, TAC_SDCA_ENT_##ent, \
5438c89fedSNiranjan H Y 		     TAC_SDCA_CTL_USAGE, 0)
5538c89fedSNiranjan H Y #define TAC_XU_BYPASS_REG(func, xu)                        \
5638c89fedSNiranjan H Y 	SDW_SDCA_CTL(TAC_FUNCTION_ID_##func, TAC_SDCA_ENT_##xu, \
5738c89fedSNiranjan H Y 			TAC_SDCA_CTL_XU_BYPASS, 0)
5838c89fedSNiranjan H Y 
5938c89fedSNiranjan H Y /* mute registers */
6038c89fedSNiranjan H Y #define FU21_L_MUTE_REG  TAC_MUTE_REG(SA, FU21, LEFT)
6138c89fedSNiranjan H Y #define FU21_R_MUTE_REG  TAC_MUTE_REG(SA, FU21, RIGHT)
6238c89fedSNiranjan H Y #define FU23_L_MUTE_REG  TAC_MUTE_REG(SA, FU23, LEFT)
6338c89fedSNiranjan H Y #define FU23_R_MUTE_REG  TAC_MUTE_REG(SA, FU23, RIGHT)
6438c89fedSNiranjan H Y #define FU26_MUTE_REG    TAC_MUTE_REG(SA, FU26, LEFT)
6538c89fedSNiranjan H Y #define FU11_L_MUTE_REG  TAC_MUTE_REG(SM, FU11, LEFT)
6638c89fedSNiranjan H Y #define FU11_R_MUTE_REG  TAC_MUTE_REG(SM, FU11, RIGHT)
6738c89fedSNiranjan H Y #define FU113_L_MUTE_REG TAC_MUTE_REG(SM, FU113, LEFT)
6838c89fedSNiranjan H Y #define FU113_R_MUTE_REG TAC_MUTE_REG(SM, FU113, RIGHT)
6938c89fedSNiranjan H Y #define FU41_L_MUTE_REG  TAC_MUTE_REG(UAJ, FU41, LEFT)
7038c89fedSNiranjan H Y #define FU41_R_MUTE_REG  TAC_MUTE_REG(UAJ, FU41, RIGHT)
7138c89fedSNiranjan H Y #define FU36_MUTE_REG    TAC_MUTE_REG(UAJ, FU36, RIGHT)
7238c89fedSNiranjan H Y 
7338c89fedSNiranjan H Y /* it/ot usage */
7438c89fedSNiranjan H Y #define IT11_USAGE_REG  TAC_USAGE_REG(SM, IT11)
7538c89fedSNiranjan H Y #define IT41_USAGE_REG  TAC_USAGE_REG(UAJ, IT41)
7638c89fedSNiranjan H Y #define IT33_USAGE_REG  TAC_USAGE_REG(UAJ, IT33)
7738c89fedSNiranjan H Y #define OT113_USAGE_REG TAC_USAGE_REG(SM, OT113)
7838c89fedSNiranjan H Y #define OT45_USAGE_REG TAC_USAGE_REG(UAJ, OT45)
7938c89fedSNiranjan H Y #define OT36_USAGE_REG TAC_USAGE_REG(UAJ, OT36)
8038c89fedSNiranjan H Y 
8138c89fedSNiranjan H Y /* xu bypass */
8238c89fedSNiranjan H Y #define XU12_BYPASS_REG TAC_XU_BYPASS_REG(SM, XU12)
8338c89fedSNiranjan H Y #define XU42_BYPASS_REG TAC_XU_BYPASS_REG(UAJ, XU42)
8438c89fedSNiranjan H Y 
8538c89fedSNiranjan H Y #define TAC_DSP_ALGO_STATUS		TAC_REG_SDW(0, 3, 12)
8638c89fedSNiranjan H Y #define TAC_DSP_ALGO_STATUS_RUNNING	0x20
8738c89fedSNiranjan H Y #define TAC_FW_HDR_SIZE		88
8838c89fedSNiranjan H Y #define TAC_FW_FILE_HDR	 20
8938c89fedSNiranjan H Y #define TAC_MAX_FW_CHUNKS 512
9038c89fedSNiranjan H Y 
9138c89fedSNiranjan H Y #define TAC_UAJ_PREP_CONNECTED		0xff
9238c89fedSNiranjan H Y #define TAC_UAJ_PREP_DISCONNECTED	0xdf
9338c89fedSNiranjan H Y 
9438c89fedSNiranjan H Y struct tac_fw_hdr {
9538c89fedSNiranjan H Y 	u32 size;
9638c89fedSNiranjan H Y 	u32 version_offset;
9738c89fedSNiranjan H Y 	u32 plt_id;
9838c89fedSNiranjan H Y 	u32 ppc3_ver;
9938c89fedSNiranjan H Y 	u64 timestamp;
10038c89fedSNiranjan H Y 	u8 ddc_name[64];
10138c89fedSNiranjan H Y };
10238c89fedSNiranjan H Y 
10338c89fedSNiranjan H Y /* Firmware file/chunk structure */
10438c89fedSNiranjan H Y struct tac_fw_file {
10538c89fedSNiranjan H Y 	u32 vendor_id;
10638c89fedSNiranjan H Y 	u32 file_id;
10738c89fedSNiranjan H Y 	u32 version;
10838c89fedSNiranjan H Y 	u32 length;
10938c89fedSNiranjan H Y 	u32 dest_addr;
11038c89fedSNiranjan H Y 	u8 *fw_data;
11138c89fedSNiranjan H Y };
11238c89fedSNiranjan H Y 
11338c89fedSNiranjan H Y /* TLV for volume control */
11438c89fedSNiranjan H Y static const DECLARE_TLV_DB_SCALE(tac5xx2_amp_tlv, 0, 50, 0);
11538c89fedSNiranjan H Y static const DECLARE_TLV_DB_SCALE(tac5xx2_dvc_tlv, -7200, 50, 0);
11638c89fedSNiranjan H Y 
11738c89fedSNiranjan H Y /* Q7.8 volume control parameters: range -72dB to +6dB, step 0.5dB */
11838c89fedSNiranjan H Y #define TAC_DVC_STEP		128	/* 0.5 dB in Q7.8 format */
11938c89fedSNiranjan H Y #define TAC_DVC_MIN		(-144)	/* -72 dB / 0.5 dB step */
12038c89fedSNiranjan H Y #define TAC_DVC_MAX		12	/* +6 dB / 0.5 dB step */
12138c89fedSNiranjan H Y 
12238c89fedSNiranjan H Y /* TAC-specific stereo volume control macro using SDW_SDCA_CTL (single control for L/R) */
12338c89fedSNiranjan H Y #define TAC_DOUBLE_Q78_TLV(name, func_id, ent_id) \
12438c89fedSNiranjan H Y 	SDCA_DOUBLE_Q78_TLV(name, \
12538c89fedSNiranjan H Y 			    SDW_SDCA_CTL(TAC_FUNCTION_ID_##func_id, TAC_SDCA_ENT_##ent_id, \
12638c89fedSNiranjan H Y 					 TAC_SDCA_CHANNEL_GAIN, TAC_CHANNEL_LEFT), \
12738c89fedSNiranjan H Y 			    SDW_SDCA_CTL(TAC_FUNCTION_ID_##func_id, TAC_SDCA_ENT_##ent_id, \
12838c89fedSNiranjan H Y 					 TAC_SDCA_CHANNEL_GAIN, TAC_CHANNEL_RIGHT), \
12938c89fedSNiranjan H Y 			    TAC_DVC_MIN, TAC_DVC_MAX, TAC_DVC_STEP, tac5xx2_dvc_tlv)
13038c89fedSNiranjan H Y 
13138c89fedSNiranjan H Y struct tac5xx2_prv {
13238c89fedSNiranjan H Y 	struct snd_soc_component *component;
13338c89fedSNiranjan H Y 	struct sdw_slave *sdw_peripheral;
13438c89fedSNiranjan H Y 	struct sdca_function_data *sa_func_data;
13538c89fedSNiranjan H Y 	struct sdca_function_data *sm_func_data;
13638c89fedSNiranjan H Y 	struct sdca_function_data *uaj_func_data;
13738c89fedSNiranjan H Y 	struct sdca_function_data *hid_func_data;
13838c89fedSNiranjan H Y 	enum sdw_slave_status status;
13938c89fedSNiranjan H Y 	struct regmap *regmap;
14038c89fedSNiranjan H Y 	struct device *dev;
14138c89fedSNiranjan H Y 	bool hw_init;
14238c89fedSNiranjan H Y 	bool first_hw_init_done;
14338c89fedSNiranjan H Y 	u32 part_id;
14438c89fedSNiranjan H Y 	u32 rev_id;
14538c89fedSNiranjan H Y 	struct snd_soc_jack *hs_jack;
14638c89fedSNiranjan H Y 	int jack_type;
14738c89fedSNiranjan H Y 	 /* Custom fw binary. UMP File Download is not used. */
14838c89fedSNiranjan H Y 	unsigned int fw_file_cnt;
14938c89fedSNiranjan H Y 	struct tac_fw_file *fw_files;
15038c89fedSNiranjan H Y 	struct completion fw_caching_complete;
15138c89fedSNiranjan H Y 	bool fw_dl_success;
15238c89fedSNiranjan H Y 	u8 fw_binaryname[64];
15338c89fedSNiranjan H Y };
15438c89fedSNiranjan H Y 
15538c89fedSNiranjan H Y static const struct reg_default tac_reg_default[] = {
15638c89fedSNiranjan H Y 	{TAC_SW_RESET, 0x0},
15738c89fedSNiranjan H Y 	{TAC_SLEEP_MODEZ, 0x0},
15838c89fedSNiranjan H Y 	{TAC_FEATURE_PDZ, 0x0},
15938c89fedSNiranjan H Y 	{TAC_TX_CH_EN, 0xf0},
16038c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x5), 0xcf},
16138c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x6), 0xa},
16238c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x7), 0x0},
16338c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x8), 0xfe},
16438c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x9), 0x9},
16538c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0xa), 0x28},
16638c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0xb), 0x1},
16738c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0xc), 0x11},
16838c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0xd), 0x11},
16938c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0xe), 0x61},
17038c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0xf), 0x0},
17138c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x10), 0x50},
17238c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x11), 0x70},
17338c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x12), 0x60},
17438c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x13), 0x28},
17538c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x14), 0x0},
17638c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x15), 0x18},
17738c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x16), 0x20},
17838c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x17), 0x0},
17938c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x18), 0x18},
18038c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x19), 0x54},
18138c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x1a), 0x8},
18238c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x1b), 0x0},
18338c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x1c), 0x30},
18438c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x1d), 0x0},
18538c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x1e), 0x0},
18638c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x1f), 0x0},
18738c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x20), 0x0},
18838c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x21), 0x20},
18938c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x22), 0x21},
19038c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x23), 0x22},
19138c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x24), 0x23},
19238c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x25), 0x4},
19338c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x26), 0x5},
19438c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x27), 0x6},
19538c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x28), 0x7},
19638c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x29), 0x0},
19738c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x2a), 0x0},
19838c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x2b), 0x0},
19938c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x2c), 0x20},
20038c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x2d), 0x21},
20138c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x2e), 0x2},
20238c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x2f), 0x3},
20338c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x30), 0x4},
20438c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x31), 0x5},
20538c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x32), 0x6},
20638c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x33), 0x7},
20738c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x34), 0x0},
20838c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x35), 0x90},
20938c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x36), 0x80},
21038c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x37), 0x0},
21138c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x39), 0x0},
21238c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x3a), 0x90},
21338c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x3b), 0x80},
21438c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x3c), 0x0},
21538c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x3e), 0x0},
21638c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x3f), 0x90},
21738c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x40), 0x80},
21838c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x41), 0x0},
21938c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x43), 0x90},
22038c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x44), 0x80},
22138c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x45), 0x0},
22238c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x47), 0x90},
22338c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x48), 0x80},
22438c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x49), 0x0},
22538c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x4b), 0x90},
22638c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x4c), 0x80},
22738c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x4d), 0x0},
22838c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x4f), 0x31},
22938c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x50), 0x0},
23038c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x51), 0x0},
23138c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x52), 0x90},
23238c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x53), 0x80},
23338c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x55), 0x90},
23438c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x56), 0x80},
23538c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x58), 0x90},
23638c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x59), 0x80},
23738c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x5b), 0x90},
23838c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x5c), 0x80},
23938c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x5e), 0x8},
24038c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x5f), 0x8},
24138c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x60), 0x0},
24238c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x61), 0x0},
24338c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x62), 0xff},
24438c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x63), 0xc0},
24538c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x64), 0x5},
24638c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x65), 0x3},
24738c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x66), 0x0},
24838c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x67), 0x0},
24938c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x68), 0x0},
25038c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x69), 0x8},
25138c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x6a), 0x0},
25238c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x6b), 0xa0},
25338c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x6c), 0x18},
25438c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x6d), 0x18},
25538c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x6e), 0x18},
25638c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x6f), 0x18},
25738c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x70), 0x88},
25838c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x71), 0xff},
25938c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x72), 0x0},
26038c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x73), 0x31},
26138c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x74), 0xc0},
26238c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x75), 0x0},
26338c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x76), 0x0},
26438c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x77), 0x0},
26538c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x78), 0x0},
26638c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x7b), 0x0},
26738c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x7c), 0xd0},
26838c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 0, 0x7e), 0x0},
26938c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x1), 0x0},
27038c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x2), 0x0},
27138c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x3), 0x0},
27238c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x4), 0x4},
27338c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x5), 0x0},
27438c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x6), 0x0},
27538c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x7), 0x0},
27638c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x8), 0x0},
27738c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x9), 0x0},
27838c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0xa), 0x0},
27938c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0xb), 0x1},
28038c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0xc), 0x0},
28138c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0xd), 0x0},
28238c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0xe), 0x0},
28338c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0xf), 0x8},
28438c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x10), 0x0},
28538c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x11), 0x0},
28638c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x12), 0x1},
28738c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x13), 0x0},
28838c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x14), 0x0},
28938c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x15), 0x0},
29038c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x16), 0x0},
29138c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x17), 0x0},
29238c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x18), 0x0},
29338c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x19), 0x0},
29438c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x1a), 0x0},
29538c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x1b), 0x0},
29638c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x1c), 0x0},
29738c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x1d), 0x0},
29838c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x1e), 0x2},
29938c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x1f), 0x8},
30038c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x20), 0x9},
30138c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x21), 0xa},
30238c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x22), 0xb},
30338c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x23), 0xc},
30438c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x24), 0xd},
30538c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x25), 0xe},
30638c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x26), 0xf},
30738c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x27), 0x8},
30838c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x28), 0x9},
30938c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x29), 0xa},
31038c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x2a), 0xb},
31138c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x2b), 0xc},
31238c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x2c), 0xd},
31338c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x2d), 0xe},
31438c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x2e), 0xf},
31538c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x2f), 0x0},
31638c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x30), 0x0},
31738c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x31), 0x0},
31838c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x32), 0x0},
31938c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x33), 0x0},
32038c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x34), 0x0},
32138c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x35), 0x0},
32238c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x36), 0x0},
32338c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x37), 0x0},
32438c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x38), 0x98},
32538c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x39), 0x0},
32638c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x3a), 0x0},
32738c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x3b), 0x0},
32838c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x3c), 0x1},
32938c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x3d), 0x2},
33038c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x3e), 0x3},
33138c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x3f), 0x4},
33238c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x40), 0x5},
33338c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x41), 0x6},
33438c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x42), 0x7},
33538c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x43), 0x0},
33638c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x44), 0x0},
33738c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x45), 0x1},
33838c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x46), 0x2},
33938c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x47), 0x3},
34038c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x48), 0x4},
34138c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x49), 0x5},
34238c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x4a), 0x6},
34338c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x4b), 0x7},
34438c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x4c), 0x98},
34538c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x4d), 0x0},
34638c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x4e), 0x0},
34738c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x4f), 0x0},
34838c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x50), 0x1},
34938c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x51), 0x2},
35038c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x52), 0x3},
35138c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x53), 0x4},
35238c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x54), 0x5},
35338c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x55), 0x6},
35438c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x56), 0x7},
35538c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x57), 0x0},
35638c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x58), 0x0},
35738c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x59), 0x1},
35838c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x5a), 0x2},
35938c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x5b), 0x3},
36038c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x5c), 0x4},
36138c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x5d), 0x5},
36238c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x5e), 0x6},
36338c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x5f), 0x7},
36438c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x60), 0x98},
36538c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x61), 0x0},
36638c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x62), 0x0},
36738c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x63), 0x0},
36838c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x64), 0x1},
36938c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x65), 0x2},
37038c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x66), 0x3},
37138c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x67), 0x4},
37238c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x68), 0x5},
37338c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x69), 0x6},
37438c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x6a), 0x7},
37538c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x6b), 0x0},
37638c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x6c), 0x0},
37738c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x6d), 0x1},
37838c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x6e), 0x2},
37938c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x6f), 0x3},
38038c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x70), 0x4},
38138c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x71), 0x5},
38238c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x72), 0x6},
38338c89fedSNiranjan H Y 	{TAC_REG_SDW(0, 1, 0x73), 0x7},
38438c89fedSNiranjan H Y };
38538c89fedSNiranjan H Y 
38638c89fedSNiranjan H Y static const struct reg_sequence tac_spk_seq[] = {
38738c89fedSNiranjan H Y 	REG_SEQ0(SDW_SDCA_CTL(TAC_FUNCTION_ID_SA, TAC_SDCA_ENT_FU21,
38838c89fedSNiranjan H Y 			      TAC_SDCA_CHANNEL_GAIN, TAC_CHANNEL_LEFT), 0),
38938c89fedSNiranjan H Y 	REG_SEQ0(SDW_SDCA_CTL(TAC_FUNCTION_ID_SA, TAC_SDCA_ENT_FU21,
39038c89fedSNiranjan H Y 			      TAC_SDCA_CHANNEL_GAIN, TAC_CHANNEL_RIGHT), 0),
39138c89fedSNiranjan H Y 	REG_SEQ0(SDW_SDCA_CTL(TAC_FUNCTION_ID_SA, TAC_SDCA_ENT_FU23,
39238c89fedSNiranjan H Y 			      TAC_SDCA_CHANNEL_GAIN, TAC_CHANNEL_LEFT), 0),
39338c89fedSNiranjan H Y 	REG_SEQ0(SDW_SDCA_CTL(TAC_FUNCTION_ID_SA, TAC_SDCA_ENT_FU23,
39438c89fedSNiranjan H Y 			      TAC_SDCA_CHANNEL_GAIN, TAC_CHANNEL_RIGHT), 0),
39538c89fedSNiranjan H Y };
39638c89fedSNiranjan H Y 
39738c89fedSNiranjan H Y static const struct reg_sequence tac_sm_seq[] = {
39838c89fedSNiranjan H Y 	REG_SEQ0(SDW_SDCA_CTL(TAC_FUNCTION_ID_SM, TAC_SDCA_ENT_FU113,
39938c89fedSNiranjan H Y 			      TAC_SDCA_CHANNEL_GAIN, TAC_CHANNEL_LEFT), 0),
40038c89fedSNiranjan H Y 	REG_SEQ0(SDW_SDCA_CTL(TAC_FUNCTION_ID_SM, TAC_SDCA_ENT_FU113,
40138c89fedSNiranjan H Y 			      TAC_SDCA_CHANNEL_GAIN, TAC_CHANNEL_RIGHT), 0),
40238c89fedSNiranjan H Y 	REG_SEQ0(SDW_SDCA_CTL(TAC_FUNCTION_ID_SM, TAC_SDCA_ENT_FU11,
40338c89fedSNiranjan H Y 			      TAC_SDCA_CHANNEL_GAIN, TAC_CHANNEL_LEFT), 0),
40438c89fedSNiranjan H Y 	REG_SEQ0(SDW_SDCA_CTL(TAC_FUNCTION_ID_SM, TAC_SDCA_ENT_FU11,
40538c89fedSNiranjan H Y 			      TAC_SDCA_CHANNEL_GAIN, TAC_CHANNEL_RIGHT), 0),
40638c89fedSNiranjan H Y };
40738c89fedSNiranjan H Y 
40838c89fedSNiranjan H Y static const struct reg_sequence tac_uaj_seq[] = {
40938c89fedSNiranjan H Y 	REG_SEQ0(SDW_SDCA_CTL(TAC_FUNCTION_ID_UAJ, TAC_SDCA_ENT_FU41,
41038c89fedSNiranjan H Y 			      TAC_SDCA_CHANNEL_GAIN, TAC_CHANNEL_LEFT), 0),
41138c89fedSNiranjan H Y 	REG_SEQ0(SDW_SDCA_CTL(TAC_FUNCTION_ID_UAJ, TAC_SDCA_ENT_FU41,
41238c89fedSNiranjan H Y 			      TAC_SDCA_CHANNEL_GAIN, TAC_CHANNEL_RIGHT), 0),
41338c89fedSNiranjan H Y 	REG_SEQ0(SDW_SDCA_CTL(TAC_FUNCTION_ID_UAJ, TAC_SDCA_ENT_FU36,
41438c89fedSNiranjan H Y 			      TAC_SDCA_CHANNEL_GAIN, TAC_JACK_MONO_CS), 0),
41538c89fedSNiranjan H Y };
41638c89fedSNiranjan H Y 
tac_volatile_reg(struct device * dev,unsigned int reg)41738c89fedSNiranjan H Y static bool tac_volatile_reg(struct device *dev, unsigned int reg)
41838c89fedSNiranjan H Y {
41938c89fedSNiranjan H Y 	switch (reg) {
42038c89fedSNiranjan H Y 	case TAC_REG_SDW(0, 0, 1) ... TAC_REG_SDW(0, 0, 5):
42138c89fedSNiranjan H Y 	case TAC_REG_SDW(0, 2, 1) ... TAC_REG_SDW(0, 2, 6):
42238c89fedSNiranjan H Y 	case TAC_REG_SDW(0, 2, 24) ... TAC_REG_SDW(0, 2, 55):
42338c89fedSNiranjan H Y 	case SDW_SDCA_CTL(TAC_FUNCTION_ID_HID, TAC_SDCA_ENT_HID1,
42438c89fedSNiranjan H Y 			  TAC_SDCA_CTL_HIDTX_CURRENT_OWNER, 0):
42538c89fedSNiranjan H Y 	case SDW_SDCA_CTL(TAC_FUNCTION_ID_HID, TAC_SDCA_ENT_HID1,
42638c89fedSNiranjan H Y 			  TAC_SDCA_CTL_HIDTX_MESSAGE_OFFSET, 0):
42738c89fedSNiranjan H Y 	case SDW_SDCA_CTL(TAC_FUNCTION_ID_UAJ, TAC_SDCA_ENT_GE35,
42838c89fedSNiranjan H Y 			  TAC_SDCA_CTL_DET_MODE, 0):
42938c89fedSNiranjan H Y 	case SDW_SDCA_CTL(TAC_FUNCTION_ID_SA, TAC_SDCA_ENT_PDE23,
43038c89fedSNiranjan H Y 			  TAC_SDCA_REQUESTED_PS, 0):
43138c89fedSNiranjan H Y 	case SDW_SDCA_CTL(TAC_FUNCTION_ID_SM, TAC_SDCA_ENT_PDE11,
43238c89fedSNiranjan H Y 			  TAC_SDCA_REQUESTED_PS, 0):
43338c89fedSNiranjan H Y 	case SDW_SDCA_CTL(TAC_FUNCTION_ID_UAJ, TAC_SDCA_ENT_PDE47,
43438c89fedSNiranjan H Y 			  TAC_SDCA_REQUESTED_PS, 0):
43538c89fedSNiranjan H Y 	case SDW_SDCA_CTL(TAC_FUNCTION_ID_UAJ, TAC_SDCA_ENT_PDE34,
43638c89fedSNiranjan H Y 			  TAC_SDCA_REQUESTED_PS, 0):
43738c89fedSNiranjan H Y 	case SDW_SDCA_CTL(TAC_FUNCTION_ID_SA, TAC_SDCA_ENT_PDE23,
43838c89fedSNiranjan H Y 			  TAC_SDCA_ACTUAL_PS, 0):
43938c89fedSNiranjan H Y 	case SDW_SDCA_CTL(TAC_FUNCTION_ID_SM, TAC_SDCA_ENT_PDE11,
44038c89fedSNiranjan H Y 			  TAC_SDCA_ACTUAL_PS, 0):
44138c89fedSNiranjan H Y 	case SDW_SDCA_CTL(TAC_FUNCTION_ID_UAJ, TAC_SDCA_ENT_PDE47,
44238c89fedSNiranjan H Y 			  TAC_SDCA_ACTUAL_PS, 0):
44338c89fedSNiranjan H Y 	case SDW_SDCA_CTL(TAC_FUNCTION_ID_UAJ, TAC_SDCA_ENT_PDE34,
44438c89fedSNiranjan H Y 			  TAC_SDCA_ACTUAL_PS, 0):
44538c89fedSNiranjan H Y 	case SDW_SCP_SDCA_INT1:
44638c89fedSNiranjan H Y 	case SDW_SCP_SDCA_INT2:
44738c89fedSNiranjan H Y 	case SDW_SCP_SDCA_INT3:
44838c89fedSNiranjan H Y 	case SDW_SCP_SDCA_INT4:
44938c89fedSNiranjan H Y 	case SDW_SDCA_CTL(1, 0, 0x10, 0):
45038c89fedSNiranjan H Y 	case SDW_SDCA_CTL(2, 0, 0x10, 0):
45138c89fedSNiranjan H Y 	case SDW_SDCA_CTL(3, 0, 0x10, 0):
45238c89fedSNiranjan H Y 	case SDW_SDCA_CTL(4, 0, 0x1, 0):
45338c89fedSNiranjan H Y 	case 0x44007F80 ... 0x44007F87:
45438c89fedSNiranjan H Y 	case TAC_DSP_ALGO_STATUS:	/* DSP algo status - always read from HW */
45538c89fedSNiranjan H Y 		return true;
45638c89fedSNiranjan H Y 	default:
45738c89fedSNiranjan H Y 		break;
45838c89fedSNiranjan H Y 	}
45938c89fedSNiranjan H Y 
46038c89fedSNiranjan H Y 	return false;
46138c89fedSNiranjan H Y }
46238c89fedSNiranjan H Y 
tac_sdca_mbq_size(struct device * dev,unsigned int reg)46338c89fedSNiranjan H Y static int tac_sdca_mbq_size(struct device *dev, unsigned int reg)
46438c89fedSNiranjan H Y {
46538c89fedSNiranjan H Y 	switch (reg) {
46638c89fedSNiranjan H Y 	case SDW_SDCA_CTL(TAC_FUNCTION_ID_SA, TAC_SDCA_ENT_FU21,
46738c89fedSNiranjan H Y 			  TAC_SDCA_CHANNEL_VOLUME, TAC_CHANNEL_LEFT):
46838c89fedSNiranjan H Y 	case SDW_SDCA_CTL(TAC_FUNCTION_ID_SA, TAC_SDCA_ENT_FU21,
46938c89fedSNiranjan H Y 			  TAC_SDCA_CHANNEL_VOLUME, TAC_CHANNEL_RIGHT):
47038c89fedSNiranjan H Y 	case SDW_SDCA_CTL(TAC_FUNCTION_ID_SA, TAC_SDCA_ENT_FU23,
47138c89fedSNiranjan H Y 			  TAC_SDCA_CHANNEL_GAIN, TAC_CHANNEL_LEFT):
47238c89fedSNiranjan H Y 	case SDW_SDCA_CTL(TAC_FUNCTION_ID_SA, TAC_SDCA_ENT_FU23,
47338c89fedSNiranjan H Y 			  TAC_SDCA_CHANNEL_GAIN, TAC_CHANNEL_RIGHT):
47438c89fedSNiranjan H Y 	case SDW_SDCA_CTL(TAC_FUNCTION_ID_SA, TAC_SDCA_ENT_FU23,
47538c89fedSNiranjan H Y 			  TAC_SDCA_MASTER_GAIN, 0):
47638c89fedSNiranjan H Y 	case SDW_SDCA_CTL(TAC_FUNCTION_ID_SM, TAC_SDCA_ENT_FU113,
47738c89fedSNiranjan H Y 			  TAC_SDCA_CHANNEL_GAIN, TAC_CHANNEL_LEFT):
47838c89fedSNiranjan H Y 	case SDW_SDCA_CTL(TAC_FUNCTION_ID_SM, TAC_SDCA_ENT_FU113,
47938c89fedSNiranjan H Y 			  TAC_SDCA_CHANNEL_GAIN, TAC_CHANNEL_RIGHT):
48038c89fedSNiranjan H Y 	case SDW_SDCA_CTL(TAC_FUNCTION_ID_SM, TAC_SDCA_ENT_FU11,
48138c89fedSNiranjan H Y 			  TAC_SDCA_CHANNEL_GAIN, TAC_CHANNEL_LEFT):
48238c89fedSNiranjan H Y 	case SDW_SDCA_CTL(TAC_FUNCTION_ID_SM, TAC_SDCA_ENT_FU11,
48338c89fedSNiranjan H Y 			  TAC_SDCA_CHANNEL_GAIN, TAC_CHANNEL_RIGHT):
48438c89fedSNiranjan H Y 	case SDW_SDCA_CTL(TAC_FUNCTION_ID_UAJ, TAC_SDCA_ENT_FU41,
48538c89fedSNiranjan H Y 			  TAC_SDCA_CHANNEL_GAIN, TAC_CHANNEL_LEFT):
48638c89fedSNiranjan H Y 	case SDW_SDCA_CTL(TAC_FUNCTION_ID_UAJ, TAC_SDCA_ENT_FU41,
48738c89fedSNiranjan H Y 			  TAC_SDCA_CHANNEL_GAIN, TAC_CHANNEL_RIGHT):
48838c89fedSNiranjan H Y 	case SDW_SDCA_CTL(TAC_FUNCTION_ID_UAJ, TAC_SDCA_ENT_FU36,
48938c89fedSNiranjan H Y 			  TAC_SDCA_CHANNEL_GAIN, TAC_JACK_MONO_CS):
49038c89fedSNiranjan H Y 		return 2;
49138c89fedSNiranjan H Y 
49238c89fedSNiranjan H Y 	default:
49338c89fedSNiranjan H Y 		return 1;
49438c89fedSNiranjan H Y 	}
49538c89fedSNiranjan H Y }
49638c89fedSNiranjan H Y 
49738c89fedSNiranjan H Y static const struct regmap_sdw_mbq_cfg tac_mbq_cfg = {
49838c89fedSNiranjan H Y 	.mbq_size = tac_sdca_mbq_size,
49938c89fedSNiranjan H Y };
50038c89fedSNiranjan H Y 
50138c89fedSNiranjan H Y static const struct regmap_config tac_regmap = {
50238c89fedSNiranjan H Y 	.reg_bits = 32,
50338c89fedSNiranjan H Y 	.val_bits = 16, /* mbq support */
50438c89fedSNiranjan H Y 	.reg_defaults = tac_reg_default,
50538c89fedSNiranjan H Y 	.num_reg_defaults = ARRAY_SIZE(tac_reg_default),
50638c89fedSNiranjan H Y 	.max_register = 0x47FFFFFF,
50738c89fedSNiranjan H Y 	.cache_type = REGCACHE_MAPLE,
50838c89fedSNiranjan H Y 	.volatile_reg = tac_volatile_reg,
50938c89fedSNiranjan H Y 	.use_single_read = true,
51038c89fedSNiranjan H Y 	.use_single_write = true,
51138c89fedSNiranjan H Y };
51238c89fedSNiranjan H Y 
51338c89fedSNiranjan H Y /* Check if device has UAJ (Universal Audio Jack) support */
tac_has_uaj_support(struct tac5xx2_prv * tac_dev)51438c89fedSNiranjan H Y static bool tac_has_uaj_support(struct tac5xx2_prv *tac_dev)
51538c89fedSNiranjan H Y {
51638c89fedSNiranjan H Y 	return tac_dev->uaj_func_data;
51738c89fedSNiranjan H Y }
51838c89fedSNiranjan H Y 
51938c89fedSNiranjan H Y /* Forward declaration for headset detection */
52038c89fedSNiranjan H Y static int tac5xx2_sdca_headset_detect(struct tac5xx2_prv *tac_dev);
52138c89fedSNiranjan H Y 
52238c89fedSNiranjan H Y /* Volume controls for mic, hp and mic cap */
52338c89fedSNiranjan H Y static const struct snd_kcontrol_new tac5xx2_snd_controls[] = {
52438c89fedSNiranjan H Y 	SOC_DOUBLE_R_RANGE_TLV("Amp Volume", TAC_AMP_LVL_CFG0, TAC_AMP_LVL_CFG1,
52538c89fedSNiranjan H Y 			       2, 0, 44, 1, tac5xx2_amp_tlv),
52638c89fedSNiranjan H Y 	TAC_DOUBLE_Q78_TLV("DMIC Capture Volume", SM, FU113),
52738c89fedSNiranjan H Y 	TAC_DOUBLE_Q78_TLV("Speaker Volume", SA, FU21),
52838c89fedSNiranjan H Y };
52938c89fedSNiranjan H Y 
53038c89fedSNiranjan H Y static const struct snd_kcontrol_new tac_uaj_controls[] = {
53138c89fedSNiranjan H Y 	TAC_DOUBLE_Q78_TLV("UAJ Playback Volume", UAJ, FU41),
53238c89fedSNiranjan H Y 	SDCA_SINGLE_Q78_TLV("UAJ Capture Volume",
53338c89fedSNiranjan H Y 			    SDW_SDCA_CTL(TAC_FUNCTION_ID_UAJ, TAC_SDCA_ENT_FU36,
53438c89fedSNiranjan H Y 					 TAC_SDCA_CHANNEL_GAIN, TAC_JACK_MONO_CS),
53538c89fedSNiranjan H Y 			   TAC_DVC_MIN, TAC_DVC_MAX, TAC_DVC_STEP, tac5xx2_dvc_tlv),
53638c89fedSNiranjan H Y };
53738c89fedSNiranjan H Y 
53838c89fedSNiranjan H Y static const struct snd_soc_dapm_widget tac5xx2_common_widgets[] = {
53938c89fedSNiranjan H Y 	/* Port 1: Speaker Playback Path */
54038c89fedSNiranjan H Y 	SND_SOC_DAPM_AIF_IN("AIF1 Playback", "DP1 Speaker Playback", 0,
54138c89fedSNiranjan H Y 			    SND_SOC_NOPM, 0, 0),
54238c89fedSNiranjan H Y 	SND_SOC_DAPM_PGA("FU21_L", FU21_L_MUTE_REG, 0, 1, NULL, 0),
54338c89fedSNiranjan H Y 	SND_SOC_DAPM_PGA("FU21_R", FU21_R_MUTE_REG, 0, 1, NULL, 0),
54438c89fedSNiranjan H Y 	SND_SOC_DAPM_PGA("FU23_L", FU23_L_MUTE_REG, 0, 1, NULL, 0),
54538c89fedSNiranjan H Y 	SND_SOC_DAPM_PGA("FU23_R", FU23_R_MUTE_REG, 0, 1, NULL, 0),
54638c89fedSNiranjan H Y 	SND_SOC_DAPM_OUTPUT("SPK_L"),
54738c89fedSNiranjan H Y 	SND_SOC_DAPM_OUTPUT("SPK_R"),
54838c89fedSNiranjan H Y 
54938c89fedSNiranjan H Y 	/* Port 3: Smart Mic (DMIC) Capture Path */
55038c89fedSNiranjan H Y 	SND_SOC_DAPM_AIF_OUT("AIF3 Capture", "DP3 Mic Capture", 0, SND_SOC_NOPM, 0, 0),
55138c89fedSNiranjan H Y 	SND_SOC_DAPM_INPUT("DMIC_L"),
55238c89fedSNiranjan H Y 	SND_SOC_DAPM_INPUT("DMIC_R"),
55338c89fedSNiranjan H Y 	SND_SOC_DAPM_PGA("IT11", IT11_USAGE_REG, 0, 0, NULL, 0),
55438c89fedSNiranjan H Y 	SND_SOC_DAPM_SUPPLY("CS113", SND_SOC_NOPM, 0, 0, NULL, 0),
55538c89fedSNiranjan H Y 	SND_SOC_DAPM_PGA("FU11_L", FU11_L_MUTE_REG, 0, 1, NULL, 0),
55638c89fedSNiranjan H Y 	SND_SOC_DAPM_PGA("FU11_R", FU11_R_MUTE_REG, 0, 1, NULL, 0),
55738c89fedSNiranjan H Y 	SND_SOC_DAPM_PGA("PPU11", SND_SOC_NOPM, 0, 0, NULL, 0),
55838c89fedSNiranjan H Y 	SND_SOC_DAPM_PGA("XU12", XU12_BYPASS_REG, 0, 0, NULL, 0),
55938c89fedSNiranjan H Y 	SND_SOC_DAPM_PGA("FU113_L", FU113_L_MUTE_REG, 0, 1, NULL, 0),
56038c89fedSNiranjan H Y 	SND_SOC_DAPM_PGA("FU113_R", FU113_R_MUTE_REG, 0, 1, NULL, 0),
56138c89fedSNiranjan H Y 	SND_SOC_DAPM_PGA("OT113", OT113_USAGE_REG, 0, 0, NULL, 0),
56238c89fedSNiranjan H Y };
56338c89fedSNiranjan H Y 
56438c89fedSNiranjan H Y static const struct snd_soc_dapm_widget tac_uaj_widgets[] = {
56538c89fedSNiranjan H Y 	/* Port 4: UAJ (Headphone) Playback Path */
56638c89fedSNiranjan H Y 	SND_SOC_DAPM_AIF_IN("AIF4 Playback", "DP4 UAJ Speaker Playback", 0,
56738c89fedSNiranjan H Y 			    SND_SOC_NOPM, 0, 0),
56838c89fedSNiranjan H Y 	SND_SOC_DAPM_PGA("IT41", IT41_USAGE_REG, 0, 0, NULL, 0),
56938c89fedSNiranjan H Y 	SND_SOC_DAPM_PGA("FU41_L", FU41_L_MUTE_REG, 0, 1, NULL, 0),
57038c89fedSNiranjan H Y 	SND_SOC_DAPM_PGA("FU41_R", FU41_R_MUTE_REG, 0, 1, NULL, 0),
57138c89fedSNiranjan H Y 	SND_SOC_DAPM_PGA("XU42", XU42_BYPASS_REG, 0, 0, NULL, 0),
57238c89fedSNiranjan H Y 	SND_SOC_DAPM_SUPPLY("CS41", SND_SOC_NOPM, 0, 0, NULL, 0),
57338c89fedSNiranjan H Y 	SND_SOC_DAPM_DAC("OT45", "DP4 UAJ Speaker Playback", OT45_USAGE_REG, 0, 0),
57438c89fedSNiranjan H Y 	SND_SOC_DAPM_OUTPUT("HP_L"),
57538c89fedSNiranjan H Y 	SND_SOC_DAPM_OUTPUT("HP_R"),
57638c89fedSNiranjan H Y 
57738c89fedSNiranjan H Y 	/* Port 7: UAJ (Headset Mic) Capture Path */
57838c89fedSNiranjan H Y 	SND_SOC_DAPM_AIF_OUT("AIF7 Capture", "DP7 UAJ Mic Capture", 0,
57938c89fedSNiranjan H Y 			     SND_SOC_NOPM, 0, 0),
58038c89fedSNiranjan H Y 	SND_SOC_DAPM_INPUT("UAJ_MIC"),
58138c89fedSNiranjan H Y 	SND_SOC_DAPM_ADC("IT33", "DP7 UAJ Mic Capture", IT33_USAGE_REG, 0, 0),
58238c89fedSNiranjan H Y 	SND_SOC_DAPM_PGA("FU36", FU36_MUTE_REG, 0, 1, NULL, 0),
58338c89fedSNiranjan H Y 	SND_SOC_DAPM_SUPPLY("CS36", SND_SOC_NOPM, 0, 0, NULL, 0),
58438c89fedSNiranjan H Y 	SND_SOC_DAPM_PGA("OT36", OT36_USAGE_REG, 0, 0, NULL, 0),
58538c89fedSNiranjan H Y };
58638c89fedSNiranjan H Y 
58738c89fedSNiranjan H Y static const struct snd_soc_dapm_route tac5xx2_common_routes[] = {
58838c89fedSNiranjan H Y 	/* Speaker Playback Path */
58938c89fedSNiranjan H Y 	{"FU21_L", NULL, "AIF1 Playback"},
59038c89fedSNiranjan H Y 	{"FU21_R", NULL, "AIF1 Playback"},
59138c89fedSNiranjan H Y 
59238c89fedSNiranjan H Y 	{"FU23_L", NULL, "FU21_L"},
59338c89fedSNiranjan H Y 	{"FU23_R", NULL, "FU21_R"},
59438c89fedSNiranjan H Y 
59538c89fedSNiranjan H Y 	{"SPK_L", NULL, "FU23_L"},
59638c89fedSNiranjan H Y 	{"SPK_R", NULL, "FU23_R"},
59738c89fedSNiranjan H Y 
59838c89fedSNiranjan H Y 	/* Smart Mic DAPM Routes */
59938c89fedSNiranjan H Y 	{"IT11", NULL, "DMIC_L"},
60038c89fedSNiranjan H Y 	{"IT11", NULL, "DMIC_R"},
60138c89fedSNiranjan H Y 	{"FU11_L", NULL, "IT11"},
60238c89fedSNiranjan H Y 	{"FU11_R", NULL, "IT11"},
60338c89fedSNiranjan H Y 	{"PPU11", NULL, "FU11_L"},
60438c89fedSNiranjan H Y 	{"PPU11", NULL, "FU11_R"},
60538c89fedSNiranjan H Y 	{"XU12", NULL, "PPU11"},
60638c89fedSNiranjan H Y 	{"FU113_L", NULL, "XU12"},
60738c89fedSNiranjan H Y 	{"FU113_R", NULL, "XU12"},
60838c89fedSNiranjan H Y 	{"FU113_L", NULL, "CS113"},
60938c89fedSNiranjan H Y 	{"FU113_R", NULL, "CS113"},
61038c89fedSNiranjan H Y 	{"OT113", NULL, "FU113_L"},
61138c89fedSNiranjan H Y 	{"OT113", NULL, "FU113_R"},
61238c89fedSNiranjan H Y 	{"OT113", NULL, "CS113"},
61338c89fedSNiranjan H Y 	{"AIF3 Capture", NULL, "OT113"},
61438c89fedSNiranjan H Y };
61538c89fedSNiranjan H Y 
61638c89fedSNiranjan H Y static const struct snd_soc_dapm_route tac_uaj_routes[] = {
61738c89fedSNiranjan H Y 	/* UAJ Playback routes */
61838c89fedSNiranjan H Y 	{"IT41", NULL, "AIF4 Playback"},
61938c89fedSNiranjan H Y 	{"IT41", NULL, "CS41"},
62038c89fedSNiranjan H Y 	{"FU41_L", NULL, "IT41"},
62138c89fedSNiranjan H Y 	{"FU41_R", NULL, "IT41"},
62238c89fedSNiranjan H Y 	{"XU42", NULL, "FU41_L"},
62338c89fedSNiranjan H Y 	{"XU42", NULL, "FU41_R"},
62438c89fedSNiranjan H Y 	{"OT45", NULL, "XU42"},
62538c89fedSNiranjan H Y 	{"OT45", NULL, "CS41"},
62638c89fedSNiranjan H Y 	{"HP_L", NULL, "OT45"},
62738c89fedSNiranjan H Y 	{"HP_R", NULL, "OT45"},
62838c89fedSNiranjan H Y 
62938c89fedSNiranjan H Y 	/* UAJ Capture routes */
63038c89fedSNiranjan H Y 	{"IT33", NULL, "UAJ_MIC"},
63138c89fedSNiranjan H Y 	{"IT33", NULL, "CS36"},
63238c89fedSNiranjan H Y 	{"FU36", NULL, "IT33"},
63338c89fedSNiranjan H Y 	{"OT36", NULL, "FU36"},
63438c89fedSNiranjan H Y 	{"OT36", NULL, "CS36"},
63538c89fedSNiranjan H Y 	{"AIF7 Capture", NULL, "OT36"},
63638c89fedSNiranjan H Y };
63738c89fedSNiranjan H Y 
tac_set_sdw_stream(struct snd_soc_dai * dai,void * sdw_stream,s32 direction)63838c89fedSNiranjan H Y static s32 tac_set_sdw_stream(struct snd_soc_dai *dai,
63938c89fedSNiranjan H Y 			      void *sdw_stream, s32 direction)
64038c89fedSNiranjan H Y {
64138c89fedSNiranjan H Y 	if (sdw_stream)
64238c89fedSNiranjan H Y 		snd_soc_dai_dma_data_set(dai, direction, sdw_stream);
64338c89fedSNiranjan H Y 
64438c89fedSNiranjan H Y 	return 0;
64538c89fedSNiranjan H Y }
64638c89fedSNiranjan H Y 
tac_sdw_shutdown(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)64738c89fedSNiranjan H Y static void tac_sdw_shutdown(struct snd_pcm_substream *substream,
64838c89fedSNiranjan H Y 			     struct snd_soc_dai *dai)
64938c89fedSNiranjan H Y {
65038c89fedSNiranjan H Y 	snd_soc_dai_set_dma_data(dai, substream, NULL);
65138c89fedSNiranjan H Y }
65238c89fedSNiranjan H Y 
tac_clear_latch(struct tac5xx2_prv * priv)65338c89fedSNiranjan H Y static int tac_clear_latch(struct tac5xx2_prv *priv)
65438c89fedSNiranjan H Y {
65538c89fedSNiranjan H Y 	/* CLR_REG is a self-clearing bit */
65638c89fedSNiranjan H Y 	return regmap_update_bits(priv->regmap, TAC_INT_CFG,
65738c89fedSNiranjan H Y 				  TAC_INT_CFG_CLR_REG, TAC_INT_CFG_CLR_REG);
65838c89fedSNiranjan H Y }
65938c89fedSNiranjan H Y 
tac_sdw_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params,struct snd_soc_dai * dai)66038c89fedSNiranjan H Y static int tac_sdw_hw_params(struct snd_pcm_substream *substream,
66138c89fedSNiranjan H Y 			     struct snd_pcm_hw_params *params,
66238c89fedSNiranjan H Y 			     struct snd_soc_dai *dai)
66338c89fedSNiranjan H Y {
66438c89fedSNiranjan H Y 	struct snd_soc_component *component = dai->component;
66538c89fedSNiranjan H Y 	struct tac5xx2_prv *tac_dev = snd_soc_component_get_drvdata(component);
66638c89fedSNiranjan H Y 	struct sdw_slave *sdw_peripheral = tac_dev->sdw_peripheral;
66738c89fedSNiranjan H Y 	struct sdw_stream_runtime *sdw_stream;
66838c89fedSNiranjan H Y 	struct sdw_stream_config stream_config = {0};
66938c89fedSNiranjan H Y 	struct sdw_port_config port_config = {0};
67038c89fedSNiranjan H Y 	u8 sample_rate_idx = 0;
67138c89fedSNiranjan H Y 	int function_id;
67238c89fedSNiranjan H Y 	int pde_entity;
67338c89fedSNiranjan H Y 	int port_num;
67438c89fedSNiranjan H Y 	int ret;
67538c89fedSNiranjan H Y 
67638c89fedSNiranjan H Y 	if (!tac_dev->hw_init) {
67738c89fedSNiranjan H Y 		dev_err(tac_dev->dev,
67838c89fedSNiranjan H Y 			"error: operation without hw initialization");
67938c89fedSNiranjan H Y 		return -EINVAL;
68038c89fedSNiranjan H Y 	}
68138c89fedSNiranjan H Y 
68238c89fedSNiranjan H Y 	sdw_stream = snd_soc_dai_get_dma_data(dai, substream);
68338c89fedSNiranjan H Y 	if (!sdw_stream) {
68438c89fedSNiranjan H Y 		dev_err(tac_dev->dev, "failed to get dma data");
68538c89fedSNiranjan H Y 		return -EINVAL;
68638c89fedSNiranjan H Y 	}
68738c89fedSNiranjan H Y 
68838c89fedSNiranjan H Y 	ret = tac_clear_latch(tac_dev);
68938c89fedSNiranjan H Y 	if (ret)
69038c89fedSNiranjan H Y 		dev_warn(tac_dev->dev, "clear latch failed, err=%d", ret);
69138c89fedSNiranjan H Y 
69238c89fedSNiranjan H Y 	switch (dai->id) {
69338c89fedSNiranjan H Y 	case TAC5XX2_DMIC:
69438c89fedSNiranjan H Y 		function_id = TAC_FUNCTION_ID_SM;
69538c89fedSNiranjan H Y 		pde_entity = TAC_SDCA_ENT_PDE11;
69638c89fedSNiranjan H Y 		port_num = TAC_SDW_PORT_NUM_DMIC;
69738c89fedSNiranjan H Y 		break;
69838c89fedSNiranjan H Y 	case TAC5XX2_UAJ:
69938c89fedSNiranjan H Y 		function_id = TAC_FUNCTION_ID_UAJ;
70038c89fedSNiranjan H Y 		pde_entity = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
70138c89fedSNiranjan H Y 				TAC_SDCA_ENT_PDE47 : TAC_SDCA_ENT_PDE34;
70238c89fedSNiranjan H Y 		port_num = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
70338c89fedSNiranjan H Y 				TAC_SDW_PORT_NUM_UAJ_PLAYBACK :
70438c89fedSNiranjan H Y 				TAC_SDW_PORT_NUM_UAJ_CAPTURE;
70538c89fedSNiranjan H Y 		break;
70638c89fedSNiranjan H Y 	case TAC5XX2_SPK:
70738c89fedSNiranjan H Y 		function_id = TAC_FUNCTION_ID_SA;
70838c89fedSNiranjan H Y 		pde_entity = TAC_SDCA_ENT_PDE23;
70938c89fedSNiranjan H Y 		port_num = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
71038c89fedSNiranjan H Y 				TAC_SDW_PORT_NUM_SPK_PLAYBACK :
71138c89fedSNiranjan H Y 				TAC_SDW_PORT_NUM_SPK_CAPTURE;
71238c89fedSNiranjan H Y 		break;
71338c89fedSNiranjan H Y 	default:
71438c89fedSNiranjan H Y 		dev_err(tac_dev->dev, "Invalid dai id: %d for power up\n", dai->id);
71538c89fedSNiranjan H Y 		return -EINVAL;
71638c89fedSNiranjan H Y 	}
71738c89fedSNiranjan H Y 
71838c89fedSNiranjan H Y 	snd_sdw_params_to_config(substream, params, &stream_config, &port_config);
71938c89fedSNiranjan H Y 	port_config.num = port_num;
72038c89fedSNiranjan H Y 	ret = sdw_stream_add_slave(sdw_peripheral, &stream_config,
72138c89fedSNiranjan H Y 				   &port_config, 1, sdw_stream);
72238c89fedSNiranjan H Y 	if (ret) {
72338c89fedSNiranjan H Y 		dev_err(dai->dev,
72438c89fedSNiranjan H Y 			"Unable to configure port %d: %d\n", port_num, ret);
72538c89fedSNiranjan H Y 		return ret;
72638c89fedSNiranjan H Y 	}
72738c89fedSNiranjan H Y 
72838c89fedSNiranjan H Y 	switch (params_rate(params)) {
72938c89fedSNiranjan H Y 	case 48000:
73038c89fedSNiranjan H Y 		sample_rate_idx = 0x01;
73138c89fedSNiranjan H Y 		break;
73238c89fedSNiranjan H Y 	case 44100:
73338c89fedSNiranjan H Y 		sample_rate_idx = 0x02;
73438c89fedSNiranjan H Y 		break;
73538c89fedSNiranjan H Y 	case 96000:
73638c89fedSNiranjan H Y 		sample_rate_idx = 0x03;
73738c89fedSNiranjan H Y 		break;
73838c89fedSNiranjan H Y 	case 88200:
73938c89fedSNiranjan H Y 		sample_rate_idx = 0x04;
74038c89fedSNiranjan H Y 		break;
74138c89fedSNiranjan H Y 	default:
74238c89fedSNiranjan H Y 		dev_dbg(tac_dev->dev, "Unsupported sample rate: %d Hz",
74338c89fedSNiranjan H Y 			params_rate(params));
74438c89fedSNiranjan H Y 		return -EINVAL;
74538c89fedSNiranjan H Y 	}
74638c89fedSNiranjan H Y 
74738c89fedSNiranjan H Y 	switch (function_id) {
74838c89fedSNiranjan H Y 	case TAC_FUNCTION_ID_SM:
74938c89fedSNiranjan H Y 		ret = regmap_write(tac_dev->regmap,
75038c89fedSNiranjan H Y 				   SDW_SDCA_CTL(function_id, TAC_SDCA_ENT_CS113,
75138c89fedSNiranjan H Y 						TAC_SDCA_CTL_CS_SAMP_RATE_IDX, 0),
75238c89fedSNiranjan H Y 			sample_rate_idx);
75338c89fedSNiranjan H Y 		if (ret) {
75438c89fedSNiranjan H Y 			dev_err(tac_dev->dev, "Failed to set CS113 sample rate: %d", ret);
75538c89fedSNiranjan H Y 			return ret;
75638c89fedSNiranjan H Y 		}
75738c89fedSNiranjan H Y 
75838c89fedSNiranjan H Y 		break;
75938c89fedSNiranjan H Y 	case TAC_FUNCTION_ID_UAJ:
76038c89fedSNiranjan H Y 		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
76138c89fedSNiranjan H Y 			ret = regmap_write(tac_dev->regmap,
76238c89fedSNiranjan H Y 					   SDW_SDCA_CTL(function_id, TAC_SDCA_ENT_CS41,
76338c89fedSNiranjan H Y 							TAC_SDCA_CTL_CS_SAMP_RATE_IDX, 0),
76438c89fedSNiranjan H Y 					sample_rate_idx);
76538c89fedSNiranjan H Y 			if (ret) {
76638c89fedSNiranjan H Y 				dev_err(tac_dev->dev, "Failed to set CS41 sample rate: %d", ret);
76738c89fedSNiranjan H Y 				return ret;
76838c89fedSNiranjan H Y 			}
76938c89fedSNiranjan H Y 		} else {
77038c89fedSNiranjan H Y 			ret = regmap_write(tac_dev->regmap,
77138c89fedSNiranjan H Y 					   SDW_SDCA_CTL(function_id, TAC_SDCA_ENT_CS36,
77238c89fedSNiranjan H Y 							TAC_SDCA_CTL_CS_SAMP_RATE_IDX, 0),
77338c89fedSNiranjan H Y 					sample_rate_idx);
77438c89fedSNiranjan H Y 			if (ret) {
77538c89fedSNiranjan H Y 				dev_err(tac_dev->dev, "Failed to set CS36 sample rate: %d", ret);
77638c89fedSNiranjan H Y 				return ret;
77738c89fedSNiranjan H Y 			}
77838c89fedSNiranjan H Y 		}
77938c89fedSNiranjan H Y 		break;
78038c89fedSNiranjan H Y 	case TAC_FUNCTION_ID_SA:
78138c89fedSNiranjan H Y 		/* SmartAmp: no additional sample rate configuration needed */
78238c89fedSNiranjan H Y 		break;
78338c89fedSNiranjan H Y 	}
78438c89fedSNiranjan H Y 
78538c89fedSNiranjan H Y 	ret = regmap_write(tac_dev->regmap, SDW_SDCA_CTL(function_id, pde_entity,
78638c89fedSNiranjan H Y 							 TAC_SDCA_REQUESTED_PS, 0), 0);
78738c89fedSNiranjan H Y 	if (ret) {
78838c89fedSNiranjan H Y 		dev_err(tac_dev->dev,
78938c89fedSNiranjan H Y 			"failed to set func %d, entity %d's requested PS to 0: %d\n",
79038c89fedSNiranjan H Y 			function_id, pde_entity, ret);
79138c89fedSNiranjan H Y 		return ret;
79238c89fedSNiranjan H Y 	}
79338c89fedSNiranjan H Y 
79438c89fedSNiranjan H Y 	ret = sdca_asoc_pde_poll_actual_ps(tac_dev->regmap, function_id, pde_entity,
79538c89fedSNiranjan H Y 					   SDCA_PDE_PS3, SDCA_PDE_PS0, NULL, 0);
79638c89fedSNiranjan H Y 	if (ret)
79738c89fedSNiranjan H Y 		dev_err(tac_dev->dev, "failed to transition func %d, pde %d from PS3 -> PS0, err=%d\n",
79838c89fedSNiranjan H Y 			function_id, pde_entity, ret);
79938c89fedSNiranjan H Y 	return ret;
80038c89fedSNiranjan H Y }
80138c89fedSNiranjan H Y 
tac_sdw_pcm_hw_free(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)80238c89fedSNiranjan H Y static int tac_sdw_pcm_hw_free(struct snd_pcm_substream *substream,
80338c89fedSNiranjan H Y 			       struct snd_soc_dai *dai)
80438c89fedSNiranjan H Y {
80538c89fedSNiranjan H Y 	struct sdw_stream_runtime *sdw_stream = snd_soc_dai_get_dma_data(dai, substream);
80638c89fedSNiranjan H Y 	struct tac5xx2_prv *tac_dev = snd_soc_component_get_drvdata(dai->component);
80738c89fedSNiranjan H Y 	int pde_entity, function_id;
80838c89fedSNiranjan H Y 	int ret;
80938c89fedSNiranjan H Y 
81038c89fedSNiranjan H Y 	sdw_stream_remove_slave(tac_dev->sdw_peripheral, sdw_stream);
81138c89fedSNiranjan H Y 
81238c89fedSNiranjan H Y 	switch (dai->id) {
81338c89fedSNiranjan H Y 	case TAC5XX2_DMIC:
81438c89fedSNiranjan H Y 		pde_entity = TAC_SDCA_ENT_PDE11;
81538c89fedSNiranjan H Y 		function_id = TAC_FUNCTION_ID_SM;
81638c89fedSNiranjan H Y 		break;
81738c89fedSNiranjan H Y 	case TAC5XX2_UAJ:
81838c89fedSNiranjan H Y 		function_id = TAC_FUNCTION_ID_UAJ;
81938c89fedSNiranjan H Y 		pde_entity = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
82038c89fedSNiranjan H Y 				TAC_SDCA_ENT_PDE47 : TAC_SDCA_ENT_PDE34;
82138c89fedSNiranjan H Y 		break;
82238c89fedSNiranjan H Y 	case TAC5XX2_SPK:
82338c89fedSNiranjan H Y 		function_id = TAC_FUNCTION_ID_SA;
82438c89fedSNiranjan H Y 		pde_entity = TAC_SDCA_ENT_PDE23;
82538c89fedSNiranjan H Y 		break;
82638c89fedSNiranjan H Y 	default:
82738c89fedSNiranjan H Y 		dev_err(tac_dev->dev, "unhandled dai %d for power down\n", dai->id);
82838c89fedSNiranjan H Y 		return -EINVAL;
82938c89fedSNiranjan H Y 	}
83038c89fedSNiranjan H Y 
83138c89fedSNiranjan H Y 	ret = regmap_write(tac_dev->regmap, SDW_SDCA_CTL(function_id, pde_entity,
83238c89fedSNiranjan H Y 							 TAC_SDCA_REQUESTED_PS, 0),
83338c89fedSNiranjan H Y 			   SDCA_PDE_PS3);
83438c89fedSNiranjan H Y 	if (ret) {
83538c89fedSNiranjan H Y 		dev_err(tac_dev->dev,
83638c89fedSNiranjan H Y 			"failed to set func %d, entity %d's requested PS to 3: %d\n",
83738c89fedSNiranjan H Y 			function_id, pde_entity, ret);
83838c89fedSNiranjan H Y 		return ret;
83938c89fedSNiranjan H Y 	}
84038c89fedSNiranjan H Y 
84138c89fedSNiranjan H Y 	ret = sdca_asoc_pde_poll_actual_ps(tac_dev->regmap, function_id,
84238c89fedSNiranjan H Y 					   pde_entity, SDCA_PDE_PS0, SDCA_PDE_PS3,
84338c89fedSNiranjan H Y 					   NULL, 0);
84438c89fedSNiranjan H Y 	if (ret)
84538c89fedSNiranjan H Y 		dev_err(tac_dev->dev,
84638c89fedSNiranjan H Y 			"failed to transition func %d, pde %d from PS0 -> PS3, err=%d\n",
84738c89fedSNiranjan H Y 			function_id, pde_entity, ret);
84838c89fedSNiranjan H Y 
84938c89fedSNiranjan H Y 	return ret;
85038c89fedSNiranjan H Y }
85138c89fedSNiranjan H Y 
85238c89fedSNiranjan H Y static const struct snd_soc_dai_ops tac_dai_ops = {
85338c89fedSNiranjan H Y 	.hw_params = tac_sdw_hw_params,
85438c89fedSNiranjan H Y 	.hw_free = tac_sdw_pcm_hw_free,
85538c89fedSNiranjan H Y 	.set_stream = tac_set_sdw_stream,
85638c89fedSNiranjan H Y 	.shutdown = tac_sdw_shutdown,
85738c89fedSNiranjan H Y };
85838c89fedSNiranjan H Y 
tac5xx2_sdca_btn_type(unsigned char * buffer,struct tac5xx2_prv * tac_dev)85938c89fedSNiranjan H Y static int tac5xx2_sdca_btn_type(unsigned char *buffer, struct tac5xx2_prv *tac_dev)
86038c89fedSNiranjan H Y {
86138c89fedSNiranjan H Y 	switch (*buffer) {
86238c89fedSNiranjan H Y 	case 1: /* play pause */
86338c89fedSNiranjan H Y 		return SND_JACK_BTN_0;
86438c89fedSNiranjan H Y 	case 10: /* vol down */
86538c89fedSNiranjan H Y 		return SND_JACK_BTN_3;
86638c89fedSNiranjan H Y 	case 8: /* vol up */
86738c89fedSNiranjan H Y 		return SND_JACK_BTN_2;
86838c89fedSNiranjan H Y 	case 4: /* long press */
86938c89fedSNiranjan H Y 		return SND_JACK_BTN_1;
87038c89fedSNiranjan H Y 	case 2: /* next song */
87138c89fedSNiranjan H Y 	case 32: /* next song */
87238c89fedSNiranjan H Y 		return SND_JACK_BTN_4;
87338c89fedSNiranjan H Y 	default:
87438c89fedSNiranjan H Y 		return 0;
87538c89fedSNiranjan H Y 	}
87638c89fedSNiranjan H Y }
87738c89fedSNiranjan H Y 
tac5xx2_sdca_button_detect(struct tac5xx2_prv * tac_dev)87838c89fedSNiranjan H Y static int tac5xx2_sdca_button_detect(struct tac5xx2_prv *tac_dev)
87938c89fedSNiranjan H Y {
88038c89fedSNiranjan H Y 	unsigned int btn_type, offset, idx;
88138c89fedSNiranjan H Y 	int ret, value, owner;
88238c89fedSNiranjan H Y 	u8 buf[2];
88338c89fedSNiranjan H Y 
88438c89fedSNiranjan H Y 	ret = regmap_read(tac_dev->regmap,
88538c89fedSNiranjan H Y 			  SDW_SDCA_CTL(TAC_FUNCTION_ID_HID, TAC_SDCA_ENT_HID1,
88638c89fedSNiranjan H Y 				       TAC_SDCA_CTL_HIDTX_CURRENT_OWNER, 0), &owner);
88738c89fedSNiranjan H Y 	if (ret) {
88838c89fedSNiranjan H Y 		dev_err(tac_dev->dev,
88938c89fedSNiranjan H Y 			"Failed to read current UMP message owner 0x%x", ret);
89038c89fedSNiranjan H Y 		return ret;
89138c89fedSNiranjan H Y 	}
89238c89fedSNiranjan H Y 
89338c89fedSNiranjan H Y 	if (owner == SDCA_UMP_OWNER_DEVICE) {
89438c89fedSNiranjan H Y 		dev_dbg(tac_dev->dev, "skip button detect as current owner is not host\n");
89538c89fedSNiranjan H Y 		return 0;
89638c89fedSNiranjan H Y 	}
89738c89fedSNiranjan H Y 
89838c89fedSNiranjan H Y 	ret = regmap_read(tac_dev->regmap,
89938c89fedSNiranjan H Y 			  SDW_SDCA_CTL(TAC_FUNCTION_ID_HID, TAC_SDCA_ENT_HID1,
90038c89fedSNiranjan H Y 				       TAC_SDCA_CTL_HIDTX_MESSAGE_OFFSET, 0), &offset);
90138c89fedSNiranjan H Y 	if (ret) {
90238c89fedSNiranjan H Y 		dev_err(tac_dev->dev,
90338c89fedSNiranjan H Y 			"Failed to read current UMP message offset: %d", ret);
90438c89fedSNiranjan H Y 		goto end_btn_det;
90538c89fedSNiranjan H Y 	}
90638c89fedSNiranjan H Y 
90738c89fedSNiranjan H Y 	dev_dbg(tac_dev->dev, "button detect: message offset = %x", offset);
90838c89fedSNiranjan H Y 
90938c89fedSNiranjan H Y 	for (idx = 0; idx < sizeof(buf); idx++) {
91038c89fedSNiranjan H Y 		ret = regmap_read(tac_dev->regmap,
91138c89fedSNiranjan H Y 				  TAC_BUF_ADDR_HID1 + offset + idx, &value);
91238c89fedSNiranjan H Y 		if (ret) {
91338c89fedSNiranjan H Y 			dev_err(tac_dev->dev,
91438c89fedSNiranjan H Y 				"Failed to read HID buffer: %d", ret);
91538c89fedSNiranjan H Y 			goto end_btn_det;
91638c89fedSNiranjan H Y 		}
91738c89fedSNiranjan H Y 		buf[idx] = value & 0xff;
91838c89fedSNiranjan H Y 	}
91938c89fedSNiranjan H Y 
92038c89fedSNiranjan H Y 	if (buf[0] == 0x1) {
92138c89fedSNiranjan H Y 		btn_type = tac5xx2_sdca_btn_type(&buf[1], tac_dev);
92238c89fedSNiranjan H Y 		ret = btn_type;
92338c89fedSNiranjan H Y 	}
92438c89fedSNiranjan H Y 
92538c89fedSNiranjan H Y end_btn_det:
92638c89fedSNiranjan H Y 	regmap_write(tac_dev->regmap,
92738c89fedSNiranjan H Y 		     SDW_SDCA_CTL(TAC_FUNCTION_ID_HID, TAC_SDCA_ENT_HID1,
92838c89fedSNiranjan H Y 				  TAC_SDCA_CTL_HIDTX_CURRENT_OWNER, 0), 0x01);
92938c89fedSNiranjan H Y 
93038c89fedSNiranjan H Y 	return ret;
93138c89fedSNiranjan H Y }
93238c89fedSNiranjan H Y 
tac5xx2_sdca_headset_detect(struct tac5xx2_prv * tac_dev)93338c89fedSNiranjan H Y static int tac5xx2_sdca_headset_detect(struct tac5xx2_prv *tac_dev)
93438c89fedSNiranjan H Y {
93538c89fedSNiranjan H Y 	int val, ret;
93638c89fedSNiranjan H Y 	u8 jack_prep;
93738c89fedSNiranjan H Y 
93838c89fedSNiranjan H Y 	ret = regmap_read(tac_dev->regmap,
93938c89fedSNiranjan H Y 			  SDW_SDCA_CTL(TAC_FUNCTION_ID_UAJ, TAC_SDCA_ENT_GE35,
94038c89fedSNiranjan H Y 				       TAC_SDCA_CTL_DET_MODE, 0), &val);
94138c89fedSNiranjan H Y 	if (ret) {
94238c89fedSNiranjan H Y 		dev_err(tac_dev->dev, "Failed to read the detect mode");
94338c89fedSNiranjan H Y 		return ret;
94438c89fedSNiranjan H Y 	}
94538c89fedSNiranjan H Y 
94638c89fedSNiranjan H Y 	jack_prep = TAC_UAJ_PREP_CONNECTED;
94738c89fedSNiranjan H Y 
94838c89fedSNiranjan H Y 	switch (val) {
94938c89fedSNiranjan H Y 	case 4:
95038c89fedSNiranjan H Y 		tac_dev->jack_type = SND_JACK_MICROPHONE;
95138c89fedSNiranjan H Y 		break;
95238c89fedSNiranjan H Y 	case 5:
95338c89fedSNiranjan H Y 		tac_dev->jack_type = SND_JACK_HEADPHONE;
95438c89fedSNiranjan H Y 		break;
95538c89fedSNiranjan H Y 	case 6:
95638c89fedSNiranjan H Y 		tac_dev->jack_type = SND_JACK_HEADSET;
95738c89fedSNiranjan H Y 		break;
95838c89fedSNiranjan H Y 	case 0:
95938c89fedSNiranjan H Y 	default:
96038c89fedSNiranjan H Y 		tac_dev->jack_type = 0;
96138c89fedSNiranjan H Y 		jack_prep = TAC_UAJ_PREP_DISCONNECTED;
96238c89fedSNiranjan H Y 		break;
96338c89fedSNiranjan H Y 	}
96438c89fedSNiranjan H Y 
96538c89fedSNiranjan H Y 	ret = regmap_write(tac_dev->regmap,
96638c89fedSNiranjan H Y 			   SDW_SDCA_CTL(TAC_FUNCTION_ID_UAJ, TAC_SDCA_ENT_GE35,
96738c89fedSNiranjan H Y 					TAC_SDCA_CTL_SEL_MODE, 0), val);
96838c89fedSNiranjan H Y 	if (ret)
96938c89fedSNiranjan H Y 		dev_err(tac_dev->dev, "Failed to update the jack type to device");
97038c89fedSNiranjan H Y 
97138c89fedSNiranjan H Y 	/*
97238c89fedSNiranjan H Y 	 * When uaj is uplugged and booted, we end up with the channel prepare
97338c89fedSNiranjan H Y 	 * timeout error for the uaj ports. This writes allows the channel prepare
97438c89fedSNiranjan H Y 	 * to succeed when the uaj is not plugged in.
97538c89fedSNiranjan H Y 	 */
97638c89fedSNiranjan H Y 	if (tac_dev->rev_id >= 0x30) {
97738c89fedSNiranjan H Y 		ret = regmap_write(tac_dev->regmap, TAC_REG_SDW(0, 3, 127), jack_prep);
97838c89fedSNiranjan H Y 		if (ret)
97938c89fedSNiranjan H Y 			dev_warn(tac_dev->dev, "Failed to write jack_prep register: %d\n", ret);
98038c89fedSNiranjan H Y 	}
98138c89fedSNiranjan H Y 
98238c89fedSNiranjan H Y 	return 0;
98338c89fedSNiranjan H Y }
98438c89fedSNiranjan H Y 
tac5xx2_jack_init(struct tac5xx2_prv * tac_dev)98538c89fedSNiranjan H Y static int tac5xx2_jack_init(struct tac5xx2_prv *tac_dev)
98638c89fedSNiranjan H Y {
98738c89fedSNiranjan H Y 	u32 jd_int_mask, hid_int_mask;
98838c89fedSNiranjan H Y 	int ret = 0;
98938c89fedSNiranjan H Y 
99038c89fedSNiranjan H Y 	if (tac_dev->rev_id >= 0x30) {
99138c89fedSNiranjan H Y 		jd_int_mask = SDW_SCP_SDCA_INTMASK_SDCA_12;
99238c89fedSNiranjan H Y 		hid_int_mask = SDW_SCP_SDCA_INTMASK_SDCA_17;
99338c89fedSNiranjan H Y 	} else {
99438c89fedSNiranjan H Y 		jd_int_mask = SDW_SCP_SDCA_INTMASK_SDCA_11;
99538c89fedSNiranjan H Y 		hid_int_mask = SDW_SCP_SDCA_INTMASK_SDCA_16;
99638c89fedSNiranjan H Y 	}
99738c89fedSNiranjan H Y 
99838c89fedSNiranjan H Y 	if (!tac_dev->hs_jack)
99938c89fedSNiranjan H Y 		goto disable_interrupts;
100038c89fedSNiranjan H Y 
100138c89fedSNiranjan H Y 	ret = regmap_write(tac_dev->regmap, SDW_SCP_SDCA_INTMASK2, jd_int_mask);
100238c89fedSNiranjan H Y 	if (ret) {
100338c89fedSNiranjan H Y 		dev_err(tac_dev->dev,
100438c89fedSNiranjan H Y 			"Failed to register jack detection interrupt: %d\n", ret);
100538c89fedSNiranjan H Y 		goto disable_interrupts;
100638c89fedSNiranjan H Y 	}
100738c89fedSNiranjan H Y 
100838c89fedSNiranjan H Y 	ret = regmap_write(tac_dev->regmap, SDW_SCP_SDCA_INTMASK3, hid_int_mask);
100938c89fedSNiranjan H Y 	if (ret) {
101038c89fedSNiranjan H Y 		dev_err(tac_dev->dev,
101138c89fedSNiranjan H Y 			"Failed to register for button detect interrupt: %d\n", ret);
101238c89fedSNiranjan H Y 		goto disable_interrupts;
101338c89fedSNiranjan H Y 	}
101438c89fedSNiranjan H Y 
101538c89fedSNiranjan H Y 	return 0;
101638c89fedSNiranjan H Y 
101738c89fedSNiranjan H Y disable_interrupts:
101838c89fedSNiranjan H Y 	/* ignore errors while disabling interrupts */
101938c89fedSNiranjan H Y 	regmap_write(tac_dev->regmap, SDW_SCP_SDCA_INTMASK2, 0);
102038c89fedSNiranjan H Y 	regmap_write(tac_dev->regmap, SDW_SCP_SDCA_INTMASK3, 0);
102138c89fedSNiranjan H Y 
102238c89fedSNiranjan H Y 	return ret;
102338c89fedSNiranjan H Y }
102438c89fedSNiranjan H Y 
tac5xx2_set_jack(struct snd_soc_component * component,struct snd_soc_jack * hs_jack,void * data)102538c89fedSNiranjan H Y static int tac5xx2_set_jack(struct snd_soc_component *component,
102638c89fedSNiranjan H Y 			    struct snd_soc_jack *hs_jack, void *data)
102738c89fedSNiranjan H Y {
102838c89fedSNiranjan H Y 	struct tac5xx2_prv *tac_dev = snd_soc_component_get_drvdata(component);
102938c89fedSNiranjan H Y 	int ret;
103038c89fedSNiranjan H Y 
103138c89fedSNiranjan H Y 	tac_dev->hs_jack = hs_jack;
103238c89fedSNiranjan H Y 
103338c89fedSNiranjan H Y 	/* resume can happen only after first hw_init */
103438c89fedSNiranjan H Y 	if (!tac_dev->first_hw_init_done)
103538c89fedSNiranjan H Y 		return 0;
103638c89fedSNiranjan H Y 
103738c89fedSNiranjan H Y 	ret = pm_runtime_resume_and_get(component->dev);
103838c89fedSNiranjan H Y 	if (ret < 0) {
103938c89fedSNiranjan H Y 		if (ret != -EACCES) {
104038c89fedSNiranjan H Y 			dev_err(component->dev,
104138c89fedSNiranjan H Y 				"%s: failed to resume %d\n", __func__, ret);
104238c89fedSNiranjan H Y 			return ret;
104338c89fedSNiranjan H Y 		}
104438c89fedSNiranjan H Y 
104538c89fedSNiranjan H Y 		/* pm_runtime not enabled yet */
104638c89fedSNiranjan H Y 		dev_dbg(component->dev,
104738c89fedSNiranjan H Y 			"%s: skipping jack init for now\n", __func__);
104838c89fedSNiranjan H Y 		return 0;
104938c89fedSNiranjan H Y 	}
105038c89fedSNiranjan H Y 
105138c89fedSNiranjan H Y 	ret = tac5xx2_jack_init(tac_dev);
105238c89fedSNiranjan H Y 	if (ret)
105338c89fedSNiranjan H Y 		dev_err(tac_dev->dev, "jack init failed, err=%d\n", ret);
105438c89fedSNiranjan H Y 
105538c89fedSNiranjan H Y 	pm_runtime_mark_last_busy(component->dev);
105638c89fedSNiranjan H Y 	pm_runtime_put_autosuspend(component->dev);
105738c89fedSNiranjan H Y 
105838c89fedSNiranjan H Y 	return ret;
105938c89fedSNiranjan H Y }
106038c89fedSNiranjan H Y 
tac_interrupt_callback(struct sdw_slave * slave,struct sdw_slave_intr_status * status)106138c89fedSNiranjan H Y static int tac_interrupt_callback(struct sdw_slave *slave,
106238c89fedSNiranjan H Y 				  struct sdw_slave_intr_status *status)
106338c89fedSNiranjan H Y {
106438c89fedSNiranjan H Y 	unsigned int sdca_int2, sdca_int3, jack_report_mask = 0;
106538c89fedSNiranjan H Y 	struct tac5xx2_prv *tac_dev = dev_get_drvdata(&slave->dev);
106638c89fedSNiranjan H Y 	struct device *dev = &slave->dev;
106738c89fedSNiranjan H Y 	u32 headset_detect_chk, hid_detect_chk;
106838c89fedSNiranjan H Y 	int btn_type = 0;
106938c89fedSNiranjan H Y 	int ret = 0;
107038c89fedSNiranjan H Y 
107138c89fedSNiranjan H Y 	if (status->control_port) {
107238c89fedSNiranjan H Y 		if (status->control_port & SDW_SCP_INT1_PARITY)
107338c89fedSNiranjan H Y 			dev_warn(dev, "SCP: Parity error interrupt");
107438c89fedSNiranjan H Y 		if (status->control_port & SDW_SCP_INT1_BUS_CLASH)
107538c89fedSNiranjan H Y 			dev_warn(dev, "SCP: Bus clash interrupt");
107638c89fedSNiranjan H Y 	}
107738c89fedSNiranjan H Y 
107838c89fedSNiranjan H Y 	if (!tac_has_uaj_support(tac_dev))
107938c89fedSNiranjan H Y 		return 0;
108038c89fedSNiranjan H Y 
108138c89fedSNiranjan H Y 	ret = regmap_read(tac_dev->regmap, SDW_SCP_SDCA_INT2, &sdca_int2);
108238c89fedSNiranjan H Y 	if (ret) {
108338c89fedSNiranjan H Y 		dev_err(dev, "Failed to read UAJ Interrupt, reg:%#x err=%d\n",
108438c89fedSNiranjan H Y 			SDW_SCP_SDCA_INT2, ret);
108538c89fedSNiranjan H Y 		return ret;
108638c89fedSNiranjan H Y 	}
108738c89fedSNiranjan H Y 
108838c89fedSNiranjan H Y 	ret = regmap_read(tac_dev->regmap, SDW_SCP_SDCA_INT3, &sdca_int3);
108938c89fedSNiranjan H Y 	if (ret) {
109038c89fedSNiranjan H Y 		dev_err(dev, "Failed to read HID interrupt reg=%#x: err=%d",
109138c89fedSNiranjan H Y 			SDW_SCP_SDCA_INT3, ret);
109238c89fedSNiranjan H Y 		return ret;
109338c89fedSNiranjan H Y 	}
109438c89fedSNiranjan H Y 
109538c89fedSNiranjan H Y 	dev_dbg(dev, "SDCA_INT2: 0x%02x, SDCA_INT3: 0x%02x\n",
109638c89fedSNiranjan H Y 		sdca_int2, sdca_int3);
109738c89fedSNiranjan H Y 
109838c89fedSNiranjan H Y 	if (tac_dev->rev_id >= 0x30) {
109938c89fedSNiranjan H Y 		headset_detect_chk = SDW_SCP_SDCA_INT_SDCA_12;
110038c89fedSNiranjan H Y 		hid_detect_chk = SDW_SCP_SDCA_INT_SDCA_17;
110138c89fedSNiranjan H Y 	} else {
110238c89fedSNiranjan H Y 		headset_detect_chk = SDW_SCP_SDCA_INT_SDCA_11;
110338c89fedSNiranjan H Y 		hid_detect_chk = SDW_SCP_SDCA_INT_SDCA_16;
110438c89fedSNiranjan H Y 	}
110538c89fedSNiranjan H Y 
110638c89fedSNiranjan H Y 	if (sdca_int2 & headset_detect_chk) {
110738c89fedSNiranjan H Y 		ret = tac5xx2_sdca_headset_detect(tac_dev);
110838c89fedSNiranjan H Y 		if (ret < 0)
110938c89fedSNiranjan H Y 			goto clear;
111038c89fedSNiranjan H Y 		jack_report_mask |= SND_JACK_HEADSET;
111138c89fedSNiranjan H Y 	}
111238c89fedSNiranjan H Y 
111338c89fedSNiranjan H Y 	if (sdca_int3 & hid_detect_chk) {
111438c89fedSNiranjan H Y 		btn_type = tac5xx2_sdca_button_detect(tac_dev);
111538c89fedSNiranjan H Y 		if (btn_type < 0)
111638c89fedSNiranjan H Y 			btn_type = 0;
111738c89fedSNiranjan H Y 		jack_report_mask |= SND_JACK_BTN_0 | SND_JACK_BTN_1 |
111838c89fedSNiranjan H Y 			SND_JACK_BTN_2 | SND_JACK_BTN_3 | SND_JACK_BTN_4;
111938c89fedSNiranjan H Y 	}
112038c89fedSNiranjan H Y 
112138c89fedSNiranjan H Y 	if (tac_dev->jack_type == 0)
112238c89fedSNiranjan H Y 		btn_type = 0;
112338c89fedSNiranjan H Y 
112438c89fedSNiranjan H Y 	dev_dbg(tac_dev->dev, "in %s, jack_type=%d\n", __func__, tac_dev->jack_type);
112538c89fedSNiranjan H Y 	dev_dbg(tac_dev->dev, "in %s, btn_type=0x%x\n", __func__, btn_type);
112638c89fedSNiranjan H Y 
112738c89fedSNiranjan H Y 	if (!tac_dev->hs_jack)
112838c89fedSNiranjan H Y 		goto clear;
112938c89fedSNiranjan H Y 
113038c89fedSNiranjan H Y 	snd_soc_jack_report(tac_dev->hs_jack, tac_dev->jack_type | btn_type,
113138c89fedSNiranjan H Y 			    jack_report_mask);
113238c89fedSNiranjan H Y 
113338c89fedSNiranjan H Y clear:
113438c89fedSNiranjan H Y 	if (sdca_int2) {
113538c89fedSNiranjan H Y 		ret = regmap_write(tac_dev->regmap, SDW_SCP_SDCA_INT2, sdca_int2);
113638c89fedSNiranjan H Y 		if (ret)
113738c89fedSNiranjan H Y 			dev_dbg(tac_dev->dev, "Failed to clear jack interrupt\n");
113838c89fedSNiranjan H Y 	}
113938c89fedSNiranjan H Y 
114038c89fedSNiranjan H Y 	if (sdca_int3) {
114138c89fedSNiranjan H Y 		ret = regmap_write(tac_dev->regmap, SDW_SCP_SDCA_INT3, sdca_int3);
114238c89fedSNiranjan H Y 		if (ret)
114338c89fedSNiranjan H Y 			dev_dbg(tac_dev->dev, "failed to clear hid interrupt\n");
114438c89fedSNiranjan H Y 	}
114538c89fedSNiranjan H Y 
114638c89fedSNiranjan H Y 	return 0;
114738c89fedSNiranjan H Y }
114838c89fedSNiranjan H Y 
114938c89fedSNiranjan H Y static struct snd_soc_dai_driver tac5572_dai_driver[] = {
115038c89fedSNiranjan H Y 	{
115138c89fedSNiranjan H Y 		.name = "tac5xx2-aif1",
115238c89fedSNiranjan H Y 		.id = TAC5XX2_SPK,
115338c89fedSNiranjan H Y 		.playback = {
115438c89fedSNiranjan H Y 			.stream_name = "DP1 Speaker Playback",
115538c89fedSNiranjan H Y 			.channels_min = 1,
115638c89fedSNiranjan H Y 			.channels_max = 2,
115738c89fedSNiranjan H Y 			.rates = TAC5XX2_DEVICE_RATES,
115838c89fedSNiranjan H Y 			.formats = TAC5XX2_DEVICE_FORMATS,
115938c89fedSNiranjan H Y 		},
116038c89fedSNiranjan H Y 		.ops = &tac_dai_ops,
116138c89fedSNiranjan H Y 	},
116238c89fedSNiranjan H Y 	{
116338c89fedSNiranjan H Y 		.name = "tac5xx2-aif2",
116438c89fedSNiranjan H Y 		.id = TAC5XX2_DMIC,
116538c89fedSNiranjan H Y 		.capture = {
116638c89fedSNiranjan H Y 			.stream_name = "DP3 Mic Capture",
116738c89fedSNiranjan H Y 			.channels_min = 1,
116838c89fedSNiranjan H Y 			.channels_max = 4,
116938c89fedSNiranjan H Y 			.rates = TAC5XX2_DEVICE_RATES,
117038c89fedSNiranjan H Y 			.formats = TAC5XX2_DEVICE_FORMATS,
117138c89fedSNiranjan H Y 		},
117238c89fedSNiranjan H Y 		.ops = &tac_dai_ops,
117338c89fedSNiranjan H Y 	},
117438c89fedSNiranjan H Y 	{
117538c89fedSNiranjan H Y 		.name = "tac5xx2-aif3",
117638c89fedSNiranjan H Y 		.id = TAC5XX2_UAJ,
117738c89fedSNiranjan H Y 		.playback = {
117838c89fedSNiranjan H Y 			.stream_name = "DP4 UAJ Speaker Playback",
117938c89fedSNiranjan H Y 			.channels_min = 1,
118038c89fedSNiranjan H Y 			.channels_max = 2,
118138c89fedSNiranjan H Y 			.rates = TAC5XX2_DEVICE_RATES,
118238c89fedSNiranjan H Y 			.formats = TAC5XX2_DEVICE_FORMATS,
118338c89fedSNiranjan H Y 		},
118438c89fedSNiranjan H Y 		.capture = {
118538c89fedSNiranjan H Y 			.stream_name = "DP7 UAJ Mic Capture",
118638c89fedSNiranjan H Y 			.channels_min = 1,
118738c89fedSNiranjan H Y 			.channels_max = 2,
118838c89fedSNiranjan H Y 			.rates = TAC5XX2_DEVICE_RATES,
118938c89fedSNiranjan H Y 			.formats = TAC5XX2_DEVICE_FORMATS,
119038c89fedSNiranjan H Y 		},
119138c89fedSNiranjan H Y 		.ops = &tac_dai_ops,
119238c89fedSNiranjan H Y 	},
119338c89fedSNiranjan H Y };
119438c89fedSNiranjan H Y 
119538c89fedSNiranjan H Y static struct snd_soc_dai_driver tac5672_dai_driver[] = {
119638c89fedSNiranjan H Y 	{
119738c89fedSNiranjan H Y 		.name = "tac5xx2-aif1",
119838c89fedSNiranjan H Y 		.id = TAC5XX2_SPK,
119938c89fedSNiranjan H Y 		.playback = {
120038c89fedSNiranjan H Y 			.stream_name = "DP1 Speaker Playback",
120138c89fedSNiranjan H Y 			.channels_min = 1,
120238c89fedSNiranjan H Y 			.channels_max = 2,
120338c89fedSNiranjan H Y 			.rates = TAC5XX2_DEVICE_RATES,
120438c89fedSNiranjan H Y 			.formats = TAC5XX2_DEVICE_FORMATS,
120538c89fedSNiranjan H Y 		},
120638c89fedSNiranjan H Y 		.capture = {
120738c89fedSNiranjan H Y 			.stream_name = "DP8 IV Sense Capture",
120838c89fedSNiranjan H Y 			.channels_min = 1,
120938c89fedSNiranjan H Y 			.channels_max = 4,
121038c89fedSNiranjan H Y 			.rates = TAC5XX2_DEVICE_RATES,
121138c89fedSNiranjan H Y 			.formats = TAC5XX2_DEVICE_FORMATS,
121238c89fedSNiranjan H Y 		},
121338c89fedSNiranjan H Y 		.ops = &tac_dai_ops,
121438c89fedSNiranjan H Y 		.symmetric_rate = 1,
121538c89fedSNiranjan H Y 	},
121638c89fedSNiranjan H Y 	{
121738c89fedSNiranjan H Y 		.name = "tac5xx2-aif2",
121838c89fedSNiranjan H Y 		.id = TAC5XX2_DMIC,
121938c89fedSNiranjan H Y 		.capture = {
122038c89fedSNiranjan H Y 			.stream_name = "DP3 Mic Capture",
122138c89fedSNiranjan H Y 			.channels_min = 1,
122238c89fedSNiranjan H Y 			.channels_max = 4,
122338c89fedSNiranjan H Y 			.rates = TAC5XX2_DEVICE_RATES,
122438c89fedSNiranjan H Y 			.formats = TAC5XX2_DEVICE_FORMATS,
122538c89fedSNiranjan H Y 		},
122638c89fedSNiranjan H Y 		.ops = &tac_dai_ops,
122738c89fedSNiranjan H Y 	},
122838c89fedSNiranjan H Y 	{
122938c89fedSNiranjan H Y 		.name = "tac5xx2-aif3",
123038c89fedSNiranjan H Y 		.id = TAC5XX2_UAJ,
123138c89fedSNiranjan H Y 		.playback = {
123238c89fedSNiranjan H Y 			.stream_name = "DP4 UAJ Speaker Playback",
123338c89fedSNiranjan H Y 			.channels_min = 1,
123438c89fedSNiranjan H Y 			.channels_max = 2,
123538c89fedSNiranjan H Y 			.rates = TAC5XX2_DEVICE_RATES,
123638c89fedSNiranjan H Y 			.formats = TAC5XX2_DEVICE_FORMATS,
123738c89fedSNiranjan H Y 		},
123838c89fedSNiranjan H Y 		.capture = {
123938c89fedSNiranjan H Y 			.stream_name = "DP7 UAJ Mic Capture",
124038c89fedSNiranjan H Y 			.channels_min = 1,
124138c89fedSNiranjan H Y 			.channels_max = 2,
124238c89fedSNiranjan H Y 			.rates = TAC5XX2_DEVICE_RATES,
124338c89fedSNiranjan H Y 			.formats = TAC5XX2_DEVICE_FORMATS,
124438c89fedSNiranjan H Y 		},
124538c89fedSNiranjan H Y 		.ops = &tac_dai_ops,
124638c89fedSNiranjan H Y 	},
124738c89fedSNiranjan H Y };
124838c89fedSNiranjan H Y 
124938c89fedSNiranjan H Y static struct snd_soc_dai_driver tac5682_dai_driver[] = {
125038c89fedSNiranjan H Y 	{
125138c89fedSNiranjan H Y 		.name = "tac5xx2-aif1",
125238c89fedSNiranjan H Y 		.id = TAC5XX2_SPK,
125338c89fedSNiranjan H Y 		.playback = {
125438c89fedSNiranjan H Y 			.stream_name = "DP1 Speaker Playback",
125538c89fedSNiranjan H Y 			.channels_min = 1,
125638c89fedSNiranjan H Y 			.channels_max = 2,
125738c89fedSNiranjan H Y 			.rates = TAC5XX2_DEVICE_RATES,
125838c89fedSNiranjan H Y 			.formats = TAC5XX2_DEVICE_FORMATS,
125938c89fedSNiranjan H Y 		},
126038c89fedSNiranjan H Y 		.capture = {
126138c89fedSNiranjan H Y 			.stream_name = "DP2 Echo Reference Capture",
126238c89fedSNiranjan H Y 			.channels_min = 1,
126338c89fedSNiranjan H Y 			.channels_max = 4,
126438c89fedSNiranjan H Y 			.rates = TAC5XX2_DEVICE_RATES,
126538c89fedSNiranjan H Y 			.formats = TAC5XX2_DEVICE_FORMATS,
126638c89fedSNiranjan H Y 		},
126738c89fedSNiranjan H Y 		.ops = &tac_dai_ops,
126838c89fedSNiranjan H Y 		.symmetric_rate = 1,
126938c89fedSNiranjan H Y 	},
127038c89fedSNiranjan H Y 	{
127138c89fedSNiranjan H Y 		.name = "tac5xx2-aif2",
127238c89fedSNiranjan H Y 		.id = TAC5XX2_DMIC,
127338c89fedSNiranjan H Y 		.capture = {
127438c89fedSNiranjan H Y 			.stream_name = "DP3 Mic Capture",
127538c89fedSNiranjan H Y 			.channels_min = 1,
127638c89fedSNiranjan H Y 			.channels_max = 4,
127738c89fedSNiranjan H Y 			.rates = TAC5XX2_DEVICE_RATES,
127838c89fedSNiranjan H Y 			.formats = TAC5XX2_DEVICE_FORMATS,
127938c89fedSNiranjan H Y 		},
128038c89fedSNiranjan H Y 		.ops = &tac_dai_ops,
128138c89fedSNiranjan H Y 	},
128238c89fedSNiranjan H Y 	{
128338c89fedSNiranjan H Y 		.name = "tac5xx2-aif3",
128438c89fedSNiranjan H Y 		.id = TAC5XX2_UAJ,
128538c89fedSNiranjan H Y 		.playback = {
128638c89fedSNiranjan H Y 			.stream_name = "DP4 UAJ Speaker Playback",
128738c89fedSNiranjan H Y 			.channels_min = 1,
128838c89fedSNiranjan H Y 			.channels_max = 2,
128938c89fedSNiranjan H Y 			.rates = TAC5XX2_DEVICE_RATES,
129038c89fedSNiranjan H Y 			.formats = TAC5XX2_DEVICE_FORMATS,
129138c89fedSNiranjan H Y 		},
129238c89fedSNiranjan H Y 		.capture = {
129338c89fedSNiranjan H Y 			.stream_name = "DP7 UAJ Mic Capture",
129438c89fedSNiranjan H Y 			.channels_min = 1,
129538c89fedSNiranjan H Y 			.channels_max = 2,
129638c89fedSNiranjan H Y 			.rates = TAC5XX2_DEVICE_RATES,
129738c89fedSNiranjan H Y 			.formats = TAC5XX2_DEVICE_FORMATS,
129838c89fedSNiranjan H Y 		},
129938c89fedSNiranjan H Y 		.ops = &tac_dai_ops,
130038c89fedSNiranjan H Y 	},
130138c89fedSNiranjan H Y };
130238c89fedSNiranjan H Y 
130338c89fedSNiranjan H Y static struct snd_soc_dai_driver tas2883_dai_driver[] = {
130438c89fedSNiranjan H Y 	{
130538c89fedSNiranjan H Y 		.name = "tac5xx2-aif1",
130638c89fedSNiranjan H Y 		.id = TAC5XX2_SPK,
130738c89fedSNiranjan H Y 		.playback = {
130838c89fedSNiranjan H Y 			.stream_name = "DP1 Speaker Playback",
130938c89fedSNiranjan H Y 			.channels_min = 1,
131038c89fedSNiranjan H Y 			.channels_max = 2,
131138c89fedSNiranjan H Y 			.rates = TAC5XX2_DEVICE_RATES,
131238c89fedSNiranjan H Y 			.formats = TAC5XX2_DEVICE_FORMATS,
131338c89fedSNiranjan H Y 		},
131438c89fedSNiranjan H Y 		.ops = &tac_dai_ops,
131538c89fedSNiranjan H Y 		.symmetric_rate = 1,
131638c89fedSNiranjan H Y 	},
131738c89fedSNiranjan H Y 	{
131838c89fedSNiranjan H Y 		.name = "tac5xx2-aif2",
131938c89fedSNiranjan H Y 		.id = TAC5XX2_DMIC,
132038c89fedSNiranjan H Y 		.capture = {
132138c89fedSNiranjan H Y 			.stream_name = "DP3 Mic Capture",
132238c89fedSNiranjan H Y 			.channels_min = 1,
132338c89fedSNiranjan H Y 			.channels_max = 4,
132438c89fedSNiranjan H Y 			.rates = TAC5XX2_DEVICE_RATES,
132538c89fedSNiranjan H Y 			.formats = TAC5XX2_DEVICE_FORMATS,
132638c89fedSNiranjan H Y 		},
132738c89fedSNiranjan H Y 		.ops = &tac_dai_ops,
132838c89fedSNiranjan H Y 	},
132938c89fedSNiranjan H Y };
133038c89fedSNiranjan H Y 
tac_component_probe(struct snd_soc_component * component)133138c89fedSNiranjan H Y static s32 tac_component_probe(struct snd_soc_component *component)
133238c89fedSNiranjan H Y {
133338c89fedSNiranjan H Y 	struct tac5xx2_prv *tac_dev = snd_soc_component_get_drvdata(component);
133438c89fedSNiranjan H Y 	int ret;
133538c89fedSNiranjan H Y 
133638c89fedSNiranjan H Y 	ret = pm_runtime_resume(component->dev);
133738c89fedSNiranjan H Y 	if (ret < 0 && ret != -EACCES)
133838c89fedSNiranjan H Y 		return ret;
133938c89fedSNiranjan H Y 
134038c89fedSNiranjan H Y 	if (!tac_has_uaj_support(tac_dev))
134138c89fedSNiranjan H Y 		goto done_comp_probe;
134238c89fedSNiranjan H Y 
134338c89fedSNiranjan H Y 	ret = snd_soc_dapm_new_controls(snd_soc_component_to_dapm(component),
134438c89fedSNiranjan H Y 					tac_uaj_widgets,
134538c89fedSNiranjan H Y 					ARRAY_SIZE(tac_uaj_widgets));
134638c89fedSNiranjan H Y 	if (ret) {
134738c89fedSNiranjan H Y 		dev_err(component->dev, "Failed to add UAJ widgets: %d\n", ret);
134838c89fedSNiranjan H Y 		return ret;
134938c89fedSNiranjan H Y 	}
135038c89fedSNiranjan H Y 
135138c89fedSNiranjan H Y 	ret = snd_soc_dapm_add_routes(snd_soc_component_to_dapm(component),
135238c89fedSNiranjan H Y 				      tac_uaj_routes, ARRAY_SIZE(tac_uaj_routes));
135338c89fedSNiranjan H Y 	if (ret) {
135438c89fedSNiranjan H Y 		dev_err(component->dev, "Failed to add UAJ routes: %d\n", ret);
135538c89fedSNiranjan H Y 		return ret;
135638c89fedSNiranjan H Y 	}
135738c89fedSNiranjan H Y 
135838c89fedSNiranjan H Y 	ret = snd_soc_add_component_controls(component, tac_uaj_controls,
135938c89fedSNiranjan H Y 					     ARRAY_SIZE(tac_uaj_controls));
136038c89fedSNiranjan H Y 	if (ret) {
136138c89fedSNiranjan H Y 		dev_err(component->dev, "Failed to add UAJ controls: %d\n", ret);
136238c89fedSNiranjan H Y 			return ret;
136338c89fedSNiranjan H Y 	}
136438c89fedSNiranjan H Y 
136538c89fedSNiranjan H Y done_comp_probe:
136638c89fedSNiranjan H Y 	tac_dev->component = component;
136738c89fedSNiranjan H Y 	return 0;
136838c89fedSNiranjan H Y }
136938c89fedSNiranjan H Y 
tac_component_remove(struct snd_soc_component * codec)137038c89fedSNiranjan H Y static void tac_component_remove(struct snd_soc_component *codec)
137138c89fedSNiranjan H Y {
137238c89fedSNiranjan H Y 	struct tac5xx2_prv *tac_dev = snd_soc_component_get_drvdata(codec);
137338c89fedSNiranjan H Y 
137438c89fedSNiranjan H Y 	tac_dev->component = NULL;
137538c89fedSNiranjan H Y }
137638c89fedSNiranjan H Y 
137738c89fedSNiranjan H Y static const struct snd_soc_component_driver soc_codec_driver_tacdevice = {
137838c89fedSNiranjan H Y 	.probe = tac_component_probe,
137938c89fedSNiranjan H Y 	.remove = tac_component_remove,
138038c89fedSNiranjan H Y 	.controls = tac5xx2_snd_controls,
138138c89fedSNiranjan H Y 	.num_controls = ARRAY_SIZE(tac5xx2_snd_controls),
138238c89fedSNiranjan H Y 	.dapm_widgets = tac5xx2_common_widgets,
138338c89fedSNiranjan H Y 	.num_dapm_widgets = ARRAY_SIZE(tac5xx2_common_widgets),
138438c89fedSNiranjan H Y 	.dapm_routes = tac5xx2_common_routes,
138538c89fedSNiranjan H Y 	.num_dapm_routes = ARRAY_SIZE(tac5xx2_common_routes),
138638c89fedSNiranjan H Y 	.idle_bias_on = 0,
138738c89fedSNiranjan H Y 	.endianness = 1,
138838c89fedSNiranjan H Y };
138938c89fedSNiranjan H Y 
tac_init(struct tac5xx2_prv * tac_dev)139038c89fedSNiranjan H Y static s32 tac_init(struct tac5xx2_prv *tac_dev)
139138c89fedSNiranjan H Y {
139238c89fedSNiranjan H Y 	struct snd_soc_component_driver *component_driver;
139338c89fedSNiranjan H Y 	struct snd_soc_dai_driver *dai_drv;
139438c89fedSNiranjan H Y 	int num_dais;
139538c89fedSNiranjan H Y 	s32 ret;
139638c89fedSNiranjan H Y 
139738c89fedSNiranjan H Y 	dev_set_drvdata(tac_dev->dev, tac_dev);
139838c89fedSNiranjan H Y 
139938c89fedSNiranjan H Y 	switch (tac_dev->part_id) {
140038c89fedSNiranjan H Y 	case 0x5572:
140138c89fedSNiranjan H Y 		dai_drv = tac5572_dai_driver;
140238c89fedSNiranjan H Y 		num_dais = ARRAY_SIZE(tac5572_dai_driver);
140338c89fedSNiranjan H Y 		break;
140438c89fedSNiranjan H Y 	case 0x5672:
140538c89fedSNiranjan H Y 		dai_drv = tac5672_dai_driver;
140638c89fedSNiranjan H Y 		num_dais = ARRAY_SIZE(tac5672_dai_driver);
140738c89fedSNiranjan H Y 		break;
140838c89fedSNiranjan H Y 	case 0x5682:
140938c89fedSNiranjan H Y 		dai_drv = tac5682_dai_driver;
141038c89fedSNiranjan H Y 		num_dais = ARRAY_SIZE(tac5682_dai_driver);
141138c89fedSNiranjan H Y 		break;
141238c89fedSNiranjan H Y 	case 0x2883:
141338c89fedSNiranjan H Y 		dai_drv = tas2883_dai_driver;
141438c89fedSNiranjan H Y 		num_dais = ARRAY_SIZE(tas2883_dai_driver);
141538c89fedSNiranjan H Y 		break;
141638c89fedSNiranjan H Y 	default:
141738c89fedSNiranjan H Y 		dev_err(tac_dev->dev, "Unsupported device: 0x%x\n",
141838c89fedSNiranjan H Y 			tac_dev->part_id);
141938c89fedSNiranjan H Y 		return -EINVAL;
142038c89fedSNiranjan H Y 	}
142138c89fedSNiranjan H Y 
142238c89fedSNiranjan H Y 	component_driver = devm_kzalloc(tac_dev->dev, sizeof(*component_driver),
142338c89fedSNiranjan H Y 					GFP_KERNEL);
142438c89fedSNiranjan H Y 	if (!component_driver)
142538c89fedSNiranjan H Y 		return -ENOMEM;
142638c89fedSNiranjan H Y 
142738c89fedSNiranjan H Y 	memcpy(component_driver, &soc_codec_driver_tacdevice, sizeof(*component_driver));
142838c89fedSNiranjan H Y 	if (tac_has_uaj_support(tac_dev))
142938c89fedSNiranjan H Y 		component_driver->set_jack = tac5xx2_set_jack;
143038c89fedSNiranjan H Y 
143138c89fedSNiranjan H Y 	ret = devm_snd_soc_register_component(tac_dev->dev, component_driver,
143238c89fedSNiranjan H Y 					      dai_drv, num_dais);
143338c89fedSNiranjan H Y 	if (ret) {
143438c89fedSNiranjan H Y 		dev_err(tac_dev->dev, "%s: codec register error:%d.\n",
143538c89fedSNiranjan H Y 			__func__, ret);
143638c89fedSNiranjan H Y 		return ret;
143738c89fedSNiranjan H Y 	}
143838c89fedSNiranjan H Y 
143938c89fedSNiranjan H Y 	return 0;
144038c89fedSNiranjan H Y }
144138c89fedSNiranjan H Y 
tac5xx2_sdca_dev_suspend(struct device * dev)144238c89fedSNiranjan H Y static s32 tac5xx2_sdca_dev_suspend(struct device *dev)
144338c89fedSNiranjan H Y {
144438c89fedSNiranjan H Y 	struct tac5xx2_prv *tac_dev = dev_get_drvdata(dev);
144538c89fedSNiranjan H Y 
144638c89fedSNiranjan H Y 	if (!tac_dev->hw_init)
1447ab50528aSCharles Keepax 		return 0;
1448*ea9ff3b7SCharles Keepax 
1449*ea9ff3b7SCharles Keepax 	regcache_cache_only(tac_dev->regmap, true);
1450ab50528aSCharles Keepax 	return 0;
1451*ea9ff3b7SCharles Keepax }
145238c89fedSNiranjan H Y 
tac5xx2_sdca_dev_system_suspend(struct device * dev)145338c89fedSNiranjan H Y static s32 tac5xx2_sdca_dev_system_suspend(struct device *dev)
145438c89fedSNiranjan H Y {
145538c89fedSNiranjan H Y 	return tac5xx2_sdca_dev_suspend(dev);
145638c89fedSNiranjan H Y }
145738c89fedSNiranjan H Y 
tac5xx2_sdca_dev_resume(struct device * dev)145838c89fedSNiranjan H Y static s32 tac5xx2_sdca_dev_resume(struct device *dev)
145938c89fedSNiranjan H Y {
146038c89fedSNiranjan H Y 	struct tac5xx2_prv *tac_dev = dev_get_drvdata(dev);
146138c89fedSNiranjan H Y 	struct sdw_slave *slave = dev_to_sdw_dev(dev);
146238c89fedSNiranjan H Y 	int ret;
146338c89fedSNiranjan H Y 
146438c89fedSNiranjan H Y 	if (!tac_dev->first_hw_init_done) {
146538c89fedSNiranjan H Y 		dev_dbg(dev, "Device not initialized yet, skipping resume sync\n");
146638c89fedSNiranjan H Y 		return 0;
146738c89fedSNiranjan H Y 	}
146838c89fedSNiranjan H Y 
146938c89fedSNiranjan H Y 	ret = sdw_slave_wait_for_init(slave, TAC5XX2_PROBE_TIMEOUT_MS);
147038c89fedSNiranjan H Y 	if (ret) {
147138c89fedSNiranjan H Y 		sdw_show_ping_status(slave->bus, true);
147238c89fedSNiranjan H Y 		return ret;
147338c89fedSNiranjan H Y 	}
147438c89fedSNiranjan H Y 
147538c89fedSNiranjan H Y 	regcache_cache_only(tac_dev->regmap, false);
147638c89fedSNiranjan H Y 	regcache_mark_dirty(tac_dev->regmap);
147738c89fedSNiranjan H Y 	ret = regcache_sync(tac_dev->regmap);
147838c89fedSNiranjan H Y 	if (ret < 0)
147938c89fedSNiranjan H Y 		dev_warn(dev, "Failed to sync regcache: %d\n", ret);
148038c89fedSNiranjan H Y 
148138c89fedSNiranjan H Y 	/* Detect and set jack type for UAJ path before playback.
148238c89fedSNiranjan H Y 	 * This is required as jack detection does not trigger interrupt
148338c89fedSNiranjan H Y 	 * when device is in runtime_pm suspend with bus in clock stop mode.
148438c89fedSNiranjan H Y 	 */
148538c89fedSNiranjan H Y 	if (tac_has_uaj_support(tac_dev))
148638c89fedSNiranjan H Y 		tac5xx2_sdca_headset_detect(tac_dev);
148738c89fedSNiranjan H Y 
148838c89fedSNiranjan H Y 	return 0;
148938c89fedSNiranjan H Y }
149038c89fedSNiranjan H Y 
149138c89fedSNiranjan H Y static const struct dev_pm_ops tac5xx2_sdca_pm = {
149238c89fedSNiranjan H Y 	SYSTEM_SLEEP_PM_OPS(tac5xx2_sdca_dev_system_suspend, tac5xx2_sdca_dev_resume)
149338c89fedSNiranjan H Y 	RUNTIME_PM_OPS(tac5xx2_sdca_dev_suspend, tac5xx2_sdca_dev_resume, NULL)
149438c89fedSNiranjan H Y };
149538c89fedSNiranjan H Y 
tac_fw_read_hdr(const u8 * data,struct tac_fw_hdr * hdr)149638c89fedSNiranjan H Y static s32 tac_fw_read_hdr(const u8 *data, struct tac_fw_hdr *hdr)
149738c89fedSNiranjan H Y {
149838c89fedSNiranjan H Y 	hdr->size = get_unaligned_le32(data);
149938c89fedSNiranjan H Y 	hdr->version_offset = get_unaligned_le32(data + 4);
150038c89fedSNiranjan H Y 	hdr->plt_id = get_unaligned_le32(data + 8);
150138c89fedSNiranjan H Y 	hdr->ppc3_ver = get_unaligned_le32(data + 12);
150238c89fedSNiranjan H Y 	memcpy(hdr->ddc_name, data + 16, 64);
150338c89fedSNiranjan H Y 	hdr->ddc_name[63] = 0;
150438c89fedSNiranjan H Y 	hdr->timestamp = get_unaligned_le64(data + 80);
150538c89fedSNiranjan H Y 
150638c89fedSNiranjan H Y 	return TAC_FW_HDR_SIZE;
150738c89fedSNiranjan H Y }
150838c89fedSNiranjan H Y 
tac_fw_get_next_file(const u8 * data,size_t data_size,struct tac_fw_file * file)150938c89fedSNiranjan H Y static s32 tac_fw_get_next_file(const u8 *data, size_t data_size, struct tac_fw_file *file)
151038c89fedSNiranjan H Y {
151138c89fedSNiranjan H Y 	u32 file_length;
151238c89fedSNiranjan H Y 
151338c89fedSNiranjan H Y 	/* Validate file header size */
151438c89fedSNiranjan H Y 	if (data_size < TAC_FW_FILE_HDR)
151538c89fedSNiranjan H Y 		return -EINVAL;
151638c89fedSNiranjan H Y 
151738c89fedSNiranjan H Y 	file->vendor_id = get_unaligned_le32(&data[0]);
151838c89fedSNiranjan H Y 	file->file_id = get_unaligned_le32(&data[4]);
151938c89fedSNiranjan H Y 	file->version = get_unaligned_le32(&data[8]);
152038c89fedSNiranjan H Y 	file->length = get_unaligned_le32(&data[12]);
152138c89fedSNiranjan H Y 	file->dest_addr = get_unaligned_le32(&data[16]);
152238c89fedSNiranjan H Y 	file_length = file->length;
152338c89fedSNiranjan H Y 
152438c89fedSNiranjan H Y 	/* Validate file payload exists */
152538c89fedSNiranjan H Y 	if (data_size < TAC_FW_FILE_HDR + file_length)
152638c89fedSNiranjan H Y 		return -EINVAL;
152738c89fedSNiranjan H Y 
152838c89fedSNiranjan H Y 	file->fw_data = (u8 *)&data[20];
152938c89fedSNiranjan H Y 
153038c89fedSNiranjan H Y 	return file_length + sizeof(u32) * 5;
153138c89fedSNiranjan H Y }
153238c89fedSNiranjan H Y 
tac5xx2_fw_ready(const struct firmware * fmw,void * context)153338c89fedSNiranjan H Y static void tac5xx2_fw_ready(const struct firmware *fmw, void *context)
153438c89fedSNiranjan H Y {
153538c89fedSNiranjan H Y 	struct tac5xx2_prv *tac_dev = context;
153638c89fedSNiranjan H Y 	struct tac_fw_file *files;
153738c89fedSNiranjan H Y 	u32 fw_hdr_size;
153838c89fedSNiranjan H Y 	u32 num_files = 0;
153938c89fedSNiranjan H Y 	struct tac_fw_hdr hdr;
154038c89fedSNiranjan H Y 	struct tm tm_time;
154138c89fedSNiranjan H Y 	size_t img_sz;
154238c89fedSNiranjan H Y 	u32 offset;
154338c89fedSNiranjan H Y 	s32 ret = 0;
154438c89fedSNiranjan H Y 	u8 *buf;
154538c89fedSNiranjan H Y 
154638c89fedSNiranjan H Y 	if (!fmw || !fmw->data || fmw->size == 0 || fmw->size < TAC_FW_HDR_SIZE + TAC_FW_FILE_HDR) {
154738c89fedSNiranjan H Y 		dev_err(tac_dev->dev, "fw file: %s is empty or invalid\n",
154838c89fedSNiranjan H Y 			tac_dev->fw_binaryname);
154938c89fedSNiranjan H Y 		goto out;
155038c89fedSNiranjan H Y 	}
155138c89fedSNiranjan H Y 
155238c89fedSNiranjan H Y 	/* Verify firmware size from header */
155338c89fedSNiranjan H Y 	fw_hdr_size = get_unaligned_le32(fmw->data);
155438c89fedSNiranjan H Y 	if (fw_hdr_size != fmw->size) {
155538c89fedSNiranjan H Y 		dev_err(tac_dev->dev, "firmware size mismatch: hdr=%u, actual=%zu\n",
155638c89fedSNiranjan H Y 			fw_hdr_size, fmw->size);
155738c89fedSNiranjan H Y 		goto out;
155838c89fedSNiranjan H Y 	}
155938c89fedSNiranjan H Y 
156038c89fedSNiranjan H Y 	files = devm_kzalloc(tac_dev->dev, sizeof(*files) * TAC_MAX_FW_CHUNKS, GFP_KERNEL);
156138c89fedSNiranjan H Y 	buf = devm_kmemdup(tac_dev->dev, fmw->data, fmw->size, GFP_KERNEL);
156238c89fedSNiranjan H Y 	if (!files || !buf)
156338c89fedSNiranjan H Y 		goto out;
156438c89fedSNiranjan H Y 
156538c89fedSNiranjan H Y 	/* validate the cache the firmware */
156638c89fedSNiranjan H Y 	img_sz = fmw->size;
156738c89fedSNiranjan H Y 	offset = tac_fw_read_hdr(buf, &hdr);
156838c89fedSNiranjan H Y 	while (offset < img_sz && num_files < TAC_MAX_FW_CHUNKS) {
156938c89fedSNiranjan H Y 		u32 file_length;
157038c89fedSNiranjan H Y 
157138c89fedSNiranjan H Y 		if (offset + TAC_FW_FILE_HDR > img_sz) {
157238c89fedSNiranjan H Y 			dev_warn(tac_dev->dev, "Incomplete block header at offset %d\n",
157338c89fedSNiranjan H Y 				 offset);
157438c89fedSNiranjan H Y 			goto out;
157538c89fedSNiranjan H Y 		}
157638c89fedSNiranjan H Y 		/* Validate that the file payload doesn't exceed buffer */
157738c89fedSNiranjan H Y 		file_length = get_unaligned_le32(&buf[offset + 12]);
157838c89fedSNiranjan H Y 		/* Check for integer overflow and buffer bounds */
157938c89fedSNiranjan H Y 		if (file_length > img_sz || offset > img_sz - TAC_FW_FILE_HDR ||
158038c89fedSNiranjan H Y 		    file_length > img_sz - offset - TAC_FW_FILE_HDR) {
158138c89fedSNiranjan H Y 			dev_warn(tac_dev->dev, "File at offset %d exceeds buffer: length=%u, available=%zu\n",
158238c89fedSNiranjan H Y 				 offset, file_length, img_sz - offset - TAC_FW_FILE_HDR);
158338c89fedSNiranjan H Y 			goto out;
158438c89fedSNiranjan H Y 		}
158538c89fedSNiranjan H Y 		ret = tac_fw_get_next_file(&buf[offset], img_sz - offset, &files[num_files]);
158638c89fedSNiranjan H Y 		if (ret < 0) {
158738c89fedSNiranjan H Y 			dev_err(tac_dev->dev, "Failed to parse file at offset %d\n", offset);
158838c89fedSNiranjan H Y 			goto out;
158938c89fedSNiranjan H Y 		}
159038c89fedSNiranjan H Y 		offset += ret;
159138c89fedSNiranjan H Y 		num_files++;
159238c89fedSNiranjan H Y 	}
159338c89fedSNiranjan H Y 
159438c89fedSNiranjan H Y 	if (num_files == 0) {
159538c89fedSNiranjan H Y 		dev_err(tac_dev->dev, "firmware with no files\n");
159638c89fedSNiranjan H Y 		goto out;
159738c89fedSNiranjan H Y 	}
159838c89fedSNiranjan H Y 
159938c89fedSNiranjan H Y 	/* cache ready to use validated firmware */
160038c89fedSNiranjan H Y 	tac_dev->fw_file_cnt = num_files;
160138c89fedSNiranjan H Y 	tac_dev->fw_files = files;
160238c89fedSNiranjan H Y 
160338c89fedSNiranjan H Y 	time64_to_tm(hdr.timestamp, 0, &tm_time);
160438c89fedSNiranjan H Y 	dev_dbg(tac_dev->dev, "fw file: %s, num_files=%u, ts:%04ld-%02d-%02d %02d:%02d\n",
160538c89fedSNiranjan H Y 		tac_dev->fw_binaryname, tac_dev->fw_file_cnt,
160638c89fedSNiranjan H Y 		tm_time.tm_year + 1900, tm_time.tm_mon + 1, tm_time.tm_mday,
160738c89fedSNiranjan H Y 		tm_time.tm_hour, tm_time.tm_min);
160838c89fedSNiranjan H Y 	dev_dbg(tac_dev->dev, "fw file: DDC Name: %s\n", hdr.ddc_name);
160938c89fedSNiranjan H Y 	dev_dbg(tac_dev->dev, "fw file: PPC3 Version: 3.%ld.%ld.%ld\n",
161038c89fedSNiranjan H Y 		FIELD_GET(GENMASK(31, 24), hdr.ppc3_ver),
161138c89fedSNiranjan H Y 		FIELD_GET(GENMASK(23, 16), hdr.ppc3_ver),
161238c89fedSNiranjan H Y 		FIELD_GET(GENMASK(15, 8), hdr.ppc3_ver) & 0x3f);
161338c89fedSNiranjan H Y 
161438c89fedSNiranjan H Y out:
161538c89fedSNiranjan H Y 	complete_all(&tac_dev->fw_caching_complete);
161638c89fedSNiranjan H Y 	if (fmw)
161738c89fedSNiranjan H Y 		release_firmware(fmw);
161838c89fedSNiranjan H Y }
161938c89fedSNiranjan H Y 
tac_load_and_cache_firmware_async(struct tac5xx2_prv * tac_dev)162038c89fedSNiranjan H Y static int tac_load_and_cache_firmware_async(struct tac5xx2_prv *tac_dev)
162138c89fedSNiranjan H Y {
162238c89fedSNiranjan H Y 	tac_dev->fw_file_cnt = 0;
162338c89fedSNiranjan H Y 	tac_dev->fw_files = NULL; /* ready to download files */
162438c89fedSNiranjan H Y 
162538c89fedSNiranjan H Y 	return request_firmware_nowait(THIS_MODULE, FW_ACTION_UEVENT,
162638c89fedSNiranjan H Y 				       tac_dev->fw_binaryname, tac_dev->dev,
162738c89fedSNiranjan H Y 				       GFP_KERNEL, tac_dev, tac5xx2_fw_ready);
162838c89fedSNiranjan H Y }
162938c89fedSNiranjan H Y 
tac_download(struct tac5xx2_prv * tac_dev)163038c89fedSNiranjan H Y static int tac_download(struct tac5xx2_prv *tac_dev)
163138c89fedSNiranjan H Y {
163238c89fedSNiranjan H Y 	struct tac_fw_file *files = tac_dev->fw_files;
163338c89fedSNiranjan H Y 	u32 num_files = tac_dev->fw_file_cnt;
163438c89fedSNiranjan H Y 	u32 i;
163538c89fedSNiranjan H Y 	int ret = 0;
163638c89fedSNiranjan H Y 
163738c89fedSNiranjan H Y 	for (i = 0; i < num_files; i++) {
163838c89fedSNiranjan H Y 		ret = sdw_nwrite_no_pm(tac_dev->sdw_peripheral, files[i].dest_addr,
163938c89fedSNiranjan H Y 				       files[i].length, files[i].fw_data);
164038c89fedSNiranjan H Y 		if (ret < 0) {
164138c89fedSNiranjan H Y 			dev_dbg(tac_dev->dev,
164238c89fedSNiranjan H Y 				"FW write failed at addr 0x%x: %d\n",
164338c89fedSNiranjan H Y 				files[i].dest_addr, ret);
164438c89fedSNiranjan H Y 			return ret;
164538c89fedSNiranjan H Y 		}
164638c89fedSNiranjan H Y 	}
164738c89fedSNiranjan H Y 
164838c89fedSNiranjan H Y 	return 0;
164938c89fedSNiranjan H Y }
165038c89fedSNiranjan H Y 
165138c89fedSNiranjan H Y /*
165238c89fedSNiranjan H Y  * tac5xx2 uses custom firmware binary fw.
165338c89fedSNiranjan H Y  * This is not using UMP File Download.
165438c89fedSNiranjan H Y  */
tac_download_fw_to_hw(struct tac5xx2_prv * tac_dev)165538c89fedSNiranjan H Y static s32 tac_download_fw_to_hw(struct tac5xx2_prv *tac_dev)
165638c89fedSNiranjan H Y {
165738c89fedSNiranjan H Y 	int ret;
165838c89fedSNiranjan H Y 
165938c89fedSNiranjan H Y 	ret = tac_download(tac_dev);
166038c89fedSNiranjan H Y 	if (ret < 0) {
166138c89fedSNiranjan H Y 		dev_err(tac_dev->dev, "Firmware download failed: %d\n", ret);
166238c89fedSNiranjan H Y 		return ret;
166338c89fedSNiranjan H Y 	}
166438c89fedSNiranjan H Y 
166538c89fedSNiranjan H Y 	dev_dbg(tac_dev->dev, "Firmware download complete: %d chunks\n",
166638c89fedSNiranjan H Y 		tac_dev->fw_file_cnt);
166738c89fedSNiranjan H Y 	tac_dev->fw_dl_success = true;
166838c89fedSNiranjan H Y 
166938c89fedSNiranjan H Y 	return 0;
167038c89fedSNiranjan H Y }
167138c89fedSNiranjan H Y 
tac_get_pci_dev(struct sdw_slave * peripheral)167238c89fedSNiranjan H Y static struct pci_dev *tac_get_pci_dev(struct sdw_slave *peripheral)
167338c89fedSNiranjan H Y {
167438c89fedSNiranjan H Y 	struct device *dev = &peripheral->dev;
167538c89fedSNiranjan H Y 
167638c89fedSNiranjan H Y 	for (; dev; dev = dev->parent) {
167738c89fedSNiranjan H Y 		if (dev_is_pci(dev))
167838c89fedSNiranjan H Y 			return to_pci_dev(dev);
167938c89fedSNiranjan H Y 	}
168038c89fedSNiranjan H Y 
168138c89fedSNiranjan H Y 	return NULL;
168238c89fedSNiranjan H Y }
168338c89fedSNiranjan H Y 
tac_generate_fw_name(struct sdw_slave * slave,char * name,size_t size)168438c89fedSNiranjan H Y static void tac_generate_fw_name(struct sdw_slave *slave, char *name, size_t size)
168538c89fedSNiranjan H Y {
168638c89fedSNiranjan H Y 	struct sdw_bus *bus = slave->bus;
168738c89fedSNiranjan H Y 	u16 part_id = slave->id.part_id;
168838c89fedSNiranjan H Y 	u8 unique_id = slave->id.unique_id;
168938c89fedSNiranjan H Y 	struct pci_dev *pci = tac_get_pci_dev(slave);
169038c89fedSNiranjan H Y 
169138c89fedSNiranjan H Y 	if (pci)
169238c89fedSNiranjan H Y 		scnprintf(name, size, "%04X-%04X-%1X-%1X.bin", part_id,
169338c89fedSNiranjan H Y 			  pci->subsystem_device, bus->link_id, unique_id);
169438c89fedSNiranjan H Y 	else
169538c89fedSNiranjan H Y 		/* Default firmware name based on part ID */
169638c89fedSNiranjan H Y 		scnprintf(name, size, "%s%04x-%1X-%1X.bin",
169738c89fedSNiranjan H Y 			  part_id == 0x2883 ? "tas" : "tac",
169838c89fedSNiranjan H Y 			  part_id, bus->link_id, unique_id);
169938c89fedSNiranjan H Y }
170038c89fedSNiranjan H Y 
tac_io_init(struct device * dev,struct sdw_slave * slave,bool first)170138c89fedSNiranjan H Y static int tac_io_init(struct device *dev, struct sdw_slave *slave, bool first)
170238c89fedSNiranjan H Y {
170338c89fedSNiranjan H Y 	struct tac5xx2_prv *tac_dev = dev_get_drvdata(dev);
170438c89fedSNiranjan H Y 	u64 time;
170538c89fedSNiranjan H Y 	int ret;
170638c89fedSNiranjan H Y 
170738c89fedSNiranjan H Y 	if (tac_dev->hw_init) {
170838c89fedSNiranjan H Y 		dev_dbg(dev, "early return hw_init already done..");
170938c89fedSNiranjan H Y 		return 0;
171038c89fedSNiranjan H Y 	}
171138c89fedSNiranjan H Y 
171238c89fedSNiranjan H Y 	time = wait_for_completion_timeout(&tac_dev->fw_caching_complete,
171338c89fedSNiranjan H Y 					   msecs_to_jiffies(TAC5XX2_FW_CACHE_TIMEOUT_MS));
171438c89fedSNiranjan H Y 	if (!time) {
171538c89fedSNiranjan H Y 		ret = -ETIMEDOUT;
171638c89fedSNiranjan H Y 		dev_warn(tac_dev->dev, "%s: fw caching timeout\n", __func__);
171738c89fedSNiranjan H Y 		goto io_init_err;
171838c89fedSNiranjan H Y 	}
171938c89fedSNiranjan H Y 
172038c89fedSNiranjan H Y 	if (!tac_dev->rev_id) {
172138c89fedSNiranjan H Y 		ret = regmap_read(tac_dev->regmap, TAC_REV_ID, &tac_dev->rev_id);
172238c89fedSNiranjan H Y 		if (ret) {
172338c89fedSNiranjan H Y 			dev_err(tac_dev->dev, "failed to rev id, err=%d\n", ret);
172438c89fedSNiranjan H Y 			goto io_init_err;
172538c89fedSNiranjan H Y 		}
172638c89fedSNiranjan H Y 		dev_dbg(tac_dev->dev, "detected rev_id 0x%x", tac_dev->rev_id);
172738c89fedSNiranjan H Y 	}
172838c89fedSNiranjan H Y 
172938c89fedSNiranjan H Y 	if (tac_dev->fw_files && tac_dev->fw_file_cnt > 0) {
173038c89fedSNiranjan H Y 		ret = tac_download_fw_to_hw(tac_dev);
173138c89fedSNiranjan H Y 		if (ret) {
173238c89fedSNiranjan H Y 			dev_err(tac_dev->dev, "FW download failed, fw: %d\n", ret);
173338c89fedSNiranjan H Y 			goto io_init_err;
173438c89fedSNiranjan H Y 		}
173538c89fedSNiranjan H Y 	}
173638c89fedSNiranjan H Y 
173738c89fedSNiranjan H Y 	if (tac_dev->sa_func_data) {
173838c89fedSNiranjan H Y 		ret = sdca_regmap_write_init(dev, tac_dev->regmap,
173938c89fedSNiranjan H Y 					     tac_dev->sa_func_data);
174038c89fedSNiranjan H Y 		if (ret) {
174138c89fedSNiranjan H Y 			dev_err(dev, "smartamp init table update failed\n");
174238c89fedSNiranjan H Y 			goto io_init_err;
174338c89fedSNiranjan H Y 		}
174438c89fedSNiranjan H Y 		dev_dbg(dev, "smartamp init done\n");
174538c89fedSNiranjan H Y 
174638c89fedSNiranjan H Y 		if (first) {
174738c89fedSNiranjan H Y 			ret = regmap_multi_reg_write(tac_dev->regmap, tac_spk_seq,
174838c89fedSNiranjan H Y 						     ARRAY_SIZE(tac_spk_seq));
174938c89fedSNiranjan H Y 			if (ret) {
175038c89fedSNiranjan H Y 				dev_err(dev, "init writes failed, err=%d", ret);
175138c89fedSNiranjan H Y 				goto io_init_err;
175238c89fedSNiranjan H Y 			}
175338c89fedSNiranjan H Y 		}
175438c89fedSNiranjan H Y 	}
175538c89fedSNiranjan H Y 
175638c89fedSNiranjan H Y 	if (tac_dev->sm_func_data) {
175738c89fedSNiranjan H Y 		ret = sdca_regmap_write_init(dev, tac_dev->regmap,
175838c89fedSNiranjan H Y 					     tac_dev->sm_func_data);
175938c89fedSNiranjan H Y 		if (ret) {
176038c89fedSNiranjan H Y 			dev_err(dev, "smartmic init table update failed\n");
176138c89fedSNiranjan H Y 			goto io_init_err;
176238c89fedSNiranjan H Y 		}
176338c89fedSNiranjan H Y 		dev_dbg(dev, "smartmic init done\n");
176438c89fedSNiranjan H Y 
176538c89fedSNiranjan H Y 		if (first) {
176638c89fedSNiranjan H Y 			ret = regmap_multi_reg_write(tac_dev->regmap, tac_sm_seq,
176738c89fedSNiranjan H Y 						     ARRAY_SIZE(tac_sm_seq));
176838c89fedSNiranjan H Y 			if (ret) {
176938c89fedSNiranjan H Y 				dev_err(tac_dev->dev,
177038c89fedSNiranjan H Y 					"init writes failed, err=%d", ret);
177138c89fedSNiranjan H Y 				goto io_init_err;
177238c89fedSNiranjan H Y 			}
177338c89fedSNiranjan H Y 		}
177438c89fedSNiranjan H Y 	}
177538c89fedSNiranjan H Y 
177638c89fedSNiranjan H Y 	if (tac_dev->uaj_func_data) {
177738c89fedSNiranjan H Y 		ret = sdca_regmap_write_init(dev, tac_dev->regmap,
177838c89fedSNiranjan H Y 					     tac_dev->uaj_func_data);
177938c89fedSNiranjan H Y 		if (ret) {
178038c89fedSNiranjan H Y 			dev_err(dev, "uaj init table update failed\n");
178138c89fedSNiranjan H Y 			goto io_init_err;
178238c89fedSNiranjan H Y 		}
178338c89fedSNiranjan H Y 		dev_dbg(dev, "uaj init done\n");
178438c89fedSNiranjan H Y 
178538c89fedSNiranjan H Y 		if (first) {
178638c89fedSNiranjan H Y 			ret = regmap_multi_reg_write(tac_dev->regmap, tac_uaj_seq,
178738c89fedSNiranjan H Y 						     ARRAY_SIZE(tac_uaj_seq));
178838c89fedSNiranjan H Y 			if (ret) {
178938c89fedSNiranjan H Y 				dev_err(tac_dev->dev,
179038c89fedSNiranjan H Y 					"init writes failed, err=%d", ret);
179138c89fedSNiranjan H Y 				goto io_init_err;
179238c89fedSNiranjan H Y 			}
179338c89fedSNiranjan H Y 
179438c89fedSNiranjan H Y 			if (tac_dev->hs_jack) {
179538c89fedSNiranjan H Y 				ret = tac5xx2_jack_init(tac_dev);
179638c89fedSNiranjan H Y 				if (ret) {
179738c89fedSNiranjan H Y 					dev_err(tac_dev->dev, "jack init failed");
179838c89fedSNiranjan H Y 					goto io_init_err;
179938c89fedSNiranjan H Y 				}
180038c89fedSNiranjan H Y 			}
180138c89fedSNiranjan H Y 		}
180238c89fedSNiranjan H Y 	}
180338c89fedSNiranjan H Y 
180438c89fedSNiranjan H Y 	if (tac_dev->hid_func_data) {
180538c89fedSNiranjan H Y 		ret = sdca_regmap_write_init(dev, tac_dev->regmap,
180638c89fedSNiranjan H Y 					     tac_dev->hid_func_data);
180738c89fedSNiranjan H Y 		if (ret) {
180838c89fedSNiranjan H Y 			dev_err(dev, "hid init table update failed\n");
180938c89fedSNiranjan H Y 			goto io_init_err;
181038c89fedSNiranjan H Y 		}
181138c89fedSNiranjan H Y 		dev_dbg(dev, "hid init done\n");
181238c89fedSNiranjan H Y 	}
181338c89fedSNiranjan H Y 
181438c89fedSNiranjan H Y 	tac_dev->hw_init = true;
181538c89fedSNiranjan H Y 
181638c89fedSNiranjan H Y 	return 0;
181738c89fedSNiranjan H Y 
181838c89fedSNiranjan H Y io_init_err:
181938c89fedSNiranjan H Y 	dev_err(dev, "init writes failed, err=%d", ret);
182038c89fedSNiranjan H Y 	return ret;
182138c89fedSNiranjan H Y }
182238c89fedSNiranjan H Y 
tac_update_status(struct sdw_slave * slave,enum sdw_slave_status status)182338c89fedSNiranjan H Y static int tac_update_status(struct sdw_slave *slave,
182438c89fedSNiranjan H Y 			     enum sdw_slave_status status)
182538c89fedSNiranjan H Y {
182638c89fedSNiranjan H Y 	struct tac5xx2_prv *tac_dev = dev_get_drvdata(&slave->dev);
182738c89fedSNiranjan H Y 	struct device *dev = &slave->dev;
182838c89fedSNiranjan H Y 	bool first = false;
182938c89fedSNiranjan H Y 	int ret;
183038c89fedSNiranjan H Y 
183138c89fedSNiranjan H Y 	tac_dev->status = status;
183238c89fedSNiranjan H Y 	if (status == SDW_SLAVE_UNATTACHED) {
183338c89fedSNiranjan H Y 		tac_dev->hw_init = false;
183438c89fedSNiranjan H Y 		tac_dev->fw_dl_success = false;
183538c89fedSNiranjan H Y 	}
183638c89fedSNiranjan H Y 
183738c89fedSNiranjan H Y 	if (tac_dev->hw_init || tac_dev->status != SDW_SLAVE_ATTACHED) {
183838c89fedSNiranjan H Y 		dev_dbg(dev, "%s: early return, hw_init=%d, status=%d",
183938c89fedSNiranjan H Y 			__func__, tac_dev->hw_init, tac_dev->status);
184038c89fedSNiranjan H Y 		return 0;
184138c89fedSNiranjan H Y 	}
184238c89fedSNiranjan H Y 
184338c89fedSNiranjan H Y 	if (!tac_dev->first_hw_init_done) {
184438c89fedSNiranjan H Y 		pm_runtime_set_active(tac_dev->dev);
184538c89fedSNiranjan H Y 		tac_dev->first_hw_init_done = true;
184638c89fedSNiranjan H Y 		first = true;
184738c89fedSNiranjan H Y 	}
184838c89fedSNiranjan H Y 
184938c89fedSNiranjan H Y 	pm_runtime_get_noresume(tac_dev->dev);
185038c89fedSNiranjan H Y 
185138c89fedSNiranjan H Y 	regcache_mark_dirty(tac_dev->regmap);
185238c89fedSNiranjan H Y 	regcache_cache_only(tac_dev->regmap, false);
185338c89fedSNiranjan H Y 	ret = tac_io_init(&slave->dev, slave, first);
185438c89fedSNiranjan H Y 	if (ret) {
185538c89fedSNiranjan H Y 		dev_err(dev, "Device initialization failed: %d\n", ret);
185638c89fedSNiranjan H Y 		goto err_out;
185738c89fedSNiranjan H Y 	}
185838c89fedSNiranjan H Y 
185938c89fedSNiranjan H Y 	ret = regcache_sync(tac_dev->regmap);
186038c89fedSNiranjan H Y 	if (ret)
186138c89fedSNiranjan H Y 		dev_warn(dev, "Failed to sync regcache after init: %d\n", ret);
186238c89fedSNiranjan H Y 
186338c89fedSNiranjan H Y err_out:
186438c89fedSNiranjan H Y 	pm_runtime_mark_last_busy(tac_dev->dev);
186538c89fedSNiranjan H Y 	pm_runtime_put_autosuspend(tac_dev->dev);
186638c89fedSNiranjan H Y 
186738c89fedSNiranjan H Y 	return ret;
186838c89fedSNiranjan H Y }
186938c89fedSNiranjan H Y 
tac5xx2_sdw_read_prop(struct sdw_slave * peripheral)187038c89fedSNiranjan H Y static int tac5xx2_sdw_read_prop(struct sdw_slave *peripheral)
187138c89fedSNiranjan H Y {
187238c89fedSNiranjan H Y 	struct device *dev = &peripheral->dev;
187338c89fedSNiranjan H Y 	int ret;
187438c89fedSNiranjan H Y 
187538c89fedSNiranjan H Y 	ret = sdw_slave_read_prop(peripheral);
187638c89fedSNiranjan H Y 	if (ret) {
187738c89fedSNiranjan H Y 		dev_err(dev, "sdw_slave_read_prop failed: %d", ret);
187838c89fedSNiranjan H Y 		return ret;
187938c89fedSNiranjan H Y 	}
188038c89fedSNiranjan H Y 
188138c89fedSNiranjan H Y 	return 0;
188238c89fedSNiranjan H Y }
188338c89fedSNiranjan H Y 
tac_port_prep(struct sdw_slave * slave,struct sdw_prepare_ch * prep_ch,enum sdw_port_prep_ops pre_ops)188438c89fedSNiranjan H Y static int tac_port_prep(struct sdw_slave *slave, struct sdw_prepare_ch *prep_ch,
188538c89fedSNiranjan H Y 			 enum sdw_port_prep_ops pre_ops)
188638c89fedSNiranjan H Y {
188738c89fedSNiranjan H Y 	struct device *dev = &slave->dev;
188838c89fedSNiranjan H Y 	struct tac5xx2_prv *tac_dev = dev_get_drvdata(dev);
188938c89fedSNiranjan H Y 	unsigned int val;
189038c89fedSNiranjan H Y 	int ret;
189138c89fedSNiranjan H Y 
189238c89fedSNiranjan H Y 	if (pre_ops != SDW_OPS_PORT_POST_PREP)
189338c89fedSNiranjan H Y 		return 0;
189438c89fedSNiranjan H Y 
189538c89fedSNiranjan H Y 	if (!tac_dev->fw_dl_success)
189638c89fedSNiranjan H Y 		return 0;
189738c89fedSNiranjan H Y 
189838c89fedSNiranjan H Y 	ret = regmap_read(tac_dev->regmap, TAC_DSP_ALGO_STATUS, &val);
189938c89fedSNiranjan H Y 	if (ret) {
190038c89fedSNiranjan H Y 		dev_err(dev, "Failed to read algo status: %d\n", ret);
190138c89fedSNiranjan H Y 		return ret;
190238c89fedSNiranjan H Y 	}
190338c89fedSNiranjan H Y 
190438c89fedSNiranjan H Y 	if (val != TAC_DSP_ALGO_STATUS_RUNNING) {
190538c89fedSNiranjan H Y 		dev_dbg(dev, "Algo not running (0x%02x), re-enabling\n", val);
190638c89fedSNiranjan H Y 		ret = regmap_write(tac_dev->regmap, TAC_DSP_ALGO_STATUS,
190738c89fedSNiranjan H Y 				   TAC_DSP_ALGO_STATUS_RUNNING);
190838c89fedSNiranjan H Y 		if (ret) {
190938c89fedSNiranjan H Y 			dev_err(dev, "Failed to re-enable algo: %d\n", ret);
191038c89fedSNiranjan H Y 			return ret;
191138c89fedSNiranjan H Y 		}
191238c89fedSNiranjan H Y 	}
191338c89fedSNiranjan H Y 
191438c89fedSNiranjan H Y 	return 0;
191538c89fedSNiranjan H Y }
191638c89fedSNiranjan H Y 
191738c89fedSNiranjan H Y static const struct sdw_slave_ops tac_sdw_ops = {
191838c89fedSNiranjan H Y 	.read_prop = tac5xx2_sdw_read_prop,
191938c89fedSNiranjan H Y 	.update_status = tac_update_status,
192038c89fedSNiranjan H Y 	.interrupt_callback = tac_interrupt_callback,
192138c89fedSNiranjan H Y 	.port_prep = tac_port_prep,
192238c89fedSNiranjan H Y };
192338c89fedSNiranjan H Y 
tac_sdw_probe(struct sdw_slave * peripheral,const struct sdw_device_id * id)192438c89fedSNiranjan H Y static s32 tac_sdw_probe(struct sdw_slave *peripheral,
192538c89fedSNiranjan H Y 			 const struct sdw_device_id *id)
192638c89fedSNiranjan H Y {
192738c89fedSNiranjan H Y 	struct sdca_function_data *function_data = NULL;
192838c89fedSNiranjan H Y 	struct device *dev = &peripheral->dev;
192938c89fedSNiranjan H Y 	struct tac5xx2_prv *tac_dev;
193038c89fedSNiranjan H Y 	struct regmap *regmap;
193138c89fedSNiranjan H Y 	int ret, i;
193238c89fedSNiranjan H Y 
193338c89fedSNiranjan H Y 	tac_dev = devm_kzalloc(dev, sizeof(*tac_dev), GFP_KERNEL);
193438c89fedSNiranjan H Y 	if (!tac_dev)
193538c89fedSNiranjan H Y 		return dev_err_probe(dev, -ENOMEM,
193638c89fedSNiranjan H Y 				     "Failed devm_kzalloc");
193738c89fedSNiranjan H Y 
193838c89fedSNiranjan H Y 	if (peripheral->sdca_data.num_functions > 0) {
193938c89fedSNiranjan H Y 		dev_dbg(dev, "SDCA functions found: %d",
194038c89fedSNiranjan H Y 			peripheral->sdca_data.num_functions);
194138c89fedSNiranjan H Y 
194238c89fedSNiranjan H Y 		for (i = 0; i < peripheral->sdca_data.num_functions; i++) {
194338c89fedSNiranjan H Y 			struct sdca_function_data **func_ptr;
194438c89fedSNiranjan H Y 			const char *func_name;
194538c89fedSNiranjan H Y 
194638c89fedSNiranjan H Y 			switch (peripheral->sdca_data.function[i].type) {
194738c89fedSNiranjan H Y 			case SDCA_FUNCTION_TYPE_SMART_AMP:
194838c89fedSNiranjan H Y 				func_ptr = &tac_dev->sa_func_data;
194938c89fedSNiranjan H Y 				func_name = "smartamp";
195038c89fedSNiranjan H Y 				break;
195138c89fedSNiranjan H Y 			case SDCA_FUNCTION_TYPE_SMART_MIC:
195238c89fedSNiranjan H Y 				func_ptr = &tac_dev->sm_func_data;
195338c89fedSNiranjan H Y 				func_name = "smartmic";
195438c89fedSNiranjan H Y 				break;
195538c89fedSNiranjan H Y 			case SDCA_FUNCTION_TYPE_UAJ:
195638c89fedSNiranjan H Y 				func_ptr = &tac_dev->uaj_func_data;
195738c89fedSNiranjan H Y 				func_name = "uaj";
195838c89fedSNiranjan H Y 				break;
195938c89fedSNiranjan H Y 			case SDCA_FUNCTION_TYPE_HID:
196038c89fedSNiranjan H Y 				func_ptr = &tac_dev->hid_func_data;
196138c89fedSNiranjan H Y 				func_name = "hid";
196238c89fedSNiranjan H Y 				break;
196338c89fedSNiranjan H Y 			default:
196438c89fedSNiranjan H Y 				continue;
196538c89fedSNiranjan H Y 			}
196638c89fedSNiranjan H Y 
196738c89fedSNiranjan H Y 			function_data = devm_kzalloc(dev, sizeof(*function_data),
196838c89fedSNiranjan H Y 						     GFP_KERNEL);
196938c89fedSNiranjan H Y 			if (!function_data)
197038c89fedSNiranjan H Y 				return dev_err_probe(dev, -ENOMEM,
197138c89fedSNiranjan H Y 						     "failed to allocate %s function data",
197238c89fedSNiranjan H Y 						     func_name);
197338c89fedSNiranjan H Y 			function_data->desc = &peripheral->sdca_data.function[i];
197438c89fedSNiranjan H Y 			ret = sdca_parse_function(dev, function_data);
197538c89fedSNiranjan H Y 			if (!ret)
197638c89fedSNiranjan H Y 				*func_ptr = function_data;
197738c89fedSNiranjan H Y 			else
197838c89fedSNiranjan H Y 				devm_kfree(dev, function_data);
197938c89fedSNiranjan H Y 		}
198038c89fedSNiranjan H Y 	}
198138c89fedSNiranjan H Y 
198238c89fedSNiranjan H Y 	dev_dbg(dev, "SDCA functions enabled: SA=%s SM=%s UAJ=%s HID=%s",
198338c89fedSNiranjan H Y 		tac_dev->sa_func_data ? "yes" : "no",
198438c89fedSNiranjan H Y 		tac_dev->sm_func_data ? "yes" : "no",
198538c89fedSNiranjan H Y 		tac_dev->uaj_func_data ? "yes" : "no",
198638c89fedSNiranjan H Y 		tac_dev->hid_func_data ? "yes" : "no");
198738c89fedSNiranjan H Y 
198838c89fedSNiranjan H Y 	tac_dev->dev = dev;
198938c89fedSNiranjan H Y 	tac_dev->sdw_peripheral = peripheral;
199038c89fedSNiranjan H Y 	tac_dev->hw_init = false;
199138c89fedSNiranjan H Y 	tac_dev->first_hw_init_done = false;
199238c89fedSNiranjan H Y 	tac_dev->part_id = id->part_id;
199338c89fedSNiranjan H Y 	tac_dev->rev_id = 0x0;
199438c89fedSNiranjan H Y 	dev_set_drvdata(dev, tac_dev);
199538c89fedSNiranjan H Y 
199638c89fedSNiranjan H Y 	regmap = devm_regmap_init_sdw_mbq_cfg(&peripheral->dev, peripheral,
199738c89fedSNiranjan H Y 					      &tac_regmap, &tac_mbq_cfg);
199838c89fedSNiranjan H Y 	if (IS_ERR(regmap))
199938c89fedSNiranjan H Y 		return dev_err_probe(dev, PTR_ERR(regmap),
200038c89fedSNiranjan H Y 				     "Failed devm_regmap_init_sdw\n");
200138c89fedSNiranjan H Y 
200238c89fedSNiranjan H Y 	regcache_cache_only(regmap, true);
200338c89fedSNiranjan H Y 	tac_dev->regmap = regmap;
200438c89fedSNiranjan H Y 	tac_dev->jack_type = 0;
200538c89fedSNiranjan H Y 	init_completion(&tac_dev->fw_caching_complete);
200638c89fedSNiranjan H Y 
200738c89fedSNiranjan H Y 	tac_generate_fw_name(peripheral, tac_dev->fw_binaryname,
200838c89fedSNiranjan H Y 			     sizeof(tac_dev->fw_binaryname));
200938c89fedSNiranjan H Y 
201038c89fedSNiranjan H Y 	ret = tac_load_and_cache_firmware_async(tac_dev);
201138c89fedSNiranjan H Y 	if (ret) {
201238c89fedSNiranjan H Y 		complete_all(&tac_dev->fw_caching_complete);
201338c89fedSNiranjan H Y 		dev_dbg(dev, "failed to load fw: %d, use rom mode\n", ret);
201438c89fedSNiranjan H Y 	}
201538c89fedSNiranjan H Y 
201638c89fedSNiranjan H Y 	ret = tac_init(tac_dev);
201738c89fedSNiranjan H Y 	if (ret)
201838c89fedSNiranjan H Y 		return dev_err_probe(dev, ret,
201938c89fedSNiranjan H Y 				     "failed to initialize tac device\n");
202038c89fedSNiranjan H Y 
202138c89fedSNiranjan H Y 	/* set autosuspend parameters */
202238c89fedSNiranjan H Y 	pm_runtime_set_autosuspend_delay(dev, 3000);
202338c89fedSNiranjan H Y 	pm_runtime_use_autosuspend(dev);
202438c89fedSNiranjan H Y 
202538c89fedSNiranjan H Y 	/* make sure the device does not suspend immediately */
202638c89fedSNiranjan H Y 	pm_runtime_mark_last_busy(dev);
202738c89fedSNiranjan H Y 
202838c89fedSNiranjan H Y 	pm_runtime_enable(dev);
202938c89fedSNiranjan H Y 	/* the device is still not in active */
203038c89fedSNiranjan H Y 
203138c89fedSNiranjan H Y 	return 0;
203238c89fedSNiranjan H Y }
203338c89fedSNiranjan H Y 
tac_sdw_remove(struct sdw_slave * peripheral)203438c89fedSNiranjan H Y static void tac_sdw_remove(struct sdw_slave *peripheral)
203538c89fedSNiranjan H Y {
203638c89fedSNiranjan H Y 	struct tac5xx2_prv *tac_dev = dev_get_drvdata(&peripheral->dev);
203738c89fedSNiranjan H Y 
203838c89fedSNiranjan H Y 	pm_runtime_disable(tac_dev->dev);
203938c89fedSNiranjan H Y 
2040 	dev_set_drvdata(&peripheral->dev, NULL);
2041 }
2042 
2043 static const struct sdw_device_id tac_sdw_id[] = {
2044 	SDW_SLAVE_ENTRY(0x0102, 0x5572, 0),
2045 	SDW_SLAVE_ENTRY(0x0102, 0x5672, 0),
2046 	SDW_SLAVE_ENTRY(0x0102, 0x5682, 0),
2047 	SDW_SLAVE_ENTRY(0x0102, 0x2883, 0),
2048 	{},
2049 };
2050 MODULE_DEVICE_TABLE(sdw, tac_sdw_id);
2051 
2052 static struct sdw_driver tac_sdw_driver = {
2053 	.driver = {
2054 		.name = "slave-tac5xx2",
2055 		.pm = pm_ptr(&tac5xx2_sdca_pm),
2056 	},
2057 	.probe = tac_sdw_probe,
2058 	.remove = tac_sdw_remove,
2059 	.ops = &tac_sdw_ops,
2060 	.id_table = tac_sdw_id,
2061 };
2062 module_sdw_driver(tac_sdw_driver);
2063 
2064 MODULE_IMPORT_NS("SND_SOC_SDCA");
2065 MODULE_AUTHOR("Texas Instruments Inc.");
2066 MODULE_DESCRIPTION("ASoC TAC5XX2 SoundWire Driver");
2067 MODULE_LICENSE("GPL");
2068