From: Thomas Zimmermann <tzimmermann@suse.de> To: airlied@linux.ie, daniel@ffwll.ch, b.zolnierkie@samsung.com Cc: linux-fbdev@vger.kernel.org, Thomas Zimmermann <tzimmermann@suse.de>, dri-devel@lists.freedesktop.org Subject: [PATCH 10/11] drm/fbdevdrm: Add CRTC Date: Tue, 26 Mar 2019 09:17:43 +0000 [thread overview] Message-ID: <20190326091744.11542-11-tzimmermann@suse.de> (raw) In-Reply-To: <20190326091744.11542-1-tzimmermann@suse.de> Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> --- drivers/gpu/drm/fbdevdrm/fbdevdrm_modeset.c | 150 +++++++++++++++++++- 1 file changed, 149 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/fbdevdrm/fbdevdrm_modeset.c b/drivers/gpu/drm/fbdevdrm/fbdevdrm_modeset.c index 3473b85acbf1..87f56ec76edf 100644 --- a/drivers/gpu/drm/fbdevdrm/fbdevdrm_modeset.c +++ b/drivers/gpu/drm/fbdevdrm/fbdevdrm_modeset.c @@ -18,10 +18,18 @@ #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_modeset_helper.h> #include <drm/drm_modeset_helper_vtables.h> +#include <drm/drm_print.h> #include <drm/drm_probe_helper.h> #include <linux/fb.h> +#include "fbdevdrm_modes.h" #include "fbdevdrm_primary.h" +static struct fbdevdrm_modeset* fbdevdrm_modeset_of_crtc( + struct drm_crtc *crtc) +{ + return container_of(crtc, struct fbdevdrm_modeset, crtc); +} + /* * CRTC */ @@ -29,18 +37,124 @@ static enum drm_mode_status crtc_helper_mode_valid( struct drm_crtc *crtc, const struct drm_display_mode *mode) { + static const unsigned char bits_per_pixel[] = { + 32, 16, 8, 24, 15 + }; + + struct fbdevdrm_modeset *modeset; + struct fb_var_screeninfo fb_var; + size_t i; + int ret; + + modeset = fbdevdrm_modeset_of_crtc(crtc); + + if (!modeset->fb_info->fbops->fb_check_var) + return MODE_OK; + + for (i = 0; i < ARRAY_SIZE(bits_per_pixel); ++i) { + + memcpy(&fb_var, &modeset->fb_info->var, sizeof(fb_var)); + fbdevdrm_update_fb_var_screeninfo_from_mode(&fb_var, mode); + fb_var.bits_per_pixel = bits_per_pixel[i]; + + ret = modeset->fb_info->fbops->fb_check_var(&fb_var, modeset->fb_info); + if (ret) + continue; /* generally not supported */ + if ((mode->hdisplay != fb_var.xres) || + (mode->vdisplay != fb_var.yres)) + continue; /* unsupported resolution */ + if (KHZ2PICOS(mode->clock) != fb_var.pixclock) + continue; /* unsupported pixel clock */ + + break; /* mode successfully tested */ + } + if (i = ARRAY_SIZE(bits_per_pixel)) + return MODE_BAD; /* mode is not support */ + return MODE_OK; } +static int fbdevdrm_update_fb_var_screeninfo_from_crtc( + struct fb_var_screeninfo *fb_var, struct drm_crtc* crtc) +{ + struct drm_plane *primary = crtc->primary; + struct fbdevdrm_modeset *modeset = fbdevdrm_modeset_of_crtc(crtc); + + if (primary && primary->state && primary->state->fb) + return fbdevdrm_update_fb_var_screeninfo_from_framebuffer( + fb_var, primary->state->fb, + modeset->fb_info->fix.smem_len); + + fb_var->xres_virtual = fb_var->xres; + fb_var->yres_virtual = fb_var->yres; + fb_var->bits_per_pixel = modeset->dev->mode_config.preferred_depth; + + return 0; +} + static bool crtc_helper_mode_fixup(struct drm_crtc *crtc, const struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { + struct fbdevdrm_modeset *modeset; + struct fb_var_screeninfo fb_var; + int ret; + + modeset = fbdevdrm_modeset_of_crtc(crtc); + + if (!modeset->fb_info->fbops->fb_check_var) + return true; + + fbdevdrm_init_fb_var_screeninfo_from_mode(&fb_var, mode); + + ret = fbdevdrm_update_fb_var_screeninfo_from_crtc(&fb_var, crtc); + if (ret) + return true; + + ret = modeset->fb_info->fbops->fb_check_var(&fb_var, modeset->fb_info); + if (ret < 0) + return false; + + drm_mode_update_from_fb_var_screeninfo(adjusted_mode, &fb_var); + return true; } static void crtc_helper_mode_set_nofb(struct drm_crtc *crtc) -{ } +{ + struct fbdevdrm_modeset *modeset; + struct fb_var_screeninfo fb_var; + int ret; + + /* As this is atomic mode setting, any function call is not + * allowed to fail. If it does, an additional test should be + * added to crtc_helper_atomic_check(). + */ + + modeset = fbdevdrm_modeset_of_crtc(crtc); + + memset(&fb_var, 0, sizeof(fb_var)); + fbdevdrm_update_fb_var_screeninfo_from_mode(&fb_var, &crtc->state->adjusted_mode); + + if (crtc->primary && crtc->primary->state && crtc->primary->state->fb) { + ret = fbdevdrm_update_fb_var_screeninfo_from_framebuffer( + &fb_var, crtc->primary->state->fb, + modeset->fb_info->fix.smem_len); + if (ret) + return; + } else { + fb_var.xres_virtual = fb_var.xres; + fb_var.yres_virtual = fb_var.yres; + } + + fb_var.activate = FB_ACTIVATE_NOW; + + ret = fb_set_var(modeset->fb_info, &fb_var); + if (ret) { + DRM_ERROR("fbdevdrm: fb_set_var() failed: %d\n", ret); + return; + } +} static int crtc_helper_mode_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb, @@ -53,6 +167,40 @@ static int crtc_helper_mode_set_base_atomic(struct drm_crtc *crtc, static int crtc_helper_atomic_check(struct drm_crtc *crtc, struct drm_crtc_state *state) { + struct fbdevdrm_modeset *modeset; + struct fb_videomode fb_mode, fb_var_mode; + + modeset = fbdevdrm_modeset_of_crtc(crtc); + + /* DRM porting notes: when fbcon takes over the console, it regularly + * changes the display mode. Where's apparently no way to detect this + * directly from fbcon itself. DRM's mode information might therefore + * be out of data, after it takes over the display at a later time. + * Here, we test the CRTC's current mode with the fbdev state. If they + * do not match, we request a mode change from DRM. If you port an + * fbdev driver to DRM, you can remove this code section, DRM will + * be in full control of the display device and doesn't have to react + * to changes from external sources. + */ + + if (!state->mode_changed && state->adjusted_mode.clock) { + fbdevdrm_init_fb_videomode_from_mode(&fb_mode, &state->adjusted_mode); + fb_var_to_videomode(&fb_var_mode, &modeset->fb_info->var); + if (!fb_mode_is_equal(&fb_mode, &fb_var_mode)) + state->mode_changed = true; + } + + /* TODO: The vblank interupt is currently not supported. We set + * the corresponding flag as a workaround. Some fbdev drivers + * support FBIO_WAITFORVSYNC, which we might use for querying + * vblanks. + * + * DRM porting notes: if you're porting an fbdev driver to DRM, + * remove this line and instead signal a vblank event from the + * interupt handler. + */ + state->no_vblank = true; + return 0; } -- 2.21.0
WARNING: multiple messages have this Message-ID (diff)
From: Thomas Zimmermann <tzimmermann@suse.de> To: airlied@linux.ie, daniel@ffwll.ch, b.zolnierkie@samsung.com Cc: linux-fbdev@vger.kernel.org, Thomas Zimmermann <tzimmermann@suse.de>, dri-devel@lists.freedesktop.org Subject: [PATCH 10/11] drm/fbdevdrm: Add CRTC Date: Tue, 26 Mar 2019 10:17:43 +0100 [thread overview] Message-ID: <20190326091744.11542-11-tzimmermann@suse.de> (raw) In-Reply-To: <20190326091744.11542-1-tzimmermann@suse.de> Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> --- drivers/gpu/drm/fbdevdrm/fbdevdrm_modeset.c | 150 +++++++++++++++++++- 1 file changed, 149 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/fbdevdrm/fbdevdrm_modeset.c b/drivers/gpu/drm/fbdevdrm/fbdevdrm_modeset.c index 3473b85acbf1..87f56ec76edf 100644 --- a/drivers/gpu/drm/fbdevdrm/fbdevdrm_modeset.c +++ b/drivers/gpu/drm/fbdevdrm/fbdevdrm_modeset.c @@ -18,10 +18,18 @@ #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_modeset_helper.h> #include <drm/drm_modeset_helper_vtables.h> +#include <drm/drm_print.h> #include <drm/drm_probe_helper.h> #include <linux/fb.h> +#include "fbdevdrm_modes.h" #include "fbdevdrm_primary.h" +static struct fbdevdrm_modeset* fbdevdrm_modeset_of_crtc( + struct drm_crtc *crtc) +{ + return container_of(crtc, struct fbdevdrm_modeset, crtc); +} + /* * CRTC */ @@ -29,18 +37,124 @@ static enum drm_mode_status crtc_helper_mode_valid( struct drm_crtc *crtc, const struct drm_display_mode *mode) { + static const unsigned char bits_per_pixel[] = { + 32, 16, 8, 24, 15 + }; + + struct fbdevdrm_modeset *modeset; + struct fb_var_screeninfo fb_var; + size_t i; + int ret; + + modeset = fbdevdrm_modeset_of_crtc(crtc); + + if (!modeset->fb_info->fbops->fb_check_var) + return MODE_OK; + + for (i = 0; i < ARRAY_SIZE(bits_per_pixel); ++i) { + + memcpy(&fb_var, &modeset->fb_info->var, sizeof(fb_var)); + fbdevdrm_update_fb_var_screeninfo_from_mode(&fb_var, mode); + fb_var.bits_per_pixel = bits_per_pixel[i]; + + ret = modeset->fb_info->fbops->fb_check_var(&fb_var, modeset->fb_info); + if (ret) + continue; /* generally not supported */ + if ((mode->hdisplay != fb_var.xres) || + (mode->vdisplay != fb_var.yres)) + continue; /* unsupported resolution */ + if (KHZ2PICOS(mode->clock) != fb_var.pixclock) + continue; /* unsupported pixel clock */ + + break; /* mode successfully tested */ + } + if (i == ARRAY_SIZE(bits_per_pixel)) + return MODE_BAD; /* mode is not support */ + return MODE_OK; } +static int fbdevdrm_update_fb_var_screeninfo_from_crtc( + struct fb_var_screeninfo *fb_var, struct drm_crtc* crtc) +{ + struct drm_plane *primary = crtc->primary; + struct fbdevdrm_modeset *modeset = fbdevdrm_modeset_of_crtc(crtc); + + if (primary && primary->state && primary->state->fb) + return fbdevdrm_update_fb_var_screeninfo_from_framebuffer( + fb_var, primary->state->fb, + modeset->fb_info->fix.smem_len); + + fb_var->xres_virtual = fb_var->xres; + fb_var->yres_virtual = fb_var->yres; + fb_var->bits_per_pixel = modeset->dev->mode_config.preferred_depth; + + return 0; +} + static bool crtc_helper_mode_fixup(struct drm_crtc *crtc, const struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { + struct fbdevdrm_modeset *modeset; + struct fb_var_screeninfo fb_var; + int ret; + + modeset = fbdevdrm_modeset_of_crtc(crtc); + + if (!modeset->fb_info->fbops->fb_check_var) + return true; + + fbdevdrm_init_fb_var_screeninfo_from_mode(&fb_var, mode); + + ret = fbdevdrm_update_fb_var_screeninfo_from_crtc(&fb_var, crtc); + if (ret) + return true; + + ret = modeset->fb_info->fbops->fb_check_var(&fb_var, modeset->fb_info); + if (ret < 0) + return false; + + drm_mode_update_from_fb_var_screeninfo(adjusted_mode, &fb_var); + return true; } static void crtc_helper_mode_set_nofb(struct drm_crtc *crtc) -{ } +{ + struct fbdevdrm_modeset *modeset; + struct fb_var_screeninfo fb_var; + int ret; + + /* As this is atomic mode setting, any function call is not + * allowed to fail. If it does, an additional test should be + * added to crtc_helper_atomic_check(). + */ + + modeset = fbdevdrm_modeset_of_crtc(crtc); + + memset(&fb_var, 0, sizeof(fb_var)); + fbdevdrm_update_fb_var_screeninfo_from_mode(&fb_var, &crtc->state->adjusted_mode); + + if (crtc->primary && crtc->primary->state && crtc->primary->state->fb) { + ret = fbdevdrm_update_fb_var_screeninfo_from_framebuffer( + &fb_var, crtc->primary->state->fb, + modeset->fb_info->fix.smem_len); + if (ret) + return; + } else { + fb_var.xres_virtual = fb_var.xres; + fb_var.yres_virtual = fb_var.yres; + } + + fb_var.activate = FB_ACTIVATE_NOW; + + ret = fb_set_var(modeset->fb_info, &fb_var); + if (ret) { + DRM_ERROR("fbdevdrm: fb_set_var() failed: %d\n", ret); + return; + } +} static int crtc_helper_mode_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb, @@ -53,6 +167,40 @@ static int crtc_helper_mode_set_base_atomic(struct drm_crtc *crtc, static int crtc_helper_atomic_check(struct drm_crtc *crtc, struct drm_crtc_state *state) { + struct fbdevdrm_modeset *modeset; + struct fb_videomode fb_mode, fb_var_mode; + + modeset = fbdevdrm_modeset_of_crtc(crtc); + + /* DRM porting notes: when fbcon takes over the console, it regularly + * changes the display mode. Where's apparently no way to detect this + * directly from fbcon itself. DRM's mode information might therefore + * be out of data, after it takes over the display at a later time. + * Here, we test the CRTC's current mode with the fbdev state. If they + * do not match, we request a mode change from DRM. If you port an + * fbdev driver to DRM, you can remove this code section, DRM will + * be in full control of the display device and doesn't have to react + * to changes from external sources. + */ + + if (!state->mode_changed && state->adjusted_mode.clock) { + fbdevdrm_init_fb_videomode_from_mode(&fb_mode, &state->adjusted_mode); + fb_var_to_videomode(&fb_var_mode, &modeset->fb_info->var); + if (!fb_mode_is_equal(&fb_mode, &fb_var_mode)) + state->mode_changed = true; + } + + /* TODO: The vblank interupt is currently not supported. We set + * the corresponding flag as a workaround. Some fbdev drivers + * support FBIO_WAITFORVSYNC, which we might use for querying + * vblanks. + * + * DRM porting notes: if you're porting an fbdev driver to DRM, + * remove this line and instead signal a vblank event from the + * interupt handler. + */ + state->no_vblank = true; + return 0; } -- 2.21.0 _______________________________________________ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
next prev parent reply other threads:[~2019-03-26 9:17 UTC|newest] Thread overview: 64+ messages / expand[flat|nested] mbox.gz Atom feed top 2019-03-26 9:17 [RFC][PATCH 00/11] DRM driver for fbdev devices Thomas Zimmermann 2019-03-26 9:17 ` Thomas Zimmermann 2019-03-26 9:17 ` [PATCH 01/11] drm/fbdevdrm: Add driver skeleton Thomas Zimmermann 2019-03-26 9:17 ` Thomas Zimmermann 2019-03-26 9:17 ` [PATCH 02/11] drm/fbdevdrm: Add fbdevdrm device Thomas Zimmermann 2019-03-26 9:17 ` Thomas Zimmermann 2019-03-26 16:03 ` Adam Jackson 2019-03-26 16:03 ` Adam Jackson 2019-03-27 7:55 ` Thomas Zimmermann 2019-03-27 7:55 ` Thomas Zimmermann 2019-03-27 8:03 ` Daniel Vetter 2019-03-27 8:03 ` Daniel Vetter 2019-03-26 9:17 ` [PATCH 03/11] drm/fbdevdrm: Add memory management Thomas Zimmermann 2019-03-26 9:17 ` Thomas Zimmermann 2019-03-26 9:17 ` [PATCH 04/11] drm/fbdevdrm: Add file operations Thomas Zimmermann 2019-03-26 9:17 ` Thomas Zimmermann 2019-03-26 9:17 ` [PATCH 05/11] drm/fbdevdrm: Add GEM and dumb interfaces Thomas Zimmermann 2019-03-26 9:17 ` Thomas Zimmermann 2019-03-26 9:17 ` [PATCH 06/11] drm/fbdevdrm: Add modesetting infrastructure Thomas Zimmermann 2019-03-26 9:17 ` Thomas Zimmermann 2019-03-26 9:17 ` [PATCH 07/11] drm/fbdevdrm: Add DRM <-> fbdev pixel-format conversion Thomas Zimmermann 2019-03-26 9:17 ` Thomas Zimmermann 2019-03-26 16:29 ` Ville Syrjälä 2019-03-26 16:29 ` Ville Syrjälä 2019-03-27 8:28 ` Thomas Zimmermann 2019-03-27 8:28 ` Thomas Zimmermann 2019-03-27 10:00 ` Ville Syrjälä 2019-03-27 10:00 ` Ville Syrjälä 2019-03-26 9:17 ` [PATCH 08/11] drm/fbdevdrm: Add mode conversion DRM <-> fbdev Thomas Zimmermann 2019-03-26 9:17 ` Thomas Zimmermann 2019-03-26 9:17 ` [PATCH 09/11] drm/fbdevdrm: Add primary plane Thomas Zimmermann 2019-03-26 9:17 ` Thomas Zimmermann 2019-03-26 13:33 ` Mathieu Malaterre 2019-03-26 13:33 ` Mathieu Malaterre 2019-03-26 13:57 ` Thomas Zimmermann 2019-03-26 13:57 ` Thomas Zimmermann 2019-03-27 9:37 ` Thomas Zimmermann 2019-03-27 9:37 ` Thomas Zimmermann 2019-04-02 7:08 ` Mathieu Malaterre 2019-04-02 7:08 ` Mathieu Malaterre 2019-03-26 9:17 ` Thomas Zimmermann [this message] 2019-03-26 9:17 ` [PATCH 10/11] drm/fbdevdrm: Add CRTC Thomas Zimmermann 2019-03-26 9:17 ` [PATCH 11/11] drm/fbdevdrm: Detect and validate display modes Thomas Zimmermann 2019-03-26 9:17 ` Thomas Zimmermann 2019-03-26 16:47 ` Ville Syrjälä 2019-03-26 16:47 ` Ville Syrjälä 2019-03-26 18:20 ` Daniel Vetter 2019-03-26 18:20 ` Daniel Vetter 2019-03-27 8:31 ` Thomas Zimmermann 2019-03-27 8:31 ` Thomas Zimmermann 2019-03-26 14:53 ` [RFC][PATCH 00/11] DRM driver for fbdev devices Daniel Vetter 2019-03-26 14:53 ` Daniel Vetter 2019-03-27 9:10 ` Thomas Zimmermann 2019-03-27 9:10 ` Thomas Zimmermann 2019-03-27 9:41 ` Daniel Vetter 2019-03-27 9:41 ` Daniel Vetter 2019-03-27 9:55 ` Michel Dänzer 2019-03-27 9:55 ` Michel Dänzer 2019-03-27 10:58 ` Daniel Vetter 2019-03-27 10:58 ` Daniel Vetter 2019-03-27 14:46 ` Thomas Zimmermann 2019-03-27 14:46 ` Thomas Zimmermann 2019-03-27 17:05 ` Daniel Vetter 2019-03-27 17:05 ` Daniel Vetter
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20190326091744.11542-11-tzimmermann@suse.de \ --to=tzimmermann@suse.de \ --cc=airlied@linux.ie \ --cc=b.zolnierkie@samsung.com \ --cc=daniel@ffwll.ch \ --cc=dri-devel@lists.freedesktop.org \ --cc=linux-fbdev@vger.kernel.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.