Merge the CRTC functions of ofdrm and simpledrm. Replace the code in each driver with the shared helpers. Set up callbacks with initializer macros. Ofdrm supports a gamma LUT, while simpledrm does not. So far ofdrm's LUT size has been hard-coded in the driver CRTC's atomic_check helper. Now pass the size of the LUT to the sysfb device. Ofdrm's custom atomic_flush is still required to apply changes to the LUT. Simpledrm passes a LUT size of 0, which disables the gamma LUT. Signed-off-by: Thomas Zimmermann <tzimmermann@xxxxxxx> --- drivers/gpu/drm/sysfb/drm_sysfb_helper.c | 40 ++++++++++++++++++ drivers/gpu/drm/sysfb/drm_sysfb_helper.h | 9 ++++ drivers/gpu/drm/sysfb/ofdrm.c | 53 ++++-------------------- drivers/gpu/drm/sysfb/simpledrm.c | 17 +------- 4 files changed, 57 insertions(+), 62 deletions(-) diff --git a/drivers/gpu/drm/sysfb/drm_sysfb_helper.c b/drivers/gpu/drm/sysfb/drm_sysfb_helper.c index 368061b6f514..ed9139f56e59 100644 --- a/drivers/gpu/drm/sysfb/drm_sysfb_helper.c +++ b/drivers/gpu/drm/sysfb/drm_sysfb_helper.c @@ -4,6 +4,8 @@ #include <linux/slab.h> #include <linux/module.h> +#include <drm/drm_atomic.h> +#include <drm/drm_atomic_helper.h> #include <drm/drm_atomic_state_helper.h> #include <drm/drm_print.h> #include <drm/drm_probe_helper.h> @@ -48,6 +50,44 @@ static void drm_sysfb_crtc_state_destroy(struct drm_sysfb_crtc_state *sysfb_crtc kfree(sysfb_crtc_state); } +enum drm_mode_status drm_sysfb_crtc_helper_mode_valid(struct drm_crtc *crtc, + const struct drm_display_mode *mode) +{ + struct drm_sysfb_device *sysfb = to_drm_sysfb_device(crtc->dev); + + return drm_crtc_helper_mode_valid_fixed(crtc, mode, &sysfb->fb_mode); +} +EXPORT_SYMBOL(drm_sysfb_crtc_helper_mode_valid); + +int drm_sysfb_crtc_helper_atomic_check(struct drm_crtc *crtc, struct drm_atomic_state *new_state) +{ + struct drm_device *dev = crtc->dev; + struct drm_sysfb_device *sysfb = to_drm_sysfb_device(dev); + struct drm_crtc_state *new_crtc_state = drm_atomic_get_new_crtc_state(new_state, crtc); + int ret; + + if (!new_crtc_state->enable) + return 0; + + ret = drm_atomic_helper_check_crtc_primary_plane(new_crtc_state); + if (ret) + return ret; + + if (new_crtc_state->color_mgmt_changed) { + const size_t gamma_lut_length = + sysfb->fb_gamma_lut_size * sizeof(struct drm_color_lut); + const struct drm_property_blob *gamma_lut = new_crtc_state->gamma_lut; + + if (gamma_lut && (gamma_lut->length != gamma_lut_length)) { + drm_dbg(dev, "Incorrect gamma_lut length %zu\n", gamma_lut->length); + return -EINVAL; + } + } + + return 0; +} +EXPORT_SYMBOL(drm_sysfb_crtc_helper_atomic_check); + void drm_sysfb_crtc_reset(struct drm_crtc *crtc) { struct drm_sysfb_crtc_state *sysfb_crtc_state; diff --git a/drivers/gpu/drm/sysfb/drm_sysfb_helper.h b/drivers/gpu/drm/sysfb/drm_sysfb_helper.h index 91da27405a46..c8e5ac6b9b63 100644 --- a/drivers/gpu/drm/sysfb/drm_sysfb_helper.h +++ b/drivers/gpu/drm/sysfb/drm_sysfb_helper.h @@ -28,6 +28,7 @@ struct drm_sysfb_device { struct drm_display_mode fb_mode; const struct drm_format_info *fb_format; unsigned int fb_pitch; + unsigned int fb_gamma_lut_size; /* hardware-framebuffer kernel address */ struct iosys_map fb_addr; @@ -55,6 +56,14 @@ to_drm_sysfb_crtc_state(struct drm_crtc_state *base) return container_of(base, struct drm_sysfb_crtc_state, base); } +enum drm_mode_status drm_sysfb_crtc_helper_mode_valid(struct drm_crtc *crtc, + const struct drm_display_mode *mode); +int drm_sysfb_crtc_helper_atomic_check(struct drm_crtc *crtc, struct drm_atomic_state *new_state); + +#define DRM_SYSFB_CRTC_HELPER_FUNCS \ + .mode_valid = drm_sysfb_crtc_helper_mode_valid, \ + .atomic_check = drm_sysfb_crtc_helper_atomic_check + void drm_sysfb_crtc_reset(struct drm_crtc *crtc); struct drm_crtc_state *drm_sysfb_crtc_atomic_duplicate_state(struct drm_crtc *crtc); void drm_sysfb_crtc_atomic_destroy_state(struct drm_crtc *crtc, struct drm_crtc_state *crtc_state); diff --git a/drivers/gpu/drm/sysfb/ofdrm.c b/drivers/gpu/drm/sysfb/ofdrm.c index faaf35ba17f3..29dbb69dd7ac 100644 --- a/drivers/gpu/drm/sysfb/ofdrm.c +++ b/drivers/gpu/drm/sysfb/ofdrm.c @@ -862,42 +862,6 @@ static const struct drm_plane_funcs ofdrm_primary_plane_funcs = { DRM_GEM_SHADOW_PLANE_FUNCS, }; -static enum drm_mode_status ofdrm_crtc_helper_mode_valid(struct drm_crtc *crtc, - const struct drm_display_mode *mode) -{ - struct drm_sysfb_device *sysfb = to_drm_sysfb_device(crtc->dev); - - return drm_crtc_helper_mode_valid_fixed(crtc, mode, &sysfb->fb_mode); -} - -static int ofdrm_crtc_helper_atomic_check(struct drm_crtc *crtc, - struct drm_atomic_state *new_state) -{ - static const size_t gamma_lut_length = OFDRM_GAMMA_LUT_SIZE * sizeof(struct drm_color_lut); - - struct drm_device *dev = crtc->dev; - struct drm_crtc_state *new_crtc_state = drm_atomic_get_new_crtc_state(new_state, crtc); - int ret; - - if (!new_crtc_state->enable) - return 0; - - ret = drm_atomic_helper_check_crtc_primary_plane(new_crtc_state); - if (ret) - return ret; - - if (new_crtc_state->color_mgmt_changed) { - struct drm_property_blob *gamma_lut = new_crtc_state->gamma_lut; - - if (gamma_lut && (gamma_lut->length != gamma_lut_length)) { - drm_dbg(dev, "Incorrect gamma_lut length %zu\n", gamma_lut->length); - return -EINVAL; - } - } - - return 0; -} - static void ofdrm_crtc_helper_atomic_flush(struct drm_crtc *crtc, struct drm_atomic_state *state) { struct ofdrm_device *odev = ofdrm_device_of_dev(crtc->dev); @@ -914,14 +878,8 @@ static void ofdrm_crtc_helper_atomic_flush(struct drm_crtc *crtc, struct drm_ato } } -/* - * The CRTC is always enabled. Screen updates are performed by - * the primary plane's atomic_update function. Disabling clears - * the screen in the primary plane's atomic_disable function. - */ static const struct drm_crtc_helper_funcs ofdrm_crtc_helper_funcs = { - .mode_valid = ofdrm_crtc_helper_mode_valid, - .atomic_check = ofdrm_crtc_helper_atomic_check, + DRM_SYSFB_CRTC_HELPER_FUNCS, .atomic_flush = ofdrm_crtc_helper_atomic_flush, }; @@ -1163,6 +1121,8 @@ static struct ofdrm_device *ofdrm_device_create(struct drm_driver *drv, sysfb->fb_mode = drm_sysfb_mode(width, height, 0, 0); sysfb->fb_format = format; sysfb->fb_pitch = linebytes; + if (odev->cmap_base) + sysfb->fb_gamma_lut_size = OFDRM_GAMMA_LUT_SIZE; drm_dbg(dev, "display mode={" DRM_MODE_FMT "}\n", DRM_MODE_ARG(&sysfb->fb_mode)); drm_dbg(dev, "framebuffer format=%p4cc, size=%dx%d, linebytes=%d byte\n", @@ -1211,9 +1171,10 @@ static struct ofdrm_device *ofdrm_device_create(struct drm_driver *drv, return ERR_PTR(ret); drm_crtc_helper_add(crtc, &ofdrm_crtc_helper_funcs); - if (odev->cmap_base) { - drm_mode_crtc_set_gamma_size(crtc, OFDRM_GAMMA_LUT_SIZE); - drm_crtc_enable_color_mgmt(crtc, 0, false, OFDRM_GAMMA_LUT_SIZE); + if (sysfb->fb_gamma_lut_size) { + ret = drm_mode_crtc_set_gamma_size(crtc, sysfb->fb_gamma_lut_size); + if (!ret) + drm_crtc_enable_color_mgmt(crtc, 0, false, sysfb->fb_gamma_lut_size); } /* Encoder */ diff --git a/drivers/gpu/drm/sysfb/simpledrm.c b/drivers/gpu/drm/sysfb/simpledrm.c index 986177e4a0f0..9616e67ea42c 100644 --- a/drivers/gpu/drm/sysfb/simpledrm.c +++ b/drivers/gpu/drm/sysfb/simpledrm.c @@ -14,7 +14,6 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_state_helper.h> #include <drm/drm_connector.h> -#include <drm/drm_crtc_helper.h> #include <drm/drm_damage_helper.h> #include <drm/drm_device.h> #include <drm/drm_drv.h> @@ -696,22 +695,8 @@ static const struct drm_plane_funcs simpledrm_primary_plane_funcs = { DRM_GEM_SHADOW_PLANE_FUNCS, }; -static enum drm_mode_status simpledrm_crtc_helper_mode_valid(struct drm_crtc *crtc, - const struct drm_display_mode *mode) -{ - struct drm_sysfb_device *sysfb = to_drm_sysfb_device(crtc->dev); - - return drm_crtc_helper_mode_valid_fixed(crtc, mode, &sysfb->fb_mode); -} - -/* - * The CRTC is always enabled. Screen updates are performed by - * the primary plane's atomic_update function. Disabling clears - * the screen in the primary plane's atomic_disable function. - */ static const struct drm_crtc_helper_funcs simpledrm_crtc_helper_funcs = { - .mode_valid = simpledrm_crtc_helper_mode_valid, - .atomic_check = drm_crtc_helper_atomic_check, + DRM_SYSFB_CRTC_HELPER_FUNCS, }; static const struct drm_crtc_funcs simpledrm_crtc_funcs = { -- 2.48.1