1. 12 Apr, 2023 4 commits
    • Richard Fitzgerald's avatar
      ASoC: cs35l56: Add basic system suspend handling · f9dc6b87
      Richard Fitzgerald authored
      This adds the main handling for system suspend but does not handle
      re-patching the firmware after system resume.
      
      This is a multi-stage suspend and resume because if there is a
      RESET line it is almost certain that it will be shared by all the
      amps. So every amp must have done its suspend before we can
      assert RESET. Likewise we must de-assert RESET before the amps
      can resume.
      
      It's preferable to assert RESET before we turning off regulators, and
      while they power up.
      
      The actual suspend and resume is done by using the pair
      pm_runtime_force_suspend() and pm_runtime_force_resume() to
      re-use our runtime suspend/resume sequences.
      
      pm_runtime_force_suspend() will disable our pm_runtime. If we were
      runtime-resumed it calls our runtime_suspend().
      
      pm_runtime_force_resume() re-enables pm_runtime and if we were
      originally runtime-resumed before the pm_runtime_force_suspend()
      it calls our runtime_resume(). Otherwise it leaves us
      runtime-suspended.
      
      The general process is therefore:
      
       suspend() -> finish dsp_work and then run our runtime_suspend
       suspend_late() -> assert RESET and turn off supplies
       resume_early() -> enable supplies and de-assert RESET
       resume() -> pm_runtime_force_resume()
      
      In addition, to prevent the IRQ handler running in the period
      between pm_runtime_force_suspend() and pm_runtime_force_resume()
      the parent IRQ is temporarily disabled:
       - from suspend until suspend_noirq
       - from resume_noirq until resume
      Signed-off-by: default avatarRichard Fitzgerald <rf@opensource.cirrus.com>
      Link: https://lore.kernel.org/r/20230411152528.329803-6-rf@opensource.cirrus.comSigned-off-by: default avatarMark Brown <broonie@kernel.org>
      f9dc6b87
    • Richard Fitzgerald's avatar
      ASoC: cs35l56: Always wait for firmware boot in runtime-resume · f00abadd
      Richard Fitzgerald authored
      When we are resuming from a system suspend the CS35L56 has probably
      been hard reset (usually a power-on reset). So we must wait for the
      firmware to boot. On SoundWire we also need it to re-initialize before
      we can read the registers to check the CS35L56 state.
      
      The simplest way to handle this is for runtime-resume to always wait
      for firmware boot. If the firmware is already booted the overhead is
      only one register read.
      
      The system-resume will have to runtime-resume the driver anyway before
      attempting any register access. So this will automatically include the
      wait for initialization on SoundWire.
      Signed-off-by: default avatarRichard Fitzgerald <rf@opensource.cirrus.com>
      Link: https://lore.kernel.org/r/20230411152528.329803-5-rf@opensource.cirrus.comSigned-off-by: default avatarMark Brown <broonie@kernel.org>
      f00abadd
    • Richard Fitzgerald's avatar
      ASoC: cs35l56: Skip first init_completion wait in dsp_work if init_done · 7816e340
      Richard Fitzgerald authored
      At the start of dsp_work() only wait for init_completion if !init_done.
      This allows system suspend to re-queue dsp_work() without having to
      do a dummy complete() of init_completion.
      
      A dummy completion in system suspend would have to be conditional on
      init_done. But that would create a possible race condition between our
      system resume and cs35l56_init() in the corner case that we suspend right
      after the SoundWire core has enumerated and reported ATTACHED.
      
      It is safer and simpler to have cs35l56_init() as the only place that
      init_completion is completed, and dsp_work() as the only place that
      it is consumed.
      Signed-off-by: default avatarRichard Fitzgerald <rf@opensource.cirrus.com>
      Link: https://lore.kernel.org/r/20230411152528.329803-4-rf@opensource.cirrus.comSigned-off-by: default avatarMark Brown <broonie@kernel.org>
      7816e340
    • Richard Fitzgerald's avatar
      ASoC: cs35l56: Use DAPM widget for firmware PLAY/PAUSE · 7b98a1ef
      Richard Fitzgerald authored
      If we use a DAPM widget instead of mute_stream() to send the
      PLAY command we can issue the plays to multiple amps in parallel.
      With mute_stream each codec driver instance is called one at a
      time so we get N * PS0 delay time.
      
      DAPM does each stage on every widget in a card before moving to
      the next stage. So all amps will do the PRE_PMU then all will do
      the POST_PMU. The PLAY is sent in the PRE_PMU so that they all
      power-up in parallel. After the PS0 wait in the first POST_PMU
      all the other amps will also be ready so there won't be any extra
      delay, or it will be negligible.
      
      There's also no point waiting for the MBOX ack in the PRE_PMU.
      We won't see a PS0 state in POST_PMU if it didn't ack the PLAY
      command. So we can save a little extra time.
      Signed-off-by: default avatarRichard Fitzgerald <rf@opensource.cirrus.com>
      Link: https://lore.kernel.org/r/20230411152528.329803-3-rf@opensource.cirrus.comSigned-off-by: default avatarMark Brown <broonie@kernel.org>
      7b98a1ef
  2. 11 Apr, 2023 10 commits
  3. 07 Apr, 2023 2 commits
  4. 06 Apr, 2023 24 commits