From d25654b3fad9906ca80912701fd4bd6e2419f54d Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Mon, 5 Sep 2022 16:16:45 +0200 Subject: drm/probe-helper: Add drm_connector_helper_get_modes_fixed() Add drm_connector_helper_get_modes_fixed(), which duplicates a single display mode for a connector. Convert drivers. v2: * rename 'static' and 'hw' to 'fixed' everywhere * fix typo 'there' to 'their' (Sam) Signed-off-by: Thomas Zimmermann Reviewed-by: Sam Ravnborg Link: https://patchwork.freedesktop.org/patch/msgid/20220905141648.22013-2-tzimmermann@suse.de --- include/drm/drm_probe_helper.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'include/drm') diff --git a/include/drm/drm_probe_helper.h b/include/drm/drm_probe_helper.h index 8075e02aa865..d261838a7790 100644 --- a/include/drm/drm_probe_helper.h +++ b/include/drm/drm_probe_helper.h @@ -7,6 +7,7 @@ struct drm_connector; struct drm_device; +struct drm_display_mode; struct drm_modeset_acquire_ctx; int drm_helper_probe_single_connector_modes(struct drm_connector @@ -27,6 +28,8 @@ void drm_kms_helper_poll_enable(struct drm_device *dev); bool drm_kms_helper_is_poll_worker(void); int drm_connector_helper_get_modes_from_ddc(struct drm_connector *connector); +int drm_connector_helper_get_modes_fixed(struct drm_connector *connector, + const struct drm_display_mode *fixed_mode); int drm_connector_helper_get_modes(struct drm_connector *connector); #endif -- cgit v1.2.3 From 216b9bbaeaea96b7f05c220f61855d174be972d8 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Mon, 5 Sep 2022 16:16:46 +0200 Subject: drm/probe-helper: Add drm_crtc_helper_mode_valid_fixed() Add drm_crtc_helper_mode_valid_fixed(), which validates a given mode against a display hardware's mode. Convert simpledrm and use it in a few other drivers with static modes. v4: * remove empty line after opening brace v2: * rename 'static' and 'hw' to 'fixed' everywhere Signed-off-by: Thomas Zimmermann Reviewed-by: Sam Ravnborg Link: https://patchwork.freedesktop.org/patch/msgid/20220905141648.22013-3-tzimmermann@suse.de --- drivers/gpu/drm/drm_mipi_dbi.c | 18 ++++++++++++++++++ drivers/gpu/drm/drm_probe_helper.c | 24 ++++++++++++++++++++++++ drivers/gpu/drm/panel/panel-ilitek-ili9341.c | 1 + drivers/gpu/drm/tiny/hx8357d.c | 1 + drivers/gpu/drm/tiny/ili9163.c | 1 + drivers/gpu/drm/tiny/ili9341.c | 1 + drivers/gpu/drm/tiny/ili9486.c | 1 + drivers/gpu/drm/tiny/mi0283qt.c | 1 + drivers/gpu/drm/tiny/panel-mipi-dbi.c | 1 + drivers/gpu/drm/tiny/repaper.c | 10 ++++++++++ drivers/gpu/drm/tiny/simpledrm.c | 10 +--------- drivers/gpu/drm/tiny/st7735r.c | 1 + include/drm/drm_mipi_dbi.h | 2 ++ include/drm/drm_probe_helper.h | 8 ++++++-- 14 files changed, 69 insertions(+), 11 deletions(-) (limited to 'include/drm') diff --git a/drivers/gpu/drm/drm_mipi_dbi.c b/drivers/gpu/drm/drm_mipi_dbi.c index de2a5be67415..a6ac56580876 100644 --- a/drivers/gpu/drm/drm_mipi_dbi.c +++ b/drivers/gpu/drm/drm_mipi_dbi.c @@ -309,6 +309,24 @@ err_drm_dev_exit: drm_dev_exit(idx); } +/** + * mipi_dbi_pipe_mode_valid - MIPI DBI mode-valid helper + * @pipe: Simple display pipe + * @mode: The mode to test + * + * This function validates a given display mode against the MIPI DBI's hardware + * display. Drivers can use this as their &drm_simple_display_pipe_funcs->mode_valid + * callback. + */ +enum drm_mode_status mipi_dbi_pipe_mode_valid(struct drm_simple_display_pipe *pipe, + const struct drm_display_mode *mode) +{ + struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(pipe->crtc.dev); + + return drm_crtc_helper_mode_valid_fixed(&pipe->crtc, mode, &dbidev->mode); +} +EXPORT_SYMBOL(mipi_dbi_pipe_mode_valid); + /** * mipi_dbi_pipe_update - Display pipe update helper * @pipe: Simple display pipe diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c index 818150a1b3b0..69b0b2b9cc1c 100644 --- a/drivers/gpu/drm/drm_probe_helper.c +++ b/drivers/gpu/drm/drm_probe_helper.c @@ -1014,6 +1014,30 @@ bool drm_helper_hpd_irq_event(struct drm_device *dev) } EXPORT_SYMBOL(drm_helper_hpd_irq_event); +/** + * drm_crtc_helper_mode_valid_fixed - Validates a display mode + * @crtc: the crtc + * @mode: the mode to validate + * @fixed_mode: the display hardware's mode + * + * Returns: + * MODE_OK on success, or another mode-status code otherwise. + */ +enum drm_mode_status drm_crtc_helper_mode_valid_fixed(struct drm_crtc *crtc, + const struct drm_display_mode *mode, + const struct drm_display_mode *fixed_mode) +{ + if (mode->hdisplay != fixed_mode->hdisplay && mode->vdisplay != fixed_mode->vdisplay) + return MODE_ONE_SIZE; + else if (mode->hdisplay != fixed_mode->hdisplay) + return MODE_ONE_WIDTH; + else if (mode->vdisplay != fixed_mode->vdisplay) + return MODE_ONE_HEIGHT; + + return MODE_OK; +} +EXPORT_SYMBOL(drm_crtc_helper_mode_valid_fixed); + /** * drm_connector_helper_get_modes_from_ddc - Updates the connector's EDID * property from the connector's diff --git a/drivers/gpu/drm/panel/panel-ilitek-ili9341.c b/drivers/gpu/drm/panel/panel-ilitek-ili9341.c index 7da09e34385d..39dc40cf681f 100644 --- a/drivers/gpu/drm/panel/panel-ilitek-ili9341.c +++ b/drivers/gpu/drm/panel/panel-ilitek-ili9341.c @@ -576,6 +576,7 @@ out_exit: } static const struct drm_simple_display_pipe_funcs ili9341_dbi_funcs = { + .mode_valid = mipi_dbi_pipe_mode_valid, .enable = ili9341_dbi_enable, .disable = mipi_dbi_pipe_disable, .update = mipi_dbi_pipe_update, diff --git a/drivers/gpu/drm/tiny/hx8357d.c b/drivers/gpu/drm/tiny/hx8357d.c index 57f229a785bf..48c24aa8c28a 100644 --- a/drivers/gpu/drm/tiny/hx8357d.c +++ b/drivers/gpu/drm/tiny/hx8357d.c @@ -181,6 +181,7 @@ out_exit: } static const struct drm_simple_display_pipe_funcs hx8357d_pipe_funcs = { + .mode_valid = mipi_dbi_pipe_mode_valid, .enable = yx240qv29_enable, .disable = mipi_dbi_pipe_disable, .update = mipi_dbi_pipe_update, diff --git a/drivers/gpu/drm/tiny/ili9163.c b/drivers/gpu/drm/tiny/ili9163.c index 86439e50e304..9a1a5943bee0 100644 --- a/drivers/gpu/drm/tiny/ili9163.c +++ b/drivers/gpu/drm/tiny/ili9163.c @@ -100,6 +100,7 @@ out_exit: } static const struct drm_simple_display_pipe_funcs ili9163_pipe_funcs = { + .mode_valid = mipi_dbi_pipe_mode_valid, .enable = yx240qv29_enable, .disable = mipi_dbi_pipe_disable, .update = mipi_dbi_pipe_update, diff --git a/drivers/gpu/drm/tiny/ili9341.c b/drivers/gpu/drm/tiny/ili9341.c index b8826a0b086b..69b265e78096 100644 --- a/drivers/gpu/drm/tiny/ili9341.c +++ b/drivers/gpu/drm/tiny/ili9341.c @@ -137,6 +137,7 @@ out_exit: } static const struct drm_simple_display_pipe_funcs ili9341_pipe_funcs = { + .mode_valid = mipi_dbi_pipe_mode_valid, .enable = yx240qv29_enable, .disable = mipi_dbi_pipe_disable, .update = mipi_dbi_pipe_update, diff --git a/drivers/gpu/drm/tiny/ili9486.c b/drivers/gpu/drm/tiny/ili9486.c index a5b433a8e0d8..c80028bb1d11 100644 --- a/drivers/gpu/drm/tiny/ili9486.c +++ b/drivers/gpu/drm/tiny/ili9486.c @@ -150,6 +150,7 @@ static void waveshare_enable(struct drm_simple_display_pipe *pipe, } static const struct drm_simple_display_pipe_funcs waveshare_pipe_funcs = { + .mode_valid = mipi_dbi_pipe_mode_valid, .enable = waveshare_enable, .disable = mipi_dbi_pipe_disable, .update = mipi_dbi_pipe_update, diff --git a/drivers/gpu/drm/tiny/mi0283qt.c b/drivers/gpu/drm/tiny/mi0283qt.c index 27f1bd4da2f4..bc522fb3d94d 100644 --- a/drivers/gpu/drm/tiny/mi0283qt.c +++ b/drivers/gpu/drm/tiny/mi0283qt.c @@ -141,6 +141,7 @@ out_exit: } static const struct drm_simple_display_pipe_funcs mi0283qt_pipe_funcs = { + .mode_valid = mipi_dbi_pipe_mode_valid, .enable = mi0283qt_enable, .disable = mipi_dbi_pipe_disable, .update = mipi_dbi_pipe_update, diff --git a/drivers/gpu/drm/tiny/panel-mipi-dbi.c b/drivers/gpu/drm/tiny/panel-mipi-dbi.c index a76fefa8adbc..955a61d628e7 100644 --- a/drivers/gpu/drm/tiny/panel-mipi-dbi.c +++ b/drivers/gpu/drm/tiny/panel-mipi-dbi.c @@ -212,6 +212,7 @@ out_exit: } static const struct drm_simple_display_pipe_funcs panel_mipi_dbi_pipe_funcs = { + .mode_valid = mipi_dbi_pipe_mode_valid, .enable = panel_mipi_dbi_enable, .disable = mipi_dbi_pipe_disable, .update = mipi_dbi_pipe_update, diff --git a/drivers/gpu/drm/tiny/repaper.c b/drivers/gpu/drm/tiny/repaper.c index 01fbd00411fc..e62f4d16b2c6 100644 --- a/drivers/gpu/drm/tiny/repaper.c +++ b/drivers/gpu/drm/tiny/repaper.c @@ -621,6 +621,15 @@ static void power_off(struct repaper_epd *epd) gpiod_set_value_cansleep(epd->discharge, 0); } +static enum drm_mode_status repaper_pipe_mode_valid(struct drm_simple_display_pipe *pipe, + const struct drm_display_mode *mode) +{ + struct drm_crtc *crtc = &pipe->crtc; + struct repaper_epd *epd = drm_to_epd(crtc->dev); + + return drm_crtc_helper_mode_valid_fixed(crtc, mode, epd->mode); +} + static void repaper_pipe_enable(struct drm_simple_display_pipe *pipe, struct drm_crtc_state *crtc_state, struct drm_plane_state *plane_state) @@ -831,6 +840,7 @@ static void repaper_pipe_update(struct drm_simple_display_pipe *pipe, } static const struct drm_simple_display_pipe_funcs repaper_pipe_funcs = { + .mode_valid = repaper_pipe_mode_valid, .enable = repaper_pipe_enable, .disable = repaper_pipe_disable, .update = repaper_pipe_update, diff --git a/drivers/gpu/drm/tiny/simpledrm.c b/drivers/gpu/drm/tiny/simpledrm.c index c79576844ec0..5bed4d564104 100644 --- a/drivers/gpu/drm/tiny/simpledrm.c +++ b/drivers/gpu/drm/tiny/simpledrm.c @@ -570,15 +570,7 @@ static enum drm_mode_status simpledrm_crtc_helper_mode_valid(struct drm_crtc *cr { struct simpledrm_device *sdev = simpledrm_device_of_dev(crtc->dev); - if (mode->hdisplay != sdev->mode.hdisplay && - mode->vdisplay != sdev->mode.vdisplay) - return MODE_ONE_SIZE; - else if (mode->hdisplay != sdev->mode.hdisplay) - return MODE_ONE_WIDTH; - else if (mode->vdisplay != sdev->mode.vdisplay) - return MODE_ONE_HEIGHT; - - return MODE_OK; + return drm_crtc_helper_mode_valid_fixed(crtc, mode, &sdev->mode); } static int simpledrm_crtc_helper_atomic_check(struct drm_crtc *crtc, diff --git a/drivers/gpu/drm/tiny/st7735r.c b/drivers/gpu/drm/tiny/st7735r.c index d2042a0f02dd..c36ba08acda1 100644 --- a/drivers/gpu/drm/tiny/st7735r.c +++ b/drivers/gpu/drm/tiny/st7735r.c @@ -133,6 +133,7 @@ out_exit: } static const struct drm_simple_display_pipe_funcs st7735r_pipe_funcs = { + .mode_valid = mipi_dbi_pipe_mode_valid, .enable = st7735r_pipe_enable, .disable = mipi_dbi_pipe_disable, .update = mipi_dbi_pipe_update, diff --git a/include/drm/drm_mipi_dbi.h b/include/drm/drm_mipi_dbi.h index dad2f187b64b..14eaecb1825c 100644 --- a/include/drm/drm_mipi_dbi.h +++ b/include/drm/drm_mipi_dbi.h @@ -155,6 +155,8 @@ int mipi_dbi_dev_init_with_formats(struct mipi_dbi_dev *dbidev, int mipi_dbi_dev_init(struct mipi_dbi_dev *dbidev, const struct drm_simple_display_pipe_funcs *funcs, const struct drm_display_mode *mode, unsigned int rotation); +enum drm_mode_status mipi_dbi_pipe_mode_valid(struct drm_simple_display_pipe *pipe, + const struct drm_display_mode *mode); void mipi_dbi_pipe_update(struct drm_simple_display_pipe *pipe, struct drm_plane_state *old_state); void mipi_dbi_enable_flush(struct mipi_dbi_dev *dbidev, diff --git a/include/drm/drm_probe_helper.h b/include/drm/drm_probe_helper.h index d261838a7790..5880daa14624 100644 --- a/include/drm/drm_probe_helper.h +++ b/include/drm/drm_probe_helper.h @@ -3,11 +3,11 @@ #ifndef __DRM_PROBE_HELPER_H__ #define __DRM_PROBE_HELPER_H__ -#include +#include struct drm_connector; +struct drm_crtc; struct drm_device; -struct drm_display_mode; struct drm_modeset_acquire_ctx; int drm_helper_probe_single_connector_modes(struct drm_connector @@ -27,6 +27,10 @@ void drm_kms_helper_poll_disable(struct drm_device *dev); void drm_kms_helper_poll_enable(struct drm_device *dev); bool drm_kms_helper_is_poll_worker(void); +enum drm_mode_status drm_crtc_helper_mode_valid_fixed(struct drm_crtc *crtc, + const struct drm_display_mode *mode, + const struct drm_display_mode *fixed_mode); + int drm_connector_helper_get_modes_from_ddc(struct drm_connector *connector); int drm_connector_helper_get_modes_fixed(struct drm_connector *connector, const struct drm_display_mode *fixed_mode); -- cgit v1.2.3 From 385d1bba890f9b94322ca7fdfa778311f1ea0813 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Mon, 5 Sep 2022 16:16:47 +0200 Subject: drm/modes: Add initializer macro DRM_MODE_INIT() The macro DRM_MODE_INIT() initializes an instance of struct drm_display_mode with typical parameters. Convert simpledrm and also update the macro DRM_SIMPLE_MODE(). v3: * fix DRM_MODE_INIT() docs (kernel test robot) Signed-off-by: Thomas Zimmermann Reviewed-by: Sam Ravnborg Link: https://patchwork.freedesktop.org/patch/msgid/20220905141648.22013-4-tzimmermann@suse.de --- drivers/gpu/drm/tiny/simpledrm.c | 23 +++++++++-------------- include/drm/drm_modes.h | 35 ++++++++++++++++++++++++++++++----- 2 files changed, 39 insertions(+), 19 deletions(-) (limited to 'include/drm') diff --git a/drivers/gpu/drm/tiny/simpledrm.c b/drivers/gpu/drm/tiny/simpledrm.c index 5bed4d564104..404290760c60 100644 --- a/drivers/gpu/drm/tiny/simpledrm.c +++ b/drivers/gpu/drm/tiny/simpledrm.c @@ -30,16 +30,6 @@ #define DRIVER_MAJOR 1 #define DRIVER_MINOR 0 -/* - * Assume a monitor resolution of 96 dpi to - * get a somewhat reasonable screen size. - */ -#define RES_MM(d) \ - (((d) * 254ul) / (96ul * 10ul)) - -#define SIMPLEDRM_MODE(hd, vd) \ - DRM_SIMPLE_MODE(hd, vd, RES_MM(hd), RES_MM(vd)) - /* * Helpers for simplefb */ @@ -641,10 +631,15 @@ static const struct drm_mode_config_funcs simpledrm_mode_config_funcs = { static struct drm_display_mode simpledrm_mode(unsigned int width, unsigned int height) { - struct drm_display_mode mode = { SIMPLEDRM_MODE(width, height) }; - - mode.clock = mode.hdisplay * mode.vdisplay * 60 / 1000 /* kHz */; - drm_mode_set_name(&mode); + /* + * Assume a monitor resolution of 96 dpi to + * get a somewhat reasonable screen size. + */ + const struct drm_display_mode mode = { + DRM_MODE_INIT(60, width, height, + DRM_MODE_RES_MM(width, 96ul), + DRM_MODE_RES_MM(height, 96ul)) + }; return mode; } diff --git a/include/drm/drm_modes.h b/include/drm/drm_modes.h index a80ae9639e96..b0c680e6f670 100644 --- a/include/drm/drm_modes.h +++ b/include/drm/drm_modes.h @@ -138,6 +138,35 @@ enum drm_mode_status { .vsync_start = (vss), .vsync_end = (vse), .vtotal = (vt), \ .vscan = (vs), .flags = (f) +/** + * DRM_MODE_RES_MM - Calculates the display size from resolution and DPI + * @res: The resolution in pixel + * @dpi: The number of dots per inch + */ +#define DRM_MODE_RES_MM(res, dpi) \ + (((res) * 254ul) / ((dpi) * 10ul)) + +#define __DRM_MODE_INIT(pix, hd, vd, hd_mm, vd_mm) \ + .type = DRM_MODE_TYPE_DRIVER, .clock = (pix), \ + .hdisplay = (hd), .hsync_start = (hd), .hsync_end = (hd), \ + .htotal = (hd), .vdisplay = (vd), .vsync_start = (vd), \ + .vsync_end = (vd), .vtotal = (vd), .width_mm = (hd_mm), \ + .height_mm = (vd_mm) + +/** + * DRM_MODE_INIT - Initialize display mode + * @hz: Vertical refresh rate in Hertz + * @hd: Horizontal resolution, width + * @vd: Vertical resolution, height + * @hd_mm: Display width in millimeters + * @vd_mm: Display height in millimeters + * + * This macro initializes a &drm_display_mode that contains information about + * refresh rate, resolution and physical size. + */ +#define DRM_MODE_INIT(hz, hd, vd, hd_mm, vd_mm) \ + __DRM_MODE_INIT((hd) * (vd) * (hz) / 1000 /* kHz */, hd, vd, hd_mm, vd_mm) + /** * DRM_SIMPLE_MODE - Simple display mode * @hd: Horizontal resolution, width @@ -149,11 +178,7 @@ enum drm_mode_status { * resolution and physical size. */ #define DRM_SIMPLE_MODE(hd, vd, hd_mm, vd_mm) \ - .type = DRM_MODE_TYPE_DRIVER, .clock = 1 /* pass validation */, \ - .hdisplay = (hd), .hsync_start = (hd), .hsync_end = (hd), \ - .htotal = (hd), .vdisplay = (vd), .vsync_start = (vd), \ - .vsync_end = (vd), .vtotal = (vd), .width_mm = (hd_mm), \ - .height_mm = (vd_mm) + __DRM_MODE_INIT(1 /* pass validation */, hd, vd, hd_mm, vd_mm) #define CRTC_INTERLACE_HALVE_V (1 << 0) /* halve V values for interlacing */ #define CRTC_STEREO_DOUBLE (1 << 1) /* adjust timings for stereo modes */ -- cgit v1.2.3 From 4a85b0b51e211fba03c081e1e47f8871e4b3088f Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Mon, 5 Sep 2022 16:16:48 +0200 Subject: drm/format-helper: Add drm_fb_build_fourcc_list() helper Add drm_fb_build_fourcc_list() function that builds a list of supported formats from native and emulated ones. Helpful for all drivers that do format conversion as part of their plane updates. Update current caller. v3: * improve warnings on ignored formats (Sam) v2: * use u32 instead of uint32_t (Sam) * print a warning if output array is too small (Sam) * comment fixes (Sam) Signed-off-by: Thomas Zimmermann Reviewed-by: Sam Ravnborg Link: https://patchwork.freedesktop.org/patch/msgid/20220905141648.22013-5-tzimmermann@suse.de --- drivers/gpu/drm/drm_format_helper.c | 108 ++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/tiny/simpledrm.c | 47 ++-------------- include/drm/drm_format_helper.h | 11 +++- 3 files changed, 123 insertions(+), 43 deletions(-) (limited to 'include/drm') diff --git a/drivers/gpu/drm/drm_format_helper.c b/drivers/gpu/drm/drm_format_helper.c index 56642816fdff..4afc4ac27342 100644 --- a/drivers/gpu/drm/drm_format_helper.c +++ b/drivers/gpu/drm/drm_format_helper.c @@ -793,3 +793,111 @@ void drm_fb_xrgb8888_to_mono(struct iosys_map *dst, const unsigned int *dst_pitc kfree(src32); } EXPORT_SYMBOL(drm_fb_xrgb8888_to_mono); + +static bool is_listed_fourcc(const uint32_t *fourccs, size_t nfourccs, uint32_t fourcc) +{ + const uint32_t *fourccs_end = fourccs + nfourccs; + + while (fourccs < fourccs_end) { + if (*fourccs == fourcc) + return true; + ++fourccs; + } + return false; +} + +/** + * drm_fb_build_fourcc_list - Filters a list of supported color formats against + * the device's native formats + * @dev: DRM device + * @native_fourccs: 4CC codes of natively supported color formats + * @native_nfourccs: The number of entries in @native_fourccs + * @driver_fourccs: 4CC codes of all driver-supported color formats + * @driver_nfourccs: The number of entries in @driver_fourccs + * @fourccs_out: Returns 4CC codes of supported color formats + * @nfourccs_out: The number of available entries in @fourccs_out + * + * This function create a list of supported color format from natively + * supported formats and the emulated formats. + * At a minimum, most userspace programs expect at least support for + * XRGB8888 on the primary plane. Devices that have to emulate the + * format, and possibly others, can use drm_fb_build_fourcc_list() to + * create a list of supported color formats. The returned list can + * be handed over to drm_universal_plane_init() et al. Native formats + * will go before emulated formats. Other heuristics might be applied + * to optimize the order. Formats near the beginning of the list are + * usually preferred over formats near the end of the list. + * + * Returns: + * The number of color-formats 4CC codes returned in @fourccs_out. + */ +size_t drm_fb_build_fourcc_list(struct drm_device *dev, + const u32 *native_fourccs, size_t native_nfourccs, + const u32 *driver_fourccs, size_t driver_nfourccs, + u32 *fourccs_out, size_t nfourccs_out) +{ + u32 *fourccs = fourccs_out; + const u32 *fourccs_end = fourccs_out + nfourccs_out; + bool found_native = false; + size_t i; + + /* + * The device's native formats go first. + */ + + for (i = 0; i < native_nfourccs; ++i) { + u32 fourcc = native_fourccs[i]; + + if (is_listed_fourcc(fourccs_out, fourccs - fourccs_out, fourcc)) { + continue; /* skip duplicate entries */ + } else if (fourccs == fourccs_end) { + drm_warn(dev, "Ignoring native format %p4cc\n", &fourcc); + continue; /* end of available output buffer */ + } + + drm_dbg_kms(dev, "adding native format %p4cc\n", &fourcc); + + if (!found_native) + found_native = is_listed_fourcc(driver_fourccs, driver_nfourccs, fourcc); + *fourccs = fourcc; + ++fourccs; + } + + /* + * The plane's atomic_update helper converts the framebuffer's color format + * to a native format when copying to device memory. + * + * If there is not a single format supported by both, device and + * driver, the native formats are likely not supported by the conversion + * helpers. Therefore *only* support the native formats and add a + * conversion helper ASAP. + */ + if (!found_native) { + drm_warn(dev, "Format conversion helpers required to add extra formats.\n"); + goto out; + } + + /* + * The extra formats, emulated by the driver, go second. + */ + + for (i = 0; (i < driver_nfourccs) && (fourccs < fourccs_end); ++i) { + u32 fourcc = driver_fourccs[i]; + + if (is_listed_fourcc(fourccs_out, fourccs - fourccs_out, fourcc)) { + continue; /* skip duplicate and native entries */ + } else if (fourccs == fourccs_end) { + drm_warn(dev, "Ignoring emulated format %p4cc\n", &fourcc); + continue; /* end of available output buffer */ + } + + drm_dbg_kms(dev, "adding emulated format %p4cc\n", &fourcc); + + *fourccs = fourcc; + ++fourccs; + } + +out: + return fourccs - fourccs_out; +} +EXPORT_SYMBOL(drm_fb_build_fourcc_list); diff --git a/drivers/gpu/drm/tiny/simpledrm.c b/drivers/gpu/drm/tiny/simpledrm.c index 404290760c60..777ccd250871 100644 --- a/drivers/gpu/drm/tiny/simpledrm.c +++ b/drivers/gpu/drm/tiny/simpledrm.c @@ -644,45 +644,6 @@ static struct drm_display_mode simpledrm_mode(unsigned int width, return mode; } -static const uint32_t *simpledrm_device_formats(struct simpledrm_device *sdev, - size_t *nformats_out) -{ - struct drm_device *dev = &sdev->dev; - size_t i; - - if (sdev->nformats) - goto out; /* don't rebuild list on recurring calls */ - - /* native format goes first */ - sdev->formats[0] = sdev->format->format; - sdev->nformats = 1; - - /* default formats go second */ - for (i = 0; i < ARRAY_SIZE(simpledrm_primary_plane_formats); ++i) { - if (simpledrm_primary_plane_formats[i] == sdev->format->format) - continue; /* native format already went first */ - sdev->formats[sdev->nformats] = simpledrm_primary_plane_formats[i]; - sdev->nformats++; - } - - /* - * TODO: The simpledrm driver converts framebuffers to the native - * format when copying them to device memory. If there are more - * formats listed than supported by the driver, the native format - * is not supported by the conversion helpers. Therefore *only* - * support the native format and add a conversion helper ASAP. - */ - if (drm_WARN_ONCE(dev, i != sdev->nformats, - "format conversion helpers required for %p4cc", - &sdev->format->format)) { - sdev->nformats = 1; - } - -out: - *nformats_out = sdev->nformats; - return sdev->formats; -} - static struct simpledrm_device *simpledrm_device_create(struct drm_driver *drv, struct platform_device *pdev) { @@ -699,7 +660,6 @@ static struct simpledrm_device *simpledrm_device_create(struct drm_driver *drv, struct drm_encoder *encoder; struct drm_connector *connector; unsigned long max_width, max_height; - const uint32_t *formats; size_t nformats; int ret; @@ -811,11 +771,14 @@ static struct simpledrm_device *simpledrm_device_create(struct drm_driver *drv, /* Primary plane */ - formats = simpledrm_device_formats(sdev, &nformats); + nformats = drm_fb_build_fourcc_list(dev, &format->format, 1, + simpledrm_primary_plane_formats, + ARRAY_SIZE(simpledrm_primary_plane_formats), + sdev->formats, ARRAY_SIZE(sdev->formats)); primary_plane = &sdev->primary_plane; ret = drm_universal_plane_init(dev, primary_plane, 0, &simpledrm_primary_plane_funcs, - formats, nformats, + sdev->formats, nformats, simpledrm_primary_plane_format_modifiers, DRM_PLANE_TYPE_PRIMARY, NULL); if (ret) diff --git a/include/drm/drm_format_helper.h b/include/drm/drm_format_helper.h index caa181194335..eb5c98cf82b8 100644 --- a/include/drm/drm_format_helper.h +++ b/include/drm/drm_format_helper.h @@ -6,11 +6,15 @@ #ifndef __LINUX_DRM_FORMAT_HELPER_H #define __LINUX_DRM_FORMAT_HELPER_H -struct iosys_map; +#include + +struct drm_device; struct drm_format_info; struct drm_framebuffer; struct drm_rect; +struct iosys_map; + unsigned int drm_fb_clip_offset(unsigned int pitch, const struct drm_format_info *format, const struct drm_rect *clip); @@ -44,4 +48,9 @@ void drm_fb_xrgb8888_to_mono(struct iosys_map *dst, const unsigned int *dst_pitc const struct iosys_map *src, const struct drm_framebuffer *fb, const struct drm_rect *clip); +size_t drm_fb_build_fourcc_list(struct drm_device *dev, + const u32 *native_fourccs, size_t native_nfourccs, + const u32 *extra_fourccs, size_t extra_nfourccs, + u32 *fourccs_out, size_t nfourccs_out); + #endif /* __LINUX_DRM_FORMAT_HELPER_H */ -- cgit v1.2.3 From 8401bd361f5991ccfe9377e502fa37203ad70320 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Tue, 13 Sep 2022 18:23:07 +0200 Subject: drm/plane-helper: Add a drm_plane_helper_atomic_check() helper Provides a default plane state check handler for primary planes that are a fullscreen scanout buffer and whose state scale and position can't change. There are some drivers that duplicate this logic in their helpers, such as simpledrm and ssd130x. Factor out this common code into a plane helper and make drivers use it. Suggested-by: Thomas Zimmermann Signed-off-by: Javier Martinez Canillas Reviewed-by: Thomas Zimmermann Link: https://patchwork.freedesktop.org/patch/msgid/20220913162307.121503-1-javierm@redhat.com --- drivers/gpu/drm/drm_plane_helper.c | 30 ++++++++++++++++++++++++++++++ drivers/gpu/drm/solomon/ssd130x.c | 18 +----------------- drivers/gpu/drm/tiny/simpledrm.c | 25 +------------------------ include/drm/drm_plane_helper.h | 1 + 4 files changed, 33 insertions(+), 41 deletions(-) (limited to 'include/drm') diff --git a/drivers/gpu/drm/drm_plane_helper.c b/drivers/gpu/drm/drm_plane_helper.c index c7785967f5bf..db04d9a32ce8 100644 --- a/drivers/gpu/drm/drm_plane_helper.c +++ b/drivers/gpu/drm/drm_plane_helper.c @@ -278,3 +278,33 @@ void drm_plane_helper_destroy(struct drm_plane *plane) kfree(plane); } EXPORT_SYMBOL(drm_plane_helper_destroy); + +/** + * drm_plane_helper_atomic_check() - Helper to check plane atomic-state + * @plane: plane to check + * @state: atomic state object + * + * Provides a default plane-state check handler for planes whose atomic-state + * scale and positioning are not expected to change since the plane is always + * a fullscreen scanout buffer. + * + * This is often the case for the primary plane of simple framebuffers. + * + * RETURNS: + * Zero on success, or an errno code otherwise. + */ +int drm_plane_helper_atomic_check(struct drm_plane *plane, struct drm_atomic_state *state) +{ + struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, plane); + struct drm_crtc *new_crtc = new_plane_state->crtc; + struct drm_crtc_state *new_crtc_state = NULL; + + if (new_crtc) + new_crtc_state = drm_atomic_get_new_crtc_state(state, new_crtc); + + return drm_atomic_helper_check_plane_state(new_plane_state, new_crtc_state, + DRM_PLANE_NO_SCALING, + DRM_PLANE_NO_SCALING, + false, false); +} +EXPORT_SYMBOL(drm_plane_helper_atomic_check); diff --git a/drivers/gpu/drm/solomon/ssd130x.c b/drivers/gpu/drm/solomon/ssd130x.c index c95221fff474..7fae9480aa11 100644 --- a/drivers/gpu/drm/solomon/ssd130x.c +++ b/drivers/gpu/drm/solomon/ssd130x.c @@ -565,22 +565,6 @@ static int ssd130x_fb_blit_rect(struct drm_framebuffer *fb, const struct iosys_m return ret; } -static int ssd130x_primary_plane_helper_atomic_check(struct drm_plane *plane, - struct drm_atomic_state *new_state) -{ - struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(new_state, plane); - struct drm_crtc *new_crtc = new_plane_state->crtc; - struct drm_crtc_state *new_crtc_state = NULL; - - if (new_crtc) - new_crtc_state = drm_atomic_get_new_crtc_state(new_state, new_crtc); - - return drm_atomic_helper_check_plane_state(new_plane_state, new_crtc_state, - DRM_PLANE_NO_SCALING, - DRM_PLANE_NO_SCALING, - false, false); -} - static void ssd130x_primary_plane_helper_atomic_update(struct drm_plane *plane, struct drm_atomic_state *old_state) { @@ -623,7 +607,7 @@ static void ssd130x_primary_plane_helper_atomic_disable(struct drm_plane *plane, static const struct drm_plane_helper_funcs ssd130x_primary_plane_helper_funcs = { DRM_GEM_SHADOW_PLANE_HELPER_FUNCS, - .atomic_check = ssd130x_primary_plane_helper_atomic_check, + .atomic_check = drm_plane_helper_atomic_check, .atomic_update = ssd130x_primary_plane_helper_atomic_update, .atomic_disable = ssd130x_primary_plane_helper_atomic_disable, }; diff --git a/drivers/gpu/drm/tiny/simpledrm.c b/drivers/gpu/drm/tiny/simpledrm.c index 777ccd250871..ea5b3239a659 100644 --- a/drivers/gpu/drm/tiny/simpledrm.c +++ b/drivers/gpu/drm/tiny/simpledrm.c @@ -469,29 +469,6 @@ static const uint64_t simpledrm_primary_plane_format_modifiers[] = { DRM_FORMAT_MOD_INVALID }; -static int simpledrm_primary_plane_helper_atomic_check(struct drm_plane *plane, - struct drm_atomic_state *new_state) -{ - struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(new_state, plane); - struct drm_crtc *new_crtc = new_plane_state->crtc; - struct drm_crtc_state *new_crtc_state = NULL; - int ret; - - if (new_crtc) - new_crtc_state = drm_atomic_get_new_crtc_state(new_state, new_crtc); - - ret = drm_atomic_helper_check_plane_state(new_plane_state, new_crtc_state, - DRM_PLANE_NO_SCALING, - DRM_PLANE_NO_SCALING, - false, false); - if (ret) - return ret; - else if (!new_plane_state->visible) - return 0; - - return 0; -} - static void simpledrm_primary_plane_helper_atomic_update(struct drm_plane *plane, struct drm_atomic_state *old_state) { @@ -543,7 +520,7 @@ static void simpledrm_primary_plane_helper_atomic_disable(struct drm_plane *plan static const struct drm_plane_helper_funcs simpledrm_primary_plane_helper_funcs = { DRM_GEM_SHADOW_PLANE_HELPER_FUNCS, - .atomic_check = simpledrm_primary_plane_helper_atomic_check, + .atomic_check = drm_plane_helper_atomic_check, .atomic_update = simpledrm_primary_plane_helper_atomic_update, .atomic_disable = simpledrm_primary_plane_helper_atomic_disable, }; diff --git a/include/drm/drm_plane_helper.h b/include/drm/drm_plane_helper.h index 1781fab24dd6..7760b27b0323 100644 --- a/include/drm/drm_plane_helper.h +++ b/include/drm/drm_plane_helper.h @@ -41,5 +41,6 @@ int drm_plane_helper_update_primary(struct drm_plane *plane, struct drm_crtc *cr int drm_plane_helper_disable_primary(struct drm_plane *plane, struct drm_modeset_acquire_ctx *ctx); void drm_plane_helper_destroy(struct drm_plane *plane); +int drm_plane_helper_atomic_check(struct drm_plane *plane, struct drm_atomic_state *state); #endif -- cgit v1.2.3 From 7221941c4f3249f6e67090820c827326e2e4459f Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Fri, 9 Sep 2022 12:59:44 +0200 Subject: drm/plane: Remove drm_plane_init() Open-code drm_plane_init() and remove the function from DRM. The implementation of drm_plane_init() is a simple wrapper around a call to drm_universal_plane_init(), so drivers can just use that instead. Signed-off-by: Thomas Zimmermann Reviewed-by: Javier Martinez Canillas Reviewed-by: Laurent Pinchart Reviewed-by: Lyude Paul # nouveau Acked-by: Jyri Sarha Link: https://patchwork.freedesktop.org/patch/msgid/20220909105947.6487-2-tzimmermann@suse.de --- drivers/gpu/drm/drm_modeset_helper.c | 3 +-- drivers/gpu/drm/drm_plane.c | 32 ------------------------------ drivers/gpu/drm/nouveau/dispnv04/overlay.c | 13 ++++++------ drivers/gpu/drm/shmobile/shmob_drm_plane.c | 7 ++++--- drivers/gpu/drm/tilcdc/tilcdc_plane.c | 9 ++++----- include/drm/drm_plane.h | 8 +------- 6 files changed, 17 insertions(+), 55 deletions(-) (limited to 'include/drm') diff --git a/drivers/gpu/drm/drm_modeset_helper.c b/drivers/gpu/drm/drm_modeset_helper.c index bd609a978848..611dd01fb604 100644 --- a/drivers/gpu/drm/drm_modeset_helper.c +++ b/drivers/gpu/drm/drm_modeset_helper.c @@ -100,8 +100,7 @@ EXPORT_SYMBOL(drm_helper_mode_fill_fb_struct); * This is the minimal list of formats that seem to be safe for modeset use * with all current DRM drivers. Most hardware can actually support more * formats than this and drivers may specify a more accurate list when - * creating the primary plane. However drivers that still call - * drm_plane_init() will use this minimal format list as the default. + * creating the primary plane. */ static const uint32_t safe_modeset_formats[] = { DRM_FORMAT_XRGB8888, diff --git a/drivers/gpu/drm/drm_plane.c b/drivers/gpu/drm/drm_plane.c index 726f2f163c26..0f14b4d3bb10 100644 --- a/drivers/gpu/drm/drm_plane.c +++ b/drivers/gpu/drm/drm_plane.c @@ -482,38 +482,6 @@ void drm_plane_unregister_all(struct drm_device *dev) } } -/** - * drm_plane_init - Initialize a legacy plane - * @dev: DRM device - * @plane: plane object to init - * @possible_crtcs: bitmask of possible CRTCs - * @funcs: callbacks for the new plane - * @formats: array of supported formats (DRM_FORMAT\_\*) - * @format_count: number of elements in @formats - * @is_primary: plane type (primary vs overlay) - * - * Legacy API to initialize a DRM plane. - * - * New drivers should call drm_universal_plane_init() instead. - * - * Returns: - * Zero on success, error code on failure. - */ -int drm_plane_init(struct drm_device *dev, struct drm_plane *plane, - uint32_t possible_crtcs, - const struct drm_plane_funcs *funcs, - const uint32_t *formats, unsigned int format_count, - bool is_primary) -{ - enum drm_plane_type type; - - type = is_primary ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY; - return drm_universal_plane_init(dev, plane, possible_crtcs, funcs, - formats, format_count, - NULL, type, NULL); -} -EXPORT_SYMBOL(drm_plane_init); - /** * drm_plane_cleanup - Clean up the core plane usage * @plane: plane to cleanup diff --git a/drivers/gpu/drm/nouveau/dispnv04/overlay.c b/drivers/gpu/drm/nouveau/dispnv04/overlay.c index 37e63e98cd08..33f29736024a 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/overlay.c +++ b/drivers/gpu/drm/nouveau/dispnv04/overlay.c @@ -296,9 +296,10 @@ nv10_overlay_init(struct drm_device *device) break; } - ret = drm_plane_init(device, &plane->base, 3 /* both crtc's */, - &nv10_plane_funcs, - formats, num_formats, false); + ret = drm_universal_plane_init(device, &plane->base, 3 /* both crtc's */, + &nv10_plane_funcs, + formats, num_formats, NULL, + DRM_PLANE_TYPE_OVERLAY, NULL); if (ret) goto err; @@ -475,9 +476,9 @@ nv04_overlay_init(struct drm_device *device) if (!plane) return; - ret = drm_plane_init(device, &plane->base, 1 /* single crtc */, - &nv04_plane_funcs, - formats, 2, false); + ret = drm_universal_plane_init(device, &plane->base, 1 /* single crtc */, + &nv04_plane_funcs, formats, 2, NULL, + DRM_PLANE_TYPE_OVERLAY, NULL); if (ret) goto err; diff --git a/drivers/gpu/drm/shmobile/shmob_drm_plane.c b/drivers/gpu/drm/shmobile/shmob_drm_plane.c index 54228424793a..6c5f0cbe7d95 100644 --- a/drivers/gpu/drm/shmobile/shmob_drm_plane.c +++ b/drivers/gpu/drm/shmobile/shmob_drm_plane.c @@ -252,9 +252,10 @@ int shmob_drm_plane_create(struct shmob_drm_device *sdev, unsigned int index) splane->index = index; splane->alpha = 255; - ret = drm_plane_init(sdev->ddev, &splane->plane, 1, - &shmob_drm_plane_funcs, formats, - ARRAY_SIZE(formats), false); + ret = drm_universal_plane_init(sdev->ddev, &splane->plane, 1, + &shmob_drm_plane_funcs, + formats, ARRAY_SIZE(formats), NULL, + DRM_PLANE_TYPE_OVERLAY, NULL); return ret; } diff --git a/drivers/gpu/drm/tilcdc/tilcdc_plane.c b/drivers/gpu/drm/tilcdc/tilcdc_plane.c index 0ccf791301cb..cf77a8ce7398 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_plane.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_plane.c @@ -105,11 +105,10 @@ int tilcdc_plane_init(struct drm_device *dev, struct tilcdc_drm_private *priv = dev->dev_private; int ret; - ret = drm_plane_init(dev, plane, 1, - &tilcdc_plane_funcs, - priv->pixelformats, - priv->num_pixelformats, - true); + ret = drm_universal_plane_init(dev, plane, 1, &tilcdc_plane_funcs, + priv->pixelformats, + priv->num_pixelformats, + NULL, DRM_PLANE_TYPE_PRIMARY, NULL); if (ret) { dev_err(dev->dev, "Failed to initialize plane: %d\n", ret); return ret; diff --git a/include/drm/drm_plane.h b/include/drm/drm_plane.h index 89ea54652e87..910cb941f3d5 100644 --- a/include/drm/drm_plane.h +++ b/include/drm/drm_plane.h @@ -631,7 +631,7 @@ struct drm_plane { unsigned int format_count; /** * @format_default: driver hasn't supplied supported formats for the - * plane. Used by the drm_plane_init compatibility wrapper only. + * plane. Used by the non-atomic driver compatibility wrapper only. */ bool format_default; @@ -762,12 +762,6 @@ int drm_universal_plane_init(struct drm_device *dev, const uint64_t *format_modifiers, enum drm_plane_type type, const char *name, ...); -int drm_plane_init(struct drm_device *dev, - struct drm_plane *plane, - uint32_t possible_crtcs, - const struct drm_plane_funcs *funcs, - const uint32_t *formats, unsigned int format_count, - bool is_primary); void drm_plane_cleanup(struct drm_plane *plane); __printf(10, 11) -- cgit v1.2.3 From e71def057252c0b5189618ecbc7141b56db4a74b Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Fri, 9 Sep 2022 12:59:45 +0200 Subject: drm/plane: Allocate planes with drm_universal_plane_alloc() Provide drm_univeral_plane_alloc() to allocate and initialize a plane. Code for non-atomic drivers uses this pattern. Convert them to the new function. The modeset helpers contain a quirk for handling their color formats differently. Set the flag outside plane allocation. The new function is already deprecated to some extend. Drivers should rather use drmm_univeral_plane_alloc() or drm_universal_plane_init(). v2: * kerneldoc fixes (Javier) * grammar fixes in commit message Signed-off-by: Thomas Zimmermann Reviewed-by: Javier Martinez Canillas Reviewed-by: Lyude Paul # nouveau Link: https://patchwork.freedesktop.org/patch/msgid/20220909105947.6487-3-tzimmermann@suse.de --- drivers/gpu/drm/drm_modeset_helper.c | 61 ++++++++++++++------------------- drivers/gpu/drm/drm_plane.c | 38 ++++++++++++++++++++ drivers/gpu/drm/nouveau/dispnv04/crtc.c | 41 +++++++--------------- include/drm/drm_plane.h | 44 ++++++++++++++++++++++++ 4 files changed, 121 insertions(+), 63 deletions(-) (limited to 'include/drm') diff --git a/drivers/gpu/drm/drm_modeset_helper.c b/drivers/gpu/drm/drm_modeset_helper.c index 611dd01fb604..38040eebfa16 100644 --- a/drivers/gpu/drm/drm_modeset_helper.c +++ b/drivers/gpu/drm/drm_modeset_helper.c @@ -113,38 +113,6 @@ static const struct drm_plane_funcs primary_plane_funcs = { .destroy = drm_plane_helper_destroy, }; -static struct drm_plane *create_primary_plane(struct drm_device *dev) -{ - struct drm_plane *primary; - int ret; - - primary = kzalloc(sizeof(*primary), GFP_KERNEL); - if (primary == NULL) { - DRM_DEBUG_KMS("Failed to allocate primary plane\n"); - return NULL; - } - - /* - * Remove the format_default field from drm_plane when dropping - * this helper. - */ - primary->format_default = true; - - /* possible_crtc's will be filled in later by crtc_init */ - ret = drm_universal_plane_init(dev, primary, 0, - &primary_plane_funcs, - safe_modeset_formats, - ARRAY_SIZE(safe_modeset_formats), - NULL, - DRM_PLANE_TYPE_PRIMARY, NULL); - if (ret) { - kfree(primary); - primary = NULL; - } - - return primary; -} - /** * drm_crtc_init - Legacy CRTC initialization function * @dev: DRM device @@ -176,10 +144,33 @@ int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc, const struct drm_crtc_funcs *funcs) { struct drm_plane *primary; + int ret; + + /* possible_crtc's will be filled in later by crtc_init */ + primary = __drm_universal_plane_alloc(dev, sizeof(*primary), 0, 0, + &primary_plane_funcs, + safe_modeset_formats, + ARRAY_SIZE(safe_modeset_formats), + NULL, DRM_PLANE_TYPE_PRIMARY, NULL); + if (IS_ERR(primary)) + return PTR_ERR(primary); - primary = create_primary_plane(dev); - return drm_crtc_init_with_planes(dev, crtc, primary, NULL, funcs, - NULL); + /* + * Remove the format_default field from drm_plane when dropping + * this helper. + */ + primary->format_default = true; + + ret = drm_crtc_init_with_planes(dev, crtc, primary, NULL, funcs, NULL); + if (ret) + goto err_drm_plane_cleanup; + + return 0; + +err_drm_plane_cleanup: + drm_plane_cleanup(primary); + kfree(primary); + return ret; } EXPORT_SYMBOL(drm_crtc_init); diff --git a/drivers/gpu/drm/drm_plane.c b/drivers/gpu/drm/drm_plane.c index 0f14b4d3bb10..33357629a7f5 100644 --- a/drivers/gpu/drm/drm_plane.c +++ b/drivers/gpu/drm/drm_plane.c @@ -448,6 +448,44 @@ void *__drmm_universal_plane_alloc(struct drm_device *dev, size_t size, } EXPORT_SYMBOL(__drmm_universal_plane_alloc); +void *__drm_universal_plane_alloc(struct drm_device *dev, size_t size, + size_t offset, uint32_t possible_crtcs, + const struct drm_plane_funcs *funcs, + const uint32_t *formats, unsigned int format_count, + const uint64_t *format_modifiers, + enum drm_plane_type type, + const char *name, ...) +{ + void *container; + struct drm_plane *plane; + va_list ap; + int ret; + + if (drm_WARN_ON(dev, !funcs)) + return ERR_PTR(-EINVAL); + + container = kzalloc(size, GFP_KERNEL); + if (!container) + return ERR_PTR(-ENOMEM); + + plane = container + offset; + + va_start(ap, name); + ret = __drm_universal_plane_init(dev, plane, possible_crtcs, funcs, + formats, format_count, format_modifiers, + type, name, ap); + va_end(ap); + if (ret) + goto err_kfree; + + return container; + +err_kfree: + kfree(container); + return ERR_PTR(ret); +} +EXPORT_SYMBOL(__drm_universal_plane_alloc); + int drm_plane_register_all(struct drm_device *dev) { unsigned int num_planes = 0; diff --git a/drivers/gpu/drm/nouveau/dispnv04/crtc.c b/drivers/gpu/drm/nouveau/dispnv04/crtc.c index 660c4cbc0b3d..6b8a014b5e97 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/crtc.c +++ b/drivers/gpu/drm/nouveau/dispnv04/crtc.c @@ -1281,32 +1281,6 @@ static const struct drm_plane_funcs nv04_primary_plane_funcs = { .destroy = drm_plane_helper_destroy, }; -static struct drm_plane * -create_primary_plane(struct drm_device *dev) -{ - struct drm_plane *primary; - int ret; - - primary = kzalloc(sizeof(*primary), GFP_KERNEL); - if (primary == NULL) { - DRM_DEBUG_KMS("Failed to allocate primary plane\n"); - return NULL; - } - - /* possible_crtc's will be filled in later by crtc_init */ - ret = drm_universal_plane_init(dev, primary, 0, - &nv04_primary_plane_funcs, - modeset_formats, - ARRAY_SIZE(modeset_formats), NULL, - DRM_PLANE_TYPE_PRIMARY, NULL); - if (ret) { - kfree(primary); - primary = NULL; - } - - return primary; -} - static int nv04_crtc_vblank_handler(struct nvif_notify *notify) { struct nouveau_crtc *nv_crtc = @@ -1321,6 +1295,7 @@ nv04_crtc_create(struct drm_device *dev, int crtc_num) { struct nouveau_display *disp = nouveau_display(dev); struct nouveau_crtc *nv_crtc; + struct drm_plane *primary; int ret; nv_crtc = kzalloc(sizeof(*nv_crtc), GFP_KERNEL); @@ -1335,8 +1310,18 @@ nv04_crtc_create(struct drm_device *dev, int crtc_num) nv_crtc->save = nv_crtc_save; nv_crtc->restore = nv_crtc_restore; - drm_crtc_init_with_planes(dev, &nv_crtc->base, - create_primary_plane(dev), NULL, + primary = __drm_universal_plane_alloc(dev, sizeof(*primary), 0, 0, + &nv04_primary_plane_funcs, + modeset_formats, + ARRAY_SIZE(modeset_formats), NULL, + DRM_PLANE_TYPE_PRIMARY, NULL); + if (IS_ERR(primary)) { + ret = PTR_ERR(primary); + kfree(nv_crtc); + return ret; + } + + drm_crtc_init_with_planes(dev, &nv_crtc->base, primary, NULL, &nv04_crtc_funcs, NULL); drm_crtc_helper_add(&nv_crtc->base, &nv04_crtc_helper_funcs); drm_mode_crtc_set_gamma_size(&nv_crtc->base, 256); diff --git a/include/drm/drm_plane.h b/include/drm/drm_plane.h index 910cb941f3d5..447e664e49d5 100644 --- a/include/drm/drm_plane.h +++ b/include/drm/drm_plane.h @@ -809,6 +809,50 @@ void *__drmm_universal_plane_alloc(struct drm_device *dev, format_count, format_modifiers, \ plane_type, name, ##__VA_ARGS__)) +__printf(10, 11) +void *__drm_universal_plane_alloc(struct drm_device *dev, + size_t size, size_t offset, + uint32_t possible_crtcs, + const struct drm_plane_funcs *funcs, + const uint32_t *formats, + unsigned int format_count, + const uint64_t *format_modifiers, + enum drm_plane_type plane_type, + const char *name, ...); + +/** + * drm_universal_plane_alloc() - Allocate and initialize an universal plane object + * @dev: DRM device + * @type: the type of the struct which contains struct &drm_plane + * @member: the name of the &drm_plane within @type + * @possible_crtcs: bitmask of possible CRTCs + * @funcs: callbacks for the new plane + * @formats: array of supported formats (DRM_FORMAT\_\*) + * @format_count: number of elements in @formats + * @format_modifiers: array of struct drm_format modifiers terminated by + * DRM_FORMAT_MOD_INVALID + * @plane_type: type of plane (overlay, primary, cursor) + * @name: printf style format string for the plane name, or NULL for default name + * + * Allocates and initializes a plane object of type @type. The caller + * is responsible for releasing the allocated memory with kfree(). + * + * Drivers are encouraged to use drmm_universal_plane_alloc() instead. + * + * Drivers that only support the DRM_FORMAT_MOD_LINEAR modifier support may set + * @format_modifiers to NULL. The plane will advertise the linear modifier. + * + * Returns: + * Pointer to new plane, or ERR_PTR on failure. + */ +#define drm_universal_plane_alloc(dev, type, member, possible_crtcs, funcs, formats, \ + format_count, format_modifiers, plane_type, name, ...) \ + ((type *)__drm_universal_plane_alloc(dev, sizeof(type), \ + offsetof(type, member), \ + possible_crtcs, funcs, formats, \ + format_count, format_modifiers, \ + plane_type, name, ##__VA_ARGS__)) + /** * drm_plane_index - find the index of a registered plane * @plane: plane to find index for -- cgit v1.2.3 From 02d6f9a13ef3316da5c64540c5a376f07781c853 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Fri, 9 Sep 2022 12:59:47 +0200 Subject: drm/plane-helper: Provide DRM_PLANE_NON_ATOMIC_FUNCS initializer macro Provide DRM_PLANE_NON_ATOMIC_FUNCS, which initializes plane functions of non-atomic drivers to default values. The macro is not supposed to be used in new code, but helps with documenting and finding existing users. Signed-off-by: Thomas Zimmermann Reviewed-by: Javier Martinez Canillas Reviewed-by: Laurent Pinchart Reviewed-by: Lyude Paul # nouveau Link: https://patchwork.freedesktop.org/patch/msgid/20220909105947.6487-5-tzimmermann@suse.de --- drivers/gpu/drm/drm_modeset_helper.c | 4 +--- drivers/gpu/drm/nouveau/dispnv04/crtc.c | 4 +--- include/drm/drm_plane_helper.h | 12 ++++++++++++ 3 files changed, 14 insertions(+), 6 deletions(-) (limited to 'include/drm') diff --git a/drivers/gpu/drm/drm_modeset_helper.c b/drivers/gpu/drm/drm_modeset_helper.c index 38040eebfa16..f858dfedf2cf 100644 --- a/drivers/gpu/drm/drm_modeset_helper.c +++ b/drivers/gpu/drm/drm_modeset_helper.c @@ -108,9 +108,7 @@ static const uint32_t safe_modeset_formats[] = { }; static const struct drm_plane_funcs primary_plane_funcs = { - .update_plane = drm_plane_helper_update_primary, - .disable_plane = drm_plane_helper_disable_primary, - .destroy = drm_plane_helper_destroy, + DRM_PLANE_NON_ATOMIC_FUNCS, }; /** diff --git a/drivers/gpu/drm/nouveau/dispnv04/crtc.c b/drivers/gpu/drm/nouveau/dispnv04/crtc.c index 6b8a014b5e97..ee92d576d277 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/crtc.c +++ b/drivers/gpu/drm/nouveau/dispnv04/crtc.c @@ -1276,9 +1276,7 @@ static const uint32_t modeset_formats[] = { }; static const struct drm_plane_funcs nv04_primary_plane_funcs = { - .update_plane = drm_plane_helper_update_primary, - .disable_plane = drm_plane_helper_disable_primary, - .destroy = drm_plane_helper_destroy, + DRM_PLANE_NON_ATOMIC_FUNCS, }; static int nv04_crtc_vblank_handler(struct nvif_notify *notify) diff --git a/include/drm/drm_plane_helper.h b/include/drm/drm_plane_helper.h index 7760b27b0323..ff83d2621687 100644 --- a/include/drm/drm_plane_helper.h +++ b/include/drm/drm_plane_helper.h @@ -43,4 +43,16 @@ int drm_plane_helper_disable_primary(struct drm_plane *plane, void drm_plane_helper_destroy(struct drm_plane *plane); int drm_plane_helper_atomic_check(struct drm_plane *plane, struct drm_atomic_state *state); +/** + * DRM_PLANE_NON_ATOMIC_FUNCS - Default plane functions for non-atomic drivers + * + * This macro initializes plane functions for non-atomic drivers to default + * values. Non-atomic interfaces are deprecated and should not be used in new + * drivers. + */ +#define DRM_PLANE_NON_ATOMIC_FUNCS \ + .update_plane = drm_plane_helper_update_primary, \ + .disable_plane = drm_plane_helper_disable_primary, \ + .destroy = drm_plane_helper_destroy + #endif -- cgit v1.2.3