1 // SPDX-License-Identifier: GPL-2.0-only 2 // Copyright (c) 2023-2024 Qualcomm Innovation Center, Inc. All rights reserved. 3 // Copyright, 2025 Linaro Ltd 4 5 #include <linux/component.h> 6 #include <linux/device.h> 7 #include <linux/irq.h> 8 #include <linux/irqdomain.h> 9 #include <linux/kernel.h> 10 #include <linux/module.h> 11 #include <linux/of.h> 12 #include <linux/platform_device.h> 13 #include <linux/pm_runtime.h> 14 #include <linux/regmap.h> 15 #include <linux/slab.h> 16 #include <linux/soundwire/sdw.h> 17 #include <linux/soundwire/sdw_registers.h> 18 #include <linux/soundwire/sdw_type.h> 19 #include <sound/soc-dapm.h> 20 #include <sound/soc.h> 21 #include "pm4125.h" 22 23 static struct wcd_sdw_ch_info pm4125_sdw_rx_ch_info[] = { 24 WCD_SDW_CH(PM4125_HPH_L, PM4125_HPH_PORT, BIT(0)), 25 WCD_SDW_CH(PM4125_HPH_R, PM4125_HPH_PORT, BIT(1)), 26 }; 27 28 static struct wcd_sdw_ch_info pm4125_sdw_tx_ch_info[] = { 29 WCD_SDW_CH(PM4125_ADC1, PM4125_ADC_1_2_DMIC1L_BCS_PORT, BIT(0)), 30 WCD_SDW_CH(PM4125_ADC2, PM4125_ADC_1_2_DMIC1L_BCS_PORT, BIT(1)), 31 }; 32 33 static struct sdw_dpn_prop pm4125_dpn_prop[PM4125_MAX_SWR_PORTS] = { 34 { 35 .num = 1, 36 .type = SDW_DPN_SIMPLE, 37 .min_ch = 1, 38 .max_ch = 8, 39 .simple_ch_prep_sm = true, 40 }, { 41 .num = 2, 42 .type = SDW_DPN_SIMPLE, 43 .min_ch = 1, 44 .max_ch = 4, 45 .simple_ch_prep_sm = true, 46 } 47 }; 48 49 int pm4125_sdw_hw_params(struct pm4125_sdw_priv *priv, struct snd_pcm_substream *substream, 50 struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) 51 { 52 struct sdw_port_config port_config[PM4125_MAX_SWR_PORTS]; 53 unsigned long ch_mask; 54 int i, j; 55 56 priv->sconfig.ch_count = 1; 57 priv->active_ports = 0; 58 for (i = 0; i < PM4125_MAX_SWR_PORTS; i++) { 59 ch_mask = priv->port_config[i].ch_mask; 60 if (!ch_mask) 61 continue; 62 63 for_each_set_bit(j, &ch_mask, 4) 64 priv->sconfig.ch_count++; 65 66 port_config[priv->active_ports] = priv->port_config[i]; 67 priv->active_ports++; 68 } 69 70 priv->sconfig.bps = 1; 71 priv->sconfig.frame_rate = params_rate(params); 72 priv->sconfig.direction = priv->is_tx ? SDW_DATA_DIR_TX : SDW_DATA_DIR_RX; 73 priv->sconfig.type = SDW_STREAM_PCM; 74 75 return sdw_stream_add_slave(priv->sdev, &priv->sconfig, &port_config[0], priv->active_ports, 76 priv->sruntime); 77 } 78 EXPORT_SYMBOL_GPL(pm4125_sdw_hw_params); 79 80 /* 81 * Handle Soundwire out-of-band interrupt event by triggering the first irq of the slave_irq 82 * irq domain, which then will be handled by the regmap_irq threaded irq. 83 * Looping is to ensure no interrupts were missed in the process. 84 */ 85 static int pm4125_interrupt_callback(struct sdw_slave *slave, struct sdw_slave_intr_status *status) 86 { 87 struct pm4125_sdw_priv *priv = dev_get_drvdata(&slave->dev); 88 89 return wcd_interrupt_callback(slave, priv->slave_irq, PM4125_DIG_SWR_INTR_STATUS_0, 90 PM4125_DIG_SWR_INTR_STATUS_1, PM4125_DIG_SWR_INTR_STATUS_2); 91 } 92 93 static const struct reg_default pm4125_defaults[] = { 94 { PM4125_ANA_MICBIAS_MICB_1_2_EN, 0x01 }, 95 { PM4125_ANA_MICBIAS_MICB_3_EN, 0x00 }, 96 { PM4125_ANA_MICBIAS_LDO_1_SETTING, 0x21 }, 97 { PM4125_ANA_MICBIAS_LDO_1_CTRL, 0x01 }, 98 { PM4125_ANA_TX_AMIC1, 0x00 }, 99 { PM4125_ANA_TX_AMIC2, 0x00 }, 100 { PM4125_ANA_MBHC_MECH, 0x39 }, 101 { PM4125_ANA_MBHC_ELECT, 0x08 }, 102 { PM4125_ANA_MBHC_ZDET, 0x10 }, 103 { PM4125_ANA_MBHC_RESULT_1, 0x00 }, 104 { PM4125_ANA_MBHC_RESULT_2, 0x00 }, 105 { PM4125_ANA_MBHC_RESULT_3, 0x00 }, 106 { PM4125_ANA_MBHC_BTN0_ZDET_VREF1, 0x00 }, 107 { PM4125_ANA_MBHC_BTN1_ZDET_VREF2, 0x10 }, 108 { PM4125_ANA_MBHC_BTN2_ZDET_VREF3, 0x20 }, 109 { PM4125_ANA_MBHC_BTN3_ZDET_DBG_400, 0x30 }, 110 { PM4125_ANA_MBHC_BTN4_ZDET_DBG_1400, 0x40 }, 111 { PM4125_ANA_MBHC_MICB2_RAMP, 0x00 }, 112 { PM4125_ANA_MBHC_CTL_1, 0x02 }, 113 { PM4125_ANA_MBHC_CTL_2, 0x05 }, 114 { PM4125_ANA_MBHC_PLUG_DETECT_CTL, 0xE9 }, 115 { PM4125_ANA_MBHC_ZDET_ANA_CTL, 0x0F }, 116 { PM4125_ANA_MBHC_ZDET_RAMP_CTL, 0x00 }, 117 { PM4125_ANA_MBHC_FSM_STATUS, 0x00 }, 118 { PM4125_ANA_MBHC_ADC_RESULT, 0x00 }, 119 { PM4125_ANA_MBHC_CTL_CLK, 0x30 }, 120 { PM4125_ANA_MBHC_ZDET_CALIB_RESULT, 0x00 }, 121 { PM4125_ANA_NCP_EN, 0x00 }, 122 { PM4125_ANA_NCP_VCTRL, 0xA7 }, 123 { PM4125_ANA_HPHPA_CNP_CTL_1, 0x54 }, 124 { PM4125_ANA_HPHPA_CNP_CTL_2, 0x2B }, 125 { PM4125_ANA_HPHPA_PA_STATUS, 0x00 }, 126 { PM4125_ANA_HPHPA_FSM_CLK, 0x12 }, 127 { PM4125_ANA_HPHPA_L_GAIN, 0x00 }, 128 { PM4125_ANA_HPHPA_R_GAIN, 0x00 }, 129 { PM4125_SWR_HPHPA_HD2, 0x1B }, 130 { PM4125_ANA_HPHPA_SPARE_CTL, 0x02 }, 131 { PM4125_ANA_SURGE_EN, 0x38 }, 132 { PM4125_ANA_COMBOPA_CTL, 0x35 }, 133 { PM4125_ANA_COMBOPA_CTL_4, 0x84 }, 134 { PM4125_ANA_COMBOPA_CTL_5, 0x05 }, 135 { PM4125_ANA_RXLDO_CTL, 0x86 }, 136 { PM4125_ANA_MBIAS_EN, 0x00 }, 137 { PM4125_DIG_SWR_CHIP_ID0, 0x00 }, 138 { PM4125_DIG_SWR_CHIP_ID1, 0x00 }, 139 { PM4125_DIG_SWR_CHIP_ID2, 0x0C }, 140 { PM4125_DIG_SWR_CHIP_ID3, 0x01 }, 141 { PM4125_DIG_SWR_SWR_TX_CLK_RATE, 0x00 }, 142 { PM4125_DIG_SWR_CDC_RST_CTL, 0x03 }, 143 { PM4125_DIG_SWR_TOP_CLK_CFG, 0x00 }, 144 { PM4125_DIG_SWR_CDC_RX_CLK_CTL, 0x00 }, 145 { PM4125_DIG_SWR_CDC_TX_CLK_CTL, 0x33 }, 146 { PM4125_DIG_SWR_SWR_RST_EN, 0x00 }, 147 { PM4125_DIG_SWR_CDC_RX_RST, 0x00 }, 148 { PM4125_DIG_SWR_CDC_RX0_CTL, 0xFC }, 149 { PM4125_DIG_SWR_CDC_RX1_CTL, 0xFC }, 150 { PM4125_DIG_SWR_CDC_TX_ANA_MODE_0_1, 0x00 }, 151 { PM4125_DIG_SWR_CDC_COMP_CTL_0, 0x00 }, 152 { PM4125_DIG_SWR_CDC_RX_DELAY_CTL, 0x66 }, 153 { PM4125_DIG_SWR_CDC_RX_GAIN_0, 0x55 }, 154 { PM4125_DIG_SWR_CDC_RX_GAIN_1, 0xA9 }, 155 { PM4125_DIG_SWR_CDC_RX_GAIN_CTL, 0x00 }, 156 { PM4125_DIG_SWR_CDC_TX0_CTL, 0x68 }, 157 { PM4125_DIG_SWR_CDC_TX1_CTL, 0x68 }, 158 { PM4125_DIG_SWR_CDC_TX_RST, 0x00 }, 159 { PM4125_DIG_SWR_CDC_REQ0_CTL, 0x01 }, 160 { PM4125_DIG_SWR_CDC_REQ1_CTL, 0x01 }, 161 { PM4125_DIG_SWR_CDC_RST, 0x00 }, 162 { PM4125_DIG_SWR_CDC_AMIC_CTL, 0x02 }, 163 { PM4125_DIG_SWR_CDC_DMIC_CTL, 0x00 }, 164 { PM4125_DIG_SWR_CDC_DMIC1_CTL, 0x00 }, 165 { PM4125_DIG_SWR_CDC_DMIC1_RATE, 0x01 }, 166 { PM4125_DIG_SWR_PDM_WD_CTL0, 0x00 }, 167 { PM4125_DIG_SWR_PDM_WD_CTL1, 0x00 }, 168 { PM4125_DIG_SWR_INTR_MODE, 0x00 }, 169 { PM4125_DIG_SWR_INTR_MASK_0, 0xFF }, 170 { PM4125_DIG_SWR_INTR_MASK_1, 0x7F }, 171 { PM4125_DIG_SWR_INTR_MASK_2, 0x0C }, 172 { PM4125_DIG_SWR_INTR_STATUS_0, 0x00 }, 173 { PM4125_DIG_SWR_INTR_STATUS_1, 0x00 }, 174 { PM4125_DIG_SWR_INTR_STATUS_2, 0x00 }, 175 { PM4125_DIG_SWR_INTR_CLEAR_0, 0x00 }, 176 { PM4125_DIG_SWR_INTR_CLEAR_1, 0x00 }, 177 { PM4125_DIG_SWR_INTR_CLEAR_2, 0x00 }, 178 { PM4125_DIG_SWR_INTR_LEVEL_0, 0x00 }, 179 { PM4125_DIG_SWR_INTR_LEVEL_1, 0x2A }, 180 { PM4125_DIG_SWR_INTR_LEVEL_2, 0x00 }, 181 { PM4125_DIG_SWR_CDC_CONN_RX0_CTL, 0x00 }, 182 { PM4125_DIG_SWR_CDC_CONN_RX1_CTL, 0x00 }, 183 { PM4125_DIG_SWR_LOOP_BACK_MODE, 0x00 }, 184 { PM4125_DIG_SWR_DRIVE_STRENGTH_0, 0x00 }, 185 { PM4125_DIG_SWR_DIG_DEBUG_CTL, 0x00 }, 186 { PM4125_DIG_SWR_DIG_DEBUG_EN, 0x00 }, 187 { PM4125_DIG_SWR_DEM_BYPASS_DATA0, 0x55 }, 188 { PM4125_DIG_SWR_DEM_BYPASS_DATA1, 0x55 }, 189 { PM4125_DIG_SWR_DEM_BYPASS_DATA2, 0x55 }, 190 { PM4125_DIG_SWR_DEM_BYPASS_DATA3, 0x01 }, 191 }; 192 193 static bool pm4125_rdwr_register(struct device *dev, unsigned int reg) 194 { 195 switch (reg) { 196 case PM4125_ANA_MICBIAS_MICB_1_2_EN: 197 case PM4125_ANA_MICBIAS_MICB_3_EN: 198 case PM4125_ANA_MICBIAS_LDO_1_SETTING: 199 case PM4125_ANA_MICBIAS_LDO_1_CTRL: 200 case PM4125_ANA_TX_AMIC1: 201 case PM4125_ANA_TX_AMIC2: 202 case PM4125_ANA_MBHC_MECH: 203 case PM4125_ANA_MBHC_ELECT: 204 case PM4125_ANA_MBHC_ZDET: 205 case PM4125_ANA_MBHC_BTN0_ZDET_VREF1: 206 case PM4125_ANA_MBHC_BTN1_ZDET_VREF2: 207 case PM4125_ANA_MBHC_BTN2_ZDET_VREF3: 208 case PM4125_ANA_MBHC_BTN3_ZDET_DBG_400: 209 case PM4125_ANA_MBHC_BTN4_ZDET_DBG_1400: 210 case PM4125_ANA_MBHC_MICB2_RAMP: 211 case PM4125_ANA_MBHC_CTL_1: 212 case PM4125_ANA_MBHC_CTL_2: 213 case PM4125_ANA_MBHC_PLUG_DETECT_CTL: 214 case PM4125_ANA_MBHC_ZDET_ANA_CTL: 215 case PM4125_ANA_MBHC_ZDET_RAMP_CTL: 216 case PM4125_ANA_MBHC_CTL_CLK: 217 case PM4125_ANA_NCP_EN: 218 case PM4125_ANA_NCP_VCTRL: 219 case PM4125_ANA_HPHPA_CNP_CTL_1: 220 case PM4125_ANA_HPHPA_CNP_CTL_2: 221 case PM4125_ANA_HPHPA_FSM_CLK: 222 case PM4125_ANA_HPHPA_L_GAIN: 223 case PM4125_ANA_HPHPA_R_GAIN: 224 case PM4125_ANA_HPHPA_SPARE_CTL: 225 case PM4125_SWR_HPHPA_HD2: 226 case PM4125_ANA_SURGE_EN: 227 case PM4125_ANA_COMBOPA_CTL: 228 case PM4125_ANA_COMBOPA_CTL_4: 229 case PM4125_ANA_COMBOPA_CTL_5: 230 case PM4125_ANA_RXLDO_CTL: 231 case PM4125_ANA_MBIAS_EN: 232 case PM4125_DIG_SWR_SWR_TX_CLK_RATE: 233 case PM4125_DIG_SWR_CDC_RST_CTL: 234 case PM4125_DIG_SWR_TOP_CLK_CFG: 235 case PM4125_DIG_SWR_CDC_RX_CLK_CTL: 236 case PM4125_DIG_SWR_CDC_TX_CLK_CTL: 237 case PM4125_DIG_SWR_SWR_RST_EN: 238 case PM4125_DIG_SWR_CDC_RX_RST: 239 case PM4125_DIG_SWR_CDC_RX0_CTL: 240 case PM4125_DIG_SWR_CDC_RX1_CTL: 241 case PM4125_DIG_SWR_CDC_TX_ANA_MODE_0_1: 242 case PM4125_DIG_SWR_CDC_COMP_CTL_0: 243 case PM4125_DIG_SWR_CDC_RX_DELAY_CTL: 244 case PM4125_DIG_SWR_CDC_RX_GAIN_0: 245 case PM4125_DIG_SWR_CDC_RX_GAIN_1: 246 case PM4125_DIG_SWR_CDC_RX_GAIN_CTL: 247 case PM4125_DIG_SWR_CDC_TX0_CTL: 248 case PM4125_DIG_SWR_CDC_TX1_CTL: 249 case PM4125_DIG_SWR_CDC_TX_RST: 250 case PM4125_DIG_SWR_CDC_REQ0_CTL: 251 case PM4125_DIG_SWR_CDC_REQ1_CTL: 252 case PM4125_DIG_SWR_CDC_RST: 253 case PM4125_DIG_SWR_CDC_AMIC_CTL: 254 case PM4125_DIG_SWR_CDC_DMIC_CTL: 255 case PM4125_DIG_SWR_CDC_DMIC1_CTL: 256 case PM4125_DIG_SWR_CDC_DMIC1_RATE: 257 case PM4125_DIG_SWR_PDM_WD_CTL0: 258 case PM4125_DIG_SWR_PDM_WD_CTL1: 259 case PM4125_DIG_SWR_INTR_MODE: 260 case PM4125_DIG_SWR_INTR_MASK_0: 261 case PM4125_DIG_SWR_INTR_MASK_1: 262 case PM4125_DIG_SWR_INTR_MASK_2: 263 case PM4125_DIG_SWR_INTR_CLEAR_0: 264 case PM4125_DIG_SWR_INTR_CLEAR_1: 265 case PM4125_DIG_SWR_INTR_CLEAR_2: 266 case PM4125_DIG_SWR_INTR_LEVEL_0: 267 case PM4125_DIG_SWR_INTR_LEVEL_1: 268 case PM4125_DIG_SWR_INTR_LEVEL_2: 269 case PM4125_DIG_SWR_CDC_CONN_RX0_CTL: 270 case PM4125_DIG_SWR_CDC_CONN_RX1_CTL: 271 case PM4125_DIG_SWR_LOOP_BACK_MODE: 272 case PM4125_DIG_SWR_DRIVE_STRENGTH_0: 273 case PM4125_DIG_SWR_DIG_DEBUG_CTL: 274 case PM4125_DIG_SWR_DIG_DEBUG_EN: 275 case PM4125_DIG_SWR_DEM_BYPASS_DATA0: 276 case PM4125_DIG_SWR_DEM_BYPASS_DATA1: 277 case PM4125_DIG_SWR_DEM_BYPASS_DATA2: 278 case PM4125_DIG_SWR_DEM_BYPASS_DATA3: 279 return true; 280 } 281 282 return false; 283 } 284 285 static bool pm4125_readable_register(struct device *dev, unsigned int reg) 286 { 287 switch (reg) { 288 case PM4125_ANA_MBHC_RESULT_1: 289 case PM4125_ANA_MBHC_RESULT_2: 290 case PM4125_ANA_MBHC_RESULT_3: 291 case PM4125_ANA_MBHC_FSM_STATUS: 292 case PM4125_ANA_MBHC_ADC_RESULT: 293 case PM4125_ANA_MBHC_ZDET_CALIB_RESULT: 294 case PM4125_ANA_HPHPA_PA_STATUS: 295 case PM4125_DIG_SWR_CHIP_ID0: 296 case PM4125_DIG_SWR_CHIP_ID1: 297 case PM4125_DIG_SWR_CHIP_ID2: 298 case PM4125_DIG_SWR_CHIP_ID3: 299 case PM4125_DIG_SWR_INTR_STATUS_0: 300 case PM4125_DIG_SWR_INTR_STATUS_1: 301 case PM4125_DIG_SWR_INTR_STATUS_2: 302 return true; 303 } 304 return pm4125_rdwr_register(dev, reg); 305 } 306 307 static bool pm4125_volatile_register(struct device *dev, unsigned int reg) 308 { 309 switch (reg) { 310 case PM4125_ANA_MBHC_RESULT_1: 311 case PM4125_ANA_MBHC_RESULT_2: 312 case PM4125_ANA_MBHC_RESULT_3: 313 case PM4125_ANA_MBHC_FSM_STATUS: 314 case PM4125_ANA_MBHC_ADC_RESULT: 315 case PM4125_ANA_MBHC_ZDET_CALIB_RESULT: 316 case PM4125_ANA_HPHPA_PA_STATUS: 317 case PM4125_DIG_SWR_CHIP_ID0: 318 case PM4125_DIG_SWR_CHIP_ID1: 319 case PM4125_DIG_SWR_CHIP_ID2: 320 case PM4125_DIG_SWR_CHIP_ID3: 321 case PM4125_DIG_SWR_INTR_STATUS_0: 322 case PM4125_DIG_SWR_INTR_STATUS_1: 323 case PM4125_DIG_SWR_INTR_STATUS_2: 324 return true; 325 } 326 327 return false; 328 } 329 330 static const struct regmap_config pm4125_regmap_config = { 331 .name = "pm4125_csr", 332 .reg_bits = 32, 333 .val_bits = 8, 334 .cache_type = REGCACHE_MAPLE, 335 .reg_defaults = pm4125_defaults, 336 .num_reg_defaults = ARRAY_SIZE(pm4125_defaults), 337 .max_register = PM4125_MAX_REGISTER, 338 .readable_reg = pm4125_readable_register, 339 .writeable_reg = pm4125_rdwr_register, 340 .volatile_reg = pm4125_volatile_register, 341 }; 342 343 static const struct sdw_slave_ops pm4125_slave_ops = { 344 .update_status = wcd_update_status, 345 .interrupt_callback = pm4125_interrupt_callback, 346 }; 347 348 static int pm4125_probe(struct sdw_slave *pdev, const struct sdw_device_id *id) 349 { 350 struct device *dev = &pdev->dev; 351 struct pm4125_sdw_priv *priv; 352 u8 master_ch_mask[PM4125_MAX_SWR_CH_IDS]; 353 int master_ch_mask_size = 0; 354 int ret, i; 355 356 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 357 if (!priv) 358 return -ENOMEM; 359 360 /* Port map index starts at 0, however the data port for this codec starts at index 1 */ 361 if (of_property_present(dev->of_node, "qcom,tx-port-mapping")) { 362 priv->is_tx = true; 363 ret = of_property_read_u32_array(dev->of_node, "qcom,tx-port-mapping", 364 &pdev->m_port_map[1], PM4125_MAX_TX_SWR_PORTS); 365 } else { 366 ret = of_property_read_u32_array(dev->of_node, "qcom,rx-port-mapping", 367 &pdev->m_port_map[1], PM4125_MAX_SWR_PORTS); 368 } 369 370 if (ret < 0) 371 dev_info(dev, "Error getting static port mapping for %s (%d)\n", 372 priv->is_tx ? "TX" : "RX", ret); 373 374 priv->sdev = pdev; 375 dev_set_drvdata(dev, priv); 376 377 pdev->prop.scp_int1_mask = SDW_SCP_INT1_IMPL_DEF | 378 SDW_SCP_INT1_BUS_CLASH | 379 SDW_SCP_INT1_PARITY; 380 pdev->prop.lane_control_support = true; 381 pdev->prop.simple_clk_stop_capable = true; 382 383 memset(master_ch_mask, 0, PM4125_MAX_SWR_CH_IDS); 384 385 if (priv->is_tx) { 386 master_ch_mask_size = of_property_count_u8_elems(dev->of_node, 387 "qcom,tx-channel-mapping"); 388 389 if (master_ch_mask_size) 390 ret = of_property_read_u8_array(dev->of_node, "qcom,tx-channel-mapping", 391 master_ch_mask, master_ch_mask_size); 392 } else { 393 master_ch_mask_size = of_property_count_u8_elems(dev->of_node, 394 "qcom,rx-channel-mapping"); 395 396 if (master_ch_mask_size) 397 ret = of_property_read_u8_array(dev->of_node, "qcom,rx-channel-mapping", 398 master_ch_mask, master_ch_mask_size); 399 } 400 401 if (ret < 0) 402 dev_info(dev, "Static channel mapping not specified using device channel maps\n"); 403 404 if (priv->is_tx) { 405 pdev->prop.source_ports = GENMASK(PM4125_MAX_TX_SWR_PORTS, 0); 406 pdev->prop.src_dpn_prop = pm4125_dpn_prop; 407 priv->ch_info = &pm4125_sdw_tx_ch_info[0]; 408 409 for (i = 0; i < master_ch_mask_size; i++) 410 priv->ch_info[i].master_ch_mask = PM4125_SWRM_CH_MASK(master_ch_mask[i]); 411 412 pdev->prop.wake_capable = true; 413 414 priv->regmap = devm_regmap_init_sdw(pdev, &pm4125_regmap_config); 415 if (IS_ERR(priv->regmap)) 416 return dev_err_probe(dev, PTR_ERR(priv->regmap), "regmap init failed\n"); 417 418 /* Start in cache-only until device is enumerated */ 419 regcache_cache_only(priv->regmap, true); 420 } else { 421 pdev->prop.sink_ports = GENMASK(PM4125_MAX_SWR_PORTS - 1, 0); 422 pdev->prop.sink_dpn_prop = pm4125_dpn_prop; 423 priv->ch_info = &pm4125_sdw_rx_ch_info[0]; 424 425 for (i = 0; i < master_ch_mask_size; i++) 426 priv->ch_info[i].master_ch_mask = PM4125_SWRM_CH_MASK(master_ch_mask[i]); 427 } 428 429 ret = component_add(dev, &wcd_sdw_component_ops); 430 if (ret) 431 return ret; 432 433 /* Set suspended until aggregate device is bind */ 434 pm_runtime_set_suspended(dev); 435 436 return 0; 437 } 438 439 static int pm4125_remove(struct sdw_slave *pdev) 440 { 441 struct device *dev = &pdev->dev; 442 443 component_del(dev, &wcd_sdw_component_ops); 444 445 return 0; 446 } 447 448 static const struct sdw_device_id pm4125_slave_id[] = { 449 SDW_SLAVE_ENTRY(0x0217, 0x10c, 0), /* Soundwire pm4125 RX/TX Device ID */ 450 { } 451 }; 452 MODULE_DEVICE_TABLE(sdw, pm4125_slave_id); 453 454 static int __maybe_unused pm4125_sdw_runtime_suspend(struct device *dev) 455 { 456 struct pm4125_sdw_priv *priv = dev_get_drvdata(dev); 457 458 if (priv->regmap) { 459 regcache_cache_only(priv->regmap, true); 460 regcache_mark_dirty(priv->regmap); 461 } 462 463 return 0; 464 } 465 466 static int __maybe_unused pm4125_sdw_runtime_resume(struct device *dev) 467 { 468 struct pm4125_sdw_priv *priv = dev_get_drvdata(dev); 469 470 if (priv->regmap) { 471 regcache_cache_only(priv->regmap, false); 472 regcache_sync(priv->regmap); 473 } 474 475 return 0; 476 } 477 478 static const struct dev_pm_ops pm4125_sdw_pm_ops = { 479 SET_RUNTIME_PM_OPS(pm4125_sdw_runtime_suspend, pm4125_sdw_runtime_resume, NULL) 480 }; 481 482 static struct sdw_driver pm4125_codec_driver = { 483 .probe = pm4125_probe, 484 .remove = pm4125_remove, 485 .ops = &pm4125_slave_ops, 486 .id_table = pm4125_slave_id, 487 .driver = { 488 .name = "pm4125-codec", 489 .pm = &pm4125_sdw_pm_ops, 490 } 491 }; 492 module_sdw_driver(pm4125_codec_driver); 493 494 MODULE_DESCRIPTION("PM4125 SDW codec driver"); 495 MODULE_LICENSE("GPL"); 496