1*4cc9bd8dSNiranjan H Y // SPDX-License-Identifier: GPL-2.0 2*4cc9bd8dSNiranjan H Y // 3*4cc9bd8dSNiranjan H Y // ALSA SoC Texas Instruments TAS2783 Audio Smart Amplifier 4*4cc9bd8dSNiranjan H Y // 5*4cc9bd8dSNiranjan H Y // Copyright (C) 2025 Texas Instruments Incorporated 6*4cc9bd8dSNiranjan H Y // https://www.ti.com 7*4cc9bd8dSNiranjan H Y // 8*4cc9bd8dSNiranjan H Y // The TAS2783 driver implements a flexible and configurable 9*4cc9bd8dSNiranjan H Y // algo coefficient setting for single TAS2783 chips. 10*4cc9bd8dSNiranjan H Y // 11*4cc9bd8dSNiranjan H Y // Author: Niranjan H Y <niranjanhy@ti.com> 12*4cc9bd8dSNiranjan H Y // Author: Baojun Xu <baojun.xu@ti.com> 13*4cc9bd8dSNiranjan H Y // Author: Kevin Lu <kevin-lu@ti.com> 14*4cc9bd8dSNiranjan H Y 15*4cc9bd8dSNiranjan H Y #include <linux/unaligned.h> 16*4cc9bd8dSNiranjan H Y #include <linux/crc32.h> 17*4cc9bd8dSNiranjan H Y #include <linux/efi.h> 18*4cc9bd8dSNiranjan H Y #include <linux/err.h> 19*4cc9bd8dSNiranjan H Y #include <linux/firmware.h> 20*4cc9bd8dSNiranjan H Y #include <linux/init.h> 21*4cc9bd8dSNiranjan H Y #include <linux/module.h> 22*4cc9bd8dSNiranjan H Y #include <sound/pcm_params.h> 23*4cc9bd8dSNiranjan H Y #include <linux/pm.h> 24*4cc9bd8dSNiranjan H Y #include <linux/pm_runtime.h> 25*4cc9bd8dSNiranjan H Y #include <linux/regmap.h> 26*4cc9bd8dSNiranjan H Y #include <linux/wait.h> 27*4cc9bd8dSNiranjan H Y #include <linux/soundwire/sdw.h> 28*4cc9bd8dSNiranjan H Y #include <linux/soundwire/sdw_registers.h> 29*4cc9bd8dSNiranjan H Y #include <linux/soundwire/sdw_type.h> 30*4cc9bd8dSNiranjan H Y #include <sound/sdw.h> 31*4cc9bd8dSNiranjan H Y #include <sound/soc.h> 32*4cc9bd8dSNiranjan H Y #include <sound/tlv.h> 33*4cc9bd8dSNiranjan H Y #include <sound/tas2781-tlv.h> 34*4cc9bd8dSNiranjan H Y 35*4cc9bd8dSNiranjan H Y #include "tas2783.h" 36*4cc9bd8dSNiranjan H Y 37*4cc9bd8dSNiranjan H Y #define TIMEOUT_FW_DL_MS (3000) 38*4cc9bd8dSNiranjan H Y #define FW_DL_OFFSET 36 39*4cc9bd8dSNiranjan H Y #define FW_FL_HDR 12 40*4cc9bd8dSNiranjan H Y #define TAS2783_PROBE_TIMEOUT 5000 41*4cc9bd8dSNiranjan H Y #define TAS2783_CALI_GUID EFI_GUID(0x1f52d2a1, 0xbb3a, 0x457d, 0xbc, \ 42*4cc9bd8dSNiranjan H Y 0x09, 0x43, 0xa3, 0xf4, 0x31, 0x0a, 0x92) 43*4cc9bd8dSNiranjan H Y 44*4cc9bd8dSNiranjan H Y static const u32 tas2783_cali_reg[] = { 45*4cc9bd8dSNiranjan H Y TAS2783_CAL_R0, 46*4cc9bd8dSNiranjan H Y TAS2783_CAL_INVR0, 47*4cc9bd8dSNiranjan H Y TAS2783_CAL_R0LOW, 48*4cc9bd8dSNiranjan H Y TAS2783_CAL_POWER, 49*4cc9bd8dSNiranjan H Y TAS2783_CAL_TLIM, 50*4cc9bd8dSNiranjan H Y }; 51*4cc9bd8dSNiranjan H Y 52*4cc9bd8dSNiranjan H Y struct bin_header_t { 53*4cc9bd8dSNiranjan H Y u16 vendor_id; 54*4cc9bd8dSNiranjan H Y u16 version; 55*4cc9bd8dSNiranjan H Y u32 file_id; 56*4cc9bd8dSNiranjan H Y u32 length; 57*4cc9bd8dSNiranjan H Y }; 58*4cc9bd8dSNiranjan H Y 59*4cc9bd8dSNiranjan H Y struct calibration_data { 60*4cc9bd8dSNiranjan H Y u32 is_valid; 61*4cc9bd8dSNiranjan H Y unsigned long read_sz; 62*4cc9bd8dSNiranjan H Y u8 data[TAS2783_CALIB_DATA_SZ]; 63*4cc9bd8dSNiranjan H Y }; 64*4cc9bd8dSNiranjan H Y 65*4cc9bd8dSNiranjan H Y struct tas2783_prv { 66*4cc9bd8dSNiranjan H Y struct snd_soc_component *component; 67*4cc9bd8dSNiranjan H Y struct calibration_data cali_data; 68*4cc9bd8dSNiranjan H Y struct sdw_slave *sdw_peripheral; 69*4cc9bd8dSNiranjan H Y enum sdw_slave_status status; 70*4cc9bd8dSNiranjan H Y /* calibration */ 71*4cc9bd8dSNiranjan H Y struct mutex calib_lock; 72*4cc9bd8dSNiranjan H Y /* pde and firmware download */ 73*4cc9bd8dSNiranjan H Y struct mutex pde_lock; 74*4cc9bd8dSNiranjan H Y struct regmap *regmap; 75*4cc9bd8dSNiranjan H Y struct device *dev; 76*4cc9bd8dSNiranjan H Y struct class *class; 77*4cc9bd8dSNiranjan H Y struct attribute_group *cal_attr_groups; 78*4cc9bd8dSNiranjan H Y struct tm tm; 79*4cc9bd8dSNiranjan H Y u8 rca_binaryname[64]; 80*4cc9bd8dSNiranjan H Y u8 dev_name[32]; 81*4cc9bd8dSNiranjan H Y bool hw_init; 82*4cc9bd8dSNiranjan H Y /* wq for firmware download */ 83*4cc9bd8dSNiranjan H Y wait_queue_head_t fw_wait; 84*4cc9bd8dSNiranjan H Y bool fw_dl_task_done; 85*4cc9bd8dSNiranjan H Y bool fw_dl_success; 86*4cc9bd8dSNiranjan H Y }; 87*4cc9bd8dSNiranjan H Y 88*4cc9bd8dSNiranjan H Y static const struct reg_default tas2783_reg_default[] = { 89*4cc9bd8dSNiranjan H Y {TAS2783_AMP_LEVEL, 0x28}, 90*4cc9bd8dSNiranjan H Y {TASDEV_REG_SDW(0, 0, 0x03), 0x28}, 91*4cc9bd8dSNiranjan H Y {TASDEV_REG_SDW(0, 0, 0x04), 0x21}, 92*4cc9bd8dSNiranjan H Y {TASDEV_REG_SDW(0, 0, 0x05), 0x41}, 93*4cc9bd8dSNiranjan H Y {TASDEV_REG_SDW(0, 0, 0x06), 0x00}, 94*4cc9bd8dSNiranjan H Y {TASDEV_REG_SDW(0, 0, 0x07), 0x20}, 95*4cc9bd8dSNiranjan H Y {TASDEV_REG_SDW(0, 0, 0x08), 0x09}, 96*4cc9bd8dSNiranjan H Y {TASDEV_REG_SDW(0, 0, 0x09), 0x02}, 97*4cc9bd8dSNiranjan H Y {TASDEV_REG_SDW(0, 0, 0x0a), 0x0a}, 98*4cc9bd8dSNiranjan H Y {TASDEV_REG_SDW(0, 0, 0x0c), 0x10}, 99*4cc9bd8dSNiranjan H Y {TASDEV_REG_SDW(0, 0, 0x0d), 0x13}, 100*4cc9bd8dSNiranjan H Y {TASDEV_REG_SDW(0, 0, 0x0e), 0xc2}, 101*4cc9bd8dSNiranjan H Y {TASDEV_REG_SDW(0, 0, 0x0f), 0x40}, 102*4cc9bd8dSNiranjan H Y {TASDEV_REG_SDW(0, 0, 0x10), 0x04}, 103*4cc9bd8dSNiranjan H Y {TASDEV_REG_SDW(0, 0, 0x13), 0x13}, 104*4cc9bd8dSNiranjan H Y {TASDEV_REG_SDW(0, 0, 0x14), 0x12}, 105*4cc9bd8dSNiranjan H Y {TASDEV_REG_SDW(0, 0, 0x15), 0x00}, 106*4cc9bd8dSNiranjan H Y {TASDEV_REG_SDW(0, 0, 0x16), 0x12}, 107*4cc9bd8dSNiranjan H Y {TASDEV_REG_SDW(0, 0, 0x17), 0x80}, 108*4cc9bd8dSNiranjan H Y {TAS2783_DVC_LVL, 0x00}, 109*4cc9bd8dSNiranjan H Y {TASDEV_REG_SDW(0, 0, 0x1b), 0x61}, 110*4cc9bd8dSNiranjan H Y {TASDEV_REG_SDW(0, 0, 0x1c), 0x36}, 111*4cc9bd8dSNiranjan H Y {TASDEV_REG_SDW(0, 0, 0x1d), 0x00}, 112*4cc9bd8dSNiranjan H Y {TASDEV_REG_SDW(0, 0, 0x1f), 0x01}, 113*4cc9bd8dSNiranjan H Y {TASDEV_REG_SDW(0, 0, 0x20), 0x2e}, 114*4cc9bd8dSNiranjan H Y {TASDEV_REG_SDW(0, 0, 0x21), 0x00}, 115*4cc9bd8dSNiranjan H Y {TASDEV_REG_SDW(0, 0, 0x34), 0x06}, 116*4cc9bd8dSNiranjan H Y {TASDEV_REG_SDW(0, 0, 0x35), 0xbd}, 117*4cc9bd8dSNiranjan H Y {TASDEV_REG_SDW(0, 0, 0x36), 0xad}, 118*4cc9bd8dSNiranjan H Y {TASDEV_REG_SDW(0, 0, 0x37), 0xa8}, 119*4cc9bd8dSNiranjan H Y {TASDEV_REG_SDW(0, 0, 0x38), 0x00}, 120*4cc9bd8dSNiranjan H Y {TASDEV_REG_SDW(0, 0, 0x3b), 0xfc}, 121*4cc9bd8dSNiranjan H Y {TASDEV_REG_SDW(0, 0, 0x3d), 0xdd}, 122*4cc9bd8dSNiranjan H Y {TASDEV_REG_SDW(0, 0, 0x40), 0xf6}, 123*4cc9bd8dSNiranjan H Y {TASDEV_REG_SDW(0, 0, 0x41), 0x14}, 124*4cc9bd8dSNiranjan H Y {TASDEV_REG_SDW(0, 0, 0x5c), 0x19}, 125*4cc9bd8dSNiranjan H Y {TASDEV_REG_SDW(0, 0, 0x5d), 0x80}, 126*4cc9bd8dSNiranjan H Y {TASDEV_REG_SDW(0, 0, 0x63), 0x48}, 127*4cc9bd8dSNiranjan H Y {TASDEV_REG_SDW(0, 0, 0x65), 0x08}, 128*4cc9bd8dSNiranjan H Y {TASDEV_REG_SDW(0, 0, 0x66), 0xb2}, 129*4cc9bd8dSNiranjan H Y {TASDEV_REG_SDW(0, 0, 0x67), 0x00}, 130*4cc9bd8dSNiranjan H Y {TASDEV_REG_SDW(0, 0, 0x6a), 0x12}, 131*4cc9bd8dSNiranjan H Y {TASDEV_REG_SDW(0, 0, 0x6b), 0xfb}, 132*4cc9bd8dSNiranjan H Y {TASDEV_REG_SDW(0, 0, 0x6c), 0x00}, 133*4cc9bd8dSNiranjan H Y {TASDEV_REG_SDW(0, 0, 0x6d), 0x00}, 134*4cc9bd8dSNiranjan H Y {TASDEV_REG_SDW(0, 0, 0x6e), 0x1a}, 135*4cc9bd8dSNiranjan H Y {TASDEV_REG_SDW(0, 0, 0x6f), 0x00}, 136*4cc9bd8dSNiranjan H Y {TASDEV_REG_SDW(0, 0, 0x70), 0x96}, 137*4cc9bd8dSNiranjan H Y {TASDEV_REG_SDW(0, 0, 0x71), 0x02}, 138*4cc9bd8dSNiranjan H Y {TASDEV_REG_SDW(0, 0, 0x73), 0x08}, 139*4cc9bd8dSNiranjan H Y {TASDEV_REG_SDW(0, 0, 0x75), 0xe0}, 140*4cc9bd8dSNiranjan H Y {TASDEV_REG_SDW(0, 0, 0x7a), 0x60}, 141*4cc9bd8dSNiranjan H Y {TASDEV_REG_SDW(0, 0, 0x60), 0x21}, 142*4cc9bd8dSNiranjan H Y {TASDEV_REG_SDW(0, 1, 0x02), 0x00}, 143*4cc9bd8dSNiranjan H Y {TASDEV_REG_SDW(0, 1, 0x17), 0xc0}, 144*4cc9bd8dSNiranjan H Y {TASDEV_REG_SDW(0, 1, 0x19), 0x60}, 145*4cc9bd8dSNiranjan H Y {TASDEV_REG_SDW(0, 1, 0x35), 0x75}, 146*4cc9bd8dSNiranjan H Y {TASDEV_REG_SDW(0, 1, 0x3d), 0x00}, 147*4cc9bd8dSNiranjan H Y {TASDEV_REG_SDW(0, 1, 0x3e), 0x00}, 148*4cc9bd8dSNiranjan H Y {TASDEV_REG_SDW(0, 1, 0x3f), 0x00}, 149*4cc9bd8dSNiranjan H Y {TASDEV_REG_SDW(0, 1, 0x40), 0x00}, 150*4cc9bd8dSNiranjan H Y {TASDEV_REG_SDW(0, 1, 0x41), 0x00}, 151*4cc9bd8dSNiranjan H Y {TASDEV_REG_SDW(0, 1, 0x42), 0x00}, 152*4cc9bd8dSNiranjan H Y {TASDEV_REG_SDW(0, 1, 0x43), 0x00}, 153*4cc9bd8dSNiranjan H Y {TASDEV_REG_SDW(0, 1, 0x44), 0x00}, 154*4cc9bd8dSNiranjan H Y {TASDEV_REG_SDW(0, 1, 0x45), 0x00}, 155*4cc9bd8dSNiranjan H Y {TASDEV_REG_SDW(0, 1, 0x47), 0xab}, 156*4cc9bd8dSNiranjan H Y {TASDEV_REG_SDW(0, 0xfd, 0x0d), 0x0d}, 157*4cc9bd8dSNiranjan H Y {TASDEV_REG_SDW(0, 0xfd, 0x39), 0x00}, 158*4cc9bd8dSNiranjan H Y {TASDEV_REG_SDW(0, 0xfd, 0x3e), 0x00}, 159*4cc9bd8dSNiranjan H Y {TASDEV_REG_SDW(0, 0xfd, 0x45), 0x00}, 160*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_CS21, 0x02, 0), 0x0}, 161*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_CS21, 0x10, 0), 0x0}, 162*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_CS24, 0x02, 0), 0x0}, 163*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_CS24, 0x10, 0), 0x0}, 164*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_CS26, 0x02, 0), 0x0}, 165*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_CS26, 0x10, 0), 0x0}, 166*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_CS28, 0x02, 0), 0x0}, 167*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_CS28, 0x10, 0), 0x0}, 168*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_CS127, 0x02, 0), 0x0}, 169*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_CS127, 0x10, 0), 0x0}, 170*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU21, 0x01, 1), 0x1}, 171*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU21, 0x02, 1), 0x9c00}, 172*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU23, 0x01, 0), 0x1}, 173*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU23, 0x01, 1), 0x1}, 174*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU23, 0x0b, 1), 0x0}, 175*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU23, 0x10, 0), 0x0}, 176*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU26, 0x01, 1), 0x1}, 177*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU26, 0x01, 0), 0x1}, 178*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU26, 0x0b, 1), 0x0}, 179*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU26, 0x10, 0), 0x0}, 180*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU127, 0x01, 0), 0x1}, 181*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU127, 0x01, 1), 0x1}, 182*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU127, 0x01, 2), 0x1}, 183*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU127, 0x0b, 0), 0x0}, 184*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU127, 0x0b, 1), 0x0}, 185*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU127, 0x0b, 2), 0x0}, 186*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU127, 0x10, 0), 0x0}, 187*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT21, 0x04, 0), 0x0}, 188*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT21, 0x08, 0), 0x0}, 189*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT21, 0x10, 0), 0x0}, 190*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT21, 0x11, 0), 0x0}, 191*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT26, 0x04, 0), 0x0}, 192*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT26, 0x08, 0), 0x0}, 193*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT26, 0x10, 0), 0x0}, 194*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT26, 0x11, 0), 0x0}, 195*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT28, 0x04, 0), 0x0}, 196*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT28, 0x08, 0), 0x0}, 197*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT28, 0x10, 0), 0x0}, 198*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT28, 0x11, 0), 0x0}, 199*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT29, 0x04, 0), 0x0}, 200*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT29, 0x08, 0), 0x0}, 201*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT29, 0x10, 0), 0x0}, 202*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT29, 0x11, 0), 0x0}, 203*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MFPU21, 0x01, 0), 0x0}, 204*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MFPU21, 0x04, 0), 0x0}, 205*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MFPU21, 0x05, 0), 0x1}, 206*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MFPU21, 0x08, 0), 0x0}, 207*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MFPU21, 0x10, 0), 0x0}, 208*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MFPU21, 0x11, 0), 0x0}, 209*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MFPU21, 0x12, 0), 0x0}, 210*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MFPU26, 0x01, 0), 0x0}, 211*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MFPU26, 0x04, 0), 0x0}, 212*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MFPU26, 0x05, 0), 0x1}, 213*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MFPU26, 0x08, 0), 0x0}, 214*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MFPU26, 0x10, 0), 0x0}, 215*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MFPU26, 0x11, 0), 0x0}, 216*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MFPU26, 0x12, 0), 0x0}, 217*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MU26, 0x01, 0), 0x0}, 218*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MU26, 0x01, 1), 0x0}, 219*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MU26, 0x01, 2), 0x0}, 220*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MU26, 0x01, 3), 0x0}, 221*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MU26, 0x01, 4), 0x0}, 222*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MU26, 0x01, 5), 0x0}, 223*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MU26, 0x01, 6), 0x0}, 224*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MU26, 0x01, 7), 0x0}, 225*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MU26, 0x06, 0), 0x0}, 226*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT23, 0x04, 0), 0x0}, 227*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT23, 0x08, 0), 0x0}, 228*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT24, 0x04, 0), 0x0}, 229*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT24, 0x08, 0), 0x0}, 230*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT24, 0x11, 0), 0x0}, 231*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT25, 0x04, 0), 0x0}, 232*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT25, 0x08, 0), 0x0}, 233*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT25, 0x11, 0), 0x0}, 234*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT28, 0x04, 0), 0x0}, 235*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT28, 0x08, 0), 0x0}, 236*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT28, 0x11, 0), 0x0}, 237*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x04, 0), 0x0}, 238*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x08, 0), 0x0}, 239*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x11, 0), 0x0}, 240*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 0), 0x0}, 241*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 1), 0x0}, 242*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 2), 0x0}, 243*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 3), 0x0}, 244*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 4), 0x0}, 245*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 5), 0x0}, 246*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 6), 0x0}, 247*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 7), 0x0}, 248*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 8), 0x0}, 249*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 9), 0x0}, 250*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 0xa), 0x0}, 251*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 0xb), 0x0}, 252*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 0xc), 0x0}, 253*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 0xd), 0x0}, 254*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 0xe), 0x0}, 255*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 0xf), 0x0}, 256*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PDE23, 0x1, 0), 0x3}, 257*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PDE23, 0x10, 0), 0x3}, 258*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PPU21, 0x06, 0), 0x0}, 259*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PPU21, 0x10, 0), 0x0}, 260*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PPU21, 0x11, 0), 0x0}, 261*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PPU21, 0x12, 0), 0x0}, 262*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PPU21, 0x13, 0), 0x0}, 263*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PPU26, 0x06, 0), 0x0}, 264*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PPU26, 0x10, 0), 0x0}, 265*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PPU26, 0x11, 0), 0x0}, 266*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PPU26, 0x12, 0), 0x0}, 267*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PPU26, 0x13, 0), 0x0}, 268*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_SAPU29, 0x05, 0), 0x0}, 269*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_SAPU29, 0x10, 0), 0x1}, 270*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_SAPU29, 0x11, 0), 0x0}, 271*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_SAPU29, 0x12, 0), 0x0}, 272*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_TG23, 0x10, 0), 0x0}, 273*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_XU22, 0x01, 0), 0x1}, 274*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_XU22, 0x06, 0), 0x0}, 275*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_XU22, 0x07, 0), 0x0}, 276*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_XU22, 0x08, 0), 0x0}, 277*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_XU22, 0x09, 0), 0x0}, 278*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_XU22, 0x0a, 0), 0x0}, 279*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_XU22, 0x10, 0), 0x1}, 280*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_XU22, 0x12, 0), 0x0}, 281*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_XU22, 0x13, 0), 0x0}, 282*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_XU22, 0x14, 0), 0x0}, 283*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_XU22, 0x15, 0), 0x0}, 284*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_XU22, 0x16, 0), 0x0}, 285*4cc9bd8dSNiranjan H Y {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_UDMPU23, 0x10, 0), 0x0}, 286*4cc9bd8dSNiranjan H Y }; 287*4cc9bd8dSNiranjan H Y 288*4cc9bd8dSNiranjan H Y static const struct reg_sequence tas2783_init_seq[] = { 289*4cc9bd8dSNiranjan H Y REG_SEQ0(SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PPU21, 0x10, 0x00), 0x04), 290*4cc9bd8dSNiranjan H Y REG_SEQ0(0x00800418, 0x00), 291*4cc9bd8dSNiranjan H Y REG_SEQ0(0x00800419, 0x00), 292*4cc9bd8dSNiranjan H Y REG_SEQ0(0x0080041a, 0x00), 293*4cc9bd8dSNiranjan H Y REG_SEQ0(0x0080041b, 0x00), 294*4cc9bd8dSNiranjan H Y REG_SEQ0(0x00800428, 0x40), 295*4cc9bd8dSNiranjan H Y REG_SEQ0(0x00800429, 0x00), 296*4cc9bd8dSNiranjan H Y REG_SEQ0(0x0080042a, 0x00), 297*4cc9bd8dSNiranjan H Y REG_SEQ0(0x0080042b, 0x00), 298*4cc9bd8dSNiranjan H Y REG_SEQ0(SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU23, 0x1, 0x00), 0x00), 299*4cc9bd8dSNiranjan H Y REG_SEQ0(0x0080005c, 0xD9), 300*4cc9bd8dSNiranjan H Y REG_SEQ0(0x00800082, 0x20), 301*4cc9bd8dSNiranjan H Y REG_SEQ0(0x008000a1, 0x00), 302*4cc9bd8dSNiranjan H Y REG_SEQ0(0x00800097, 0xc8), 303*4cc9bd8dSNiranjan H Y REG_SEQ0(0x00800099, 0x20), 304*4cc9bd8dSNiranjan H Y REG_SEQ0(0x008000c7, 0xaa), 305*4cc9bd8dSNiranjan H Y REG_SEQ0(0x008000b5, 0x74), 306*4cc9bd8dSNiranjan H Y REG_SEQ0(0x00800082, 0x20), 307*4cc9bd8dSNiranjan H Y REG_SEQ0(0x00807e8d, 0x0d), 308*4cc9bd8dSNiranjan H Y REG_SEQ0(0x00807eb9, 0x53), 309*4cc9bd8dSNiranjan H Y REG_SEQ0(0x00807ebe, 0x42), 310*4cc9bd8dSNiranjan H Y REG_SEQ0(0x00807ec5, 0x37), 311*4cc9bd8dSNiranjan H Y REG_SEQ0(0x00800066, 0x92), 312*4cc9bd8dSNiranjan H Y REG_SEQ0(0x00800003, 0x28), 313*4cc9bd8dSNiranjan H Y REG_SEQ0(0x00800004, 0x21), 314*4cc9bd8dSNiranjan H Y REG_SEQ0(0x00800005, 0x41), 315*4cc9bd8dSNiranjan H Y REG_SEQ0(0x00800006, 0x00), 316*4cc9bd8dSNiranjan H Y REG_SEQ0(0x00800007, 0x20), 317*4cc9bd8dSNiranjan H Y REG_SEQ0(0x0080000c, 0x10), 318*4cc9bd8dSNiranjan H Y REG_SEQ0(0x00800013, 0x08), 319*4cc9bd8dSNiranjan H Y REG_SEQ0(0x00800015, 0x00), 320*4cc9bd8dSNiranjan H Y REG_SEQ0(0x00800017, 0x80), 321*4cc9bd8dSNiranjan H Y REG_SEQ0(0x0080001a, 0x00), 322*4cc9bd8dSNiranjan H Y REG_SEQ0(0x0080001b, 0x22), 323*4cc9bd8dSNiranjan H Y REG_SEQ0(0x0080001c, 0x36), 324*4cc9bd8dSNiranjan H Y REG_SEQ0(0x0080001d, 0x01), 325*4cc9bd8dSNiranjan H Y REG_SEQ0(0x0080001f, 0x00), 326*4cc9bd8dSNiranjan H Y REG_SEQ0(0x00800020, 0x2e), 327*4cc9bd8dSNiranjan H Y REG_SEQ0(0x00800034, 0x06), 328*4cc9bd8dSNiranjan H Y REG_SEQ0(0x00800035, 0xb9), 329*4cc9bd8dSNiranjan H Y REG_SEQ0(0x00800036, 0xad), 330*4cc9bd8dSNiranjan H Y REG_SEQ0(0x00800037, 0xa8), 331*4cc9bd8dSNiranjan H Y REG_SEQ0(0x00800038, 0x00), 332*4cc9bd8dSNiranjan H Y REG_SEQ0(0x0080003b, 0xfc), 333*4cc9bd8dSNiranjan H Y REG_SEQ0(0x0080003d, 0xdd), 334*4cc9bd8dSNiranjan H Y REG_SEQ0(0x00800040, 0xf6), 335*4cc9bd8dSNiranjan H Y REG_SEQ0(0x00800041, 0x14), 336*4cc9bd8dSNiranjan H Y REG_SEQ0(0x0080005c, 0x19), 337*4cc9bd8dSNiranjan H Y REG_SEQ0(0x0080005d, 0x80), 338*4cc9bd8dSNiranjan H Y REG_SEQ0(0x00800063, 0x48), 339*4cc9bd8dSNiranjan H Y REG_SEQ0(0x00800065, 0x08), 340*4cc9bd8dSNiranjan H Y REG_SEQ0(0x00800067, 0x00), 341*4cc9bd8dSNiranjan H Y REG_SEQ0(0x0080006a, 0x12), 342*4cc9bd8dSNiranjan H Y REG_SEQ0(0x0080006b, 0x7b), 343*4cc9bd8dSNiranjan H Y REG_SEQ0(0x0080006c, 0x00), 344*4cc9bd8dSNiranjan H Y REG_SEQ0(0x0080006d, 0x00), 345*4cc9bd8dSNiranjan H Y REG_SEQ0(0x0080006e, 0x1a), 346*4cc9bd8dSNiranjan H Y REG_SEQ0(0x0080006f, 0x00), 347*4cc9bd8dSNiranjan H Y REG_SEQ0(0x00800070, 0x96), 348*4cc9bd8dSNiranjan H Y REG_SEQ0(0x00800071, 0x02), 349*4cc9bd8dSNiranjan H Y REG_SEQ0(0x00800073, 0x08), 350*4cc9bd8dSNiranjan H Y REG_SEQ0(0x00800075, 0xe0), 351*4cc9bd8dSNiranjan H Y REG_SEQ0(0x0080007a, 0x60), 352*4cc9bd8dSNiranjan H Y REG_SEQ0(0x008000bd, 0x00), 353*4cc9bd8dSNiranjan H Y REG_SEQ0(0x008000be, 0x00), 354*4cc9bd8dSNiranjan H Y REG_SEQ0(0x008000bf, 0x00), 355*4cc9bd8dSNiranjan H Y REG_SEQ0(0x008000c0, 0x00), 356*4cc9bd8dSNiranjan H Y REG_SEQ0(0x008000c1, 0x00), 357*4cc9bd8dSNiranjan H Y REG_SEQ0(0x008000c2, 0x00), 358*4cc9bd8dSNiranjan H Y REG_SEQ0(0x008000c3, 0x00), 359*4cc9bd8dSNiranjan H Y REG_SEQ0(0x008000c4, 0x00), 360*4cc9bd8dSNiranjan H Y REG_SEQ0(0x008000c5, 0x00), 361*4cc9bd8dSNiranjan H Y REG_SEQ0(0x00800008, 0x49), 362*4cc9bd8dSNiranjan H Y REG_SEQ0(0x00800009, 0x02), 363*4cc9bd8dSNiranjan H Y REG_SEQ0(0x0080000a, 0x1a), 364*4cc9bd8dSNiranjan H Y REG_SEQ0(0x0080000d, 0x93), 365*4cc9bd8dSNiranjan H Y REG_SEQ0(0x0080000e, 0x82), 366*4cc9bd8dSNiranjan H Y REG_SEQ0(0x0080000f, 0x42), 367*4cc9bd8dSNiranjan H Y REG_SEQ0(0x00800010, 0x84), 368*4cc9bd8dSNiranjan H Y REG_SEQ0(0x00800014, 0x0a), 369*4cc9bd8dSNiranjan H Y REG_SEQ0(0x00800016, 0x00), 370*4cc9bd8dSNiranjan H Y REG_SEQ0(0x00800060, 0x21), 371*4cc9bd8dSNiranjan H Y }; 372*4cc9bd8dSNiranjan H Y 373*4cc9bd8dSNiranjan H Y static int tas2783_sdca_mbq_size(struct device *dev, u32 reg) 374*4cc9bd8dSNiranjan H Y { 375*4cc9bd8dSNiranjan H Y switch (reg) { 376*4cc9bd8dSNiranjan H Y case 0x000 ... 0x080: /* Data port 0. */ 377*4cc9bd8dSNiranjan H Y case 0x100 ... 0x140: /* Data port 1. */ 378*4cc9bd8dSNiranjan H Y case 0x200 ... 0x240: /* Data port 2. */ 379*4cc9bd8dSNiranjan H Y case 0x300 ... 0x340: /* Data port 3. */ 380*4cc9bd8dSNiranjan H Y case 0x400 ... 0x440: /* Data port 4. */ 381*4cc9bd8dSNiranjan H Y case 0x500 ... 0x540: /* Data port 5. */ 382*4cc9bd8dSNiranjan H Y case 0x800000 ... 0x803fff: /* Page 0 ~ 127. */ 383*4cc9bd8dSNiranjan H Y case 0x807e80 ... 0x807eff: /* Page 253. */ 384*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_UDMPU23, 385*4cc9bd8dSNiranjan H Y TAS2783_SDCA_CTL_UDMPU_CLUSTER, 0): 386*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU21, TAS2783_SDCA_CTL_FU_MUTE, 387*4cc9bd8dSNiranjan H Y TAS2783_DEVICE_CHANNEL_LEFT): 388*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PDE23, 0x1, 0): 389*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PDE23, 0x10, 0): 390*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT21, 0x04, 0): 391*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_SAPU29, 0x10, 0): 392*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_SAPU29, 0x11, 0): 393*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_SAPU29, 0x12, 0): 394*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PPU21, 0x10, 0): 395*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PPU21, 0x11, 0): 396*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PPU26, 0x10, 0): 397*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PPU26, 0x11, 0): 398*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_TG23, 0x10, 0): 399*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_XU22, 0x01, 0): 400*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_XU22, 0x08, 0): 401*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_XU22, 0x0a, 0): 402*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_XU22, 0x10, 0): 403*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_XU22, 0x14, 0): 404*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_XU22, 0x15, 0): 405*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_XU22, 0x16, 0): 406*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT26, 0x04, 0): 407*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT28, 0x04, 0): 408*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT29, 0x04, 0): 409*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT23, 0x04, 0): 410*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT24, 0x04, 0): 411*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT28, 0x04, 0): 412*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x04, 0): 413*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 0): 414*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 1): 415*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 2): 416*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 3): 417*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 4): 418*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 5): 419*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 6): 420*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 7): 421*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 8): 422*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 9): 423*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 0xa): 424*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 0xb): 425*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 0xc): 426*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 0xd): 427*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 0xe): 428*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 0xf): 429*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_CS21, 0x02, 0): 430*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_CS21, 0x10, 0): 431*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_CS24, 0x02, 0): 432*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_CS24, 0x10, 0): 433*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_CS25, 0x02, 0): 434*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_CS25, 0x10, 0): 435*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_CS127, 0x02, 0): 436*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_CS127, 0x10, 0): 437*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_CS26, 0x02, 0): 438*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_CS26, 0x10, 0): 439*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_CS28, 0x02, 0): 440*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_CS28, 0x10, 0): 441*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MFPU21, 0x01, 0): 442*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MFPU21, 0x04, 0): 443*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MFPU21, 0x05, 0): 444*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MFPU21, 0x10, 0): 445*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MFPU21, 0x11, 0): 446*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU127, 0x01, 1): 447*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU127, 0x01, 2): 448*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU127, 0x01, 0): 449*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU26, 0x01, 1): 450*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU26, 0x01, 0): 451*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MFPU26, 0x01, 0): 452*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MFPU26, 0x04, 0): 453*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MFPU26, 0x05, 0): 454*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MFPU26, 0x10, 0): 455*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MFPU26, 0x11, 0): 456*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU23, 0x01, 0): 457*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU23, 0x01, 1): 458*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT25, 0x04, 0): 459*4cc9bd8dSNiranjan H Y return 1; 460*4cc9bd8dSNiranjan H Y 461*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT26, 0x10, 0): 462*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT26, 0x11, 0): 463*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT28, 0x10, 0): 464*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT28, 0x11, 0): 465*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT29, 0x10, 0): 466*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT29, 0x11, 0): 467*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT24, 0x11, 0): 468*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT25, 0x11, 0): 469*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT28, 0x11, 0): 470*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x11, 0): 471*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MU26, 0x01, 0): 472*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MU26, 0x01, 1): 473*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MU26, 0x01, 2): 474*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MU26, 0x01, 3): 475*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MU26, 0x01, 4): 476*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MU26, 0x01, 5): 477*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MU26, 0x01, 6): 478*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MU26, 0x01, 7): 479*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU21, 0x02, 1): 480*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU23, 0x0b, 1): 481*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU127, 0x0b, 1): 482*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU127, 0x0b, 2): 483*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU127, 0x0b, 0): 484*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU26, 0x0b, 0): 485*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU26, 0x0b, 1): 486*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_XU22, 0x07, 0): 487*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_XU22, 0x09, 0): 488*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MFPU21, 0x12, 0): 489*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MFPU26, 0x12, 0): 490*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PPU21, 0x12, 0): 491*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PPU21, 0x13, 0): 492*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PPU26, 0x12, 0): 493*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PPU26, 0x13, 0): 494*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT21, 0x10, 0): 495*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT21, 0x11, 0): 496*4cc9bd8dSNiranjan H Y return 2; 497*4cc9bd8dSNiranjan H Y 498*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU23, 0x10, 0): 499*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT21, 0x08, 0): 500*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT26, 0x08, 0): 501*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT28, 0x08, 0): 502*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT29, 0x08, 0): 503*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT23, 0x08, 0): 504*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT24, 0x08, 0): 505*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT25, 0x08, 0): 506*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT28, 0x08, 0): 507*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x08, 0): 508*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MU26, 0x06, 0): 509*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU127, 0x10, 0): 510*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU26, 0x10, 0): 511*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_XU22, 0x06, 0): 512*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_XU22, 0x12, 0): 513*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_XU22, 0x13, 0): 514*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MFPU21, 0x08, 0): 515*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MFPU26, 0x08, 0): 516*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_SAPU29, 0x05, 0): 517*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PPU21, 0x06, 0): 518*4cc9bd8dSNiranjan H Y case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PPU26, 0x06, 0): 519*4cc9bd8dSNiranjan H Y return 4; 520*4cc9bd8dSNiranjan H Y 521*4cc9bd8dSNiranjan H Y default: 522*4cc9bd8dSNiranjan H Y return 0; 523*4cc9bd8dSNiranjan H Y } 524*4cc9bd8dSNiranjan H Y } 525*4cc9bd8dSNiranjan H Y 526*4cc9bd8dSNiranjan H Y static bool tas2783_readable_register(struct device *dev, unsigned int reg) 527*4cc9bd8dSNiranjan H Y { 528*4cc9bd8dSNiranjan H Y return tas2783_sdca_mbq_size(dev, reg) > 0; 529*4cc9bd8dSNiranjan H Y } 530*4cc9bd8dSNiranjan H Y 531*4cc9bd8dSNiranjan H Y static bool tas2783_volatile_register(struct device *dev, u32 reg) 532*4cc9bd8dSNiranjan H Y { 533*4cc9bd8dSNiranjan H Y switch (reg) { 534*4cc9bd8dSNiranjan H Y case 0x000 ... 0x080: /* Data port 0. */ 535*4cc9bd8dSNiranjan H Y case 0x100 ... 0x140: /* Data port 1. */ 536*4cc9bd8dSNiranjan H Y case 0x200 ... 0x240: /* Data port 2. */ 537*4cc9bd8dSNiranjan H Y case 0x300 ... 0x340: /* Data port 3. */ 538*4cc9bd8dSNiranjan H Y case 0x400 ... 0x440: /* Data port 4. */ 539*4cc9bd8dSNiranjan H Y case 0x500 ... 0x540: /* Data port 5. */ 540*4cc9bd8dSNiranjan H Y case 0x800001: 541*4cc9bd8dSNiranjan H Y return true; 542*4cc9bd8dSNiranjan H Y 543*4cc9bd8dSNiranjan H Y default: 544*4cc9bd8dSNiranjan H Y return false; 545*4cc9bd8dSNiranjan H Y } 546*4cc9bd8dSNiranjan H Y } 547*4cc9bd8dSNiranjan H Y 548*4cc9bd8dSNiranjan H Y static const struct regmap_config tas_regmap = { 549*4cc9bd8dSNiranjan H Y .reg_bits = 32, 550*4cc9bd8dSNiranjan H Y .val_bits = 8, 551*4cc9bd8dSNiranjan H Y .readable_reg = tas2783_readable_register, 552*4cc9bd8dSNiranjan H Y .volatile_reg = tas2783_volatile_register, 553*4cc9bd8dSNiranjan H Y .reg_defaults = tas2783_reg_default, 554*4cc9bd8dSNiranjan H Y .num_reg_defaults = ARRAY_SIZE(tas2783_reg_default), 555*4cc9bd8dSNiranjan H Y .max_register = 0x41008000 + TASDEV_REG_SDW(0xa1, 0x60, 0x7f), 556*4cc9bd8dSNiranjan H Y .cache_type = REGCACHE_MAPLE, 557*4cc9bd8dSNiranjan H Y .use_single_read = true, 558*4cc9bd8dSNiranjan H Y .use_single_write = true, 559*4cc9bd8dSNiranjan H Y }; 560*4cc9bd8dSNiranjan H Y 561*4cc9bd8dSNiranjan H Y static const struct regmap_sdw_mbq_cfg tas2783_mbq_cfg = { 562*4cc9bd8dSNiranjan H Y .mbq_size = tas2783_sdca_mbq_size, 563*4cc9bd8dSNiranjan H Y }; 564*4cc9bd8dSNiranjan H Y 565*4cc9bd8dSNiranjan H Y static s32 tas2783_digital_getvol(struct snd_kcontrol *kcontrol, 566*4cc9bd8dSNiranjan H Y struct snd_ctl_elem_value *ucontrol) 567*4cc9bd8dSNiranjan H Y { 568*4cc9bd8dSNiranjan H Y return snd_soc_get_volsw(kcontrol, ucontrol); 569*4cc9bd8dSNiranjan H Y } 570*4cc9bd8dSNiranjan H Y 571*4cc9bd8dSNiranjan H Y static s32 tas2783_digital_putvol(struct snd_kcontrol *kcontrol, 572*4cc9bd8dSNiranjan H Y struct snd_ctl_elem_value *ucontrol) 573*4cc9bd8dSNiranjan H Y { 574*4cc9bd8dSNiranjan H Y return snd_soc_put_volsw(kcontrol, ucontrol); 575*4cc9bd8dSNiranjan H Y } 576*4cc9bd8dSNiranjan H Y 577*4cc9bd8dSNiranjan H Y static s32 tas2783_amp_getvol(struct snd_kcontrol *kcontrol, 578*4cc9bd8dSNiranjan H Y struct snd_ctl_elem_value *ucontrol) 579*4cc9bd8dSNiranjan H Y { 580*4cc9bd8dSNiranjan H Y return snd_soc_get_volsw(kcontrol, ucontrol); 581*4cc9bd8dSNiranjan H Y } 582*4cc9bd8dSNiranjan H Y 583*4cc9bd8dSNiranjan H Y static s32 tas2783_amp_putvol(struct snd_kcontrol *kcontrol, 584*4cc9bd8dSNiranjan H Y struct snd_ctl_elem_value *ucontrol) 585*4cc9bd8dSNiranjan H Y { 586*4cc9bd8dSNiranjan H Y return snd_soc_put_volsw(kcontrol, ucontrol); 587*4cc9bd8dSNiranjan H Y } 588*4cc9bd8dSNiranjan H Y 589*4cc9bd8dSNiranjan H Y static const struct snd_kcontrol_new tas2783_snd_controls[] = { 590*4cc9bd8dSNiranjan H Y SOC_SINGLE_RANGE_EXT_TLV("Amp Volume", TAS2783_AMP_LEVEL, 591*4cc9bd8dSNiranjan H Y 1, 0, 20, 0, tas2783_amp_getvol, 592*4cc9bd8dSNiranjan H Y tas2783_amp_putvol, tas2781_amp_tlv), 593*4cc9bd8dSNiranjan H Y SOC_SINGLE_RANGE_EXT_TLV("Speaker Volume", TAS2783_DVC_LVL, 594*4cc9bd8dSNiranjan H Y 0, 0, 200, 1, tas2783_digital_getvol, 595*4cc9bd8dSNiranjan H Y tas2783_digital_putvol, tas2781_dvc_tlv), 596*4cc9bd8dSNiranjan H Y }; 597*4cc9bd8dSNiranjan H Y 598*4cc9bd8dSNiranjan H Y static s32 tas2783_validate_calibdata(struct tas2783_prv *tas_dev, 599*4cc9bd8dSNiranjan H Y u8 *data, u32 size) 600*4cc9bd8dSNiranjan H Y { 601*4cc9bd8dSNiranjan H Y u32 ts, spk_count, size_calculated; 602*4cc9bd8dSNiranjan H Y u32 crc_calculated, crc_read, i; 603*4cc9bd8dSNiranjan H Y u32 *tmp_val; 604*4cc9bd8dSNiranjan H Y struct tm tm; 605*4cc9bd8dSNiranjan H Y 606*4cc9bd8dSNiranjan H Y i = 0; 607*4cc9bd8dSNiranjan H Y tmp_val = (u32 *)data; 608*4cc9bd8dSNiranjan H Y if (tmp_val[i++] != 2783) { 609*4cc9bd8dSNiranjan H Y dev_err(tas_dev->dev, "cal data magic number mismatch"); 610*4cc9bd8dSNiranjan H Y return -EINVAL; 611*4cc9bd8dSNiranjan H Y } 612*4cc9bd8dSNiranjan H Y 613*4cc9bd8dSNiranjan H Y spk_count = tmp_val[i++]; 614*4cc9bd8dSNiranjan H Y if (spk_count > TAS2783_CALIB_MAX_SPK_COUNT) { 615*4cc9bd8dSNiranjan H Y dev_err(tas_dev->dev, "cal data spk_count too large"); 616*4cc9bd8dSNiranjan H Y return -EINVAL; 617*4cc9bd8dSNiranjan H Y } 618*4cc9bd8dSNiranjan H Y 619*4cc9bd8dSNiranjan H Y ts = tmp_val[i++]; 620*4cc9bd8dSNiranjan H Y time64_to_tm(ts, 0, &tm); 621*4cc9bd8dSNiranjan H Y dev_dbg(tas_dev->dev, "cal data timestamp: %ld-%d-%d %d:%d:%d", 622*4cc9bd8dSNiranjan H Y tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, 623*4cc9bd8dSNiranjan H Y tm.tm_hour, tm.tm_min, tm.tm_sec); 624*4cc9bd8dSNiranjan H Y 625*4cc9bd8dSNiranjan H Y size_calculated = 626*4cc9bd8dSNiranjan H Y (spk_count * TAS2783_CALIB_PARAMS * sizeof(u32)) + 627*4cc9bd8dSNiranjan H Y TAS2783_CALIB_HDR_SZ + TAS2783_CALIB_CRC_SZ; 628*4cc9bd8dSNiranjan H Y if (size_calculated > TAS2783_CALIB_DATA_SZ) { 629*4cc9bd8dSNiranjan H Y dev_err(tas_dev->dev, "cali data sz too large"); 630*4cc9bd8dSNiranjan H Y return -EINVAL; 631*4cc9bd8dSNiranjan H Y } else if (size < size_calculated) { 632*4cc9bd8dSNiranjan H Y dev_err(tas_dev->dev, "cali data size mismatch calc=%u vs %d\n", 633*4cc9bd8dSNiranjan H Y size, size_calculated); 634*4cc9bd8dSNiranjan H Y return -EINVAL; 635*4cc9bd8dSNiranjan H Y } 636*4cc9bd8dSNiranjan H Y 637*4cc9bd8dSNiranjan H Y crc_calculated = crc32(~0, data, 638*4cc9bd8dSNiranjan H Y size_calculated - TAS2783_CALIB_CRC_SZ) ^ ~0; 639*4cc9bd8dSNiranjan H Y crc_read = tmp_val[(size_calculated - TAS2783_CALIB_CRC_SZ) / sizeof(u32)]; 640*4cc9bd8dSNiranjan H Y if (crc_calculated != crc_read) { 641*4cc9bd8dSNiranjan H Y dev_err(tas_dev->dev, 642*4cc9bd8dSNiranjan H Y "calib data integrity check fail, 0x%08x vs 0x%08x\n", 643*4cc9bd8dSNiranjan H Y crc_calculated, crc_read); 644*4cc9bd8dSNiranjan H Y return -EINVAL; 645*4cc9bd8dSNiranjan H Y } 646*4cc9bd8dSNiranjan H Y 647*4cc9bd8dSNiranjan H Y return 0; 648*4cc9bd8dSNiranjan H Y } 649*4cc9bd8dSNiranjan H Y 650*4cc9bd8dSNiranjan H Y static void tas2783_set_calib_params_to_device(struct tas2783_prv *tas_dev, u32 *cali_data) 651*4cc9bd8dSNiranjan H Y { 652*4cc9bd8dSNiranjan H Y u32 dev_count, offset, i, device_num; 653*4cc9bd8dSNiranjan H Y u32 reg_value; 654*4cc9bd8dSNiranjan H Y u8 buf[4]; 655*4cc9bd8dSNiranjan H Y 656*4cc9bd8dSNiranjan H Y dev_count = cali_data[1]; 657*4cc9bd8dSNiranjan H Y offset = 3; 658*4cc9bd8dSNiranjan H Y 659*4cc9bd8dSNiranjan H Y for (device_num = 0; device_num < dev_count; device_num++) { 660*4cc9bd8dSNiranjan H Y if (cali_data[offset] != tas_dev->sdw_peripheral->id.unique_id) { 661*4cc9bd8dSNiranjan H Y offset += TAS2783_CALIB_PARAMS; 662*4cc9bd8dSNiranjan H Y continue; 663*4cc9bd8dSNiranjan H Y } 664*4cc9bd8dSNiranjan H Y offset++; 665*4cc9bd8dSNiranjan H Y 666*4cc9bd8dSNiranjan H Y for (i = 0; i < ARRAY_SIZE(tas2783_cali_reg); i++) { 667*4cc9bd8dSNiranjan H Y reg_value = cali_data[offset + i]; 668*4cc9bd8dSNiranjan H Y buf[0] = reg_value >> 24; 669*4cc9bd8dSNiranjan H Y buf[1] = reg_value >> 16; 670*4cc9bd8dSNiranjan H Y buf[2] = reg_value >> 8; 671*4cc9bd8dSNiranjan H Y buf[3] = reg_value & 0xff; 672*4cc9bd8dSNiranjan H Y regmap_bulk_write(tas_dev->regmap, tas2783_cali_reg[i], 673*4cc9bd8dSNiranjan H Y buf, sizeof(u32)); 674*4cc9bd8dSNiranjan H Y } 675*4cc9bd8dSNiranjan H Y break; 676*4cc9bd8dSNiranjan H Y } 677*4cc9bd8dSNiranjan H Y 678*4cc9bd8dSNiranjan H Y if (device_num == dev_count) 679*4cc9bd8dSNiranjan H Y dev_err(tas_dev->dev, "device not found\n"); 680*4cc9bd8dSNiranjan H Y else 681*4cc9bd8dSNiranjan H Y dev_dbg(tas_dev->dev, "calib data update done\n"); 682*4cc9bd8dSNiranjan H Y } 683*4cc9bd8dSNiranjan H Y 684*4cc9bd8dSNiranjan H Y static s32 tas2783_update_calibdata(struct tas2783_prv *tas_dev) 685*4cc9bd8dSNiranjan H Y { 686*4cc9bd8dSNiranjan H Y efi_guid_t efi_guid = TAS2783_CALI_GUID; 687*4cc9bd8dSNiranjan H Y u32 attr, i, *tmp_val; 688*4cc9bd8dSNiranjan H Y unsigned long size; 689*4cc9bd8dSNiranjan H Y s32 ret; 690*4cc9bd8dSNiranjan H Y efi_status_t status; 691*4cc9bd8dSNiranjan H Y static efi_char16_t efi_names[][32] = { 692*4cc9bd8dSNiranjan H Y L"SmartAmpCalibrationData", L"CALI_DATA"}; 693*4cc9bd8dSNiranjan H Y 694*4cc9bd8dSNiranjan H Y tmp_val = (u32 *)tas_dev->cali_data.data; 695*4cc9bd8dSNiranjan H Y attr = 0; 696*4cc9bd8dSNiranjan H Y i = 0; 697*4cc9bd8dSNiranjan H Y 698*4cc9bd8dSNiranjan H Y /* 699*4cc9bd8dSNiranjan H Y * In some cases, the calibration is performed in Windows, 700*4cc9bd8dSNiranjan H Y * and data was saved in UEFI. Linux can access it. 701*4cc9bd8dSNiranjan H Y */ 702*4cc9bd8dSNiranjan H Y for (i = 0; i < ARRAY_SIZE(efi_names); i++) { 703*4cc9bd8dSNiranjan H Y size = 0; 704*4cc9bd8dSNiranjan H Y status = efi.get_variable(efi_names[i], &efi_guid, &attr, 705*4cc9bd8dSNiranjan H Y &size, NULL); 706*4cc9bd8dSNiranjan H Y if (size > TAS2783_CALIB_DATA_SZ) { 707*4cc9bd8dSNiranjan H Y dev_err(tas_dev->dev, "cali data too large\n"); 708*4cc9bd8dSNiranjan H Y break; 709*4cc9bd8dSNiranjan H Y } 710*4cc9bd8dSNiranjan H Y 711*4cc9bd8dSNiranjan H Y tas_dev->cali_data.read_sz = size; 712*4cc9bd8dSNiranjan H Y if (status == EFI_BUFFER_TOO_SMALL) { 713*4cc9bd8dSNiranjan H Y status = efi.get_variable(efi_names[i], &efi_guid, &attr, 714*4cc9bd8dSNiranjan H Y &tas_dev->cali_data.read_sz, 715*4cc9bd8dSNiranjan H Y tas_dev->cali_data.data); 716*4cc9bd8dSNiranjan H Y dev_dbg(tas_dev->dev, "cali get %lu bytes result:%ld\n", 717*4cc9bd8dSNiranjan H Y tas_dev->cali_data.read_sz, status); 718*4cc9bd8dSNiranjan H Y } 719*4cc9bd8dSNiranjan H Y if (status == EFI_SUCCESS) 720*4cc9bd8dSNiranjan H Y break; 721*4cc9bd8dSNiranjan H Y } 722*4cc9bd8dSNiranjan H Y 723*4cc9bd8dSNiranjan H Y if (status != EFI_SUCCESS) { 724*4cc9bd8dSNiranjan H Y /* Failed got calibration data from EFI. */ 725*4cc9bd8dSNiranjan H Y dev_dbg(tas_dev->dev, "No calibration data in UEFI."); 726*4cc9bd8dSNiranjan H Y return 0; 727*4cc9bd8dSNiranjan H Y } 728*4cc9bd8dSNiranjan H Y 729*4cc9bd8dSNiranjan H Y mutex_lock(&tas_dev->calib_lock); 730*4cc9bd8dSNiranjan H Y ret = tas2783_validate_calibdata(tas_dev, tas_dev->cali_data.data, 731*4cc9bd8dSNiranjan H Y tas_dev->cali_data.read_sz); 732*4cc9bd8dSNiranjan H Y if (!ret) 733*4cc9bd8dSNiranjan H Y tas2783_set_calib_params_to_device(tas_dev, tmp_val); 734*4cc9bd8dSNiranjan H Y mutex_unlock(&tas_dev->calib_lock); 735*4cc9bd8dSNiranjan H Y 736*4cc9bd8dSNiranjan H Y return ret; 737*4cc9bd8dSNiranjan H Y } 738*4cc9bd8dSNiranjan H Y 739*4cc9bd8dSNiranjan H Y static s32 read_header(const u8 *data, struct bin_header_t *hdr) 740*4cc9bd8dSNiranjan H Y { 741*4cc9bd8dSNiranjan H Y hdr->vendor_id = get_unaligned_le16(&data[0]); 742*4cc9bd8dSNiranjan H Y hdr->file_id = get_unaligned_le32(&data[2]); 743*4cc9bd8dSNiranjan H Y hdr->version = get_unaligned_le16(&data[6]); 744*4cc9bd8dSNiranjan H Y hdr->length = get_unaligned_le32(&data[8]); 745*4cc9bd8dSNiranjan H Y return 12; 746*4cc9bd8dSNiranjan H Y } 747*4cc9bd8dSNiranjan H Y 748*4cc9bd8dSNiranjan H Y static void tas2783_fw_ready(const struct firmware *fmw, void *context) 749*4cc9bd8dSNiranjan H Y { 750*4cc9bd8dSNiranjan H Y struct tas2783_prv *tas_dev = 751*4cc9bd8dSNiranjan H Y (struct tas2783_prv *)context; 752*4cc9bd8dSNiranjan H Y const u8 *buf = NULL; 753*4cc9bd8dSNiranjan H Y s32 offset = 0, img_sz, file_blk_size, ret; 754*4cc9bd8dSNiranjan H Y struct bin_header_t hdr; 755*4cc9bd8dSNiranjan H Y 756*4cc9bd8dSNiranjan H Y if (!fmw || !fmw->data) { 757*4cc9bd8dSNiranjan H Y /* No firmware binary, devices will work in ROM mode. */ 758*4cc9bd8dSNiranjan H Y dev_err(tas_dev->dev, 759*4cc9bd8dSNiranjan H Y "Failed to read %s, no side-effect on driver running\n", 760*4cc9bd8dSNiranjan H Y tas_dev->rca_binaryname); 761*4cc9bd8dSNiranjan H Y ret = -EINVAL; 762*4cc9bd8dSNiranjan H Y goto out; 763*4cc9bd8dSNiranjan H Y } 764*4cc9bd8dSNiranjan H Y 765*4cc9bd8dSNiranjan H Y mutex_lock(&tas_dev->pde_lock); 766*4cc9bd8dSNiranjan H Y img_sz = fmw->size; 767*4cc9bd8dSNiranjan H Y buf = fmw->data; 768*4cc9bd8dSNiranjan H Y offset += FW_DL_OFFSET; 769*4cc9bd8dSNiranjan H Y while (offset < (img_sz - FW_FL_HDR)) { 770*4cc9bd8dSNiranjan H Y memset(&hdr, 0, sizeof(hdr)); 771*4cc9bd8dSNiranjan H Y offset += read_header(&buf[offset], &hdr); 772*4cc9bd8dSNiranjan H Y dev_dbg(tas_dev->dev, 773*4cc9bd8dSNiranjan H Y "vndr=%d, file=%d, version=%d, len=%d, off=%d\n", 774*4cc9bd8dSNiranjan H Y hdr.vendor_id, hdr.file_id, hdr.version, 775*4cc9bd8dSNiranjan H Y hdr.length, offset); 776*4cc9bd8dSNiranjan H Y /* size also includes the header */ 777*4cc9bd8dSNiranjan H Y file_blk_size = hdr.length - FW_FL_HDR; 778*4cc9bd8dSNiranjan H Y 779*4cc9bd8dSNiranjan H Y switch (hdr.file_id) { 780*4cc9bd8dSNiranjan H Y case 0: 781*4cc9bd8dSNiranjan H Y ret = sdw_nwrite_no_pm(tas_dev->sdw_peripheral, 782*4cc9bd8dSNiranjan H Y PRAM_ADDR_START, file_blk_size, 783*4cc9bd8dSNiranjan H Y &buf[offset]); 784*4cc9bd8dSNiranjan H Y if (ret < 0) 785*4cc9bd8dSNiranjan H Y dev_err(tas_dev->dev, 786*4cc9bd8dSNiranjan H Y "PRAM update failed: %d", ret); 787*4cc9bd8dSNiranjan H Y break; 788*4cc9bd8dSNiranjan H Y 789*4cc9bd8dSNiranjan H Y case 1: 790*4cc9bd8dSNiranjan H Y ret = sdw_nwrite_no_pm(tas_dev->sdw_peripheral, 791*4cc9bd8dSNiranjan H Y YRAM_ADDR_START, file_blk_size, 792*4cc9bd8dSNiranjan H Y &buf[offset]); 793*4cc9bd8dSNiranjan H Y if (ret < 0) 794*4cc9bd8dSNiranjan H Y dev_err(tas_dev->dev, 795*4cc9bd8dSNiranjan H Y "YRAM update failed: %d", ret); 796*4cc9bd8dSNiranjan H Y 797*4cc9bd8dSNiranjan H Y break; 798*4cc9bd8dSNiranjan H Y 799*4cc9bd8dSNiranjan H Y default: 800*4cc9bd8dSNiranjan H Y ret = -EINVAL; 801*4cc9bd8dSNiranjan H Y dev_err(tas_dev->dev, "Unsupported file"); 802*4cc9bd8dSNiranjan H Y break; 803*4cc9bd8dSNiranjan H Y } 804*4cc9bd8dSNiranjan H Y 805*4cc9bd8dSNiranjan H Y if (ret == 0) 806*4cc9bd8dSNiranjan H Y offset += file_blk_size; 807*4cc9bd8dSNiranjan H Y else 808*4cc9bd8dSNiranjan H Y break; 809*4cc9bd8dSNiranjan H Y }; 810*4cc9bd8dSNiranjan H Y mutex_unlock(&tas_dev->pde_lock); 811*4cc9bd8dSNiranjan H Y tas2783_update_calibdata(tas_dev); 812*4cc9bd8dSNiranjan H Y 813*4cc9bd8dSNiranjan H Y out: 814*4cc9bd8dSNiranjan H Y if (!ret) 815*4cc9bd8dSNiranjan H Y tas_dev->fw_dl_success = true; 816*4cc9bd8dSNiranjan H Y tas_dev->fw_dl_task_done = true; 817*4cc9bd8dSNiranjan H Y wake_up(&tas_dev->fw_wait); 818*4cc9bd8dSNiranjan H Y if (fmw) 819*4cc9bd8dSNiranjan H Y release_firmware(fmw); 820*4cc9bd8dSNiranjan H Y } 821*4cc9bd8dSNiranjan H Y 822*4cc9bd8dSNiranjan H Y static inline s32 tas_clear_latch(struct tas2783_prv *priv) 823*4cc9bd8dSNiranjan H Y { 824*4cc9bd8dSNiranjan H Y return regmap_update_bits(priv->regmap, 825*4cc9bd8dSNiranjan H Y TASDEV_REG_SDW(0, 0, 0x5c), 826*4cc9bd8dSNiranjan H Y 0x04, 0x04); 827*4cc9bd8dSNiranjan H Y } 828*4cc9bd8dSNiranjan H Y 829*4cc9bd8dSNiranjan H Y static s32 tas_fu21_event(struct snd_soc_dapm_widget *w, 830*4cc9bd8dSNiranjan H Y struct snd_kcontrol *k, s32 event) 831*4cc9bd8dSNiranjan H Y { 832*4cc9bd8dSNiranjan H Y struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 833*4cc9bd8dSNiranjan H Y struct tas2783_prv *tas_dev = snd_soc_component_get_drvdata(component); 834*4cc9bd8dSNiranjan H Y s32 mute; 835*4cc9bd8dSNiranjan H Y 836*4cc9bd8dSNiranjan H Y switch (event) { 837*4cc9bd8dSNiranjan H Y case SND_SOC_DAPM_POST_PMU: 838*4cc9bd8dSNiranjan H Y mute = 0; 839*4cc9bd8dSNiranjan H Y break; 840*4cc9bd8dSNiranjan H Y 841*4cc9bd8dSNiranjan H Y case SND_SOC_DAPM_PRE_PMD: 842*4cc9bd8dSNiranjan H Y mute = 1; 843*4cc9bd8dSNiranjan H Y break; 844*4cc9bd8dSNiranjan H Y } 845*4cc9bd8dSNiranjan H Y 846*4cc9bd8dSNiranjan H Y return sdw_write_no_pm(tas_dev->sdw_peripheral, 847*4cc9bd8dSNiranjan H Y SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU21, 848*4cc9bd8dSNiranjan H Y TAS2783_SDCA_CTL_FU_MUTE, 1), mute); 849*4cc9bd8dSNiranjan H Y } 850*4cc9bd8dSNiranjan H Y 851*4cc9bd8dSNiranjan H Y static s32 tas_fu23_event(struct snd_soc_dapm_widget *w, 852*4cc9bd8dSNiranjan H Y struct snd_kcontrol *k, s32 event) 853*4cc9bd8dSNiranjan H Y { 854*4cc9bd8dSNiranjan H Y struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 855*4cc9bd8dSNiranjan H Y struct tas2783_prv *tas_dev = snd_soc_component_get_drvdata(component); 856*4cc9bd8dSNiranjan H Y s32 mute; 857*4cc9bd8dSNiranjan H Y 858*4cc9bd8dSNiranjan H Y switch (event) { 859*4cc9bd8dSNiranjan H Y case SND_SOC_DAPM_POST_PMU: 860*4cc9bd8dSNiranjan H Y mute = 0; 861*4cc9bd8dSNiranjan H Y break; 862*4cc9bd8dSNiranjan H Y 863*4cc9bd8dSNiranjan H Y case SND_SOC_DAPM_PRE_PMD: 864*4cc9bd8dSNiranjan H Y mute = 1; 865*4cc9bd8dSNiranjan H Y break; 866*4cc9bd8dSNiranjan H Y } 867*4cc9bd8dSNiranjan H Y 868*4cc9bd8dSNiranjan H Y return sdw_write_no_pm(tas_dev->sdw_peripheral, 869*4cc9bd8dSNiranjan H Y SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU23, 870*4cc9bd8dSNiranjan H Y TAS2783_SDCA_CTL_FU_MUTE, 1), mute); 871*4cc9bd8dSNiranjan H Y } 872*4cc9bd8dSNiranjan H Y 873*4cc9bd8dSNiranjan H Y static const struct snd_soc_dapm_widget tas_dapm_widgets[] = { 874*4cc9bd8dSNiranjan H Y SND_SOC_DAPM_AIF_IN("ASI", "ASI Playback", 0, SND_SOC_NOPM, 0, 0), 875*4cc9bd8dSNiranjan H Y SND_SOC_DAPM_AIF_OUT("ASI OUT", "ASI Capture", 0, SND_SOC_NOPM, 876*4cc9bd8dSNiranjan H Y 0, 0), 877*4cc9bd8dSNiranjan H Y SND_SOC_DAPM_DAC_E("FU21", NULL, SND_SOC_NOPM, 0, 0, tas_fu21_event, 878*4cc9bd8dSNiranjan H Y SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), 879*4cc9bd8dSNiranjan H Y SND_SOC_DAPM_DAC_E("FU23", NULL, SND_SOC_NOPM, 0, 0, tas_fu23_event, 880*4cc9bd8dSNiranjan H Y SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), 881*4cc9bd8dSNiranjan H Y SND_SOC_DAPM_OUTPUT("SPK"), 882*4cc9bd8dSNiranjan H Y SND_SOC_DAPM_INPUT("DMIC"), 883*4cc9bd8dSNiranjan H Y }; 884*4cc9bd8dSNiranjan H Y 885*4cc9bd8dSNiranjan H Y static const struct snd_soc_dapm_route tas_audio_map[] = { 886*4cc9bd8dSNiranjan H Y {"FU21", NULL, "ASI"}, 887*4cc9bd8dSNiranjan H Y {"SPK", NULL, "FU21"}, 888*4cc9bd8dSNiranjan H Y {"FU23", NULL, "ASI"}, 889*4cc9bd8dSNiranjan H Y {"SPK", NULL, "FU23"}, 890*4cc9bd8dSNiranjan H Y {"ASI OUT", NULL, "DMIC"}, 891*4cc9bd8dSNiranjan H Y }; 892*4cc9bd8dSNiranjan H Y 893*4cc9bd8dSNiranjan H Y static s32 tas_set_sdw_stream(struct snd_soc_dai *dai, 894*4cc9bd8dSNiranjan H Y void *sdw_stream, s32 direction) 895*4cc9bd8dSNiranjan H Y { 896*4cc9bd8dSNiranjan H Y if (!sdw_stream) 897*4cc9bd8dSNiranjan H Y return 0; 898*4cc9bd8dSNiranjan H Y 899*4cc9bd8dSNiranjan H Y snd_soc_dai_dma_data_set(dai, direction, sdw_stream); 900*4cc9bd8dSNiranjan H Y 901*4cc9bd8dSNiranjan H Y return 0; 902*4cc9bd8dSNiranjan H Y } 903*4cc9bd8dSNiranjan H Y 904*4cc9bd8dSNiranjan H Y static void tas_sdw_shutdown(struct snd_pcm_substream *substream, 905*4cc9bd8dSNiranjan H Y struct snd_soc_dai *dai) 906*4cc9bd8dSNiranjan H Y { 907*4cc9bd8dSNiranjan H Y snd_soc_dai_set_dma_data(dai, substream, NULL); 908*4cc9bd8dSNiranjan H Y } 909*4cc9bd8dSNiranjan H Y 910*4cc9bd8dSNiranjan H Y static s32 tas_sdw_hw_params(struct snd_pcm_substream *substream, 911*4cc9bd8dSNiranjan H Y struct snd_pcm_hw_params *params, 912*4cc9bd8dSNiranjan H Y struct snd_soc_dai *dai) 913*4cc9bd8dSNiranjan H Y { 914*4cc9bd8dSNiranjan H Y struct snd_soc_component *component = dai->component; 915*4cc9bd8dSNiranjan H Y struct tas2783_prv *tas_dev = 916*4cc9bd8dSNiranjan H Y snd_soc_component_get_drvdata(component); 917*4cc9bd8dSNiranjan H Y struct sdw_stream_config stream_config = {0}; 918*4cc9bd8dSNiranjan H Y struct sdw_port_config port_config = {0}; 919*4cc9bd8dSNiranjan H Y struct sdw_stream_runtime *sdw_stream; 920*4cc9bd8dSNiranjan H Y struct sdw_slave *sdw_peripheral = tas_dev->sdw_peripheral; 921*4cc9bd8dSNiranjan H Y s32 ret, retry = 3; 922*4cc9bd8dSNiranjan H Y 923*4cc9bd8dSNiranjan H Y if (!tas_dev->fw_dl_success) { 924*4cc9bd8dSNiranjan H Y dev_err(tas_dev->dev, "error playback without fw download"); 925*4cc9bd8dSNiranjan H Y return -EINVAL; 926*4cc9bd8dSNiranjan H Y } 927*4cc9bd8dSNiranjan H Y 928*4cc9bd8dSNiranjan H Y sdw_stream = snd_soc_dai_get_dma_data(dai, substream); 929*4cc9bd8dSNiranjan H Y if (!sdw_stream) 930*4cc9bd8dSNiranjan H Y return -EINVAL; 931*4cc9bd8dSNiranjan H Y 932*4cc9bd8dSNiranjan H Y ret = tas_clear_latch(tas_dev); 933*4cc9bd8dSNiranjan H Y if (ret) 934*4cc9bd8dSNiranjan H Y dev_err(tas_dev->dev, 935*4cc9bd8dSNiranjan H Y "clear latch failed, err=%d", ret); 936*4cc9bd8dSNiranjan H Y 937*4cc9bd8dSNiranjan H Y mutex_lock(&tas_dev->pde_lock); 938*4cc9bd8dSNiranjan H Y /* 939*4cc9bd8dSNiranjan H Y * Sometimes, there is error returned during power on. 940*4cc9bd8dSNiranjan H Y * So added retry logic to ensure power on so that 941*4cc9bd8dSNiranjan H Y * port prepare succeeds 942*4cc9bd8dSNiranjan H Y */ 943*4cc9bd8dSNiranjan H Y do { 944*4cc9bd8dSNiranjan H Y ret = regmap_write(tas_dev->regmap, 945*4cc9bd8dSNiranjan H Y SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PDE23, 946*4cc9bd8dSNiranjan H Y TAS2783_SDCA_CTL_REQ_POW_STATE, 0), 947*4cc9bd8dSNiranjan H Y TAS2783_SDCA_POW_STATE_ON); 948*4cc9bd8dSNiranjan H Y if (!ret) 949*4cc9bd8dSNiranjan H Y break; 950*4cc9bd8dSNiranjan H Y usleep_range(2000, 2200); 951*4cc9bd8dSNiranjan H Y } while (retry--); 952*4cc9bd8dSNiranjan H Y mutex_unlock(&tas_dev->pde_lock); 953*4cc9bd8dSNiranjan H Y if (ret) 954*4cc9bd8dSNiranjan H Y return ret; 955*4cc9bd8dSNiranjan H Y 956*4cc9bd8dSNiranjan H Y /* SoundWire specific configuration */ 957*4cc9bd8dSNiranjan H Y snd_sdw_params_to_config(substream, params, 958*4cc9bd8dSNiranjan H Y &stream_config, &port_config); 959*4cc9bd8dSNiranjan H Y /* port 1 for playback */ 960*4cc9bd8dSNiranjan H Y if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 961*4cc9bd8dSNiranjan H Y port_config.num = 1; 962*4cc9bd8dSNiranjan H Y else 963*4cc9bd8dSNiranjan H Y port_config.num = 2; 964*4cc9bd8dSNiranjan H Y 965*4cc9bd8dSNiranjan H Y ret = sdw_stream_add_slave(sdw_peripheral, 966*4cc9bd8dSNiranjan H Y &stream_config, &port_config, 1, sdw_stream); 967*4cc9bd8dSNiranjan H Y if (ret) 968*4cc9bd8dSNiranjan H Y dev_err(dai->dev, "Unable to configure port\n"); 969*4cc9bd8dSNiranjan H Y 970*4cc9bd8dSNiranjan H Y return ret; 971*4cc9bd8dSNiranjan H Y } 972*4cc9bd8dSNiranjan H Y 973*4cc9bd8dSNiranjan H Y static s32 tas_sdw_pcm_hw_free(struct snd_pcm_substream *substream, 974*4cc9bd8dSNiranjan H Y struct snd_soc_dai *dai) 975*4cc9bd8dSNiranjan H Y { 976*4cc9bd8dSNiranjan H Y s32 ret; 977*4cc9bd8dSNiranjan H Y struct snd_soc_component *component = dai->component; 978*4cc9bd8dSNiranjan H Y struct tas2783_prv *tas_dev = 979*4cc9bd8dSNiranjan H Y snd_soc_component_get_drvdata(component); 980*4cc9bd8dSNiranjan H Y struct sdw_stream_runtime *sdw_stream = 981*4cc9bd8dSNiranjan H Y snd_soc_dai_get_dma_data(dai, substream); 982*4cc9bd8dSNiranjan H Y 983*4cc9bd8dSNiranjan H Y sdw_stream_remove_slave(tas_dev->sdw_peripheral, sdw_stream); 984*4cc9bd8dSNiranjan H Y 985*4cc9bd8dSNiranjan H Y mutex_lock(&tas_dev->pde_lock); 986*4cc9bd8dSNiranjan H Y ret = regmap_write(tas_dev->regmap, 987*4cc9bd8dSNiranjan H Y SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PDE23, 988*4cc9bd8dSNiranjan H Y TAS2783_SDCA_CTL_REQ_POW_STATE, 0), 989*4cc9bd8dSNiranjan H Y TAS2783_SDCA_POW_STATE_OFF); 990*4cc9bd8dSNiranjan H Y mutex_unlock(&tas_dev->pde_lock); 991*4cc9bd8dSNiranjan H Y 992*4cc9bd8dSNiranjan H Y return ret; 993*4cc9bd8dSNiranjan H Y } 994*4cc9bd8dSNiranjan H Y 995*4cc9bd8dSNiranjan H Y static const struct snd_soc_dai_ops tas_dai_ops = { 996*4cc9bd8dSNiranjan H Y .hw_params = tas_sdw_hw_params, 997*4cc9bd8dSNiranjan H Y .hw_free = tas_sdw_pcm_hw_free, 998*4cc9bd8dSNiranjan H Y .set_stream = tas_set_sdw_stream, 999*4cc9bd8dSNiranjan H Y .shutdown = tas_sdw_shutdown, 1000*4cc9bd8dSNiranjan H Y }; 1001*4cc9bd8dSNiranjan H Y 1002*4cc9bd8dSNiranjan H Y static struct snd_soc_dai_driver tas_dai_driver[] = { 1003*4cc9bd8dSNiranjan H Y { 1004*4cc9bd8dSNiranjan H Y .name = "tas2783-codec", 1005*4cc9bd8dSNiranjan H Y .id = 0, 1006*4cc9bd8dSNiranjan H Y .playback = { 1007*4cc9bd8dSNiranjan H Y .stream_name = "Playback", 1008*4cc9bd8dSNiranjan H Y .channels_min = 1, 1009*4cc9bd8dSNiranjan H Y .channels_max = 4, 1010*4cc9bd8dSNiranjan H Y .rates = TAS2783_DEVICE_RATES, 1011*4cc9bd8dSNiranjan H Y .formats = TAS2783_DEVICE_FORMATS, 1012*4cc9bd8dSNiranjan H Y }, 1013*4cc9bd8dSNiranjan H Y .capture = { 1014*4cc9bd8dSNiranjan H Y .stream_name = "Capture", 1015*4cc9bd8dSNiranjan H Y .channels_min = 1, 1016*4cc9bd8dSNiranjan H Y .channels_max = 4, 1017*4cc9bd8dSNiranjan H Y .rates = TAS2783_DEVICE_RATES, 1018*4cc9bd8dSNiranjan H Y .formats = TAS2783_DEVICE_FORMATS, 1019*4cc9bd8dSNiranjan H Y }, 1020*4cc9bd8dSNiranjan H Y .ops = &tas_dai_ops, 1021*4cc9bd8dSNiranjan H Y .symmetric_rate = 1, 1022*4cc9bd8dSNiranjan H Y }, 1023*4cc9bd8dSNiranjan H Y }; 1024*4cc9bd8dSNiranjan H Y 1025*4cc9bd8dSNiranjan H Y static s32 tas_component_probe(struct snd_soc_component *component) 1026*4cc9bd8dSNiranjan H Y { 1027*4cc9bd8dSNiranjan H Y struct tas2783_prv *tas_dev = 1028*4cc9bd8dSNiranjan H Y snd_soc_component_get_drvdata(component); 1029*4cc9bd8dSNiranjan H Y 1030*4cc9bd8dSNiranjan H Y tas_dev->component = component; 1031*4cc9bd8dSNiranjan H Y tas25xx_register_misc(tas_dev->sdw_peripheral); 1032*4cc9bd8dSNiranjan H Y 1033*4cc9bd8dSNiranjan H Y return 0; 1034*4cc9bd8dSNiranjan H Y } 1035*4cc9bd8dSNiranjan H Y 1036*4cc9bd8dSNiranjan H Y static void tas_component_remove(struct snd_soc_component *codec) 1037*4cc9bd8dSNiranjan H Y { 1038*4cc9bd8dSNiranjan H Y struct tas2783_prv *tas_dev = 1039*4cc9bd8dSNiranjan H Y snd_soc_component_get_drvdata(codec); 1040*4cc9bd8dSNiranjan H Y tas25xx_deregister_misc(); 1041*4cc9bd8dSNiranjan H Y tas_dev->component = NULL; 1042*4cc9bd8dSNiranjan H Y } 1043*4cc9bd8dSNiranjan H Y 1044*4cc9bd8dSNiranjan H Y static const struct snd_soc_component_driver soc_codec_driver_tasdevice = { 1045*4cc9bd8dSNiranjan H Y .probe = tas_component_probe, 1046*4cc9bd8dSNiranjan H Y .remove = tas_component_remove, 1047*4cc9bd8dSNiranjan H Y .controls = tas2783_snd_controls, 1048*4cc9bd8dSNiranjan H Y .num_controls = ARRAY_SIZE(tas2783_snd_controls), 1049*4cc9bd8dSNiranjan H Y .dapm_widgets = tas_dapm_widgets, 1050*4cc9bd8dSNiranjan H Y .num_dapm_widgets = ARRAY_SIZE(tas_dapm_widgets), 1051*4cc9bd8dSNiranjan H Y .dapm_routes = tas_audio_map, 1052*4cc9bd8dSNiranjan H Y .num_dapm_routes = ARRAY_SIZE(tas_audio_map), 1053*4cc9bd8dSNiranjan H Y .idle_bias_on = 1, 1054*4cc9bd8dSNiranjan H Y .endianness = 1, 1055*4cc9bd8dSNiranjan H Y }; 1056*4cc9bd8dSNiranjan H Y 1057*4cc9bd8dSNiranjan H Y static s32 tas_init(struct tas2783_prv *tas_dev) 1058*4cc9bd8dSNiranjan H Y { 1059*4cc9bd8dSNiranjan H Y s32 ret; 1060*4cc9bd8dSNiranjan H Y 1061*4cc9bd8dSNiranjan H Y dev_set_drvdata(tas_dev->dev, tas_dev); 1062*4cc9bd8dSNiranjan H Y ret = devm_snd_soc_register_component(tas_dev->dev, 1063*4cc9bd8dSNiranjan H Y &soc_codec_driver_tasdevice, 1064*4cc9bd8dSNiranjan H Y tas_dai_driver, 1065*4cc9bd8dSNiranjan H Y ARRAY_SIZE(tas_dai_driver)); 1066*4cc9bd8dSNiranjan H Y if (ret) { 1067*4cc9bd8dSNiranjan H Y dev_err(tas_dev->dev, "%s: codec register error:%d.\n", 1068*4cc9bd8dSNiranjan H Y __func__, ret); 1069*4cc9bd8dSNiranjan H Y return ret; 1070*4cc9bd8dSNiranjan H Y } 1071*4cc9bd8dSNiranjan H Y 1072*4cc9bd8dSNiranjan H Y /* set autosuspend parameters */ 1073*4cc9bd8dSNiranjan H Y pm_runtime_set_autosuspend_delay(tas_dev->dev, 3000); 1074*4cc9bd8dSNiranjan H Y pm_runtime_use_autosuspend(tas_dev->dev); 1075*4cc9bd8dSNiranjan H Y /* make sure the device does not suspend immediately */ 1076*4cc9bd8dSNiranjan H Y pm_runtime_mark_last_busy(tas_dev->dev); 1077*4cc9bd8dSNiranjan H Y pm_runtime_enable(tas_dev->dev); 1078*4cc9bd8dSNiranjan H Y 1079*4cc9bd8dSNiranjan H Y return ret; 1080*4cc9bd8dSNiranjan H Y } 1081*4cc9bd8dSNiranjan H Y 1082*4cc9bd8dSNiranjan H Y static s32 tas_read_prop(struct sdw_slave *slave) 1083*4cc9bd8dSNiranjan H Y { 1084*4cc9bd8dSNiranjan H Y struct sdw_slave_prop *prop = &slave->prop; 1085*4cc9bd8dSNiranjan H Y s32 nval; 1086*4cc9bd8dSNiranjan H Y s32 i, j; 1087*4cc9bd8dSNiranjan H Y u32 bit; 1088*4cc9bd8dSNiranjan H Y unsigned long addr; 1089*4cc9bd8dSNiranjan H Y struct sdw_dpn_prop *dpn; 1090*4cc9bd8dSNiranjan H Y 1091*4cc9bd8dSNiranjan H Y prop->scp_int1_mask = 1092*4cc9bd8dSNiranjan H Y SDW_SCP_INT1_BUS_CLASH | SDW_SCP_INT1_PARITY; 1093*4cc9bd8dSNiranjan H Y prop->quirks = SDW_SLAVE_QUIRKS_INVALID_INITIAL_PARITY; 1094*4cc9bd8dSNiranjan H Y 1095*4cc9bd8dSNiranjan H Y prop->paging_support = true; 1096*4cc9bd8dSNiranjan H Y 1097*4cc9bd8dSNiranjan H Y /* first we need to allocate memory for set bits in port lists */ 1098*4cc9bd8dSNiranjan H Y prop->source_ports = 0x04; /* BITMAP: 00000100 */ 1099*4cc9bd8dSNiranjan H Y prop->sink_ports = 0x2; /* BITMAP: 00000010 */ 1100*4cc9bd8dSNiranjan H Y 1101*4cc9bd8dSNiranjan H Y nval = hweight32(prop->source_ports); 1102*4cc9bd8dSNiranjan H Y prop->src_dpn_prop = devm_kcalloc(&slave->dev, nval, 1103*4cc9bd8dSNiranjan H Y sizeof(*prop->src_dpn_prop), GFP_KERNEL); 1104*4cc9bd8dSNiranjan H Y if (!prop->src_dpn_prop) 1105*4cc9bd8dSNiranjan H Y return -ENOMEM; 1106*4cc9bd8dSNiranjan H Y 1107*4cc9bd8dSNiranjan H Y i = 0; 1108*4cc9bd8dSNiranjan H Y dpn = prop->src_dpn_prop; 1109*4cc9bd8dSNiranjan H Y addr = prop->source_ports; 1110*4cc9bd8dSNiranjan H Y for_each_set_bit(bit, &addr, 32) { 1111*4cc9bd8dSNiranjan H Y dpn[i].num = bit; 1112*4cc9bd8dSNiranjan H Y dpn[i].type = SDW_DPN_FULL; 1113*4cc9bd8dSNiranjan H Y dpn[i].simple_ch_prep_sm = false; 1114*4cc9bd8dSNiranjan H Y dpn[i].ch_prep_timeout = 10; 1115*4cc9bd8dSNiranjan H Y i++; 1116*4cc9bd8dSNiranjan H Y } 1117*4cc9bd8dSNiranjan H Y 1118*4cc9bd8dSNiranjan H Y /* do this again for sink now */ 1119*4cc9bd8dSNiranjan H Y nval = hweight32(prop->sink_ports); 1120*4cc9bd8dSNiranjan H Y prop->sink_dpn_prop = devm_kcalloc(&slave->dev, nval, 1121*4cc9bd8dSNiranjan H Y sizeof(*prop->sink_dpn_prop), GFP_KERNEL); 1122*4cc9bd8dSNiranjan H Y if (!prop->sink_dpn_prop) 1123*4cc9bd8dSNiranjan H Y return -ENOMEM; 1124*4cc9bd8dSNiranjan H Y 1125*4cc9bd8dSNiranjan H Y j = 0; 1126*4cc9bd8dSNiranjan H Y dpn = prop->sink_dpn_prop; 1127*4cc9bd8dSNiranjan H Y addr = prop->sink_ports; 1128*4cc9bd8dSNiranjan H Y for_each_set_bit(bit, &addr, 32) { 1129*4cc9bd8dSNiranjan H Y dpn[j].num = bit; 1130*4cc9bd8dSNiranjan H Y dpn[j].type = SDW_DPN_FULL; 1131*4cc9bd8dSNiranjan H Y dpn[j].simple_ch_prep_sm = false; 1132*4cc9bd8dSNiranjan H Y dpn[j].ch_prep_timeout = 10; 1133*4cc9bd8dSNiranjan H Y j++; 1134*4cc9bd8dSNiranjan H Y } 1135*4cc9bd8dSNiranjan H Y 1136*4cc9bd8dSNiranjan H Y /* set the timeout values */ 1137*4cc9bd8dSNiranjan H Y prop->clk_stop_timeout = 200; 1138*4cc9bd8dSNiranjan H Y 1139*4cc9bd8dSNiranjan H Y return 0; 1140*4cc9bd8dSNiranjan H Y } 1141*4cc9bd8dSNiranjan H Y 1142*4cc9bd8dSNiranjan H Y static s32 tas2783_sdca_dev_suspend(struct device *dev) 1143*4cc9bd8dSNiranjan H Y { 1144*4cc9bd8dSNiranjan H Y struct tas2783_prv *tas_dev = dev_get_drvdata(dev); 1145*4cc9bd8dSNiranjan H Y 1146*4cc9bd8dSNiranjan H Y if (!tas_dev->hw_init) 1147*4cc9bd8dSNiranjan H Y return 0; 1148*4cc9bd8dSNiranjan H Y 1149*4cc9bd8dSNiranjan H Y regcache_cache_only(tas_dev->regmap, true); 1150*4cc9bd8dSNiranjan H Y return 0; 1151*4cc9bd8dSNiranjan H Y } 1152*4cc9bd8dSNiranjan H Y 1153*4cc9bd8dSNiranjan H Y static s32 tas2783_sdca_dev_system_suspend(struct device *dev) 1154*4cc9bd8dSNiranjan H Y { 1155*4cc9bd8dSNiranjan H Y return tas2783_sdca_dev_suspend(dev); 1156*4cc9bd8dSNiranjan H Y } 1157*4cc9bd8dSNiranjan H Y 1158*4cc9bd8dSNiranjan H Y static s32 tas2783_sdca_dev_resume(struct device *dev) 1159*4cc9bd8dSNiranjan H Y { 1160*4cc9bd8dSNiranjan H Y struct sdw_slave *slave = dev_to_sdw_dev(dev); 1161*4cc9bd8dSNiranjan H Y struct tas2783_prv *tas_dev = dev_get_drvdata(dev); 1162*4cc9bd8dSNiranjan H Y unsigned long t; 1163*4cc9bd8dSNiranjan H Y 1164*4cc9bd8dSNiranjan H Y if (!slave->unattach_request) 1165*4cc9bd8dSNiranjan H Y goto regmap_sync; 1166*4cc9bd8dSNiranjan H Y 1167*4cc9bd8dSNiranjan H Y t = wait_for_completion_timeout(&slave->initialization_complete, 1168*4cc9bd8dSNiranjan H Y msecs_to_jiffies(TAS2783_PROBE_TIMEOUT)); 1169*4cc9bd8dSNiranjan H Y if (!t) { 1170*4cc9bd8dSNiranjan H Y dev_err(&slave->dev, "resume: initialization timed out\n"); 1171*4cc9bd8dSNiranjan H Y sdw_show_ping_status(slave->bus, true); 1172*4cc9bd8dSNiranjan H Y return -ETIMEDOUT; 1173*4cc9bd8dSNiranjan H Y } 1174*4cc9bd8dSNiranjan H Y 1175*4cc9bd8dSNiranjan H Y slave->unattach_request = 0; 1176*4cc9bd8dSNiranjan H Y 1177*4cc9bd8dSNiranjan H Y regmap_sync: 1178*4cc9bd8dSNiranjan H Y regcache_cache_only(tas_dev->regmap, false); 1179*4cc9bd8dSNiranjan H Y regcache_sync(tas_dev->regmap); 1180*4cc9bd8dSNiranjan H Y return 0; 1181*4cc9bd8dSNiranjan H Y } 1182*4cc9bd8dSNiranjan H Y 1183*4cc9bd8dSNiranjan H Y static const struct dev_pm_ops tas2783_sdca_pm = { 1184*4cc9bd8dSNiranjan H Y SYSTEM_SLEEP_PM_OPS(tas2783_sdca_dev_system_suspend, tas2783_sdca_dev_resume) 1185*4cc9bd8dSNiranjan H Y RUNTIME_PM_OPS(tas2783_sdca_dev_suspend, tas2783_sdca_dev_resume, NULL) 1186*4cc9bd8dSNiranjan H Y }; 1187*4cc9bd8dSNiranjan H Y 1188*4cc9bd8dSNiranjan H Y static s32 tas_io_init(struct device *dev, struct sdw_slave *slave) 1189*4cc9bd8dSNiranjan H Y { 1190*4cc9bd8dSNiranjan H Y struct tas2783_prv *tas_dev = dev_get_drvdata(dev); 1191*4cc9bd8dSNiranjan H Y s32 ret; 1192*4cc9bd8dSNiranjan H Y u8 unique_id = tas_dev->sdw_peripheral->id.unique_id; 1193*4cc9bd8dSNiranjan H Y 1194*4cc9bd8dSNiranjan H Y if (tas_dev->hw_init) 1195*4cc9bd8dSNiranjan H Y return 0; 1196*4cc9bd8dSNiranjan H Y 1197*4cc9bd8dSNiranjan H Y tas_dev->fw_dl_task_done = false; 1198*4cc9bd8dSNiranjan H Y tas_dev->fw_dl_success = false; 1199*4cc9bd8dSNiranjan H Y scnprintf(tas_dev->rca_binaryname, sizeof(tas_dev->rca_binaryname), 1200*4cc9bd8dSNiranjan H Y "tas2783-%01x.bin", unique_id); 1201*4cc9bd8dSNiranjan H Y 1202*4cc9bd8dSNiranjan H Y ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_UEVENT, 1203*4cc9bd8dSNiranjan H Y tas_dev->rca_binaryname, tas_dev->dev, 1204*4cc9bd8dSNiranjan H Y GFP_KERNEL, tas_dev, tas2783_fw_ready); 1205*4cc9bd8dSNiranjan H Y if (ret) { 1206*4cc9bd8dSNiranjan H Y dev_err(tas_dev->dev, 1207*4cc9bd8dSNiranjan H Y "firmware request failed for uid=%d, ret=%d\n", 1208*4cc9bd8dSNiranjan H Y unique_id, ret); 1209*4cc9bd8dSNiranjan H Y return ret; 1210*4cc9bd8dSNiranjan H Y } 1211*4cc9bd8dSNiranjan H Y 1212*4cc9bd8dSNiranjan H Y ret = wait_event_timeout(tas_dev->fw_wait, tas_dev->fw_dl_task_done, 1213*4cc9bd8dSNiranjan H Y msecs_to_jiffies(TIMEOUT_FW_DL_MS)); 1214*4cc9bd8dSNiranjan H Y if (!ret) { 1215*4cc9bd8dSNiranjan H Y dev_err(tas_dev->dev, "fw request, wait_event timeout\n"); 1216*4cc9bd8dSNiranjan H Y ret = -EAGAIN; 1217*4cc9bd8dSNiranjan H Y } else { 1218*4cc9bd8dSNiranjan H Y ret = regmap_multi_reg_write(tas_dev->regmap, tas2783_init_seq, 1219*4cc9bd8dSNiranjan H Y ARRAY_SIZE(tas2783_init_seq)); 1220*4cc9bd8dSNiranjan H Y tas_dev->hw_init = true; 1221*4cc9bd8dSNiranjan H Y } 1222*4cc9bd8dSNiranjan H Y 1223*4cc9bd8dSNiranjan H Y return ret; 1224*4cc9bd8dSNiranjan H Y } 1225*4cc9bd8dSNiranjan H Y 1226*4cc9bd8dSNiranjan H Y static s32 tas_update_status(struct sdw_slave *slave, 1227*4cc9bd8dSNiranjan H Y enum sdw_slave_status status) 1228*4cc9bd8dSNiranjan H Y { 1229*4cc9bd8dSNiranjan H Y struct tas2783_prv *tas_dev = dev_get_drvdata(&slave->dev); 1230*4cc9bd8dSNiranjan H Y struct device *dev = &slave->dev; 1231*4cc9bd8dSNiranjan H Y 1232*4cc9bd8dSNiranjan H Y dev_dbg(dev, "Perifpheral status = %s", 1233*4cc9bd8dSNiranjan H Y status == SDW_SLAVE_UNATTACHED ? "unattached" : 1234*4cc9bd8dSNiranjan H Y status == SDW_SLAVE_ATTACHED ? "attached" : "alert"); 1235*4cc9bd8dSNiranjan H Y 1236*4cc9bd8dSNiranjan H Y tas_dev->status = status; 1237*4cc9bd8dSNiranjan H Y if (status == SDW_SLAVE_UNATTACHED) 1238*4cc9bd8dSNiranjan H Y tas_dev->hw_init = false; 1239*4cc9bd8dSNiranjan H Y 1240*4cc9bd8dSNiranjan H Y /* Perform initialization only if slave status 1241*4cc9bd8dSNiranjan H Y * is present and hw_init flag is false 1242*4cc9bd8dSNiranjan H Y */ 1243*4cc9bd8dSNiranjan H Y if (tas_dev->hw_init || tas_dev->status != SDW_SLAVE_ATTACHED) 1244*4cc9bd8dSNiranjan H Y return 0; 1245*4cc9bd8dSNiranjan H Y 1246*4cc9bd8dSNiranjan H Y /* updated the cache data to device */ 1247*4cc9bd8dSNiranjan H Y regcache_cache_only(tas_dev->regmap, false); 1248*4cc9bd8dSNiranjan H Y regcache_sync(tas_dev->regmap); 1249*4cc9bd8dSNiranjan H Y 1250*4cc9bd8dSNiranjan H Y /* perform I/O transfers required for Slave initialization */ 1251*4cc9bd8dSNiranjan H Y return tas_io_init(&slave->dev, slave); 1252*4cc9bd8dSNiranjan H Y } 1253*4cc9bd8dSNiranjan H Y 1254*4cc9bd8dSNiranjan H Y static const struct sdw_slave_ops tas_sdw_ops = { 1255*4cc9bd8dSNiranjan H Y .read_prop = tas_read_prop, 1256*4cc9bd8dSNiranjan H Y .update_status = tas_update_status, 1257*4cc9bd8dSNiranjan H Y }; 1258*4cc9bd8dSNiranjan H Y 1259*4cc9bd8dSNiranjan H Y static void tas_remove(struct tas2783_prv *tas_dev) 1260*4cc9bd8dSNiranjan H Y { 1261*4cc9bd8dSNiranjan H Y snd_soc_unregister_component(tas_dev->dev); 1262*4cc9bd8dSNiranjan H Y } 1263*4cc9bd8dSNiranjan H Y 1264*4cc9bd8dSNiranjan H Y static s32 tas_sdw_probe(struct sdw_slave *peripheral, 1265*4cc9bd8dSNiranjan H Y const struct sdw_device_id *id) 1266*4cc9bd8dSNiranjan H Y { 1267*4cc9bd8dSNiranjan H Y struct regmap *regmap; 1268*4cc9bd8dSNiranjan H Y struct device *dev = &peripheral->dev; 1269*4cc9bd8dSNiranjan H Y struct tas2783_prv *tas_dev; 1270*4cc9bd8dSNiranjan H Y 1271*4cc9bd8dSNiranjan H Y tas_dev = devm_kzalloc(dev, sizeof(*tas_dev), GFP_KERNEL); 1272*4cc9bd8dSNiranjan H Y if (!tas_dev) 1273*4cc9bd8dSNiranjan H Y return dev_err_probe(dev, -ENOMEM, 1274*4cc9bd8dSNiranjan H Y "Failed devm_kzalloc"); 1275*4cc9bd8dSNiranjan H Y 1276*4cc9bd8dSNiranjan H Y tas_dev->dev = dev; 1277*4cc9bd8dSNiranjan H Y tas_dev->sdw_peripheral = peripheral; 1278*4cc9bd8dSNiranjan H Y tas_dev->hw_init = false; 1279*4cc9bd8dSNiranjan H Y mutex_init(&tas_dev->calib_lock); 1280*4cc9bd8dSNiranjan H Y mutex_init(&tas_dev->pde_lock); 1281*4cc9bd8dSNiranjan H Y 1282*4cc9bd8dSNiranjan H Y init_waitqueue_head(&tas_dev->fw_wait); 1283*4cc9bd8dSNiranjan H Y dev_set_drvdata(dev, tas_dev); 1284*4cc9bd8dSNiranjan H Y regmap = devm_regmap_init_sdw_mbq_cfg(peripheral, 1285*4cc9bd8dSNiranjan H Y &tas_regmap, 1286*4cc9bd8dSNiranjan H Y &tas2783_mbq_cfg); 1287*4cc9bd8dSNiranjan H Y if (IS_ERR(regmap)) 1288*4cc9bd8dSNiranjan H Y return dev_err_probe(dev, PTR_ERR(tas_dev->regmap), 1289*4cc9bd8dSNiranjan H Y "Failed devm_regmap_init_sdw."); 1290*4cc9bd8dSNiranjan H Y 1291*4cc9bd8dSNiranjan H Y /* keep in cache until the device is fully initialized */ 1292*4cc9bd8dSNiranjan H Y regcache_cache_only(regmap, true); 1293*4cc9bd8dSNiranjan H Y tas_dev->regmap = regmap; 1294*4cc9bd8dSNiranjan H Y return tas_init(tas_dev); 1295*4cc9bd8dSNiranjan H Y } 1296*4cc9bd8dSNiranjan H Y 1297*4cc9bd8dSNiranjan H Y static s32 tas_sdw_remove(struct sdw_slave *peripheral) 1298*4cc9bd8dSNiranjan H Y { 1299*4cc9bd8dSNiranjan H Y struct tas2783_prv *tas_dev = dev_get_drvdata(&peripheral->dev); 1300*4cc9bd8dSNiranjan H Y 1301*4cc9bd8dSNiranjan H Y pm_runtime_disable(tas_dev->dev); 1302*4cc9bd8dSNiranjan H Y tas_remove(tas_dev); 1303*4cc9bd8dSNiranjan H Y mutex_destroy(&tas_dev->calib_lock); 1304*4cc9bd8dSNiranjan H Y mutex_destroy(&tas_dev->pde_lock); 1305*4cc9bd8dSNiranjan H Y dev_set_drvdata(&peripheral->dev, NULL); 1306*4cc9bd8dSNiranjan H Y 1307*4cc9bd8dSNiranjan H Y return 0; 1308*4cc9bd8dSNiranjan H Y } 1309*4cc9bd8dSNiranjan H Y 1310*4cc9bd8dSNiranjan H Y static const struct sdw_device_id tas_sdw_id[] = { 1311*4cc9bd8dSNiranjan H Y /* chipid for the TAS2783 is 0x0000 */ 1312*4cc9bd8dSNiranjan H Y SDW_SLAVE_ENTRY(0x0102, 0x0000, 0), 1313*4cc9bd8dSNiranjan H Y {}, 1314*4cc9bd8dSNiranjan H Y }; 1315*4cc9bd8dSNiranjan H Y MODULE_DEVICE_TABLE(sdw, tas_sdw_id); 1316*4cc9bd8dSNiranjan H Y 1317*4cc9bd8dSNiranjan H Y static struct sdw_driver tas_sdw_driver = { 1318*4cc9bd8dSNiranjan H Y .driver = { 1319*4cc9bd8dSNiranjan H Y .name = "slave-tas2783", 1320*4cc9bd8dSNiranjan H Y .pm = pm_ptr(&tas2783_sdca_pm), 1321*4cc9bd8dSNiranjan H Y }, 1322*4cc9bd8dSNiranjan H Y .probe = tas_sdw_probe, 1323*4cc9bd8dSNiranjan H Y .remove = tas_sdw_remove, 1324*4cc9bd8dSNiranjan H Y .ops = &tas_sdw_ops, 1325*4cc9bd8dSNiranjan H Y .id_table = tas_sdw_id, 1326*4cc9bd8dSNiranjan H Y }; 1327*4cc9bd8dSNiranjan H Y module_sdw_driver(tas_sdw_driver); 1328*4cc9bd8dSNiranjan H Y 1329*4cc9bd8dSNiranjan H Y MODULE_AUTHOR("Texas Instruments Inc."); 1330*4cc9bd8dSNiranjan H Y MODULE_DESCRIPTION("ASoC TAS2783 SoundWire Driver"); 1331*4cc9bd8dSNiranjan H Y MODULE_LICENSE("GPL"); 1332