1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) 2 // Copyright(c) 2023 Intel Corporation. All rights reserved. 3 4 /* 5 * Soundwire Intel ops for LunarLake 6 */ 7 8 #include <linux/acpi.h> 9 #include <linux/device.h> 10 #include <linux/soundwire/sdw_registers.h> 11 #include <linux/soundwire/sdw.h> 12 #include <linux/soundwire/sdw_intel.h> 13 #include <sound/hda-mlink.h> 14 #include "cadence_master.h" 15 #include "bus.h" 16 #include "intel.h" 17 18 /* 19 * shim vendor-specific (vs) ops 20 */ 21 22 static void intel_shim_vs_init(struct sdw_intel *sdw) 23 { 24 void __iomem *shim_vs = sdw->link_res->shim_vs; 25 u16 act = 0; 26 27 u16p_replace_bits(&act, 0x1, SDW_SHIM2_INTEL_VS_ACTMCTL_DOAIS); 28 act |= SDW_SHIM2_INTEL_VS_ACTMCTL_DACTQE; 29 act |= SDW_SHIM2_INTEL_VS_ACTMCTL_DODS; 30 intel_writew(shim_vs, SDW_SHIM2_INTEL_VS_ACTMCTL, act); 31 usleep_range(10, 15); 32 } 33 34 static int intel_shim_check_wake(struct sdw_intel *sdw) 35 { 36 void __iomem *shim_vs; 37 u16 wake_sts; 38 39 shim_vs = sdw->link_res->shim_vs; 40 wake_sts = intel_readw(shim_vs, SDW_SHIM2_INTEL_VS_WAKESTS); 41 42 return wake_sts & SDW_SHIM2_INTEL_VS_WAKEEN_PWS; 43 } 44 45 static void intel_shim_wake(struct sdw_intel *sdw, bool wake_enable) 46 { 47 void __iomem *shim_vs = sdw->link_res->shim_vs; 48 u16 wake_en; 49 u16 wake_sts; 50 51 wake_en = intel_readw(shim_vs, SDW_SHIM2_INTEL_VS_WAKEEN); 52 53 if (wake_enable) { 54 /* Enable the wakeup */ 55 wake_en |= SDW_SHIM2_INTEL_VS_WAKEEN_PWE; 56 intel_writew(shim_vs, SDW_SHIM2_INTEL_VS_WAKEEN, wake_en); 57 } else { 58 /* Disable the wake up interrupt */ 59 wake_en &= ~SDW_SHIM2_INTEL_VS_WAKEEN_PWE; 60 intel_writew(shim_vs, SDW_SHIM2_INTEL_VS_WAKEEN, wake_en); 61 62 /* Clear wake status (W1C) */ 63 wake_sts = intel_readw(shim_vs, SDW_SHIM2_INTEL_VS_WAKESTS); 64 wake_sts |= SDW_SHIM2_INTEL_VS_WAKEEN_PWS; 65 intel_writew(shim_vs, SDW_SHIM2_INTEL_VS_WAKESTS, wake_sts); 66 } 67 } 68 69 static int intel_link_power_up(struct sdw_intel *sdw) 70 { 71 struct sdw_bus *bus = &sdw->cdns.bus; 72 struct sdw_master_prop *prop = &bus->prop; 73 u32 *shim_mask = sdw->link_res->shim_mask; 74 unsigned int link_id = sdw->instance; 75 u32 syncprd; 76 int ret; 77 78 mutex_lock(sdw->link_res->shim_lock); 79 80 if (!*shim_mask) { 81 /* we first need to program the SyncPRD/CPU registers */ 82 dev_dbg(sdw->cdns.dev, "first link up, programming SYNCPRD\n"); 83 84 if (prop->mclk_freq % 6000000) 85 syncprd = SDW_SHIM_SYNC_SYNCPRD_VAL_38_4; 86 else 87 syncprd = SDW_SHIM_SYNC_SYNCPRD_VAL_24; 88 89 ret = hdac_bus_eml_sdw_set_syncprd_unlocked(sdw->link_res->hbus, syncprd); 90 if (ret < 0) { 91 dev_err(sdw->cdns.dev, "%s: hdac_bus_eml_sdw_set_syncprd failed: %d\n", 92 __func__, ret); 93 goto out; 94 } 95 } 96 97 ret = hdac_bus_eml_sdw_power_up_unlocked(sdw->link_res->hbus, link_id); 98 if (ret < 0) { 99 dev_err(sdw->cdns.dev, "%s: hdac_bus_eml_sdw_power_up failed: %d\n", 100 __func__, ret); 101 goto out; 102 } 103 104 if (!*shim_mask) { 105 /* SYNCPU will change once link is active */ 106 ret = hdac_bus_eml_sdw_wait_syncpu_unlocked(sdw->link_res->hbus); 107 if (ret < 0) { 108 dev_err(sdw->cdns.dev, "%s: hdac_bus_eml_sdw_wait_syncpu failed: %d\n", 109 __func__, ret); 110 goto out; 111 } 112 } 113 114 *shim_mask |= BIT(link_id); 115 116 sdw->cdns.link_up = true; 117 118 intel_shim_vs_init(sdw); 119 120 out: 121 mutex_unlock(sdw->link_res->shim_lock); 122 123 return ret; 124 } 125 126 static int intel_link_power_down(struct sdw_intel *sdw) 127 { 128 u32 *shim_mask = sdw->link_res->shim_mask; 129 unsigned int link_id = sdw->instance; 130 int ret; 131 132 mutex_lock(sdw->link_res->shim_lock); 133 134 sdw->cdns.link_up = false; 135 136 *shim_mask &= ~BIT(link_id); 137 138 ret = hdac_bus_eml_sdw_power_down_unlocked(sdw->link_res->hbus, link_id); 139 if (ret < 0) { 140 dev_err(sdw->cdns.dev, "%s: hdac_bus_eml_sdw_power_down failed: %d\n", 141 __func__, ret); 142 143 /* 144 * we leave the sdw->cdns.link_up flag as false since we've disabled 145 * the link at this point and cannot handle interrupts any longer. 146 */ 147 } 148 149 mutex_unlock(sdw->link_res->shim_lock); 150 151 return ret; 152 } 153 154 static void intel_sync_arm(struct sdw_intel *sdw) 155 { 156 unsigned int link_id = sdw->instance; 157 158 mutex_lock(sdw->link_res->shim_lock); 159 160 hdac_bus_eml_sdw_sync_arm_unlocked(sdw->link_res->hbus, link_id); 161 162 mutex_unlock(sdw->link_res->shim_lock); 163 } 164 165 static int intel_sync_go_unlocked(struct sdw_intel *sdw) 166 { 167 int ret; 168 169 ret = hdac_bus_eml_sdw_sync_go_unlocked(sdw->link_res->hbus); 170 if (ret < 0) 171 dev_err(sdw->cdns.dev, "%s: SyncGO clear failed: %d\n", __func__, ret); 172 173 return ret; 174 } 175 176 static int intel_sync_go(struct sdw_intel *sdw) 177 { 178 int ret; 179 180 mutex_lock(sdw->link_res->shim_lock); 181 182 ret = intel_sync_go_unlocked(sdw); 183 184 mutex_unlock(sdw->link_res->shim_lock); 185 186 return ret; 187 } 188 189 static bool intel_check_cmdsync_unlocked(struct sdw_intel *sdw) 190 { 191 return hdac_bus_eml_sdw_check_cmdsync_unlocked(sdw->link_res->hbus); 192 } 193 194 /* 195 * DAI operations 196 */ 197 static const struct snd_soc_dai_ops intel_pcm_dai_ops = { 198 }; 199 200 static const struct snd_soc_component_driver dai_component = { 201 .name = "soundwire", 202 }; 203 204 /* 205 * PDI routines 206 */ 207 static void intel_pdi_init(struct sdw_intel *sdw, 208 struct sdw_cdns_stream_config *config) 209 { 210 void __iomem *shim = sdw->link_res->shim; 211 int pcm_cap; 212 213 /* PCM Stream Capability */ 214 pcm_cap = intel_readw(shim, SDW_SHIM2_PCMSCAP); 215 216 config->pcm_bd = FIELD_GET(SDW_SHIM2_PCMSCAP_BSS, pcm_cap); 217 config->pcm_in = FIELD_GET(SDW_SHIM2_PCMSCAP_ISS, pcm_cap); 218 config->pcm_out = FIELD_GET(SDW_SHIM2_PCMSCAP_ISS, pcm_cap); 219 220 dev_dbg(sdw->cdns.dev, "PCM cap bd:%d in:%d out:%d\n", 221 config->pcm_bd, config->pcm_in, config->pcm_out); 222 } 223 224 static int 225 intel_pdi_get_ch_cap(struct sdw_intel *sdw, unsigned int pdi_num) 226 { 227 void __iomem *shim = sdw->link_res->shim; 228 229 /* zero based values for channel count in register */ 230 return intel_readw(shim, SDW_SHIM2_PCMSYCHC(pdi_num)) + 1; 231 } 232 233 static void intel_pdi_get_ch_update(struct sdw_intel *sdw, 234 struct sdw_cdns_pdi *pdi, 235 unsigned int num_pdi, 236 unsigned int *num_ch) 237 { 238 int ch_count = 0; 239 int i; 240 241 for (i = 0; i < num_pdi; i++) { 242 pdi->ch_count = intel_pdi_get_ch_cap(sdw, pdi->num); 243 ch_count += pdi->ch_count; 244 pdi++; 245 } 246 247 *num_ch = ch_count; 248 } 249 250 static void intel_pdi_stream_ch_update(struct sdw_intel *sdw, 251 struct sdw_cdns_streams *stream) 252 { 253 intel_pdi_get_ch_update(sdw, stream->bd, stream->num_bd, 254 &stream->num_ch_bd); 255 256 intel_pdi_get_ch_update(sdw, stream->in, stream->num_in, 257 &stream->num_ch_in); 258 259 intel_pdi_get_ch_update(sdw, stream->out, stream->num_out, 260 &stream->num_ch_out); 261 } 262 263 static int intel_create_dai(struct sdw_cdns *cdns, 264 struct snd_soc_dai_driver *dais, 265 enum intel_pdi_type type, 266 u32 num, u32 off, u32 max_ch) 267 { 268 int i; 269 270 if (!num) 271 return 0; 272 273 for (i = off; i < (off + num); i++) { 274 dais[i].name = devm_kasprintf(cdns->dev, GFP_KERNEL, 275 "SDW%d Pin%d", 276 cdns->instance, i); 277 if (!dais[i].name) 278 return -ENOMEM; 279 280 if (type == INTEL_PDI_BD || type == INTEL_PDI_OUT) { 281 dais[i].playback.channels_min = 1; 282 dais[i].playback.channels_max = max_ch; 283 } 284 285 if (type == INTEL_PDI_BD || type == INTEL_PDI_IN) { 286 dais[i].capture.channels_min = 1; 287 dais[i].capture.channels_max = max_ch; 288 } 289 290 dais[i].ops = &intel_pcm_dai_ops; 291 } 292 293 return 0; 294 } 295 296 static int intel_register_dai(struct sdw_intel *sdw) 297 { 298 struct sdw_cdns_dai_runtime **dai_runtime_array; 299 struct sdw_cdns_stream_config config; 300 struct sdw_cdns *cdns = &sdw->cdns; 301 struct sdw_cdns_streams *stream; 302 struct snd_soc_dai_driver *dais; 303 int num_dai; 304 int ret; 305 int off = 0; 306 307 /* Read the PDI config and initialize cadence PDI */ 308 intel_pdi_init(sdw, &config); 309 ret = sdw_cdns_pdi_init(cdns, config); 310 if (ret) 311 return ret; 312 313 intel_pdi_stream_ch_update(sdw, &sdw->cdns.pcm); 314 315 /* DAIs are created based on total number of PDIs supported */ 316 num_dai = cdns->pcm.num_pdi; 317 318 dai_runtime_array = devm_kcalloc(cdns->dev, num_dai, 319 sizeof(struct sdw_cdns_dai_runtime *), 320 GFP_KERNEL); 321 if (!dai_runtime_array) 322 return -ENOMEM; 323 cdns->dai_runtime_array = dai_runtime_array; 324 325 dais = devm_kcalloc(cdns->dev, num_dai, sizeof(*dais), GFP_KERNEL); 326 if (!dais) 327 return -ENOMEM; 328 329 /* Create PCM DAIs */ 330 stream = &cdns->pcm; 331 332 ret = intel_create_dai(cdns, dais, INTEL_PDI_IN, cdns->pcm.num_in, 333 off, stream->num_ch_in); 334 if (ret) 335 return ret; 336 337 off += cdns->pcm.num_in; 338 ret = intel_create_dai(cdns, dais, INTEL_PDI_OUT, cdns->pcm.num_out, 339 off, stream->num_ch_out); 340 if (ret) 341 return ret; 342 343 off += cdns->pcm.num_out; 344 ret = intel_create_dai(cdns, dais, INTEL_PDI_BD, cdns->pcm.num_bd, 345 off, stream->num_ch_bd); 346 if (ret) 347 return ret; 348 349 return devm_snd_soc_register_component(cdns->dev, &dai_component, 350 dais, num_dai); 351 } 352 353 static void intel_program_sdi(struct sdw_intel *sdw, int dev_num) 354 { 355 int ret; 356 357 ret = hdac_bus_eml_sdw_set_lsdiid(sdw->link_res->hbus, sdw->instance, dev_num); 358 if (ret < 0) 359 dev_err(sdw->cdns.dev, "%s: could not set lsdiid for link %d %d\n", 360 __func__, sdw->instance, dev_num); 361 } 362 363 const struct sdw_intel_hw_ops sdw_intel_lnl_hw_ops = { 364 .debugfs_init = intel_ace2x_debugfs_init, 365 .debugfs_exit = intel_ace2x_debugfs_exit, 366 367 .register_dai = intel_register_dai, 368 369 .check_clock_stop = intel_check_clock_stop, 370 .start_bus = intel_start_bus, 371 .start_bus_after_reset = intel_start_bus_after_reset, 372 .start_bus_after_clock_stop = intel_start_bus_after_clock_stop, 373 .stop_bus = intel_stop_bus, 374 375 .link_power_up = intel_link_power_up, 376 .link_power_down = intel_link_power_down, 377 378 .shim_check_wake = intel_shim_check_wake, 379 .shim_wake = intel_shim_wake, 380 381 .pre_bank_switch = intel_pre_bank_switch, 382 .post_bank_switch = intel_post_bank_switch, 383 384 .sync_arm = intel_sync_arm, 385 .sync_go_unlocked = intel_sync_go_unlocked, 386 .sync_go = intel_sync_go, 387 .sync_check_cmdsync_unlocked = intel_check_cmdsync_unlocked, 388 389 .program_sdi = intel_program_sdi, 390 }; 391 EXPORT_SYMBOL_NS(sdw_intel_lnl_hw_ops, SOUNDWIRE_INTEL); 392 393 MODULE_IMPORT_NS(SND_SOC_SOF_HDA_MLINK); 394