Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ASoC: SOF: Intel: hda-dsp: Add helper for setting DSP D0ix substate

Adding helper to implement setting dsp to d0i3 or d0i0 status, this will
be needed for driver D0ix support.

Signed-off-by: Keyon Jie <yang.jie@linux.intel.com>
Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Link: https://lore.kernel.org/r/20191025224122.7718-5-pierre-louis.bossart@linux.intel.com
Signed-off-by: Mark Brown <broonie@kernel.org>

authored by

Keyon Jie and committed by
Mark Brown
62f8f766 e8f112d8

+56
+46
sound/soc/sof/intel/hda-dsp.c
··· 306 306 HDA_DSP_REG_HIPCCTL_BUSY | HDA_DSP_REG_HIPCCTL_DONE, 0); 307 307 } 308 308 309 + static int hda_dsp_wait_d0i3c_done(struct snd_sof_dev *sdev, int retry) 310 + { 311 + struct hdac_bus *bus = sof_to_bus(sdev); 312 + 313 + while (snd_hdac_chip_readb(bus, VS_D0I3C) & SOF_HDA_VS_D0I3C_CIP) { 314 + if (!retry--) 315 + return -ETIMEDOUT; 316 + usleep_range(10, 15); 317 + } 318 + 319 + return 0; 320 + } 321 + 322 + int hda_dsp_set_power_state(struct snd_sof_dev *sdev, 323 + enum sof_d0_substate d0_substate) 324 + { 325 + struct hdac_bus *bus = sof_to_bus(sdev); 326 + int retry = 50; 327 + int ret; 328 + u8 value; 329 + 330 + /* Write to D0I3C after Command-In-Progress bit is cleared */ 331 + ret = hda_dsp_wait_d0i3c_done(sdev, retry); 332 + if (ret < 0) { 333 + dev_err(bus->dev, "CIP timeout before update D0I3C!\n"); 334 + return ret; 335 + } 336 + 337 + /* Update D0I3C register */ 338 + value = d0_substate == SOF_DSP_D0I3 ? SOF_HDA_VS_D0I3C_I3 : 0; 339 + snd_hdac_chip_updateb(bus, VS_D0I3C, SOF_HDA_VS_D0I3C_I3, value); 340 + 341 + /* Wait for cmd in progress to be cleared before exiting the function */ 342 + retry = 50; 343 + ret = hda_dsp_wait_d0i3c_done(sdev, retry); 344 + if (ret < 0) { 345 + dev_err(bus->dev, "CIP timeout after D0I3C updated!\n"); 346 + return ret; 347 + } 348 + 349 + dev_vdbg(bus->dev, "D0I3C updated, register = 0x%x\n", 350 + snd_hdac_chip_readb(bus, VS_D0I3C)); 351 + 352 + return 0; 353 + } 354 + 309 355 static int hda_suspend(struct snd_sof_dev *sdev, bool runtime_suspend) 310 356 { 311 357 struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata;
+10
sound/soc/sof/intel/hda.h
··· 64 64 #define SOF_HDA_PPCTL_PIE BIT(31) 65 65 #define SOF_HDA_PPCTL_GPROCEN BIT(30) 66 66 67 + /*Vendor Specific Registers*/ 68 + #define SOF_HDA_VS_D0I3C 0x104A 69 + 70 + /* D0I3C Register fields */ 71 + #define SOF_HDA_VS_D0I3C_CIP BIT(0) /* Command-In-Progress */ 72 + #define SOF_HDA_VS_D0I3C_I3 BIT(2) /* D0i3 enable bit */ 73 + 67 74 /* DPIB entry size: 8 Bytes = 2 DWords */ 68 75 #define SOF_HDA_DPIB_ENTRY_SIZE 0x8 69 76 ··· 461 454 unsigned int core_mask); 462 455 void hda_dsp_ipc_int_enable(struct snd_sof_dev *sdev); 463 456 void hda_dsp_ipc_int_disable(struct snd_sof_dev *sdev); 457 + 458 + int hda_dsp_set_power_state(struct snd_sof_dev *sdev, 459 + enum sof_d0_substate d0_substate); 464 460 465 461 int hda_dsp_suspend(struct snd_sof_dev *sdev); 466 462 int hda_dsp_resume(struct snd_sof_dev *sdev);