Commit 2f324b42b7b24a48fe3f8a7af60ec3c9024255fa

Authored by Daniel Vetter
1 parent acf24a395c

drm/crtc-helper: Transitional functions using atomic plane helpers

These two functions allow drivers to reuse their atomic plane helpers
functions for the primary plane to implement the interfaces required
by the crtc helpers for the legacy ->set_config callback.

This is purely transitional and won't be used once the driver is fully
converted. But it allows partial conversions to the atomic plane
helpers which are functional.

v2:
- Use ->atomic_duplicate_state if available.
- Don't forget to run crtc_funcs->atomic_check.

v3: Shift source coordinates correctly for 16.16 fixed point.

v4: Don't forget to call ->atomic_destroy_state if available.

v5: Fixup kerneldoc.

v6: Reuse the plane_commit function from the transitional plane
helpers to avoid too much duplication.

v7:
- Remove some stale comment.
- Correctly handle the lack of plane->state object, necessary for
  transitional use.

v8: Fixup an embarrassing h/vdisplay mixup.

Reviewed-by: Sean Paul <seanpaul@chromium.org>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>

Showing 5 changed files with 130 additions and 5 deletions Side-by-side Diff

drivers/gpu/drm/drm_crtc_helper.c
... ... @@ -38,6 +38,7 @@
38 38 #include <drm/drm_fourcc.h>
39 39 #include <drm/drm_crtc_helper.h>
40 40 #include <drm/drm_fb_helper.h>
  41 +#include <drm/drm_plane_helper.h>
41 42 #include <drm/drm_edid.h>
42 43  
43 44 MODULE_AUTHOR("David Airlie, Jesse Barnes");
... ... @@ -888,4 +889,113 @@
888 889 drm_modeset_unlock_all(dev);
889 890 }
890 891 EXPORT_SYMBOL(drm_helper_resume_force_mode);
  892 +
  893 +/**
  894 + * drm_helper_crtc_mode_set - mode_set implementation for atomic plane helpers
  895 + * @crtc: DRM CRTC
  896 + * @mode: DRM display mode which userspace requested
  897 + * @adjusted_mode: DRM display mode adjusted by ->mode_fixup callbacks
  898 + * @x: x offset of the CRTC scanout area on the underlying framebuffer
  899 + * @y: y offset of the CRTC scanout area on the underlying framebuffer
  900 + * @old_fb: previous framebuffer
  901 + *
  902 + * This function implements a callback useable as the ->mode_set callback
  903 + * required by the crtc helpers. Besides the atomic plane helper functions for
  904 + * the primary plane the driver must also provide the ->mode_set_nofb callback
  905 + * to set up the crtc.
  906 + *
  907 + * This is a transitional helper useful for converting drivers to the atomic
  908 + * interfaces.
  909 + */
  910 +int drm_helper_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode,
  911 + struct drm_display_mode *adjusted_mode, int x, int y,
  912 + struct drm_framebuffer *old_fb)
  913 +{
  914 + struct drm_crtc_state *crtc_state;
  915 + struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
  916 + int ret;
  917 +
  918 + if (crtc->funcs->atomic_duplicate_state)
  919 + crtc_state = crtc->funcs->atomic_duplicate_state(crtc);
  920 + else if (crtc->state)
  921 + crtc_state = kmemdup(crtc->state, sizeof(*crtc_state),
  922 + GFP_KERNEL);
  923 + else
  924 + crtc_state = kzalloc(sizeof(*crtc_state), GFP_KERNEL);
  925 + if (!crtc_state)
  926 + return -ENOMEM;
  927 +
  928 + crtc_state->enable = true;
  929 + crtc_state->planes_changed = true;
  930 + drm_mode_copy(&crtc_state->mode, mode);
  931 + drm_mode_copy(&crtc_state->adjusted_mode, adjusted_mode);
  932 +
  933 + if (crtc_funcs->atomic_check) {
  934 + ret = crtc_funcs->atomic_check(crtc, crtc_state);
  935 + if (ret) {
  936 + kfree(crtc_state);
  937 +
  938 + return ret;
  939 + }
  940 + }
  941 +
  942 + swap(crtc->state, crtc_state);
  943 +
  944 + crtc_funcs->mode_set_nofb(crtc);
  945 +
  946 + if (crtc_state) {
  947 + if (crtc->funcs->atomic_destroy_state)
  948 + crtc->funcs->atomic_destroy_state(crtc, crtc_state);
  949 + else
  950 + kfree(crtc_state);
  951 + }
  952 +
  953 + return drm_helper_crtc_mode_set_base(crtc, x, y, old_fb);
  954 +}
  955 +EXPORT_SYMBOL(drm_helper_crtc_mode_set);
  956 +
  957 +/**
  958 + * drm_helper_crtc_mode_set_base - mode_set_base implementation for atomic plane helpers
  959 + * @crtc: DRM CRTC
  960 + * @x: x offset of the CRTC scanout area on the underlying framebuffer
  961 + * @y: y offset of the CRTC scanout area on the underlying framebuffer
  962 + * @old_fb: previous framebuffer
  963 + *
  964 + * This function implements a callback useable as the ->mode_set_base used
  965 + * required by the crtc helpers. The driver must provide the atomic plane helper
  966 + * functions for the primary plane.
  967 + *
  968 + * This is a transitional helper useful for converting drivers to the atomic
  969 + * interfaces.
  970 + */
  971 +int drm_helper_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
  972 + struct drm_framebuffer *old_fb)
  973 +{
  974 + struct drm_plane_state *plane_state;
  975 + struct drm_plane *plane = crtc->primary;
  976 +
  977 + if (plane->funcs->atomic_duplicate_state)
  978 + plane_state = plane->funcs->atomic_duplicate_state(plane);
  979 + else if (plane->state)
  980 + plane_state = kmemdup(plane->state, sizeof(*plane_state),
  981 + GFP_KERNEL);
  982 + else
  983 + plane_state = kzalloc(sizeof(*plane_state), GFP_KERNEL);
  984 + if (!plane_state)
  985 + return -ENOMEM;
  986 +
  987 + plane_state->crtc = crtc;
  988 + plane_state->fb = crtc->primary->fb;
  989 + plane_state->crtc_x = 0;
  990 + plane_state->crtc_y = 0;
  991 + plane_state->crtc_h = crtc->mode.vdisplay;
  992 + plane_state->crtc_w = crtc->mode.hdisplay;
  993 + plane_state->src_x = x << 16;
  994 + plane_state->src_y = y << 16;
  995 + plane_state->src_h = crtc->mode.vdisplay << 16;
  996 + plane_state->src_w = crtc->mode.hdisplay << 16;
  997 +
  998 + return drm_plane_helper_commit(plane, plane_state, old_fb);
  999 +}
  1000 +EXPORT_SYMBOL(drm_helper_crtc_mode_set_base);
