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