1. 12 Nov, 2021 9 commits
  2. 11 Nov, 2021 17 commits
  3. 10 Nov, 2021 5 commits
  4. 06 Nov, 2021 1 commit
  5. 05 Nov, 2021 8 commits
    • Maxime Ripard's avatar
      drm/vc4: hdmi: Introduce a scdc_enabled flag · 19986461
      Maxime Ripard authored
      We currently rely on two functions, vc4_hdmi_supports_scrambling() and
      vc4_hdmi_mode_needs_scrambling() to determine if we should enable and
      disable the scrambler for any given mode.
      
      Since we might need to disable the controller at boot, we also always
      run vc4_hdmi_disable_scrambling() and thus call those functions without
      a mode yet, which in turns need to make some special casing in order for
      it to work.
      
      Instead of duplicating the check for whether or not we need to take care
      of the scrambler in both vc4_hdmi_enable_scrambling() and
      vc4_hdmi_disable_scrambling(), we can do that check only when we enable
      it and store whether or not it's been enabled in our private structure.
      
      We also need to initialize that flag at true to make sure we disable the
      scrambler at boot since we can't really know its state yet.
      
      This allows to simplify a bit that part of the driver, and removes one
      user of our copy of the CRTC adjusted mode outside of KMS (since
      vc4_hdmi_disable_scrambling() might be called from the hotplug interrupt
      handler).
      
      It also removes our last user of the legacy encoder->crtc pointer.
      
      Link: https://lore.kernel.org/r/20211025141113.702757-10-maxime@cerno.techAcked-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
      Signed-off-by: default avatarMaxime Ripard <maxime@cerno.tech>
      19986461
    • Maxime Ripard's avatar
      drm/vc4: hdmi: Introduce an output_enabled flag · ebae26d6
      Maxime Ripard authored
      We currently poke at encoder->crtc in the ALSA code path to determine
      whether the HDMI output is enabled or not, and thus whether we should
      allow the audio output.
      
      However, that pointer is deprecated and shouldn't really be used by
      atomic drivers anymore. Since we have the infrastructure in place now,
      let's just create a flag that we toggle to report whether the controller
      is currently enabled and use that instead of encoder->crtc in ALSA.
      
      Link: https://lore.kernel.org/r/20211025141113.702757-9-maxime@cerno.techAcked-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
      Signed-off-by: default avatarMaxime Ripard <maxime@cerno.tech>
      ebae26d6
    • Maxime Ripard's avatar
      drm/vc4: hdmi: Check the device state in prepare() · a64ff88c
      Maxime Ripard authored
      Even though we already check that the encoder->crtc pointer is there
      during in startup(), which is part of the open() path in ASoC, nothing
      guarantees that our encoder state won't change between the time when we
      open the device and the time we prepare it.
      
      Move the sanity checks we do in startup() to a helper and call it from
      prepare().
      
      Link: https://lore.kernel.org/r/20211025141113.702757-8-maxime@cerno.tech
      Fixes: 91e99e11 ("drm/vc4: hdmi: Register HDMI codec")
      Acked-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
      Signed-off-by: default avatarMaxime Ripard <maxime@cerno.tech>
      a64ff88c
    • Maxime Ripard's avatar
      drm/vc4: hdmi: Prevent access to crtc->state outside of KMS · 633be8c3
      Maxime Ripard authored
      Accessing the crtc->state pointer from outside the modesetting context
      is not allowed. We thus need to copy whatever we need from the KMS state
      to our structure in order to access it.
      
      However, in the vc4 HDMI driver we do use that pointer in the ALSA code
      path, and potentially in the hotplug interrupt handler path.
      
      These paths both need access to the CRTC adjusted mode in order for the
      proper dividers to be set for ALSA, and the scrambler state to be
      reinstated properly for hotplug.
      
      Let's copy this mode into our private encoder structure and reference it
      from there when needed. Since that part is shared between KMS and other
      paths, we need to protect it using our mutex.
      
      Link: https://lore.kernel.org/all/YWgteNaNeaS9uWDe@phenom.ffwll.local/
      Link: https://lore.kernel.org/r/20211025141113.702757-7-maxime@cerno.tech
      Fixes: bb7d7856 ("drm/vc4: Add HDMI audio support")
      Acked-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
      Signed-off-by: default avatarMaxime Ripard <maxime@cerno.tech>
      633be8c3
    • Maxime Ripard's avatar
      drm/vc4: hdmi: Use a mutex to prevent concurrent framework access · 82cb88af
      Maxime Ripard authored
      The vc4 HDMI controller registers into the KMS, CEC and ALSA
      frameworks.
      
      However, no particular care is done to prevent the concurrent execution
      of different framework hooks from happening at the same time.
      
      In order to protect against that scenario, let's introduce a mutex that
      relevant ALSA and KMS hooks will need to take to prevent concurrent
      execution.
      
      CEC is left out at the moment though, since the .get_modes and .detect
      KMS hooks, when running cec_s_phys_addr_from_edid, can end up calling
      CEC's .adap_enable hook. This introduces some reentrancy that isn't easy
      to deal with properly.
      
      The CEC hooks also don't share much state with the rest of the driver:
      the registers are entirely separate, we don't share any variable, the
      only thing that can conflict is the CEC clock divider setup that can be
      affected by a mode set.
      
      However, after discussing it, it looks like CEC should be able to
      recover from this if it was to happen.
      
      Link: https://lore.kernel.org/r/20211025141113.702757-6-maxime@cerno.tech
      Fixes: bb7d7856 ("drm/vc4: Add HDMI audio support")
      Acked-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
      Signed-off-by: default avatarMaxime Ripard <maxime@cerno.tech>
      82cb88af
    • Maxime Ripard's avatar
      drm/vc4: hdmi: Add a spinlock to protect register access · 81fb55e5
      Maxime Ripard authored
      The vc4 HDMI driver has multiple path shared between the CEC, ALSA and
      KMS frameworks, plus two interrupt handlers (CEC and hotplug) that will
      read and modify a number of registers.
      
      Even though not bug has been reported so far, it's definitely unsafe, so
      let's just add a spinlock to protect the register access of the HDMI
      controller.
      
      Link: https://lore.kernel.org/r/20211025141113.702757-5-maxime@cerno.tech
      Fixes: c8b75bca ("drm/vc4: Add KMS support for Raspberry Pi.")
      Acked-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
      Signed-off-by: default avatarMaxime Ripard <maxime@cerno.tech>
      81fb55e5
    • Maxime Ripard's avatar
      drm/vc4: crtc: Copy assigned channel to the CRTC · eeb6ab46
      Maxime Ripard authored
      Accessing the crtc->state pointer from outside the modesetting context
      is not allowed. We thus need to copy whatever we need from the KMS state
      to our structure in order to access it.
      
      In VC4, a number of users of that pointers have crept in over the years,
      and the previous commits removed them all but the HVS channel a CRTC has
      been assigned.
      
      Let's move this channel in struct vc4_crtc at atomic_begin() time, drop
      it from our private state structure, and remove our use of crtc->state
      from our vblank handler entirely.
      
      Link: https://lore.kernel.org/all/YWgteNaNeaS9uWDe@phenom.ffwll.local/
      Link: https://lore.kernel.org/r/20211025141113.702757-4-maxime@cerno.tech
      Fixes: 87ebcd42 ("drm/vc4: crtc: Assign output to channel automatically")
      Acked-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
      Signed-off-by: default avatarMaxime Ripard <maxime@cerno.tech>
      eeb6ab46
    • Maxime Ripard's avatar
      drm/vc4: Fix non-blocking commit getting stuck forever · 0c250c15
      Maxime Ripard authored
      In some situation, we can end up being stuck on a non-blocking that went
      through properly.
      
      The situation that seems to trigger it reliably is to first start a
      non-blocking commit, and then right after, and before we had any vblank
      interrupt), start a blocking commit.
      
      This will lead to the first commit workqueue to be scheduled, setup the
      display, while the second commit is waiting for the first one to be
      completed.
      
      The vblank interrupt will then be raised, vc4_crtc_handle_vblank() will
      run and will compare the active dlist in the HVS channel to the one
      associated with the crtc->state.
      
      However, at that point, the second commit is waiting using
      drm_atomic_helper_wait_for_dependencies that occurs after
      drm_atomic_helper_swap_state has been called, so crtc->state points to
      the second commit state. vc4_crtc_handle_vblank() will compare the two
      dlist addresses and since they don't match will ignore the interrupt.
      
      The vblank event will never be reported, and the first and second commit
      will wait for the first commit completion until they timeout.
      
      The underlying reason is that it was never safe to do so. Indeed,
      accessing the ->state pointer access synchronization is based on
      ownership guarantees that can only occur within the functions and hooks
      defined as part of the KMS framework, and obviously the irq handler
      isn't one of them. The rework to move to generic helpers only uncovered
      the underlying issue.
      
      However, since the code path between
      drm_atomic_helper_wait_for_dependencies() and
      drm_atomic_helper_wait_for_vblanks() is serialised and we can't get two
      commits in that path at the same time, we can work around this issue by
      setting a variable associated to struct drm_crtc to the dlist we expect,
      and then using it from the vc4_crtc_handle_vblank() function.
      
      Since that state is shared with the modesetting path, we also need to
      introduce a spinlock to protect the code shared between the interrupt
      handler and the modesetting path, protecting only our new variable for
      now.
      
      Link: https://lore.kernel.org/all/YWgteNaNeaS9uWDe@phenom.ffwll.local/
      Link: https://lore.kernel.org/r/20211025141113.702757-3-maxime@cerno.tech
      Fixes: 56d1fe09 ("drm/vc4: Make pageflip completion handling more robust.")
      Acked-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
      Signed-off-by: default avatarMaxime Ripard <maxime@cerno.tech>
      0c250c15