drivers/gpu/drm/drm_plane_helper.c
... ... @@ -370,9 +370,9 @@
370 370 }
371 371 EXPORT_SYMBOL(drm_crtc_init);
372 372  
373   -static int
374   -plane_commit(struct drm_plane *plane, struct drm_plane_state *plane_state,
375   - struct drm_framebuffer *old_fb)
  373 +int drm_plane_helper_commit(struct drm_plane *plane,
  374 + struct drm_plane_state *plane_state,
  375 + struct drm_framebuffer *old_fb)
376 376 {
377 377 struct drm_plane_helper_funcs *plane_funcs;
378 378 struct drm_crtc *crtc[2];
... ... @@ -497,7 +497,7 @@
497 497 plane_state->src_h = src_h;
498 498 plane_state->src_w = src_w;
499 499  
500   - return plane_commit(plane, plane_state, plane->fb);
  500 + return drm_plane_helper_commit(plane, plane_state, plane->fb);
501 501 }
502 502 EXPORT_SYMBOL(drm_plane_helper_update);
503 503  
... ... @@ -536,7 +536,7 @@
536 536 plane_state->crtc = NULL;
537 537 plane_state->fb = NULL;
538 538  
539   - return plane_commit(plane, plane_state, plane->fb);
  539 + return drm_plane_helper_commit(plane, plane_state, plane->fb);
540 540 }
541 541 EXPORT_SYMBOL(drm_plane_helper_disable);
include/drm/drm_crtc.h
... ... @@ -230,6 +230,7 @@
230 230 * struct drm_crtc_state - mutable CRTC state
231 231 * @enable: whether the CRTC should be enabled, gates all other state
232 232 * @planes_changed: for use by helpers and drivers when computing state updates
  233 + * @adjusted_mode: for use by helpers and drivers to compute adjusted mode timings
233 234 * @mode: current mode timings
234 235 * @event: optional pointer to a DRM event to signal upon completion of the
235 236 * state update
... ... @@ -240,6 +241,9 @@
240 241  
241 242 /* computed state bits used by helpers and drivers */
242 243 bool planes_changed : 1;
  244 +
  245 + /* adjusted_mode: for use by helpers and drivers */
  246 + struct drm_display_mode adjusted_mode;
243 247  
244 248 struct drm_display_mode mode;
245 249  
include/drm/drm_crtc_helper.h
... ... @@ -68,6 +68,7 @@
68 68 int (*mode_set)(struct drm_crtc *crtc, struct drm_display_mode *mode,
69 69 struct drm_display_mode *adjusted_mode, int x, int y,
70 70 struct drm_framebuffer *old_fb);
  71 + void (*mode_set_nofb)(struct drm_crtc *crtc);
71 72  
72 73 /* Move the crtc on the current fb to the given position *optional* */
73 74 int (*mode_set_base)(struct drm_crtc *crtc, int x, int y,
... ... @@ -166,6 +167,12 @@
166 167 }
167 168  
168 169 extern void drm_helper_resume_force_mode(struct drm_device *dev);
  170 +
  171 +int drm_helper_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode,
  172 + struct drm_display_mode *adjusted_mode, int x, int y,
  173 + struct drm_framebuffer *old_fb);
  174 +int drm_helper_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
  175 + struct drm_framebuffer *old_fb);
169 176  
170 177 /* drm_probe_helper.c */
171 178 extern int drm_helper_probe_single_connector_modes(struct drm_connector
include/drm/drm_plane_helper.h
... ... @@ -103,5 +103,9 @@
103 103 uint32_t src_w, uint32_t src_h);
104 104 int drm_plane_helper_disable(struct drm_plane *plane);
105 105  
  106 +/* For use by drm_crtc_helper.c */
  107 +int drm_plane_helper_commit(struct drm_plane *plane,
  108 + struct drm_plane_state *plane_state,
  109 + struct drm_framebuffer *old_fb);
106 110 #endif