1. 07 6月, 2022 1 次提交
    • B
      drm/atomic: Force bridge self-refresh-exit on CRTC switch · e54a4424
      Brian Norris 提交于
      It's possible to change which CRTC is in use for a given
      connector/encoder/bridge while we're in self-refresh without fully
      disabling the connector/encoder/bridge along the way. This can confuse
      the bridge encoder/bridge, because
      (a) it needs to track the SR state (trying to perform "active"
          operations while the panel is still in SR can be Bad(TM)); and
      (b) it tracks the SR state via the CRTC state (and after the switch, the
          previous SR state is lost).
      
      Thus, we need to either somehow carry the self-refresh state over to the
      new CRTC, or else force an encoder/bridge self-refresh transition during
      such a switch.
      
      I choose the latter, so we disable the encoder (and exit PSR) before
      attaching it to the new CRTC (where we can continue to assume a clean
      (non-self-refresh) state).
      
      This fixes PSR issues seen on Rockchip RK3399 systems with
      drivers/gpu/drm/bridge/analogix/analogix_dp_core.c.
      
      Change in v2:
      
      - Drop "->enable" condition; this could possibly be "->active" to
        reflect the intended hardware state, but it also is a little
        over-specific. We want to make a transition through "disabled" any
        time we're exiting PSR at the same time as a CRTC switch.
        (Thanks Liu Ying)
      
      Cc: Liu Ying <victor.liu@oss.nxp.com>
      Cc: <stable@vger.kernel.org>
      Fixes: 1452c25b ("drm: Add helpers to kick off self refresh mode in drivers")
      Signed-off-by: NBrian Norris <briannorris@chromium.org>
      Reviewed-by: NSean Paul <seanpaul@chromium.org>
      Signed-off-by: NDouglas Anderson <dianders@chromium.org>
      Link: https://patchwork.freedesktop.org/patch/msgid/20220228122522.v2.2.Ic15a2ef69c540aee8732703103e2cff51fb9c399@changeid
      e54a4424
  2. 14 1月, 2022 1 次提交
  3. 11 1月, 2022 1 次提交
    • L
      drm/atomic: Check new_crtc_state->active to determine if CRTC needs disable in self refresh mode · 69e63001
      Liu Ying 提交于
      Actual hardware state of CRTC is controlled by the member 'active' in
      struct drm_crtc_state instead of the member 'enable', according to the
      kernel doc of the member 'enable'.  In fact, the drm client modeset
      and atomic helpers are using the member 'active' to do the control.
      
      Referencing the member 'enable' of new_crtc_state, the function
      crtc_needs_disable() may fail to reflect if CRTC needs disable in
      self refresh mode, e.g., when the framebuffer emulation will be blanked
      through the client modeset helper with the next commit, the member
      'enable' of new_crtc_state is still true while the member 'active' is
      false, hence the relevant potential encoder and bridges won't be disabled.
      
      So, let's check new_crtc_state->active to determine if CRTC needs disable
      in self refresh mode instead of new_crtc_state->enable.
      
      Fixes: 1452c25b ("drm: Add helpers to kick off self refresh mode in drivers")
      Cc: Sean Paul <seanpaul@chromium.org>
      Cc: Rob Clark <robdclark@chromium.org>
      Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
      Cc: Maxime Ripard <mripard@kernel.org>
      Cc: Thomas Zimmermann <tzimmermann@suse.de>
      Cc: David Airlie <airlied@linux.ie>
      Cc: Daniel Vetter <daniel@ffwll.ch>
      Reviewed-by: NAlex Deucher <alexander.deucher@amd.com>
      Signed-off-by: NLiu Ying <victor.liu@nxp.com>
      Signed-off-by: NAlex Deucher <alexander.deucher@amd.com>
      Link: https://patchwork.freedesktop.org/patch/msgid/20211230040626.646807-1-victor.liu@nxp.com
      69e63001
  4. 21 12月, 2021 1 次提交
  5. 26 11月, 2021 1 次提交
  6. 02 8月, 2021 1 次提交
  7. 24 6月, 2021 1 次提交
  8. 12 4月, 2021 2 次提交
  9. 26 3月, 2021 1 次提交
  10. 25 2月, 2021 3 次提交
    • M
      drm/atomic: Pass the full state to planes atomic disable and update · 977697e2
      Maxime Ripard 提交于
      The current atomic helpers have either their object state being passed as
      an argument or the full atomic state.
      
      The former is the pattern that was done at first, before switching to the
      latter for new hooks or when it was needed.
      
      Let's convert the remaining helpers to provide a consistent interface,
      this time with the planes atomic_update and atomic_disable.
      
      The conversion was done using the coccinelle script below, built tested on
      all the drivers.
      
      @@
      identifier plane, plane_state;
      symbol state;
      @@
      
       struct drm_plane_helper_funcs {
       	...
      	void (*atomic_update)(struct drm_plane *plane,
      -			      struct drm_plane_state *plane_state);
      +			      struct drm_atomic_state *state);
       	...
       }
      
      @@
      identifier plane, plane_state;
      symbol state;
      @@
      
       struct drm_plane_helper_funcs {
      	...
      	void (*atomic_disable)(struct drm_plane *plane,
      -			       struct drm_plane_state *plane_state);
      +			       struct drm_atomic_state *state);
      	...
       }
      
      @ plane_atomic_func @
      identifier helpers;
      identifier func;
      @@
      
      (
       static const struct drm_plane_helper_funcs helpers = {
       	...,
       	.atomic_update = func,
      	...,
       };
      |
       static const struct drm_plane_helper_funcs helpers = {
       	...,
       	.atomic_disable = func,
      	...,
       };
      )
      
      @@
      struct drm_plane_helper_funcs *FUNCS;
      identifier f;
      identifier crtc_state;
      identifier plane, plane_state, state;
      expression e;
      @@
      
       f(struct drm_crtc_state *crtc_state)
       {
       	...
       	struct drm_atomic_state *state = e;
       	<+...
      (
      -	FUNCS->atomic_disable(plane, plane_state)
      +	FUNCS->atomic_disable(plane, state)
      |
      -	FUNCS->atomic_update(plane, plane_state)
      +	FUNCS->atomic_update(plane, state)
      )
       	...+>
       }
      
      @@
      identifier plane_atomic_func.func;
      identifier plane;
      symbol state;
      @@
      
       func(struct drm_plane *plane,
      -    struct drm_plane_state *state)
      +    struct drm_plane_state *old_plane_state)
       {
      	<...
      -	state
      +	old_plane_state
      	...>
       }
      
      @ ignores_old_state @
      identifier plane_atomic_func.func;
      identifier plane, old_state;
      @@
      
       func(struct drm_plane *plane, struct drm_plane_state *old_state)
       {
      	... when != old_state
       }
      
      @ adds_old_state depends on plane_atomic_func && !ignores_old_state @
      identifier plane_atomic_func.func;
      identifier plane, plane_state;
      @@
      
       func(struct drm_plane *plane, struct drm_plane_state *plane_state)
       {
      +	struct drm_plane_state *plane_state = drm_atomic_get_old_plane_state(state, plane);
       	...
       }
      
      @ depends on plane_atomic_func @
      identifier plane_atomic_func.func;
      identifier plane, plane_state;
      @@
      
       func(struct drm_plane *plane,
      -     struct drm_plane_state *plane_state
      +     struct drm_atomic_state *state
           )
       { ... }
      
      @ include depends on adds_old_state @
      @@
      
       #include <drm/drm_atomic.h>
      
      @ no_include depends on !include && adds_old_state @
      @@
      
      + #include <drm/drm_atomic.h>
        #include <drm/...>
      
      @@
      identifier plane_atomic_func.func;
      identifier plane, state;
      identifier plane_state;
      @@
      
       func(struct drm_plane *plane, struct drm_atomic_state *state) {
       	...
       	struct drm_plane_state *plane_state = drm_atomic_get_old_plane_state(state, plane);
       	<+...
      -	plane_state->state
      +	state
       	...+>
       }
      Reviewed-by: NLaurent Pinchart <laurent.pinchart@ideasonboard.com>
      Signed-off-by: NMaxime Ripard <maxime@cerno.tech>
      Acked-by: NThomas Zimmermann <tzimmermann@suse.de>
      Link: https://patchwork.freedesktop.org/patch/msgid/20210219120032.260676-9-maxime@cerno.tech
      977697e2
    • M
      drm/atomic: Pass the full state to planes atomic_check · 7c11b99a
      Maxime Ripard 提交于
      The current atomic helpers have either their object state being passed as
      an argument or the full atomic state.
      
      The former is the pattern that was done at first, before switching to the
      latter for new hooks or when it was needed.
      
      Let's convert all the remaining helpers to provide a consistent
      interface, starting with the planes atomic_check.
      
      The conversion was done using the coccinelle script below plus some
      manual changes for vmwgfx, built tested on all the drivers.
      
      @@
      identifier plane, plane_state;
      symbol state;
      @@
      
       struct drm_plane_helper_funcs {
       	...
      	int (*atomic_check)(struct drm_plane *plane,
      -			    struct drm_plane_state *plane_state);
      +			    struct drm_atomic_state *state);
      	...
      }
      
      @ plane_atomic_func @
      identifier helpers;
      identifier func;
      @@
      
      static const struct drm_plane_helper_funcs helpers = {
      	...,
       	.atomic_check = func,
      	...,
      };
      
      @@
      struct drm_plane_helper_funcs *FUNCS;
      identifier f;
      identifier dev;
      identifier plane, plane_state, state;
      @@
      
       f(struct drm_device *dev, struct drm_atomic_state *state)
       {
       	<+...
      -	FUNCS->atomic_check(plane, plane_state)
      +	FUNCS->atomic_check(plane, state)
       	...+>
       }
      
      @ ignores_new_state @
      identifier plane_atomic_func.func;
      identifier plane, new_plane_state;
      @@
      
       func(struct drm_plane *plane, struct drm_plane_state *new_plane_state)
       {
      	... when != new_plane_state
       }
      
      @ adds_new_state depends on plane_atomic_func && !ignores_new_state @
      identifier plane_atomic_func.func;
      identifier plane, new_plane_state;
      @@
      
       func(struct drm_plane *plane, struct drm_plane_state *new_plane_state)
       {
      +	struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, plane);
       	...
       }
      
      @ depends on plane_atomic_func @
      identifier plane_atomic_func.func;
      identifier plane, new_plane_state;
      @@
      
       func(struct drm_plane *plane,
      -     struct drm_plane_state *new_plane_state
      +     struct drm_atomic_state *state
           )
       { ... }
      
      @ include depends on adds_new_state @
      @@
      
       #include <drm/drm_atomic.h>
      
      @ no_include depends on !include && adds_new_state @
      @@
      
      + #include <drm/drm_atomic.h>
        #include <drm/...>
      Reviewed-by: NLaurent Pinchart <laurent.pinchart@ideasonboard.com>
      Signed-off-by: NMaxime Ripard <maxime@cerno.tech>
      Acked-by: NThomas Zimmermann <tzimmermann@suse.de>
      Link: https://patchwork.freedesktop.org/patch/msgid/20210219120032.260676-4-maxime@cerno.tech
      7c11b99a
    • M
      drm/atomic: Pass the full state to planes async atomic check and update · 5ddb0bd4
      Maxime Ripard 提交于
      The current atomic helpers have either their object state being passed as
      an argument or the full atomic state.
      
      The former is the pattern that was done at first, before switching to the
      latter for new hooks or when it was needed.
      
      Let's start convert all the remaining helpers to provide a consistent
      interface, starting with the planes atomic_async_check and
      atomic_async_update.
      
      The conversion was done using the coccinelle script below, built tested on
      all the drivers.
      
      @@
      identifier plane, plane_state;
      symbol state;
      @@
      
       struct drm_plane_helper_funcs {
       	...
      	int (*atomic_async_check)(struct drm_plane *plane,
      -				  struct drm_plane_state *plane_state);
      +				  struct drm_atomic_state *state);
      	...
       }
      
      @@
      identifier plane, plane_state;
      symbol state;
      @@
       struct drm_plane_helper_funcs {
       	...
      	void (*atomic_async_update)(struct drm_plane *plane,
      -				    struct drm_plane_state *plane_state);
      +				    struct drm_atomic_state *state);
      	...
       }
      
      @ plane_atomic_func @
      identifier helpers;
      identifier func;
      @@
      
      (
       static const struct drm_plane_helper_funcs helpers = {
      	...,
       	.atomic_async_check = func,
      	...,
       };
      |
       static const struct drm_plane_helper_funcs helpers = {
       	...,
       	.atomic_async_update = func,
       	...,
       };
      )
      
      @@
      struct drm_plane_helper_funcs *FUNCS;
      identifier f;
      identifier dev;
      identifier plane, plane_state, state;
      @@
      
       f(struct drm_device *dev, struct drm_atomic_state *state)
       {
       	<+...
      -	FUNCS->atomic_async_check(plane, plane_state)
      +	FUNCS->atomic_async_check(plane, state)
       	...+>
       }
      
      @@
      struct drm_plane_helper_funcs *FUNCS;
      identifier f;
      identifier dev;
      identifier plane, plane_state, state;
      @@
      
       f(struct drm_device *dev, struct drm_atomic_state *state)
       {
       	<+...
      -	FUNCS->atomic_async_update(plane, plane_state)
      +	FUNCS->atomic_async_update(plane, state)
       	...+>
       }
      
      @@
      identifier mtk_plane_atomic_async_update;
      identifier plane;
      symbol new_state, state;
      expression e;
      @@
      
        void mtk_plane_atomic_async_update(struct drm_plane *plane, struct drm_plane_state *new_state)
      {
        ...
      - struct mtk_plane_state *state = e;
      + struct mtk_plane_state *new_plane_state = e;
        <+...
      -       state
      +       new_plane_state
        ...+>
        }
      
      @@
      identifier plane_atomic_func.func;
      identifier plane;
      symbol state;
      @@
      
       func(struct drm_plane *plane,
      -    struct drm_plane_state *state)
      +    struct drm_plane_state *new_plane_state)
       {
      	<...
      -	state
      +	new_plane_state
      	...>
       }
      
      @ ignores_new_state @
      identifier plane_atomic_func.func;
      identifier plane, new_plane_state;
      @@
      
       func(struct drm_plane *plane, struct drm_plane_state *new_plane_state)
       {
      	... when != new_plane_state
       }
      
      @ adds_new_state depends on plane_atomic_func && !ignores_new_state @
      identifier plane_atomic_func.func;
      identifier plane, new_plane_state;
      @@
      
       func(struct drm_plane *plane, struct drm_plane_state *new_plane_state)
       {
      +	struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, plane);
       	...
       }
      
      @ depends on plane_atomic_func @
      identifier plane_atomic_func.func;
      identifier plane, plane_state;
      @@
      
       func(struct drm_plane *plane,
      -     struct drm_plane_state *plane_state
      +     struct drm_atomic_state *state
           )
       { ... }
      
      @ include depends on adds_new_state @
      @@
      
       #include <drm/drm_atomic.h>
      
      @ no_include depends on !include && adds_new_state @
      @@
      
      + #include <drm/drm_atomic.h>
        #include <drm/...>
      
      @@
      identifier plane_atomic_func.func;
      identifier plane, state;
      identifier plane_state;
      @@
      
       func(struct drm_plane *plane, struct drm_atomic_state *state) {
              ...
              struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane);
              <+...
      -       plane_state->state
      +       state
              ...+>
       }
      Acked-by: NThomas Zimmermann <tzimmermann@suse.de>
      Signed-off-by: NMaxime Ripard <maxime@cerno.tech>
      Link: https://patchwork.freedesktop.org/patch/msgid/20210219120032.260676-1-maxime@cerno.tech
      5ddb0bd4
  11. 21 1月, 2021 1 次提交
  12. 19 1月, 2021 1 次提交
  13. 15 12月, 2020 2 次提交
  14. 20 11月, 2020 1 次提交
    • M
      drm: Pass the full state to connectors atomic functions · eca22edb
      Maxime Ripard 提交于
      The current atomic helpers have either their object state being passed as
      an argument or the full atomic state.
      
      The former is the pattern that was done at first, before switching to the
      latter for new hooks or when it was needed.
      
      Now that the CRTCs have been converted, let's move forward with the
      connectors to provide a consistent interface.
      
      The conversion was done using the coccinelle script below, and built tested
      on all the drivers.
      
      @@
      identifier connector, connector_state;
      @@
      
       struct drm_connector_helper_funcs {
      	...
      	struct drm_encoder* (*atomic_best_encoder)(struct drm_connector *connector,
      -						   struct drm_connector_state *connector_state);
      +						   struct drm_atomic_state *state);
      	...
      }
      
      @@
      identifier connector, connector_state;
      @@
      
       struct drm_connector_helper_funcs {
      	...
      	void (*atomic_commit)(struct drm_connector *connector,
      -			      struct drm_connector_state *connector_state);
      +			      struct drm_atomic_state *state);
      	...
      }
      
      @@
      struct drm_connector_helper_funcs *FUNCS;
      identifier state;
      identifier connector, connector_state;
      identifier f;
      @@
      
       f(..., struct drm_atomic_state *state, ...)
       {
      	<+...
      -	FUNCS->atomic_commit(connector, connector_state);
      +	FUNCS->atomic_commit(connector, state);
      	...+>
       }
      
      @@
      struct drm_connector_helper_funcs *FUNCS;
      identifier state;
      identifier connector, connector_state;
      identifier var, f;
      @@
      
       f(struct drm_atomic_state *state, ...)
       {
      	<+...
      -	var = FUNCS->atomic_best_encoder(connector, connector_state);
      +	var = FUNCS->atomic_best_encoder(connector, state);
      	...+>
       }
      
      @ connector_atomic_func @
      identifier helpers;
      identifier func;
      @@
      
      (
      static struct drm_connector_helper_funcs helpers = {
      	...,
      	.atomic_best_encoder = func,
      	...,
      };
      |
      static struct drm_connector_helper_funcs helpers = {
      	...,
      	.atomic_commit = func,
      	...,
      };
      )
      
      @@
      identifier connector_atomic_func.func;
      identifier connector;
      symbol state;
      @@
      
       func(struct drm_connector *connector,
      -      struct drm_connector_state *state
      +      struct drm_connector_state *connector_state
            )
       {
      	...
      -	state
      +	connector_state
       	...
       }
      
      @ ignores_state @
      identifier connector_atomic_func.func;
      identifier connector, connector_state;
      @@
      
       func(struct drm_connector *connector,
            struct drm_connector_state *connector_state)
      {
      	... when != connector_state
      }
      
      @ adds_state depends on connector_atomic_func && !ignores_state @
      identifier connector_atomic_func.func;
      identifier connector, connector_state;
      @@
      
       func(struct drm_connector *connector, struct drm_connector_state *connector_state)
       {
      +	struct drm_connector_state *connector_state = drm_atomic_get_new_connector_state(state, connector);
      	...
       }
      
      @ depends on connector_atomic_func @
      identifier connector_atomic_func.func;
      identifier connector_state;
      identifier connector;
      @@
      
       func(struct drm_connector *connector,
      -     struct drm_connector_state *connector_state
      +     struct drm_atomic_state *state
      	   )
       { ... }
      
      @ include depends on adds_state @
      @@
      
       #include <drm/drm_atomic.h>
      
      @ no_include depends on !include && adds_state @
      @@
      
      + #include <drm/drm_atomic.h>
        #include <drm/...>
      Signed-off-by: NMaxime Ripard <maxime@cerno.tech>
      Reviewed-by: NRodrigo Siqueira <rodrigosiqueiramelo@gmail.com>
      Reviewed-by: NVille Syrjälä <ville.syrjala@linux.intel.com>
      Acked-by: NThomas Zimmermann <tzimmermann@suse.de>
      Acked-by: NHarry Wentland <harry.wentland@amd.com>
      Cc: Leo Li <sunpeng.li@amd.com>
      Cc: Alex Deucher <alexander.deucher@amd.com>
      Cc: "Christian König" <christian.koenig@amd.com>
      Cc: Jani Nikula <jani.nikula@linux.intel.com>
      Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
      Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
      Cc: Ben Skeggs <bskeggs@redhat.com>
      Cc: Rodrigo Siqueira <rodrigosiqueiramelo@gmail.com>
      Cc: Melissa Wen <melissa.srw@gmail.com>
      Cc: Haneen Mohammed <hamohammed.sa@gmail.com>
      Link: https://patchwork.freedesktop.org/patch/msgid/20201118094758.506730-1-maxime@cerno.tech
      eca22edb
  15. 02 11月, 2020 2 次提交
    • M
      drm/atomic: Pass the full state to CRTC atomic begin and flush · f6ebe9f9
      Maxime Ripard 提交于
      The current atomic helpers have either their object state being passed as
      an argument or the full atomic state.
      
      The former is the pattern that was done at first, before switching to the
      latter for new hooks or when it was needed.
      
      Let's start convert all the remaining helpers to provide a consistent
      interface, starting with the CRTC's atomic_begin and atomic_flush.
      
      The conversion was done using the coccinelle script below, built tested on
      all the drivers and actually tested on vc4.
      
      virtual report
      
      @@
      struct drm_crtc_helper_funcs *FUNCS;
      identifier old_crtc_state, old_state;
      identifier crtc;
      identifier f;
      @@
      
       f(struct drm_crtc_state *old_crtc_state)
       {
      	...
       	struct drm_atomic_state *old_state = old_crtc_state->state;
      	<...
      -	FUNCS->atomic_begin(crtc, old_crtc_state);
      +	FUNCS->atomic_begin(crtc, old_state);
      	...>
       }
      
      @@
      struct drm_crtc_helper_funcs *FUNCS;
      identifier old_crtc_state, old_state;
      identifier crtc;
      identifier f;
      @@
      
       f(struct drm_crtc_state *old_crtc_state)
       {
      	...
       	struct drm_atomic_state *old_state = old_crtc_state->state;
      	<...
      -	FUNCS->atomic_flush(crtc, old_crtc_state);
      +	FUNCS->atomic_flush(crtc, old_state);
      	...>
       }
      
      @@
      struct drm_crtc_helper_funcs *FUNCS;
      struct drm_crtc *crtc;
      struct drm_crtc_state *crtc_state;
      identifier dev, state;
      identifier f;
      @@
      
       f(struct drm_device *dev, struct drm_atomic_state *state, ...)
       {
      	<...
      -	FUNCS->atomic_begin(crtc, crtc_state);
      +	FUNCS->atomic_begin(crtc, state);
      	...>
       }
      
      @@
      struct drm_crtc_helper_funcs *FUNCS;
      struct drm_crtc *crtc;
      struct drm_crtc_state *crtc_state;
      identifier dev, state;
      identifier f;
      @@
      
       f(struct drm_device *dev, struct drm_atomic_state *state, ...)
       {
      	<...
      -	FUNCS->atomic_flush(crtc, crtc_state);
      +	FUNCS->atomic_flush(crtc, state);
      	...>
       }
      
      @@
      identifier crtc, old_state;
      @@
      
       struct drm_crtc_helper_funcs {
      	...
      -	void (*atomic_begin)(struct drm_crtc *crtc, struct drm_crtc_state *old_state);
      +	void (*atomic_begin)(struct drm_crtc *crtc, struct drm_atomic_state *state);
      	...
      -	void (*atomic_flush)(struct drm_crtc *crtc, struct drm_crtc_state *old_state);
      +	void (*atomic_flush)(struct drm_crtc *crtc, struct drm_atomic_state *state);
      	...
      }
      
      @ crtc_atomic_func @
      identifier helpers;
      identifier func;
      @@
      
      (
      static struct drm_crtc_helper_funcs helpers = {
      	...,
      	.atomic_begin = func,
      	...,
      };
      |
      static struct drm_crtc_helper_funcs helpers = {
      	...,
      	.atomic_flush = func,
      	...,
      };
      )
      
      @ ignores_old_state @
      identifier crtc_atomic_func.func;
      identifier crtc, old_state;
      @@
      
      void func(struct drm_crtc *crtc,
      		struct drm_crtc_state *old_state)
      {
      	... when != old_state
      }
      
      @ adds_old_state depends on crtc_atomic_func && !ignores_old_state @
      identifier crtc_atomic_func.func;
      identifier crtc, old_state;
      @@
      
      void func(struct drm_crtc *crtc, struct drm_crtc_state *old_state)
      {
      +	struct drm_crtc_state *old_state = drm_atomic_get_old_crtc_state(state, crtc);
      	...
      }
      
      @ depends on crtc_atomic_func @
      identifier crtc_atomic_func.func;
      expression E;
      type T;
      @@
      
      void func(...)
      {
      	...
      -	T state = E;
      +	T crtc_state = E;
      	<+...
      -	state
      +	crtc_state
      	...+>
      
      }
      
      @ depends on crtc_atomic_func @
      identifier crtc_atomic_func.func;
      type T;
      @@
      
      void func(...)
      {
      	...
      -	T state;
      +	T crtc_state;
      	<+...
      -	state
      +	crtc_state
      	...+>
      
      }
      
      @@
      identifier old_state;
      identifier crtc;
      @@
      
       void vc4_hvs_atomic_flush(struct drm_crtc *crtc,
      -			   struct drm_crtc_state *old_state
      +			   struct drm_atomic_state *state
      			   )
      {
      +	struct drm_crtc_state *old_state = drm_atomic_get_old_crtc_state(state, crtc);
      	...
      }
      
      @@
      identifier old_state;
      identifier crtc;
      @@
      
       void vc4_hvs_atomic_flush(struct drm_crtc *crtc,
      -			   struct drm_crtc_state *old_state
      +			   struct drm_atomic_state *state
      			   );
      
      @@
      identifier old_state;
      identifier crtc;
      @@
      
       void vmw_du_crtc_atomic_begin(struct drm_crtc *crtc,
      -			   struct drm_crtc_state *old_state
      +			   struct drm_atomic_state *state
      			   )
      {
      	...
      }
      
      @@
      identifier old_state;
      identifier crtc;
      @@
      
       void vmw_du_crtc_atomic_begin(struct drm_crtc *crtc,
      -			   struct drm_crtc_state *old_state
      +			   struct drm_atomic_state *state
      			   );
      
      @@
      identifier old_state;
      identifier crtc;
      @@
      
       void vmw_du_crtc_atomic_flush(struct drm_crtc *crtc,
      -			   struct drm_crtc_state *old_state
      +			   struct drm_atomic_state *state
      			   )
      {
      	...
      }
      
      @@
      identifier old_state;
      identifier crtc;
      @@
      
       void vmw_du_crtc_atomic_flush(struct drm_crtc *crtc,
      -			   struct drm_crtc_state *old_state
      +			   struct drm_atomic_state *state
      			   );
      
      @ depends on crtc_atomic_func @
      identifier crtc_atomic_func.func;
      identifier old_state;
      identifier crtc;
      @@
      
      void func(struct drm_crtc *crtc,
      -	       struct drm_crtc_state *old_state
      +	       struct drm_atomic_state *state
      	       )
      		{ ... }
      
      @ include depends on adds_old_state @
      @@
      
       #include <drm/drm_atomic.h>
      
      @ no_include depends on !include && adds_old_state @
      @@
      
      + #include <drm/drm_atomic.h>
        #include <drm/...>
      Signed-off-by: NMaxime Ripard <maxime@cerno.tech>
      Reviewed-by: NVille Syrjälä <ville.syrjala@linux.intel.com>
      Acked-by: NDaniel Vetter <daniel.vetter@ffwll.ch>
      Acked-by: NThomas Zimmermann <tzimmermann@suse.de>
      Link: https://patchwork.freedesktop.org/patch/msgid/20201028123222.1732139-2-maxime@cerno.tech
      f6ebe9f9
    • M
      drm/atomic: Pass the full state to CRTC atomic_check · 29b77ad7
      Maxime Ripard 提交于
      The current atomic helpers have either their object state being passed as
      an argument or the full atomic state.
      
      The former is the pattern that was done at first, before switching to the
      latter for new hooks or when it was needed.
      
      Let's start convert all the remaining helpers to provide a consistent
      interface, starting with the CRTC's atomic_check.
      
      The conversion was done using the coccinelle script below,
      built tested on all the drivers and actually tested on vc4.
      
      virtual report
      
      @@
      struct drm_crtc_helper_funcs *FUNCS;
      struct drm_crtc *crtc;
      struct drm_crtc_state *crtc_state;
      identifier dev, state;
      identifier ret, f;
      @@
      
       f(struct drm_device *dev, struct drm_atomic_state *state)
       {
      	<...
      -	ret = FUNCS->atomic_check(crtc, crtc_state);
      +	ret = FUNCS->atomic_check(crtc, state);
      	...>
       }
      
      @@
      identifier crtc, new_state;
      @@
      
       struct drm_crtc_helper_funcs {
       	...
      -	int (*atomic_check)(struct drm_crtc *crtc, struct drm_crtc_state *new_state);
      +	int (*atomic_check)(struct drm_crtc *crtc, struct drm_atomic_state *state);
       	...
      }
      
      @ crtc_atomic_func @
      identifier helpers;
      identifier func;
      @@
      
      static struct drm_crtc_helper_funcs helpers = {
      	...,
      	.atomic_check = func,
      	...,
      };
      
      @ ignores_new_state @
      identifier crtc_atomic_func.func;
      identifier crtc, new_state;
      @@
      
       int func(struct drm_crtc *crtc,
      		struct drm_crtc_state *new_state)
       {
      	... when != new_state
       }
      
      @ adds_new_state depends on crtc_atomic_func && !ignores_new_state @
      identifier crtc_atomic_func.func;
      identifier crtc, new_state;
      @@
      
       int func(struct drm_crtc *crtc, struct drm_crtc_state *new_state)
       {
      +	struct drm_crtc_state *new_state = drm_atomic_get_new_crtc_state(state, crtc);
       	...
       }
      
      @ depends on crtc_atomic_func @
      identifier crtc_atomic_func.func;
      expression E;
      type T;
      @@
      
       int func(...)
       {
      	...
      -	T state = E;
      +	T crtc_state = E;
       	<+...
      -	state
      +	crtc_state
       	...+>
       }
      
      @ depends on crtc_atomic_func @
      identifier crtc_atomic_func.func;
      type T;
      @@
      
       int func(...)
       {
       	...
      -	T state;
      +	T crtc_state;
       	<+...
      -	state
      +	crtc_state
       	...+>
       }
      
      @ depends on crtc_atomic_func @
      identifier crtc_atomic_func.func;
      identifier new_state;
      identifier crtc;
      @@
      
       int func(struct drm_crtc *crtc,
      -	       struct drm_crtc_state *new_state
      +	       struct drm_atomic_state *state
      	       )
       { ... }
      
      @@
      identifier new_state;
      identifier crtc;
      @@
      
       int vmw_du_crtc_atomic_check(struct drm_crtc *crtc,
      -                             struct drm_crtc_state *new_state
      +                             struct drm_atomic_state *state
                     )
       {
      +       struct drm_crtc_state *new_state = drm_atomic_get_new_crtc_state(state, crtc);
      	...
       }
      
      @@
      identifier new_state;
      identifier crtc;
      @@
      
       int vmw_du_crtc_atomic_check(struct drm_crtc *crtc,
      -                             struct drm_crtc_state *new_state
      +                             struct drm_atomic_state *state
                     );
      
      @ include depends on adds_new_state @
      @@
      
       #include <drm/drm_atomic.h>
      
      @ no_include depends on !include && adds_new_state @
      @@
      
      + #include <drm/drm_atomic.h>
        #include <drm/...>
      Signed-off-by: NMaxime Ripard <maxime@cerno.tech>
      Reviewed-by: NVille Syrjälä <ville.syrjala@linux.intel.com>
      Acked-by: NThomas Zimmermann <tzimmermann@suse.de>
      Link: https://patchwork.freedesktop.org/patch/msgid/20201028123222.1732139-1-maxime@cerno.tech
      29b77ad7
  16. 09 10月, 2020 1 次提交
    • M
      drm/atomic: Pass the full state to CRTC atomic enable/disable · 351f950d
      Maxime Ripard 提交于
      If the CRTC driver ever needs to access the full DRM state, it can't do so
      at atomic_enable / atomic_disable time since drm_atomic_helper_swap_state
      will have cleared the pointer from the struct drm_crtc_state to the struct
      drm_atomic_state before calling those hooks.
      
      In order to allow that, let's pass the full DRM state to atomic_enable and
      atomic_disable. The conversion was done using the coccinelle script below,
      built tested on all the drivers and actually tested on vc4.
      
      virtual report
      
      @@
      struct drm_crtc_helper_funcs *FUNCS;
      identifier dev, state;
      identifier crtc, crtc_state;
      @@
      
       disable_outputs(struct drm_device *dev, struct drm_atomic_state *state)
       {
       	<...
      -	FUNCS->atomic_disable(crtc, crtc_state);
      +	FUNCS->atomic_disable(crtc, state);
       	...>
       }
      
      @@
      struct drm_crtc_helper_funcs *FUNCS;
      identifier dev, state;
      identifier crtc, crtc_state;
      @@
      
       drm_atomic_helper_commit_modeset_enables(struct drm_device *dev, struct drm_atomic_state *state)
       {
       	<...
      -	FUNCS->atomic_enable(crtc, crtc_state);
      +	FUNCS->atomic_enable(crtc, state);
       	...>
       }
      
      @@
      identifier crtc, old_state;
      @@
      
       struct drm_crtc_helper_funcs {
      	...
      -	void (*atomic_enable)(struct drm_crtc *crtc, struct drm_crtc_state *old_state);
      +	void (*atomic_enable)(struct drm_crtc *crtc, struct drm_atomic_state *state);
      	...
      -	void (*atomic_disable)(struct drm_crtc *crtc, struct drm_crtc_state *old_state);
      +	void (*atomic_disable)(struct drm_crtc *crtc, struct drm_atomic_state *state);
      	...
      }
      
      @ crtc_atomic_func @
      identifier helpers;
      identifier func;
      @@
      
      (
      static struct drm_crtc_helper_funcs helpers = {
      	...,
      	.atomic_enable = func,
      	...,
      };
      |
      static struct drm_crtc_helper_funcs helpers = {
      	...,
      	.atomic_disable = func,
      	...,
      };
      )
      
      @ ignores_old_state @
      identifier crtc_atomic_func.func;
      identifier crtc, old_state;
      @@
      
      void func(struct drm_crtc *crtc,
      		struct drm_crtc_state *old_state)
      {
      	... when != old_state
      }
      
      @ adds_old_state depends on crtc_atomic_func && !ignores_old_state @
      identifier crtc_atomic_func.func;
      identifier crtc, old_state;
      @@
      
      void func(struct drm_crtc *crtc, struct drm_crtc_state *old_state)
      {
      +	struct drm_crtc_state *old_state = drm_atomic_get_old_crtc_state(state, crtc);
      	...
      }
      
      @ depends on crtc_atomic_func @
      identifier crtc_atomic_func.func;
      expression E;
      type T;
      @@
      
      void func(...)
      {
      	...
      -	T state = E;
      +	T crtc_state = E;
      	<+...
      -	state
      +	crtc_state
      	...+>
      
      }
      
      @ depends on crtc_atomic_func @
      identifier crtc_atomic_func.func;
      type T;
      @@
      
      void func(...)
      {
      	...
      -	T state;
      +	T crtc_state;
      	<+...
      -	state
      +	crtc_state
      	...+>
      
      }
      
      @ depends on crtc_atomic_func @
      identifier crtc_atomic_func.func;
      identifier old_state;
      identifier crtc;
      @@
      
      void func(struct drm_crtc *crtc,
      -	       struct drm_crtc_state *old_state
      +	       struct drm_atomic_state *state
      	       )
      		{ ... }
      
      @ include depends on adds_old_state @
      @@
      
       #include <drm/drm_atomic.h>
      
      @ no_include depends on !include && adds_old_state @
      @@
      
      + #include <drm/drm_atomic.h>
        #include <drm/...>
      Signed-off-by: NMaxime Ripard <maxime@cerno.tech>
      Acked-by: NDaniel Vetter <daniel.vetter@ffwll.ch>
      Link: https://patchwork.freedesktop.org/patch/msgid/845aa10ef171fc0ea060495efef142a0c13f7870.1602161031.git-series.maxime@cerno.tech
      351f950d
  17. 08 10月, 2020 1 次提交
  18. 15 9月, 2020 2 次提交
  19. 18 8月, 2020 1 次提交
  20. 24 6月, 2020 1 次提交
  21. 29 5月, 2020 1 次提交
  22. 31 1月, 2020 3 次提交
    • B
      drm/bridge: Add the necessary bits to support bus format negotiation · f32df58a
      Boris Brezillon 提交于
      drm_bridge_state is extended to describe the input and output bus
      configurations. These bus configurations are exposed through the
      drm_bus_cfg struct which encodes the configuration of a physical
      bus between two components in an output pipeline, usually between
      two bridges, an encoder and a bridge, or a bridge and a connector.
      
      The bus configuration is stored in drm_bridge_state separately for
      the input and output buses, as seen from the point of view of each
      bridge. The bus configuration of a bridge output is usually identical
      to the configuration of the next bridge's input, but may differ if
      the signals are modified between the two bridges, for instance by an
      inverter on the board. The input and output configurations of a
      bridge may differ if the bridge modifies the signals internally,
      for instance by performing format conversion, or*modifying signals
      polarities.
      
      Bus format negotiation is automated by the core, drivers just have
      to implement the ->atomic_get_{output,input}_bus_fmts() hooks if they
      want to take part to this negotiation. Negotiation happens in reverse
      order, starting from the last element of the chain (the one directly
      connected to the display) up to the first element of the chain (the one
      connected to the encoder).
      During this negotiation all supported formats are tested until we find
      one that works, meaning that the formats array should be in decreasing
      preference order (assuming the driver has a preference order).
      
      Note that the bus format negotiation works even if some elements in the
      chain don't implement the ->atomic_get_{output,input}_bus_fmts() hooks.
      In that case, the core advertises only MEDIA_BUS_FMT_FIXED and lets
      the previous bridge element decide what to do (most of the time, bridge
      drivers will pick a default bus format or extract this piece of
      information from somewhere else, like a FW property).
      
      v10:
      * Add changelog to the commit message
      
      v9:
      * No changes
      
      v8:
      * Fix a test in drm_atomic_bridge_chain_select_bus_fmts() (Reported by
        Jonas)
      
      v7:
      * Adapt the code to deal with the fact that not all bridges in the
        chain have a bridge state
      
      v5 -> v6:
      * No changes
      
      v4:
      * Enhance the doc
      * Fix typos
      * Rename some parameters/fields
      * Reword the commit message
      
      v3:
      * Fix the commit message (Reported by Laurent)
      * Document the fact that bus formats should not be directly modified by
        drivers (Suggested by Laurent)
      * Document the fact that format order matters (Suggested by Laurent)
      * Propagate bus flags by default
      * Document the fact that drivers can tweak bus flags if needed
      * Let ->atomic_get_{output,input}_bus_fmts() allocate the bus format
        array (Suggested by Laurent)
      * Add a drm_atomic_helper_bridge_propagate_bus_fmt()
      * Mandate that bridge drivers return accurate input_fmts even if they
        are known to be the first element in the bridge chain
      
      v2:
      * Rework things to support more complex use cases
      Signed-off-by: NBoris Brezillon <boris.brezillon@collabora.com>
      Signed-off-by: NNeil Armstrong <narmstrong@baylibre.com>
      [narmstrong: fixed doc in include/drm/drm_bridge.h:69 fmt->format]
      Reviewed-by: NJernej Skrabec <jernej.skrabec@siol.net>
      Tested-by: NJonas Karlman <jonas@kwiboo.se>
      Link: https://patchwork.freedesktop.org/patch/msgid/20200128135514.108171-7-boris.brezillon@collabora.com
      f32df58a
    • B
      drm/bridge: Add an ->atomic_check() hook · 5061b8a9
      Boris Brezillon 提交于
      So that bridge drivers have a way to check/reject an atomic operation.
      The drm_atomic_bridge_chain_check() (which is just a wrapper around
      the ->atomic_check() hook) is called in place of
      drm_bridge_chain_mode_fixup() (when ->atomic_check() is not implemented,
      the core falls back on ->mode_fixup(), so the behavior should stay
      the same for existing bridge drivers).
      
      v10:
      * Add changelog to the commit message
      
      v8 -> v9:
      * No changes
      
      v7:
      * Fix a NULL pointer dereference
      
      v5 -> v6:
      * No changes
      
      v4:
      * Add R-bs
      
      v3:
      * No changes
      
      v2:
      * Clarify the fact that ->atomic_check() is replacing ->mode_fixup()
      Signed-off-by: NBoris Brezillon <boris.brezillon@collabora.com>
      Reviewed-by: NNeil Armstrong <narmstrong@baylibre.com>
      Reviewed-by: NLaurent Pinchart <laurent.pinchart@ideasonboard.com>
      Signed-off-by: NNeil Armstrong <narmstrong@baylibre.com>
      Reviewed by: Jernej Skrabec <jernej.skrabec@siol.net>
      Tested-by: NJonas Karlman <jonas@kwiboo.se>
      Link: https://patchwork.freedesktop.org/patch/msgid/20200128135514.108171-6-boris.brezillon@collabora.com
      5061b8a9
    • B
      drm/bridge: Add a drm_bridge_state object · 75146591
      Boris Brezillon 提交于
      One of the last remaining objects to not have its atomic state.
      
      This is being motivated by our attempt to support runtime bus-format
      negotiation between elements of the bridge chain.
      This patch just paves the road for such a feature by adding a new
      drm_bridge_state object inheriting from drm_private_obj so we can
      re-use some of the existing state initialization/tracking logic.
      
      v10:
      * Add changelog to the commit message
      
      v9:
      * Clarify the fact that the bridge->atomic_reset() and
        {connector,plane,crtc,...}->reset() semantics are different
      * Move the drm_atomic_private_obj_init() call back to
        drm_bridge_attach()
      * Check the presence of ->atomic_duplicate_state instead of
        ->atomic_reset in drm_atomic_add_encoder_bridges()
      * Fix copy&paste errors in the atomic bridge state helpers doc
      * Add A-b/R-b tags
      
      v8:
      * Move bridge state helpers out of the CONFIG_DEBUGFS section
      
      v7:
      * Move helpers, struct-defs, ... to atomic helper files to avoid the
        drm -> drm_kms_helper -> drm circular dep
      * Stop providing default implementation for atomic state reset,
        duplicate and destroy hooks (has to do with the helper/core split)
      * Drop all R-b/T-b as helpers have now be moved to other places
      
      v6:
      * Made helpers private, removed doc and moved them to satisfy dependencies
      * Renamed helpers to _default_
      
      v5:
      * Re-introduced the helpers from v4
      
      v4:
      * Fix the doc
      * Kill default helpers (inlined)
      * Fix drm_atomic_get_bridge_state() to check for an ERR_PTR()
      * Add Neil's R-b
      
      v3:
      * No changes
      
      v2:
      * Use drm_for_each_bridge_in_chain()
      * Rename helpers to be more consistent with the rest of the DRM API
      * Improve/fix the doc
      Signed-off-by: NBoris Brezillon <boris.brezillon@collabora.com>
      Signed-off-by: NNeil Armstrong <narmstrong@baylibre.com>
      Reviewed-by: NNeil Armstrong <narmstrong@baylibre.com>
      Acked-by: NDaniel Vetter <daniel.vetter@ffwll.ch>
      Link: https://patchwork.freedesktop.org/patch/msgid/20200128135514.108171-2-boris.brezillon@collabora.com
      75146591
  23. 30 1月, 2020 1 次提交
    • T
      drm: Initialize struct drm_crtc_state.no_vblank from device settings · 7beb691f
      Thomas Zimmermann 提交于
      At the end of a commit, atomic helpers can generate a fake VBLANK event
      automatically. Originally implemented for writeback connectors, the
      functionality can be used by any driver and/or hardware without proper
      VBLANK interrupt.
      
      The patch updates the documentation to make this behaviour official:
      settings struct drm_crtc_state.no_vblank to true enables automatic
      generation of fake VBLANK events.
      
      The new interface drm_dev_has_vblank() returns true if vblanking has
      been initialized for a device, or false otherwise. Atomic helpers use
      this function when initializing no_vblank in the CRTC state in
      drm_atomic_helper_check_modeset(). If vblanking has been initialized
      for a device, no_blank is disabled. Otherwise it's enabled. Hence,
      atomic helpers will automatically send out fake VBLANK events with any
      driver that did not initialize vblanking.
      
      v5:
      	* more precise documentation and commit message
      v4:
      	* replace drm_crtc_has_vblank() with drm_dev_has_vblank()
      	* add drm_dev_has_vblank() in this patch
      	* move driver changes into separate patches
      v3:
      	* squash all related changes patches into this patch
      Signed-off-by: NThomas Zimmermann <tzimmermann@suse.de>
      Acked-by: NGerd Hoffmann <kraxel@redhat.com>
      Reviewed-by: NDaniel Vetter <daniel.vetter@ffwll.ch>
      Link: https://patchwork.freedesktop.org/patch/msgid/20200129120531.6891-2-tzimmermann@suse.de
      7beb691f
  24. 08 1月, 2020 2 次提交
  25. 07 1月, 2020 2 次提交
  26. 22 12月, 2019 2 次提交
  27. 11 12月, 2019 1 次提交
  28. 09 12月, 2019 2 次提交