From a21fdd7a4cd6952f39a2e2b0695f62c376bb28f4 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Thu, 7 Nov 2019 09:33:58 +0100 Subject: drm/ast: Don't clear base address and offset with default values The content of the base-address and offset registers are state of the primary plane. Clearing it to default values will interfere with plane functions for atomic mode setting. Signed-off-by: Thomas Zimmermann Acked-by: Gerd Hoffmann Link: https://patchwork.freedesktop.org/patch/msgid/20191107083404.6852-4-tzimmermann@suse.de --- drivers/gpu/drm/ast/ast_mode.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/ast/ast_mode.c') diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index b13eaa2619ab..b3f82c2d274d 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -253,9 +253,13 @@ static void ast_set_std_reg(struct drm_crtc *crtc, struct drm_display_mode *mode ast_set_index_reg(ast, AST_IO_SEQ_PORT, (i + 1) , jreg); } - /* Set CRTC */ + /* Set CRTC; except base address and offset */ ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x11, 0x7f, 0x00); - for (i = 0; i < 25; i++) + for (i = 0; i < 12; i++) + ast_set_index_reg(ast, AST_IO_CRTC_PORT, i, stdtable->crtc[i]); + for (i = 14; i < 19; i++) + ast_set_index_reg(ast, AST_IO_CRTC_PORT, i, stdtable->crtc[i]); + for (i = 20; i < 25; i++) ast_set_index_reg(ast, AST_IO_CRTC_PORT, i, stdtable->crtc[i]); /* set AR */ -- cgit From 0d45ad989d0262e4f289600d39d765df0c8871af Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Thu, 7 Nov 2019 09:33:59 +0100 Subject: drm/ast: Split ast_set_ext_reg() into color and threshold function In ast_set_ext_reg() sets several framebuffer options and CRT threshold parameters. The former is mostly state of the primary plane; the latter is constant. Hence, split the function in two and make it work with atomic modesetting. Signed-off-by: Thomas Zimmermann Acked-by: Gerd Hoffmann Link: https://patchwork.freedesktop.org/patch/msgid/20191107083404.6852-5-tzimmermann@suse.de --- drivers/gpu/drm/ast/ast_mode.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'drivers/gpu/drm/ast/ast_mode.c') diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index b3f82c2d274d..5feb687191e0 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -419,11 +419,10 @@ static void ast_set_dclk_reg(struct drm_device *dev, struct drm_display_mode *mo ((clk_info->param3 & 0x3) << 4)); } -static void ast_set_ext_reg(struct drm_crtc *crtc, struct drm_display_mode *mode, - struct ast_vbios_mode_info *vbios_mode) +static void ast_set_color_reg(struct drm_crtc *crtc, + const struct drm_framebuffer *fb) { struct ast_private *ast = crtc->dev->dev_private; - const struct drm_framebuffer *fb = crtc->primary->fb; u8 jregA0 = 0, jregA3 = 0, jregA8 = 0; switch (fb->format->cpp[0] * 8) { @@ -448,6 +447,11 @@ static void ast_set_ext_reg(struct drm_crtc *crtc, struct drm_display_mode *mode ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa0, 0x8f, jregA0); ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa3, 0xf0, jregA3); ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa8, 0xfd, jregA8); +} + +static void ast_set_crtthd_reg(struct drm_crtc *crtc) +{ + struct ast_private *ast = crtc->dev->dev_private; /* Set Threshold */ if (ast->chip == AST2300 || ast->chip == AST2400 || @@ -467,7 +471,7 @@ static void ast_set_ext_reg(struct drm_crtc *crtc, struct drm_display_mode *mode } static void ast_set_sync_reg(struct drm_device *dev, struct drm_display_mode *mode, - struct ast_vbios_mode_info *vbios_mode) + struct ast_vbios_mode_info *vbios_mode) { struct ast_private *ast = dev->dev_private; u8 jreg; @@ -595,7 +599,8 @@ static int ast_crtc_mode_set(struct drm_crtc *crtc, ast_set_crtc_reg(crtc, adjusted_mode, &vbios_mode); ast_set_offset_reg(crtc); ast_set_dclk_reg(dev, adjusted_mode, &vbios_mode); - ast_set_ext_reg(crtc, adjusted_mode, &vbios_mode); + ast_set_color_reg(crtc, fb); + ast_set_crtthd_reg(crtc); ast_set_sync_reg(dev, adjusted_mode, &vbios_mode); ast_set_dac_reg(crtc, adjusted_mode, &vbios_mode); -- cgit From 259d14a76a27eed2828aef5e90b66aee0cb1a19d Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Thu, 7 Nov 2019 09:34:00 +0100 Subject: drm/ast: Split ast_set_vbios_mode_info() The implementation of ast_set_vbios_mode() converts a DRM display mode and framebuffer into an adjusted mode and stores information for the video BIOS to several scratch regsiters. Here we split the function into individual functions that do the conversion, set the VBIOS mode information and format information. This makes it compatible with support for primary planes and atomic modesetting. Signed-off-by: Thomas Zimmermann Acked-by: Gerd Hoffmann Link: https://patchwork.freedesktop.org/patch/msgid/20191107083404.6852-6-tzimmermann@suse.de --- drivers/gpu/drm/ast/ast_mode.c | 111 ++++++++++++++++++++++++++--------------- 1 file changed, 72 insertions(+), 39 deletions(-) (limited to 'drivers/gpu/drm/ast/ast_mode.c') diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index 5feb687191e0..c4c9fca0f00c 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -82,13 +82,12 @@ static void ast_crtc_load_lut(struct drm_crtc *crtc) ast_load_palette_index(ast, i, *r++ >> 8, *g++ >> 8, *b++ >> 8); } -static bool ast_get_vbios_mode_info(struct drm_crtc *crtc, struct drm_display_mode *mode, +static bool ast_get_vbios_mode_info(const struct drm_framebuffer *fb, + const struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode, struct ast_vbios_mode_info *vbios_mode) { - struct ast_private *ast = crtc->dev->dev_private; - const struct drm_framebuffer *fb = crtc->primary->fb; - u32 refresh_rate_index = 0, mode_id, color_index, refresh_rate; + u32 refresh_rate_index = 0, refresh_rate; const struct ast_vbios_enhtable *best = NULL; u32 hborder, vborder; bool check_sync; @@ -96,22 +95,19 @@ static bool ast_get_vbios_mode_info(struct drm_crtc *crtc, struct drm_display_mo switch (fb->format->cpp[0] * 8) { case 8: vbios_mode->std_table = &vbios_stdtable[VGAModeIndex]; - color_index = VGAModeIndex - 1; break; case 16: vbios_mode->std_table = &vbios_stdtable[HiCModeIndex]; - color_index = HiCModeIndex; break; case 24: case 32: vbios_mode->std_table = &vbios_stdtable[TrueCModeIndex]; - color_index = TrueCModeIndex; break; default: return false; } - switch (crtc->mode.crtc_hdisplay) { + switch (mode->crtc_hdisplay) { case 640: vbios_mode->enh_table = &res_640x480[refresh_rate_index]; break; @@ -122,7 +118,7 @@ static bool ast_get_vbios_mode_info(struct drm_crtc *crtc, struct drm_display_mo vbios_mode->enh_table = &res_1024x768[refresh_rate_index]; break; case 1280: - if (crtc->mode.crtc_vdisplay == 800) + if (mode->crtc_vdisplay == 800) vbios_mode->enh_table = &res_1280x800[refresh_rate_index]; else vbios_mode->enh_table = &res_1280x1024[refresh_rate_index]; @@ -134,7 +130,7 @@ static bool ast_get_vbios_mode_info(struct drm_crtc *crtc, struct drm_display_mo vbios_mode->enh_table = &res_1440x900[refresh_rate_index]; break; case 1600: - if (crtc->mode.crtc_vdisplay == 900) + if (mode->crtc_vdisplay == 900) vbios_mode->enh_table = &res_1600x900[refresh_rate_index]; else vbios_mode->enh_table = &res_1600x1200[refresh_rate_index]; @@ -143,7 +139,7 @@ static bool ast_get_vbios_mode_info(struct drm_crtc *crtc, struct drm_display_mo vbios_mode->enh_table = &res_1680x1050[refresh_rate_index]; break; case 1920: - if (crtc->mode.crtc_vdisplay == 1080) + if (mode->crtc_vdisplay == 1080) vbios_mode->enh_table = &res_1920x1080[refresh_rate_index]; else vbios_mode->enh_table = &res_1920x1200[refresh_rate_index]; @@ -154,7 +150,8 @@ static bool ast_get_vbios_mode_info(struct drm_crtc *crtc, struct drm_display_mo refresh_rate = drm_mode_vrefresh(mode); check_sync = vbios_mode->enh_table->flags & WideScreenMode; - do { + + while (1) { const struct ast_vbios_enhtable *loop = vbios_mode->enh_table; while (loop->refresh_rate != 0xff) { @@ -178,7 +175,8 @@ static bool ast_get_vbios_mode_info(struct drm_crtc *crtc, struct drm_display_mo if (best || !check_sync) break; check_sync = 0; - } while (1); + } + if (best) vbios_mode->enh_table = best; @@ -203,34 +201,65 @@ static bool ast_get_vbios_mode_info(struct drm_crtc *crtc, struct drm_display_mo vbios_mode->enh_table->vfp + vbios_mode->enh_table->vsync); - refresh_rate_index = vbios_mode->enh_table->refresh_rate_index; - mode_id = vbios_mode->enh_table->mode_id; + return true; +} - if (ast->chip == AST1180) { - /* TODO 1180 */ - } else { - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x8c, (u8)((color_index & 0xf) << 4)); - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x8d, refresh_rate_index & 0xff); - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x8e, mode_id & 0xff); - - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x91, 0x00); - if (vbios_mode->enh_table->flags & NewModeInfo) { - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x91, 0xa8); - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x92, - fb->format->cpp[0] * 8); - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x93, adjusted_mode->clock / 1000); - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x94, adjusted_mode->crtc_hdisplay); - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x95, adjusted_mode->crtc_hdisplay >> 8); - - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x96, adjusted_mode->crtc_vdisplay); - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x97, adjusted_mode->crtc_vdisplay >> 8); - } +static void ast_set_vbios_color_reg(struct drm_crtc *crtc, + const struct drm_framebuffer *fb, + const struct ast_vbios_mode_info *vbios_mode) +{ + struct ast_private *ast = crtc->dev->dev_private; + u32 color_index; + + switch (fb->format->cpp[0]) { + case 1: + color_index = VGAModeIndex - 1; + break; + case 2: + color_index = HiCModeIndex; + break; + case 3: + case 4: + color_index = TrueCModeIndex; + default: + return; } - return true; + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x8c, (u8)((color_index & 0x0f) << 4)); + + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x91, 0x00); + + if (vbios_mode->enh_table->flags & NewModeInfo) { + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x91, 0xa8); + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x92, fb->format->cpp[0] * 8); + } +} + +static void ast_set_vbios_mode_reg(struct drm_crtc *crtc, + const struct drm_display_mode *adjusted_mode, + const struct ast_vbios_mode_info *vbios_mode) +{ + struct ast_private *ast = crtc->dev->dev_private; + u32 refresh_rate_index, mode_id; + + refresh_rate_index = vbios_mode->enh_table->refresh_rate_index; + mode_id = vbios_mode->enh_table->mode_id; + + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x8d, refresh_rate_index & 0xff); + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x8e, mode_id & 0xff); + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x91, 0x00); + if (vbios_mode->enh_table->flags & NewModeInfo) { + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x91, 0xa8); + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x93, adjusted_mode->clock / 1000); + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x94, adjusted_mode->crtc_hdisplay); + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x95, adjusted_mode->crtc_hdisplay >> 8); + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x96, adjusted_mode->crtc_vdisplay); + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x97, adjusted_mode->crtc_vdisplay >> 8); + } } + static void ast_set_std_reg(struct drm_crtc *crtc, struct drm_display_mode *mode, struct ast_vbios_mode_info *vbios_mode) { @@ -581,20 +610,24 @@ static int ast_crtc_mode_set(struct drm_crtc *crtc, { struct drm_device *dev = crtc->dev; struct ast_private *ast = crtc->dev->dev_private; + const struct drm_framebuffer *fb = crtc->primary->fb; struct ast_vbios_mode_info vbios_mode; - bool ret; + bool succ; + if (ast->chip == AST1180) { DRM_ERROR("AST 1180 modesetting not supported\n"); return -EINVAL; } - ret = ast_get_vbios_mode_info(crtc, mode, adjusted_mode, &vbios_mode); - if (ret == false) + succ = ast_get_vbios_mode_info(fb, mode, adjusted_mode, &vbios_mode); + if (!succ) return -EINVAL; + ast_open_key(ast); + ast_set_vbios_color_reg(crtc, fb, &vbios_mode); + ast_set_vbios_mode_reg(crtc, adjusted_mode, &vbios_mode); ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa1, 0x06); - ast_set_std_reg(crtc, adjusted_mode, &vbios_mode); ast_set_crtc_reg(crtc, adjusted_mode, &vbios_mode); ast_set_offset_reg(crtc); -- cgit From a6ff807b71e3ffa85c1ba133d8a9fa11fcfe186d Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Thu, 7 Nov 2019 09:34:01 +0100 Subject: drm/ast: Add primary plane Like the original mode-setting code, the primary plane supports XRGB888, RGB565 and C8. The plane itself only pins BOs and sets the base address and scanline offset. The mode-setting code will be located in the CRTC's atomic helpers. v2: * don't set plane call-back functions to NULL explicitly * define plane format array in global scope Signed-off-by: Thomas Zimmermann Acked-by: Gerd Hoffmann Link: https://patchwork.freedesktop.org/patch/msgid/20191107083404.6852-7-tzimmermann@suse.de --- drivers/gpu/drm/ast/ast_drv.h | 2 + drivers/gpu/drm/ast/ast_mode.c | 89 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 89 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/ast/ast_mode.c') diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h index f44150ff5483..13560622f22a 100644 --- a/drivers/gpu/drm/ast/ast_drv.h +++ b/drivers/gpu/drm/ast/ast_drv.h @@ -121,6 +121,8 @@ struct ast_private { unsigned int next_index; } cursor; + struct drm_plane primary_plane; + bool support_wide_screen; enum { ast_use_p2a, diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index c4c9fca0f00c..dcd635115297 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -31,6 +31,8 @@ #include #include +#include +#include #include #include #include @@ -51,6 +53,7 @@ static int ast_cursor_set(struct drm_crtc *crtc, static int ast_cursor_move(struct drm_crtc *crtc, int x, int y); + static inline void ast_load_palette_index(struct ast_private *ast, u8 index, u8 red, u8 green, u8 blue) @@ -538,6 +541,62 @@ static void ast_set_start_address_crt1(struct drm_crtc *crtc, unsigned offset) } +/* + * Primary plane + */ + +static const uint32_t ast_primary_plane_formats[] = { + DRM_FORMAT_XRGB8888, + DRM_FORMAT_RGB565, + DRM_FORMAT_C8, +}; + +int ast_primary_plane_helper_atomic_check(struct drm_plane *plane, + struct drm_plane_state *state) +{ + return 0; +} + +void ast_primary_plane_helper_atomic_update(struct drm_plane *plane, + struct drm_plane_state *old_state) +{ + struct drm_plane_state *state = plane->state; + struct drm_crtc *crtc = state->crtc; + struct drm_gem_vram_object *gbo; + s64 gpu_addr; + + if (!crtc || !state->fb) + return; + + gbo = drm_gem_vram_of_gem(state->fb->obj[0]); + gpu_addr = drm_gem_vram_offset(gbo); + if (WARN_ON_ONCE(gpu_addr < 0)) + return; /* Bug: we didn't pin the BO to VRAM in prepare_fb. */ + + ast_set_offset_reg(crtc); + ast_set_start_address_crt1(crtc, (u32)gpu_addr); +} + +static const struct drm_plane_helper_funcs ast_primary_plane_helper_funcs = { + .prepare_fb = drm_gem_vram_plane_helper_prepare_fb, + .cleanup_fb = drm_gem_vram_plane_helper_cleanup_fb, + .atomic_check = ast_primary_plane_helper_atomic_check, + .atomic_update = ast_primary_plane_helper_atomic_update, +}; + +static const struct drm_plane_funcs ast_primary_plane_funcs = { + .update_plane = drm_atomic_helper_update_plane, + .disable_plane = drm_atomic_helper_disable_plane, + .destroy = drm_plane_cleanup, + .reset = drm_atomic_helper_plane_reset, + .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, +}; + +/* + * CRTC + */ + static void ast_crtc_dpms(struct drm_crtc *crtc, int mode) { struct ast_private *ast = crtc->dev->dev_private; @@ -711,16 +770,26 @@ static const struct drm_crtc_funcs ast_crtc_funcs = { static int ast_crtc_init(struct drm_device *dev) { + struct ast_private *ast = dev->dev_private; struct ast_crtc *crtc; + int ret; crtc = kzalloc(sizeof(struct ast_crtc), GFP_KERNEL); if (!crtc) return -ENOMEM; - drm_crtc_init(dev, &crtc->base, &ast_crtc_funcs); + ret = drm_crtc_init_with_planes(dev, &crtc->base, &ast->primary_plane, + NULL, &ast_crtc_funcs, NULL); + if (ret) + goto err_kfree; + drm_mode_crtc_set_gamma_size(&crtc->base, 256); drm_crtc_helper_add(&crtc->base, &ast_crtc_helper_funcs); return 0; + +err_kfree: + kfree(crtc); + return ret; } static void ast_encoder_destroy(struct drm_encoder *encoder) @@ -754,7 +823,6 @@ static void ast_encoder_commit(struct drm_encoder *encoder) } - static const struct drm_encoder_helper_funcs ast_enc_helper_funcs = { .dpms = ast_encoder_dpms, .prepare = ast_encoder_prepare, @@ -976,10 +1044,27 @@ static void ast_cursor_fini(struct drm_device *dev) int ast_mode_init(struct drm_device *dev) { + struct ast_private *ast = dev->dev_private; + int ret; + + memset(&ast->primary_plane, 0, sizeof(ast->primary_plane)); + ret = drm_universal_plane_init(dev, &ast->primary_plane, 0x01, + &ast_primary_plane_funcs, + ast_primary_plane_formats, + ARRAY_SIZE(ast_primary_plane_formats), + NULL, DRM_PLANE_TYPE_PRIMARY, NULL); + if (ret) { + DRM_ERROR("ast: drm_universal_plane_init() failed: %d\n", ret); + return ret; + } + drm_plane_helper_add(&ast->primary_plane, + &ast_primary_plane_helper_funcs); + ast_cursor_init(dev); ast_crtc_init(dev); ast_encoder_init(dev); ast_connector_init(dev); + return 0; } -- cgit From b48e1b6ffd28a2af57620c4876abe7b956314e87 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Thu, 7 Nov 2019 09:34:02 +0100 Subject: drm/ast: Add CRTC helpers for atomic modesetting As the CRTC code has already been prepared for a split between mode setting and plane handling, most of the CRTC's atomic modesetting is build upon primitives of the non-atomic implementation. Signed-off-by: Thomas Zimmermann Acked-by: Gerd Hoffmann Link: https://patchwork.freedesktop.org/patch/msgid/20191107083404.6852-8-tzimmermann@suse.de --- drivers/gpu/drm/ast/ast_mode.c | 105 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 104 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/ast/ast_mode.c') diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index dcd635115297..65ee8215f730 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -727,6 +727,103 @@ static void ast_crtc_commit(struct drm_crtc *crtc) ast_crtc_load_lut(crtc); } +static int ast_crtc_helper_atomic_check(struct drm_crtc *crtc, + struct drm_crtc_state *state) +{ + struct ast_private *ast = crtc->dev->dev_private; + struct drm_plane_state *plane_state; + bool succ; + struct drm_display_mode adjusted_mode; + struct ast_vbios_mode_info vbios_mode; + + if (ast->chip == AST1180) { + DRM_ERROR("AST 1180 modesetting not supported\n"); + return -EINVAL; + } + + plane_state = crtc->primary->state; + + if (plane_state && plane_state->fb) { + succ = ast_get_vbios_mode_info(plane_state->fb, &state->mode, + &adjusted_mode, &vbios_mode); + if (!succ) + return -EINVAL; + } + + return 0; +} + +static void ast_crtc_helper_atomic_begin(struct drm_crtc *crtc, + struct drm_crtc_state *old_crtc_state) +{ + struct ast_private *ast = crtc->dev->dev_private; + + ast_open_key(ast); +} + +static void ast_crtc_helper_atomic_flush(struct drm_crtc *crtc, + struct drm_crtc_state *old_crtc_state) +{ + const struct drm_framebuffer *fb = crtc->primary->state->fb; + struct drm_display_mode adjusted_mode; + struct ast_vbios_mode_info vbios_mode; + bool succ; + + crtc->state->no_vblank = true; + + if (!fb) + return; + + ast_set_color_reg(crtc, fb); + + memset(&adjusted_mode, 0, sizeof(adjusted_mode)); + drm_mode_copy(&adjusted_mode, &crtc->state->adjusted_mode); + + succ = ast_get_vbios_mode_info(fb, &crtc->state->adjusted_mode, + &adjusted_mode, &vbios_mode); + if (WARN_ON_ONCE(!succ)) + return; + + ast_set_vbios_color_reg(crtc, fb, &vbios_mode); +} + +static void +ast_crtc_helper_atomic_enable(struct drm_crtc *crtc, + struct drm_crtc_state *old_crtc_state) +{ + struct drm_device *dev = crtc->dev; + struct ast_private *ast = crtc->dev->dev_private; + const struct drm_framebuffer *fb = crtc->primary->state->fb; + struct drm_display_mode adjusted_mode; + struct ast_vbios_mode_info vbios_mode; + bool succ; + + memset(&adjusted_mode, 0, sizeof(adjusted_mode)); + drm_mode_copy(&adjusted_mode, &crtc->state->adjusted_mode); + + succ = ast_get_vbios_mode_info(fb, &crtc->state->adjusted_mode, + &adjusted_mode, &vbios_mode); + if (WARN_ON_ONCE(!succ)) + return; + + ast_set_vbios_mode_reg(crtc, &adjusted_mode, &vbios_mode); + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa1, 0x06); + ast_set_std_reg(crtc, &adjusted_mode, &vbios_mode); + ast_set_crtc_reg(crtc, &adjusted_mode, &vbios_mode); + ast_set_dclk_reg(dev, &adjusted_mode, &vbios_mode); + ast_set_crtthd_reg(crtc); + ast_set_sync_reg(dev, &adjusted_mode, &vbios_mode); + ast_set_dac_reg(crtc, &adjusted_mode, &vbios_mode); + + ast_crtc_dpms(crtc, DRM_MODE_DPMS_ON); +} + +static void +ast_crtc_helper_atomic_disable(struct drm_crtc *crtc, + struct drm_crtc_state *old_crtc_state) +{ + ast_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); +} static const struct drm_crtc_helper_funcs ast_crtc_helper_funcs = { .dpms = ast_crtc_dpms, @@ -735,7 +832,11 @@ static const struct drm_crtc_helper_funcs ast_crtc_helper_funcs = { .disable = ast_crtc_disable, .prepare = ast_crtc_prepare, .commit = ast_crtc_commit, - + .atomic_check = ast_crtc_helper_atomic_check, + .atomic_begin = ast_crtc_helper_atomic_begin, + .atomic_flush = ast_crtc_helper_atomic_flush, + .atomic_enable = ast_crtc_helper_atomic_enable, + .atomic_disable = ast_crtc_helper_atomic_disable, }; static void ast_crtc_reset(struct drm_crtc *crtc) @@ -766,6 +867,8 @@ static const struct drm_crtc_funcs ast_crtc_funcs = { .set_config = drm_crtc_helper_set_config, .gamma_set = ast_crtc_gamma_set, .destroy = ast_crtc_destroy, + .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, }; static int ast_crtc_init(struct drm_device *dev) -- cgit From 02f3bb751a46230f9a49d2a55b304a5847c67788 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Thu, 7 Nov 2019 09:34:03 +0100 Subject: drm/ast: Add cursor plane The cursor plane uses an internal format of ARGB4444. To userspace, we announce ARGB8888 and do the transformation internally. v2: * don't set plane call-back functions to NULL explicitly * define plane format array in global scope Signed-off-by: Thomas Zimmermann Acked-by: Gerd Hoffmann Link: https://patchwork.freedesktop.org/patch/msgid/20191107083404.6852-9-tzimmermann@suse.de --- drivers/gpu/drm/ast/ast_drv.h | 1 + drivers/gpu/drm/ast/ast_mode.c | 155 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 155 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/ast/ast_mode.c') diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h index 13560622f22a..49557a73390f 100644 --- a/drivers/gpu/drm/ast/ast_drv.h +++ b/drivers/gpu/drm/ast/ast_drv.h @@ -122,6 +122,7 @@ struct ast_private { } cursor; struct drm_plane primary_plane; + struct drm_plane cursor_plane; bool support_wide_screen; enum { diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index 65ee8215f730..3d619ca6e32f 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -54,6 +54,16 @@ static int ast_cursor_move(struct drm_crtc *crtc, int x, int y); +static u32 copy_cursor_image(u8 *src, u8 *dst, int width, int height); +static int ast_cursor_update(void *dst, void *src, unsigned int width, + unsigned int height); +static void ast_cursor_set_base(struct ast_private *ast, u64 address); +static int ast_show_cursor(struct drm_crtc *crtc, void *src, + unsigned int width, unsigned int height); +static void ast_hide_cursor(struct drm_crtc *crtc); +static int ast_cursor_move(struct drm_crtc *crtc, + int x, int y); + static inline void ast_load_palette_index(struct ast_private *ast, u8 index, u8 red, u8 green, u8 blue) @@ -593,6 +603,136 @@ static const struct drm_plane_funcs ast_primary_plane_funcs = { .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, }; +/* + * Cursor plane + */ + +static const uint32_t ast_cursor_plane_formats[] = { + DRM_FORMAT_ARGB8888, +}; + +static int +ast_cursor_plane_helper_prepare_fb(struct drm_plane *plane, + struct drm_plane_state *new_state) +{ + struct drm_framebuffer *fb = new_state->fb; + struct drm_crtc *crtc = new_state->crtc; + struct drm_gem_vram_object *gbo; + struct ast_private *ast; + int ret; + void *src, *dst; + + if (!crtc || !fb) + return 0; + + if (fb->width > AST_MAX_HWC_WIDTH || fb->height > AST_MAX_HWC_HEIGHT) + return -EINVAL; + + ast = crtc->dev->dev_private; + + gbo = drm_gem_vram_of_gem(fb->obj[0]); + src = drm_gem_vram_vmap(gbo); + if (IS_ERR(src)) { + ret = PTR_ERR(src); + goto err_drm_gem_vram_unpin; + } + + dst = drm_gem_vram_vmap(ast->cursor.gbo[ast->cursor.next_index]); + if (IS_ERR(dst)) { + ret = PTR_ERR(dst); + goto err_drm_gem_vram_vunmap_src; + } + + ret = ast_cursor_update(dst, src, fb->width, fb->height); + if (ret) + goto err_drm_gem_vram_vunmap_dst; + + /* Always unmap buffers here. Destination buffers are + * perma-pinned while the driver is active. We're only + * changing ref-counters here. + */ + drm_gem_vram_vunmap(ast->cursor.gbo[ast->cursor.next_index], dst); + drm_gem_vram_vunmap(gbo, src); + + return 0; + +err_drm_gem_vram_vunmap_dst: + drm_gem_vram_vunmap(ast->cursor.gbo[ast->cursor.next_index], dst); +err_drm_gem_vram_vunmap_src: + drm_gem_vram_vunmap(gbo, src); +err_drm_gem_vram_unpin: + drm_gem_vram_unpin(gbo); + return ret; +} + +static int ast_cursor_plane_helper_atomic_check(struct drm_plane *plane, + struct drm_plane_state *state) +{ + return 0; +} + +static void +ast_cursor_plane_helper_atomic_update(struct drm_plane *plane, + struct drm_plane_state *old_state) +{ + struct drm_plane_state *state = plane->state; + struct drm_crtc *crtc = state->crtc; + struct drm_framebuffer *fb = state->fb; + struct ast_private *ast = plane->dev->dev_private; + struct ast_crtc *ast_crtc = to_ast_crtc(crtc); + struct drm_gem_vram_object *gbo; + s64 off; + u8 jreg; + + ast_crtc->offset_x = AST_MAX_HWC_WIDTH - fb->width; + ast_crtc->offset_y = AST_MAX_HWC_WIDTH - fb->height; + + if (state->fb != old_state->fb) { + /* A new cursor image was installed. */ + gbo = ast->cursor.gbo[ast->cursor.next_index]; + off = drm_gem_vram_offset(gbo); + if (WARN_ON_ONCE(off < 0)) + return; /* Bug: we didn't pin cursor HW BO to VRAM. */ + ast_cursor_set_base(ast, off); + + ++ast->cursor.next_index; + ast->cursor.next_index %= ARRAY_SIZE(ast->cursor.gbo); + } + + ast_cursor_move(crtc, state->crtc_x, state->crtc_y); + + jreg = 0x2; + /* enable ARGB cursor */ + jreg |= 1; + ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xcb, 0xfc, jreg); +} + +static void +ast_cursor_plane_helper_atomic_disable(struct drm_plane *plane, + struct drm_plane_state *old_state) +{ + struct ast_private *ast = plane->dev->dev_private; + + ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xcb, 0xfc, 0x00); +} + +static const struct drm_plane_helper_funcs ast_cursor_plane_helper_funcs = { + .prepare_fb = ast_cursor_plane_helper_prepare_fb, + .cleanup_fb = NULL, /* not required for cursor plane */ + .atomic_check = ast_cursor_plane_helper_atomic_check, + .atomic_update = ast_cursor_plane_helper_atomic_update, + .atomic_disable = ast_cursor_plane_helper_atomic_disable, +}; + +static const struct drm_plane_funcs ast_cursor_plane_funcs = { + .update_plane = drm_atomic_helper_update_plane, + .disable_plane = drm_atomic_helper_disable_plane, + .destroy = drm_plane_cleanup, + .reset = drm_atomic_helper_plane_reset, + .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, +}; + /* * CRTC */ @@ -882,7 +1022,8 @@ static int ast_crtc_init(struct drm_device *dev) return -ENOMEM; ret = drm_crtc_init_with_planes(dev, &crtc->base, &ast->primary_plane, - NULL, &ast_crtc_funcs, NULL); + &ast->cursor_plane, &ast_crtc_funcs, + NULL); if (ret) goto err_kfree; @@ -1163,6 +1304,18 @@ int ast_mode_init(struct drm_device *dev) drm_plane_helper_add(&ast->primary_plane, &ast_primary_plane_helper_funcs); + ret = drm_universal_plane_init(dev, &ast->cursor_plane, 0x01, + &ast_cursor_plane_funcs, + ast_cursor_plane_formats, + ARRAY_SIZE(ast_cursor_plane_formats), + NULL, DRM_PLANE_TYPE_CURSOR, NULL); + if (ret) { + DRM_ERROR("drm_universal_plane_failed(): %d\n", ret); + return ret; + } + drm_plane_helper_add(&ast->cursor_plane, + &ast_cursor_plane_helper_funcs); + ast_cursor_init(dev); ast_crtc_init(dev); ast_encoder_init(dev); -- cgit From 4961eb60f14553363a0a7a9fb7b20d9c57d3ebba Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Thu, 7 Nov 2019 09:34:04 +0100 Subject: drm/ast: Enable atomic modesetting This commit sets the remaining atomic-modesetting helpers and the flag DRIVER_ATOMIC. Legacy cursor functions are removed in favor of the cursor plane. For power management, atomic helpers replace the indvidual operations that the driver currently runs. Atomic modesetting is enabled with this commit. Signed-off-by: Thomas Zimmermann Acked-by: Gerd Hoffmann Link: https://patchwork.freedesktop.org/patch/msgid/20191107083404.6852-10-tzimmermann@suse.de --- drivers/gpu/drm/ast/ast_drv.c | 24 ++-- drivers/gpu/drm/ast/ast_main.c | 5 + drivers/gpu/drm/ast/ast_mode.c | 290 +++-------------------------------------- 3 files changed, 33 insertions(+), 286 deletions(-) (limited to 'drivers/gpu/drm/ast/ast_mode.c') diff --git a/drivers/gpu/drm/ast/ast_drv.c b/drivers/gpu/drm/ast/ast_drv.c index 1f17794b0890..d763da6f0834 100644 --- a/drivers/gpu/drm/ast/ast_drv.c +++ b/drivers/gpu/drm/ast/ast_drv.c @@ -99,14 +99,14 @@ ast_pci_remove(struct pci_dev *pdev) drm_put_dev(dev); } - - static int ast_drm_freeze(struct drm_device *dev) { - drm_kms_helper_poll_disable(dev); - pci_save_state(dev->pdev); - drm_fb_helper_set_suspend_unlocked(dev->fb_helper, true); + int error; + error = drm_mode_config_helper_suspend(dev); + if (error) + return error; + pci_save_state(dev->pdev); return 0; } @@ -114,11 +114,7 @@ static int ast_drm_thaw(struct drm_device *dev) { ast_post_gpu(dev); - drm_mode_config_reset(dev); - drm_helper_resume_force_mode(dev); - drm_fb_helper_set_suspend_unlocked(dev->fb_helper, false); - - return 0; + return drm_mode_config_helper_resume(dev); } static int ast_drm_resume(struct drm_device *dev) @@ -131,8 +127,6 @@ static int ast_drm_resume(struct drm_device *dev) ret = ast_drm_thaw(dev); if (ret) return ret; - - drm_kms_helper_poll_enable(dev); return 0; } @@ -150,6 +144,7 @@ static int ast_pm_suspend(struct device *dev) pci_set_power_state(pdev, PCI_D3hot); return 0; } + static int ast_pm_resume(struct device *dev) { struct pci_dev *pdev = to_pci_dev(dev); @@ -165,7 +160,6 @@ static int ast_pm_freeze(struct device *dev) if (!ddev || !ddev->dev_private) return -ENODEV; return ast_drm_freeze(ddev); - } static int ast_pm_thaw(struct device *dev) @@ -203,7 +197,9 @@ static struct pci_driver ast_pci_driver = { DEFINE_DRM_GEM_FOPS(ast_fops); static struct drm_driver driver = { - .driver_features = DRIVER_MODESET | DRIVER_GEM, + .driver_features = DRIVER_ATOMIC | + DRIVER_GEM | + DRIVER_MODESET, .load = ast_driver_load, .unload = ast_driver_unload, diff --git a/drivers/gpu/drm/ast/ast_main.c b/drivers/gpu/drm/ast/ast_main.c index 48d57ab42955..b79f484e9bd2 100644 --- a/drivers/gpu/drm/ast/ast_main.c +++ b/drivers/gpu/drm/ast/ast_main.c @@ -28,6 +28,7 @@ #include +#include #include #include #include @@ -412,6 +413,8 @@ enum drm_mode_status ast_mode_config_mode_valid(struct drm_device *dev, static const struct drm_mode_config_funcs ast_mode_funcs = { .fb_create = drm_gem_fb_create, .mode_valid = ast_mode_config_mode_valid, + .atomic_check = drm_atomic_helper_check, + .atomic_commit = drm_atomic_helper_commit, }; static u32 ast_get_vram_info(struct drm_device *dev) @@ -529,6 +532,8 @@ int ast_driver_load(struct drm_device *dev, unsigned long flags) if (ret) goto out_free; + drm_mode_config_reset(dev); + ret = drm_fbdev_generic_setup(dev, 32); if (ret) goto out_free; diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index 3d619ca6e32f..4725ec911a66 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -45,11 +45,6 @@ static struct ast_i2c_chan *ast_i2c_create(struct drm_device *dev); static void ast_i2c_destroy(struct ast_i2c_chan *i2c); -static int ast_cursor_set(struct drm_crtc *crtc, - struct drm_file *file_priv, - uint32_t handle, - uint32_t width, - uint32_t height); static int ast_cursor_move(struct drm_crtc *crtc, int x, int y); @@ -58,9 +53,6 @@ static u32 copy_cursor_image(u8 *src, u8 *dst, int width, int height); static int ast_cursor_update(void *dst, void *src, unsigned int width, unsigned int height); static void ast_cursor_set_base(struct ast_private *ast, u64 address); -static int ast_show_cursor(struct drm_crtc *crtc, void *src, - unsigned int width, unsigned int height); -static void ast_hide_cursor(struct drm_crtc *crtc); static int ast_cursor_move(struct drm_crtc *crtc, int x, int y); @@ -434,7 +426,7 @@ static void ast_set_crtc_reg(struct drm_crtc *crtc, struct drm_display_mode *mod static void ast_set_offset_reg(struct drm_crtc *crtc) { struct ast_private *ast = crtc->dev->dev_private; - const struct drm_framebuffer *fb = crtc->primary->fb; + const struct drm_framebuffer *fb = crtc->primary->state->fb; u16 offset; @@ -528,7 +520,7 @@ static void ast_set_sync_reg(struct drm_device *dev, struct drm_display_mode *mo static bool ast_set_dac_reg(struct drm_crtc *crtc, struct drm_display_mode *mode, struct ast_vbios_mode_info *vbios_mode) { - const struct drm_framebuffer *fb = crtc->primary->fb; + const struct drm_framebuffer *fb = crtc->primary->state->fb; switch (fb->format->cpp[0] * 8) { case 8: @@ -761,112 +753,6 @@ static void ast_crtc_dpms(struct drm_crtc *crtc, int mode) } } -static int ast_crtc_do_set_base(struct drm_crtc *crtc, - struct drm_framebuffer *fb, - int x, int y, int atomic) -{ - struct drm_gem_vram_object *gbo; - int ret; - s64 gpu_addr; - - if (!atomic && fb) { - gbo = drm_gem_vram_of_gem(fb->obj[0]); - drm_gem_vram_unpin(gbo); - } - - gbo = drm_gem_vram_of_gem(crtc->primary->fb->obj[0]); - - ret = drm_gem_vram_pin(gbo, DRM_GEM_VRAM_PL_FLAG_VRAM); - if (ret) - return ret; - gpu_addr = drm_gem_vram_offset(gbo); - if (gpu_addr < 0) { - ret = (int)gpu_addr; - goto err_drm_gem_vram_unpin; - } - - ast_set_offset_reg(crtc); - ast_set_start_address_crt1(crtc, (u32)gpu_addr); - - return 0; - -err_drm_gem_vram_unpin: - drm_gem_vram_unpin(gbo); - return ret; -} - -static int ast_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, - struct drm_framebuffer *old_fb) -{ - return ast_crtc_do_set_base(crtc, old_fb, x, y, 0); -} - -static int ast_crtc_mode_set(struct drm_crtc *crtc, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode, - int x, int y, - struct drm_framebuffer *old_fb) -{ - struct drm_device *dev = crtc->dev; - struct ast_private *ast = crtc->dev->dev_private; - const struct drm_framebuffer *fb = crtc->primary->fb; - struct ast_vbios_mode_info vbios_mode; - bool succ; - - if (ast->chip == AST1180) { - DRM_ERROR("AST 1180 modesetting not supported\n"); - return -EINVAL; - } - - succ = ast_get_vbios_mode_info(fb, mode, adjusted_mode, &vbios_mode); - if (!succ) - return -EINVAL; - - ast_open_key(ast); - - ast_set_vbios_color_reg(crtc, fb, &vbios_mode); - ast_set_vbios_mode_reg(crtc, adjusted_mode, &vbios_mode); - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa1, 0x06); - ast_set_std_reg(crtc, adjusted_mode, &vbios_mode); - ast_set_crtc_reg(crtc, adjusted_mode, &vbios_mode); - ast_set_offset_reg(crtc); - ast_set_dclk_reg(dev, adjusted_mode, &vbios_mode); - ast_set_color_reg(crtc, fb); - ast_set_crtthd_reg(crtc); - ast_set_sync_reg(dev, adjusted_mode, &vbios_mode); - ast_set_dac_reg(crtc, adjusted_mode, &vbios_mode); - - ast_crtc_mode_set_base(crtc, x, y, old_fb); - - return 0; -} - -static void ast_crtc_disable(struct drm_crtc *crtc) -{ - DRM_DEBUG_KMS("\n"); - ast_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); - if (crtc->primary->fb) { - struct drm_framebuffer *fb = crtc->primary->fb; - struct drm_gem_vram_object *gbo = - drm_gem_vram_of_gem(fb->obj[0]); - - drm_gem_vram_unpin(gbo); - } - crtc->primary->fb = NULL; -} - -static void ast_crtc_prepare(struct drm_crtc *crtc) -{ - -} - -static void ast_crtc_commit(struct drm_crtc *crtc) -{ - struct ast_private *ast = crtc->dev->dev_private; - ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT, 0x1, 0xdf, 0); - ast_crtc_load_lut(crtc); -} - static int ast_crtc_helper_atomic_check(struct drm_crtc *crtc, struct drm_crtc_state *state) { @@ -966,12 +852,6 @@ ast_crtc_helper_atomic_disable(struct drm_crtc *crtc, } static const struct drm_crtc_helper_funcs ast_crtc_helper_funcs = { - .dpms = ast_crtc_dpms, - .mode_set = ast_crtc_mode_set, - .mode_set_base = ast_crtc_mode_set_base, - .disable = ast_crtc_disable, - .prepare = ast_crtc_prepare, - .commit = ast_crtc_commit, .atomic_check = ast_crtc_helper_atomic_check, .atomic_begin = ast_crtc_helper_atomic_begin, .atomic_flush = ast_crtc_helper_atomic_flush, @@ -979,21 +859,6 @@ static const struct drm_crtc_helper_funcs ast_crtc_helper_funcs = { .atomic_disable = ast_crtc_helper_atomic_disable, }; -static void ast_crtc_reset(struct drm_crtc *crtc) -{ - -} - -static int ast_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green, - u16 *blue, uint32_t size, - struct drm_modeset_acquire_ctx *ctx) -{ - ast_crtc_load_lut(crtc); - - return 0; -} - - static void ast_crtc_destroy(struct drm_crtc *crtc) { drm_crtc_cleanup(crtc); @@ -1001,12 +866,12 @@ static void ast_crtc_destroy(struct drm_crtc *crtc) } static const struct drm_crtc_funcs ast_crtc_funcs = { - .cursor_set = ast_cursor_set, - .cursor_move = ast_cursor_move, - .reset = ast_crtc_reset, + .reset = drm_atomic_helper_crtc_reset, .set_config = drm_crtc_helper_set_config, - .gamma_set = ast_crtc_gamma_set, + .gamma_set = drm_atomic_helper_legacy_gamma_set, .destroy = ast_crtc_destroy, + .set_config = drm_atomic_helper_set_config, + .page_flip = drm_atomic_helper_page_flip, .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state, .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, }; @@ -1036,6 +901,10 @@ err_kfree: return ret; } +/* + * Encoder + */ + static void ast_encoder_destroy(struct drm_encoder *encoder) { drm_encoder_cleanup(encoder); @@ -1046,34 +915,6 @@ static const struct drm_encoder_funcs ast_enc_funcs = { .destroy = ast_encoder_destroy, }; -static void ast_encoder_dpms(struct drm_encoder *encoder, int mode) -{ - -} - -static void ast_encoder_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ -} - -static void ast_encoder_prepare(struct drm_encoder *encoder) -{ - -} - -static void ast_encoder_commit(struct drm_encoder *encoder) -{ - -} - -static const struct drm_encoder_helper_funcs ast_enc_helper_funcs = { - .dpms = ast_encoder_dpms, - .prepare = ast_encoder_prepare, - .commit = ast_encoder_commit, - .mode_set = ast_encoder_mode_set, -}; - static int ast_encoder_init(struct drm_device *dev) { struct ast_encoder *ast_encoder; @@ -1084,12 +925,15 @@ static int ast_encoder_init(struct drm_device *dev) drm_encoder_init(dev, &ast_encoder->base, &ast_enc_funcs, DRM_MODE_ENCODER_DAC, NULL); - drm_encoder_helper_add(&ast_encoder->base, &ast_enc_helper_funcs); ast_encoder->base.possible_crtcs = 1; return 0; } +/* + * Connector + */ + static int ast_get_modes(struct drm_connector *connector) { struct ast_connector *ast_connector = to_ast_connector(connector); @@ -1188,14 +1032,16 @@ static void ast_connector_destroy(struct drm_connector *connector) } static const struct drm_connector_helper_funcs ast_connector_helper_funcs = { - .mode_valid = ast_mode_valid, .get_modes = ast_get_modes, + .mode_valid = ast_mode_valid, }; static const struct drm_connector_funcs ast_connector_funcs = { - .dpms = drm_helper_connector_dpms, + .reset = drm_atomic_helper_connector_reset, .fill_modes = drm_helper_probe_single_connector_modes, .destroy = ast_connector_destroy, + .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, }; static int ast_connector_init(struct drm_device *dev) @@ -1536,106 +1382,6 @@ static void ast_cursor_set_base(struct ast_private *ast, u64 address) ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xca, addr2); } -static int ast_show_cursor(struct drm_crtc *crtc, void *src, - unsigned int width, unsigned int height) -{ - struct ast_private *ast = crtc->dev->dev_private; - struct ast_crtc *ast_crtc = to_ast_crtc(crtc); - struct drm_gem_vram_object *gbo; - void *dst; - s64 off; - int ret; - u8 jreg; - - gbo = ast->cursor.gbo[ast->cursor.next_index]; - dst = drm_gem_vram_vmap(gbo); - if (IS_ERR(dst)) - return PTR_ERR(dst); - off = drm_gem_vram_offset(gbo); - if (off < 0) { - ret = (int)off; - goto err_drm_gem_vram_vunmap; - } - - ret = ast_cursor_update(dst, src, width, height); - if (ret) - goto err_drm_gem_vram_vunmap; - ast_cursor_set_base(ast, off); - - ast_crtc->offset_x = AST_MAX_HWC_WIDTH - width; - ast_crtc->offset_y = AST_MAX_HWC_WIDTH - height; - - jreg = 0x2; - /* enable ARGB cursor */ - jreg |= 1; - ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xcb, 0xfc, jreg); - - ++ast->cursor.next_index; - ast->cursor.next_index %= ARRAY_SIZE(ast->cursor.gbo); - - drm_gem_vram_vunmap(gbo, dst); - - return 0; - -err_drm_gem_vram_vunmap: - drm_gem_vram_vunmap(gbo, dst); - return ret; -} - -static void ast_hide_cursor(struct drm_crtc *crtc) -{ - struct ast_private *ast = crtc->dev->dev_private; - - ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xcb, 0xfc, 0x00); -} - -static int ast_cursor_set(struct drm_crtc *crtc, - struct drm_file *file_priv, - uint32_t handle, - uint32_t width, - uint32_t height) -{ - struct drm_gem_object *obj; - struct drm_gem_vram_object *gbo; - u8 *src; - int ret; - - if (!handle) { - ast_hide_cursor(crtc); - return 0; - } - - if (width > AST_MAX_HWC_WIDTH || height > AST_MAX_HWC_HEIGHT) - return -EINVAL; - - obj = drm_gem_object_lookup(file_priv, handle); - if (!obj) { - DRM_ERROR("Cannot find cursor object %x for crtc\n", handle); - return -ENOENT; - } - gbo = drm_gem_vram_of_gem(obj); - src = drm_gem_vram_vmap(gbo); - if (IS_ERR(src)) { - ret = PTR_ERR(src); - goto err_drm_gem_object_put_unlocked; - } - - ret = ast_show_cursor(crtc, src, width, height); - if (ret) - goto err_drm_gem_vram_vunmap; - - drm_gem_vram_vunmap(gbo, src); - drm_gem_object_put_unlocked(obj); - - return 0; - -err_drm_gem_vram_vunmap: - drm_gem_vram_vunmap(gbo, src); -err_drm_gem_object_put_unlocked: - drm_gem_object_put_unlocked(obj); - return ret; -} - static int ast_cursor_move(struct drm_crtc *crtc, int x, int y) { -- cgit From 71d873cc99309ff68d2488d32094774c77537e50 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Mon, 2 Dec 2019 12:15:51 +0100 Subject: drm/ast: Move modesetting code to CRTC's atomic_flush() When enabling the CRTC after waking up from a power-saving mode, the primary plane's framebuffer might be NULL, which leads to a stack trace as shown below. [ 632.624608] BUG: kernel NULL pointer dereference, address: 0000000000000048 [ 632.624631] #PF: supervisor read access in kernel mode [ 632.624639] #PF: error_code(0x0000) - not-present page [ 632.624647] PGD 0 P4D 0 [ 632.624654] Oops: 0000 [#1] SMP PTI [ 632.624662] CPU: 0 PID: 2082 Comm: gnome-shell Tainted: G E 5.4.0-rc7-1-default+ #114 [ 632.624673] Hardware name: Sun Microsystems SUN FIRE X2270 M2/SUN FIRE X2270 M2, BIOS 2.05 07/01/2010 [ 632.624689] RIP: 0010:ast_crtc_helper_atomic_enable+0x7d/0x680 [ast] [ 632.624698] Code: 48 8b 80 e0 02 00 00 4c 8b 60 10 31 c0 f3 48 ab 48 8b 83 78 04 00 00 4c 89 ef 48 8d 70 18 e8 9a e9 55 ce 48 8b 83 78 04 00 00 <49> 8b 7c 24 48 4c 89 ea 4c 8d 44 24 28 48 8d 4c 24 20 48 8d 70 18 [ 632.624718] RSP: 0018:ffffbe9ec123fa40 EFLAGS: 00010246 [ 632.624726] RAX: ffff95a13cfd3400 RBX: ffff95a13cf32000 RCX: 0000000000000000 [ 632.624735] RDX: 0000000000000000 RSI: ffff95a13cfd34e8 RDI: ffffbe9ec123fb40 [ 632.624744] RBP: ffffbe9ec123fb80 R08: 0000000000000000 R09: 0000000000000003 [ 632.624753] R10: 0000000000000000 R11: 0000000000000000 R12: 0000000000000000 [ 632.624762] R13: ffffbe9ec123fa70 R14: ffff95a13beb7000 R15: ffff95a13cf32800 [ 632.624772] FS: 00007f6d2763e140(0000) GS:ffff95a134000000(0000) knlGS:0000000000000000 [ 632.624782] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 632.624790] CR2: 0000000000000048 CR3: 00000001192f8004 CR4: 00000000000206f0 [ 632.624800] Call Trace: [ 632.624811] ? __lock_acquire+0x409/0x7c0 [ 632.624830] drm_atomic_helper_commit_modeset_enables+0x1af/0x200 [ 632.624840] drm_atomic_helper_commit_tail+0x32/0x70 [ 632.624849] commit_tail+0xc7/0x110 [ 632.624857] drm_atomic_helper_commit+0x121/0x130 [ 632.624867] drm_atomic_connector_commit_dpms+0xd7/0x100 [ 632.624878] set_property_atomic+0xaf/0x110 [ 632.624890] drm_mode_obj_set_property_ioctl+0xbb/0x190 [ 632.624899] ? drm_mode_obj_find_prop_id+0x40/0x40 [ 632.624909] drm_ioctl_kernel+0x86/0xd0 [ 632.624918] drm_ioctl+0x1e4/0x36b [ 632.624925] ? drm_mode_obj_find_prop_id+0x40/0x40 [ 632.624939] do_vfs_ioctl+0x4bd/0x6e0 [ 632.624949] ksys_ioctl+0x5e/0x90 [ 632.624957] __x64_sys_ioctl+0x16/0x20 [ 632.624966] do_syscall_64+0x5a/0x220 [ 632.624976] entry_SYSCALL_64_after_hwframe+0x49/0xbe [ 632.624984] RIP: 0033:0x7f6d2b0de387 [ 632.624991] Code: 00 00 90 48 8b 05 f9 9a 0c 00 64 c7 00 26 00 00 00 48 c7 c0 ff ff ff ff c3 66 2e 0f 1f 84 00 00 00 00 00 b8 10 00 00 00 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d c9 9a 0c 00 f7 d8 64 89 01 48 [ 632.625011] RSP: 002b:00007fffb49def38 EFLAGS: 00000246 ORIG_RAX: 0000000000000010 [ 632.625021] RAX: ffffffffffffffda RBX: 00007fffb49def70 RCX: 00007f6d2b0de387 [ 632.625030] RDX: 00007fffb49def70 RSI: 00000000c01864ba RDI: 0000000000000009 [ 632.625040] RBP: 00000000c01864ba R08: 0000000000000000 R09: 00000000c0c0c0c0 [ 632.625049] R10: 0000000000000030 R11: 0000000000000246 R12: 000055bc367eb920 [ 632.625058] R13: 0000000000000009 R14: 0000000000000002 R15: 0000000000000000 [ 632.625071] Modules linked in: ebtable_filter(E) ebtables(E) ip6table_filter(E) ip6_tables(E) iptable_filter(E) ip_tables(E) x_tables(E) af_packet(E) scsi_transport_iscsi(E) dmi_sysfs(E) msr(E) xfs(E) intel_powerclamp(E) coretemp(E) k) [ 632.625185] CR2: 0000000000000048 The STR is * start gdm and wait for it to switch off the display * wake up the display by pressing a key CRTC modesetting depends on the new state of the CRTC and the primary plane's framebuffer. The bugfix moves the modesetting code into the CRTC's atomic_flush() function, where it is protected from the plane's framebuffer being NULL. The CRTC's atomic-enable function, which is the modesetting's original location, still contains DPMS state handling. It's exactly the inverse of the atomic-disable function. v3: * protect modesetting from from fb == NULL v2: * do an atomic check for plane * reject invisible primary planes Signed-off-by: Thomas Zimmermann Acked-by: Gerd Hoffmann Fixes: b48e1b6ffd28 ("drm/ast: Add CRTC helpers for atomic modesetting") Cc: Gerd Hoffmann Cc: Dave Airlie Cc: Daniel Vetter Cc: "Y.C. Chen" Cc: Sam Ravnborg Link: https://patchwork.freedesktop.org/patch/msgid/20191202111557.15176-2-tzimmermann@suse.de --- drivers/gpu/drm/ast/ast_mode.c | 31 ++++++++++--------------------- 1 file changed, 10 insertions(+), 21 deletions(-) (limited to 'drivers/gpu/drm/ast/ast_mode.c') diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index 4725ec911a66..33aca817b686 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -790,6 +790,8 @@ static void ast_crtc_helper_atomic_begin(struct drm_crtc *crtc, static void ast_crtc_helper_atomic_flush(struct drm_crtc *crtc, struct drm_crtc_state *old_crtc_state) { + struct drm_device *dev = crtc->dev; + struct ast_private *ast = dev->dev_private; const struct drm_framebuffer *fb = crtc->primary->state->fb; struct drm_display_mode adjusted_mode; struct ast_vbios_mode_info vbios_mode; @@ -800,36 +802,18 @@ static void ast_crtc_helper_atomic_flush(struct drm_crtc *crtc, if (!fb) return; - ast_set_color_reg(crtc, fb); - memset(&adjusted_mode, 0, sizeof(adjusted_mode)); drm_mode_copy(&adjusted_mode, &crtc->state->adjusted_mode); succ = ast_get_vbios_mode_info(fb, &crtc->state->adjusted_mode, &adjusted_mode, &vbios_mode); if (WARN_ON_ONCE(!succ)) - return; + return; /* BUG: didn't validate this in atomic_check() */ + ast_set_color_reg(crtc, fb); ast_set_vbios_color_reg(crtc, fb, &vbios_mode); -} -static void -ast_crtc_helper_atomic_enable(struct drm_crtc *crtc, - struct drm_crtc_state *old_crtc_state) -{ - struct drm_device *dev = crtc->dev; - struct ast_private *ast = crtc->dev->dev_private; - const struct drm_framebuffer *fb = crtc->primary->state->fb; - struct drm_display_mode adjusted_mode; - struct ast_vbios_mode_info vbios_mode; - bool succ; - - memset(&adjusted_mode, 0, sizeof(adjusted_mode)); - drm_mode_copy(&adjusted_mode, &crtc->state->adjusted_mode); - - succ = ast_get_vbios_mode_info(fb, &crtc->state->adjusted_mode, - &adjusted_mode, &vbios_mode); - if (WARN_ON_ONCE(!succ)) + if (!crtc->state->mode_changed) return; ast_set_vbios_mode_reg(crtc, &adjusted_mode, &vbios_mode); @@ -840,7 +824,12 @@ ast_crtc_helper_atomic_enable(struct drm_crtc *crtc, ast_set_crtthd_reg(crtc); ast_set_sync_reg(dev, &adjusted_mode, &vbios_mode); ast_set_dac_reg(crtc, &adjusted_mode, &vbios_mode); +} +static void +ast_crtc_helper_atomic_enable(struct drm_crtc *crtc, + struct drm_crtc_state *old_crtc_state) +{ ast_crtc_dpms(crtc, DRM_MODE_DPMS_ON); } -- cgit From 2fbeec03e171654c5aec509bafee5523eea77f20 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Mon, 2 Dec 2019 12:15:52 +0100 Subject: drm/ast: Enable and disable screen in primary-plane functions Enabling and disabling the screen used to be done in the register initialization and the DPMS function. None of these places is related to the screen's output. Now the primary plane's update and disable functions handle screen display state. The primary plane can now be switched off without displaying garbage. Signed-off-by: Thomas Zimmermann Acked-by: Gerd Hoffmann Link: https://patchwork.freedesktop.org/patch/msgid/20191202111557.15176-3-tzimmermann@suse.de --- drivers/gpu/drm/ast/ast_mode.c | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) (limited to 'drivers/gpu/drm/ast/ast_mode.c') diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index 33aca817b686..542cf52df90a 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -278,12 +278,11 @@ static void ast_set_std_reg(struct drm_crtc *crtc, struct drm_display_mode *mode jreg = stdtable->misc; ast_io_write8(ast, AST_IO_MISC_PORT_WRITE, jreg); - /* Set SEQ */ + /* Set SEQ; except Screen Disable field */ ast_set_index_reg(ast, AST_IO_SEQ_PORT, 0x00, 0x03); - for (i = 0; i < 4; i++) { + ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT, 0x01, 0xdf, stdtable->seq[0]); + for (i = 1; i < 4; i++) { jreg = stdtable->seq[i]; - if (!i) - jreg |= 0x20; ast_set_index_reg(ast, AST_IO_SEQ_PORT, (i + 1) , jreg); } @@ -562,14 +561,12 @@ int ast_primary_plane_helper_atomic_check(struct drm_plane *plane, void ast_primary_plane_helper_atomic_update(struct drm_plane *plane, struct drm_plane_state *old_state) { + struct ast_private *ast = plane->dev->dev_private; struct drm_plane_state *state = plane->state; struct drm_crtc *crtc = state->crtc; struct drm_gem_vram_object *gbo; s64 gpu_addr; - if (!crtc || !state->fb) - return; - gbo = drm_gem_vram_of_gem(state->fb->obj[0]); gpu_addr = drm_gem_vram_offset(gbo); if (WARN_ON_ONCE(gpu_addr < 0)) @@ -577,6 +574,17 @@ void ast_primary_plane_helper_atomic_update(struct drm_plane *plane, ast_set_offset_reg(crtc); ast_set_start_address_crt1(crtc, (u32)gpu_addr); + + ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT, 0x1, 0xdf, 0x00); +} + +static void +ast_primary_plane_helper_atomic_disable(struct drm_plane *plane, + struct drm_plane_state *old_state) +{ + struct ast_private *ast = plane->dev->dev_private; + + ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT, 0x1, 0xdf, 0x20); } static const struct drm_plane_helper_funcs ast_primary_plane_helper_funcs = { @@ -584,6 +592,7 @@ static const struct drm_plane_helper_funcs ast_primary_plane_helper_funcs = { .cleanup_fb = drm_gem_vram_plane_helper_cleanup_fb, .atomic_check = ast_primary_plane_helper_atomic_check, .atomic_update = ast_primary_plane_helper_atomic_update, + .atomic_disable = ast_primary_plane_helper_atomic_disable, }; static const struct drm_plane_funcs ast_primary_plane_funcs = { @@ -736,11 +745,13 @@ static void ast_crtc_dpms(struct drm_crtc *crtc, int mode) if (ast->chip == AST1180) return; + /* TODO: Maybe control display signal generation with + * Sync Enable (bit CR17.7). + */ switch (mode) { case DRM_MODE_DPMS_ON: case DRM_MODE_DPMS_STANDBY: case DRM_MODE_DPMS_SUSPEND: - ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT, 0x1, 0xdf, 0); if (ast->tx_chip_type == AST_TX_DP501) ast_set_dp501_video_output(crtc->dev, 1); ast_crtc_load_lut(crtc); @@ -748,7 +759,6 @@ static void ast_crtc_dpms(struct drm_crtc *crtc, int mode) case DRM_MODE_DPMS_OFF: if (ast->tx_chip_type == AST_TX_DP501) ast_set_dp501_video_output(crtc->dev, 0); - ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT, 0x1, 0xdf, 0x20); break; } } -- cgit From ae37025d14ac423419d97b5be5cf61d433b48bab Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Mon, 2 Dec 2019 12:15:53 +0100 Subject: drm/ast: Clean up arguments of register functions In preparation of an update of the primary-plane code, this patch changes the arguments of several register-setting functions. No functional changes are made. The function ast_set_dac_reg() has no effect and therefore gets removed entirely. Signed-off-by: Thomas Zimmermann Acked-by: Gerd Hoffmann Link: https://patchwork.freedesktop.org/patch/msgid/20191202111557.15176-4-tzimmermann@suse.de --- drivers/gpu/drm/ast/ast_mode.c | 105 +++++++++++++++++------------------------ 1 file changed, 43 insertions(+), 62 deletions(-) (limited to 'drivers/gpu/drm/ast/ast_mode.c') diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index 542cf52df90a..873756cdb7e2 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -70,9 +70,8 @@ static inline void ast_load_palette_index(struct ast_private *ast, ast_io_read8(ast, AST_IO_SEQ_PORT); } -static void ast_crtc_load_lut(struct drm_crtc *crtc) +static void ast_crtc_load_lut(struct ast_private *ast, struct drm_crtc *crtc) { - struct ast_private *ast = crtc->dev->dev_private; u16 *r, *g, *b; int i; @@ -87,7 +86,7 @@ static void ast_crtc_load_lut(struct drm_crtc *crtc) ast_load_palette_index(ast, i, *r++ >> 8, *g++ >> 8, *b++ >> 8); } -static bool ast_get_vbios_mode_info(const struct drm_framebuffer *fb, +static bool ast_get_vbios_mode_info(const struct drm_format_info *format, const struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode, struct ast_vbios_mode_info *vbios_mode) @@ -97,7 +96,7 @@ static bool ast_get_vbios_mode_info(const struct drm_framebuffer *fb, u32 hborder, vborder; bool check_sync; - switch (fb->format->cpp[0] * 8) { + switch (format->cpp[0] * 8) { case 8: vbios_mode->std_table = &vbios_stdtable[VGAModeIndex]; break; @@ -209,14 +208,13 @@ static bool ast_get_vbios_mode_info(const struct drm_framebuffer *fb, return true; } -static void ast_set_vbios_color_reg(struct drm_crtc *crtc, - const struct drm_framebuffer *fb, +static void ast_set_vbios_color_reg(struct ast_private *ast, + const struct drm_format_info *format, const struct ast_vbios_mode_info *vbios_mode) { - struct ast_private *ast = crtc->dev->dev_private; u32 color_index; - switch (fb->format->cpp[0]) { + switch (format->cpp[0]) { case 1: color_index = VGAModeIndex - 1; break; @@ -236,15 +234,14 @@ static void ast_set_vbios_color_reg(struct drm_crtc *crtc, if (vbios_mode->enh_table->flags & NewModeInfo) { ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x91, 0xa8); - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x92, fb->format->cpp[0] * 8); + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x92, format->cpp[0] * 8); } } -static void ast_set_vbios_mode_reg(struct drm_crtc *crtc, +static void ast_set_vbios_mode_reg(struct ast_private *ast, const struct drm_display_mode *adjusted_mode, const struct ast_vbios_mode_info *vbios_mode) { - struct ast_private *ast = crtc->dev->dev_private; u32 refresh_rate_index, mode_id; refresh_rate_index = vbios_mode->enh_table->refresh_rate_index; @@ -265,10 +262,10 @@ static void ast_set_vbios_mode_reg(struct drm_crtc *crtc, } } -static void ast_set_std_reg(struct drm_crtc *crtc, struct drm_display_mode *mode, +static void ast_set_std_reg(struct ast_private *ast, + struct drm_display_mode *mode, struct ast_vbios_mode_info *vbios_mode) { - struct ast_private *ast = crtc->dev->dev_private; const struct ast_vbios_stdtable *stdtable; u32 i; u8 jreg; @@ -313,10 +310,10 @@ static void ast_set_std_reg(struct drm_crtc *crtc, struct drm_display_mode *mode ast_set_index_reg(ast, AST_IO_GR_PORT, i, stdtable->gr[i]); } -static void ast_set_crtc_reg(struct drm_crtc *crtc, struct drm_display_mode *mode, +static void ast_set_crtc_reg(struct ast_private *ast, + struct drm_display_mode *mode, struct ast_vbios_mode_info *vbios_mode) { - struct ast_private *ast = crtc->dev->dev_private; u8 jreg05 = 0, jreg07 = 0, jreg09 = 0, jregAC = 0, jregAD = 0, jregAE = 0; u16 temp, precache = 0; @@ -422,11 +419,9 @@ static void ast_set_crtc_reg(struct drm_crtc *crtc, struct drm_display_mode *mod ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x11, 0x7f, 0x80); } -static void ast_set_offset_reg(struct drm_crtc *crtc) +static void ast_set_offset_reg(struct ast_private *ast, + struct drm_framebuffer *fb) { - struct ast_private *ast = crtc->dev->dev_private; - const struct drm_framebuffer *fb = crtc->primary->state->fb; - u16 offset; offset = fb->pitches[0] >> 3; @@ -434,10 +429,10 @@ static void ast_set_offset_reg(struct drm_crtc *crtc) ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xb0, (offset >> 8) & 0x3f); } -static void ast_set_dclk_reg(struct drm_device *dev, struct drm_display_mode *mode, +static void ast_set_dclk_reg(struct ast_private *ast, + struct drm_display_mode *mode, struct ast_vbios_mode_info *vbios_mode) { - struct ast_private *ast = dev->dev_private; const struct ast_vbios_dclk_info *clk_info; if (ast->chip == AST2500) @@ -452,13 +447,12 @@ static void ast_set_dclk_reg(struct drm_device *dev, struct drm_display_mode *mo ((clk_info->param3 & 0x3) << 4)); } -static void ast_set_color_reg(struct drm_crtc *crtc, - const struct drm_framebuffer *fb) +static void ast_set_color_reg(struct ast_private *ast, + const struct drm_format_info *format) { - struct ast_private *ast = crtc->dev->dev_private; u8 jregA0 = 0, jregA3 = 0, jregA8 = 0; - switch (fb->format->cpp[0] * 8) { + switch (format->cpp[0] * 8) { case 8: jregA0 = 0x70; jregA3 = 0x01; @@ -482,10 +476,8 @@ static void ast_set_color_reg(struct drm_crtc *crtc, ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa8, 0xfd, jregA8); } -static void ast_set_crtthd_reg(struct drm_crtc *crtc) +static void ast_set_crtthd_reg(struct ast_private *ast) { - struct ast_private *ast = crtc->dev->dev_private; - /* Set Threshold */ if (ast->chip == AST2300 || ast->chip == AST2400 || ast->chip == AST2500) { @@ -503,10 +495,10 @@ static void ast_set_crtthd_reg(struct drm_crtc *crtc) } } -static void ast_set_sync_reg(struct drm_device *dev, struct drm_display_mode *mode, +static void ast_set_sync_reg(struct ast_private *ast, + struct drm_display_mode *mode, struct ast_vbios_mode_info *vbios_mode) { - struct ast_private *ast = dev->dev_private; u8 jreg; jreg = ast_io_read8(ast, AST_IO_MISC_PORT_READ); @@ -516,23 +508,9 @@ static void ast_set_sync_reg(struct drm_device *dev, struct drm_display_mode *mo ast_io_write8(ast, AST_IO_MISC_PORT_WRITE, jreg); } -static bool ast_set_dac_reg(struct drm_crtc *crtc, struct drm_display_mode *mode, - struct ast_vbios_mode_info *vbios_mode) +static void ast_set_start_address_crt1(struct ast_private *ast, + unsigned offset) { - const struct drm_framebuffer *fb = crtc->primary->state->fb; - - switch (fb->format->cpp[0] * 8) { - case 8: - break; - default: - return false; - } - return true; -} - -static void ast_set_start_address_crt1(struct drm_crtc *crtc, unsigned offset) -{ - struct ast_private *ast = crtc->dev->dev_private; u32 addr; addr = offset >> 2; @@ -563,7 +541,6 @@ void ast_primary_plane_helper_atomic_update(struct drm_plane *plane, { struct ast_private *ast = plane->dev->dev_private; struct drm_plane_state *state = plane->state; - struct drm_crtc *crtc = state->crtc; struct drm_gem_vram_object *gbo; s64 gpu_addr; @@ -572,8 +549,8 @@ void ast_primary_plane_helper_atomic_update(struct drm_plane *plane, if (WARN_ON_ONCE(gpu_addr < 0)) return; /* Bug: we didn't pin the BO to VRAM in prepare_fb. */ - ast_set_offset_reg(crtc); - ast_set_start_address_crt1(crtc, (u32)gpu_addr); + ast_set_offset_reg(ast, state->fb); + ast_set_start_address_crt1(ast, (u32)gpu_addr); ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT, 0x1, 0xdf, 0x00); } @@ -754,7 +731,7 @@ static void ast_crtc_dpms(struct drm_crtc *crtc, int mode) case DRM_MODE_DPMS_SUSPEND: if (ast->tx_chip_type == AST_TX_DP501) ast_set_dp501_video_output(crtc->dev, 1); - ast_crtc_load_lut(crtc); + ast_crtc_load_lut(ast, crtc); break; case DRM_MODE_DPMS_OFF: if (ast->tx_chip_type == AST_TX_DP501) @@ -780,8 +757,9 @@ static int ast_crtc_helper_atomic_check(struct drm_crtc *crtc, plane_state = crtc->primary->state; if (plane_state && plane_state->fb) { - succ = ast_get_vbios_mode_info(plane_state->fb, &state->mode, - &adjusted_mode, &vbios_mode); + succ = ast_get_vbios_mode_info(plane_state->fb->format, + &state->mode, &adjusted_mode, + &vbios_mode); if (!succ) return -EINVAL; } @@ -803,6 +781,7 @@ static void ast_crtc_helper_atomic_flush(struct drm_crtc *crtc, struct drm_device *dev = crtc->dev; struct ast_private *ast = dev->dev_private; const struct drm_framebuffer *fb = crtc->primary->state->fb; + const struct drm_format_info *format; struct drm_display_mode adjusted_mode; struct ast_vbios_mode_info vbios_mode; bool succ; @@ -812,28 +791,30 @@ static void ast_crtc_helper_atomic_flush(struct drm_crtc *crtc, if (!fb) return; + format = fb->format; + memset(&adjusted_mode, 0, sizeof(adjusted_mode)); drm_mode_copy(&adjusted_mode, &crtc->state->adjusted_mode); - succ = ast_get_vbios_mode_info(fb, &crtc->state->adjusted_mode, + succ = ast_get_vbios_mode_info(format, + &crtc->state->adjusted_mode, &adjusted_mode, &vbios_mode); if (WARN_ON_ONCE(!succ)) return; /* BUG: didn't validate this in atomic_check() */ - ast_set_color_reg(crtc, fb); - ast_set_vbios_color_reg(crtc, fb, &vbios_mode); + ast_set_color_reg(ast, format); + ast_set_vbios_color_reg(ast, format, &vbios_mode); if (!crtc->state->mode_changed) return; - ast_set_vbios_mode_reg(crtc, &adjusted_mode, &vbios_mode); + ast_set_vbios_mode_reg(ast, &adjusted_mode, &vbios_mode); ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa1, 0x06); - ast_set_std_reg(crtc, &adjusted_mode, &vbios_mode); - ast_set_crtc_reg(crtc, &adjusted_mode, &vbios_mode); - ast_set_dclk_reg(dev, &adjusted_mode, &vbios_mode); - ast_set_crtthd_reg(crtc); - ast_set_sync_reg(dev, &adjusted_mode, &vbios_mode); - ast_set_dac_reg(crtc, &adjusted_mode, &vbios_mode); + ast_set_std_reg(ast, &adjusted_mode, &vbios_mode); + ast_set_crtc_reg(ast, &adjusted_mode, &vbios_mode); + ast_set_dclk_reg(ast, &adjusted_mode, &vbios_mode); + ast_set_crtthd_reg(ast); + ast_set_sync_reg(ast, &adjusted_mode, &vbios_mode); } static void -- cgit From ae46a57d52c265948761cc17a754f99b0c495473 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Mon, 2 Dec 2019 12:15:54 +0100 Subject: drm/ast: Add plane atomic_check() functions Introducing atomic_check() for priamry and cursor plane. The functions validate the plane state and will later set format information for the CRTC's atomic_flush(). Signed-off-by: Thomas Zimmermann Acked-by: Gerd Hoffmann Link: https://patchwork.freedesktop.org/patch/msgid/20191202111557.15176-5-tzimmermann@suse.de --- drivers/gpu/drm/ast/ast_mode.c | 47 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 43 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm/ast/ast_mode.c') diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index 873756cdb7e2..59c0c702857d 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -31,6 +31,7 @@ #include #include +#include #include #include #include @@ -530,9 +531,24 @@ static const uint32_t ast_primary_plane_formats[] = { DRM_FORMAT_C8, }; -int ast_primary_plane_helper_atomic_check(struct drm_plane *plane, - struct drm_plane_state *state) +static int ast_primary_plane_helper_atomic_check(struct drm_plane *plane, + struct drm_plane_state *state) { + struct drm_crtc_state *crtc_state; + int ret; + + if (!state->crtc) + return 0; + + crtc_state = drm_atomic_get_new_crtc_state(state->state, state->crtc); + + ret = drm_atomic_helper_check_plane_state(state, crtc_state, + DRM_PLANE_HELPER_NO_SCALING, + DRM_PLANE_HELPER_NO_SCALING, + false, true); + if (ret) + return ret; + return 0; } @@ -603,8 +619,9 @@ ast_cursor_plane_helper_prepare_fb(struct drm_plane *plane, if (!crtc || !fb) return 0; - if (fb->width > AST_MAX_HWC_WIDTH || fb->height > AST_MAX_HWC_HEIGHT) - return -EINVAL; + if (WARN_ON_ONCE(fb->width > AST_MAX_HWC_WIDTH) || + WARN_ON_ONCE(fb->height > AST_MAX_HWC_HEIGHT)) + return -EINVAL; /* BUG: didn't test in atomic_check() */ ast = crtc->dev->dev_private; @@ -646,6 +663,28 @@ err_drm_gem_vram_unpin: static int ast_cursor_plane_helper_atomic_check(struct drm_plane *plane, struct drm_plane_state *state) { + struct drm_framebuffer *fb = state->fb; + struct drm_crtc_state *crtc_state; + int ret; + + if (!state->crtc) + return 0; + + crtc_state = drm_atomic_get_new_crtc_state(state->state, state->crtc); + + ret = drm_atomic_helper_check_plane_state(state, crtc_state, + DRM_PLANE_HELPER_NO_SCALING, + DRM_PLANE_HELPER_NO_SCALING, + true, true); + if (ret) + return ret; + + if (!state->visible) + return 0; + + if (fb->width > AST_MAX_HWC_WIDTH || fb->height > AST_MAX_HWC_HEIGHT) + return -EINVAL; + return 0; } -- cgit From 83be6a3ceb11bd1d5c8d83835b2a42f233198b67 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Mon, 2 Dec 2019 12:15:55 +0100 Subject: drm/ast: Introduce struct ast_crtc_state AST-specific CRTC state can be placed in the new struct ast_crtc_state. The atomic check functions of the CRTC and the primary plane will store the VBIOS mode info and the framebuffer format here. The CRTC will consume these during atomic_flush(). Signed-off-by: Thomas Zimmermann Acked-by: Gerd Hoffmann Link: https://patchwork.freedesktop.org/patch/msgid/20191202111557.15176-6-tzimmermann@suse.de --- drivers/gpu/drm/ast/ast_drv.h | 6 ++++++ drivers/gpu/drm/ast/ast_mode.c | 29 +++++++++++++++++++++++++++-- 2 files changed, 33 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/ast/ast_mode.c') diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h index 49557a73390f..e13afb8a706f 100644 --- a/drivers/gpu/drm/ast/ast_drv.h +++ b/drivers/gpu/drm/ast/ast_drv.h @@ -281,6 +281,12 @@ struct ast_vbios_mode_info { const struct ast_vbios_enhtable *enh_table; }; +struct ast_crtc_state { + struct drm_crtc_state base; +}; + +#define to_ast_crtc_state(state) container_of(state, struct ast_crtc_state, base) + extern int ast_mode_init(struct drm_device *dev); extern void ast_mode_fini(struct drm_device *dev); diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index 59c0c702857d..ad2e0562ec55 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -884,6 +884,31 @@ static void ast_crtc_destroy(struct drm_crtc *crtc) kfree(crtc); } +static struct drm_crtc_state * +ast_crtc_atomic_duplicate_state(struct drm_crtc *crtc) +{ + struct ast_crtc_state *new_ast_state; + + if (WARN_ON(!crtc->state)) + return NULL; + + new_ast_state = kmalloc(sizeof(*new_ast_state), GFP_KERNEL); + if (!new_ast_state) + return NULL; + __drm_atomic_helper_crtc_duplicate_state(crtc, &new_ast_state->base); + + return &new_ast_state->base; +} + +static void ast_crtc_atomic_destroy_state(struct drm_crtc *crtc, + struct drm_crtc_state *state) +{ + struct ast_crtc_state *ast_state = to_ast_crtc_state(state); + + __drm_atomic_helper_crtc_destroy_state(&ast_state->base); + kfree(ast_state); +} + static const struct drm_crtc_funcs ast_crtc_funcs = { .reset = drm_atomic_helper_crtc_reset, .set_config = drm_crtc_helper_set_config, @@ -891,8 +916,8 @@ static const struct drm_crtc_funcs ast_crtc_funcs = { .destroy = ast_crtc_destroy, .set_config = drm_atomic_helper_set_config, .page_flip = drm_atomic_helper_page_flip, - .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state, - .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, + .atomic_duplicate_state = ast_crtc_atomic_duplicate_state, + .atomic_destroy_state = ast_crtc_atomic_destroy_state, }; static int ast_crtc_init(struct drm_device *dev) -- cgit From e7d70cd4948e543739e9859d2b4ab30448067d32 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Mon, 2 Dec 2019 12:15:56 +0100 Subject: drm/ast: Store VBIOS mode info in struct ast_crtc_state After looking up VBIOS mode information in CRTC's atomic_check(), we can reuse it in atomic_flush(). No need for a second look-up. Signed-off-by: Thomas Zimmermann Acked-by: Gerd Hoffmann Link: https://patchwork.freedesktop.org/patch/msgid/20191202111557.15176-7-tzimmermann@suse.de --- drivers/gpu/drm/ast/ast_drv.h | 2 ++ drivers/gpu/drm/ast/ast_mode.c | 58 ++++++++++++++++++++++-------------------- 2 files changed, 32 insertions(+), 28 deletions(-) (limited to 'drivers/gpu/drm/ast/ast_mode.c') diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h index e13afb8a706f..72883b5aefa7 100644 --- a/drivers/gpu/drm/ast/ast_drv.h +++ b/drivers/gpu/drm/ast/ast_drv.h @@ -283,6 +283,8 @@ struct ast_vbios_mode_info { struct ast_crtc_state { struct drm_crtc_state base; + + struct ast_vbios_mode_info vbios_mode_info; }; #define to_ast_crtc_state(state) container_of(state, struct ast_crtc_state, base) diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index ad2e0562ec55..a27724832845 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -784,24 +784,25 @@ static int ast_crtc_helper_atomic_check(struct drm_crtc *crtc, { struct ast_private *ast = crtc->dev->dev_private; struct drm_plane_state *plane_state; + struct ast_crtc_state *ast_state; bool succ; - struct drm_display_mode adjusted_mode; - struct ast_vbios_mode_info vbios_mode; if (ast->chip == AST1180) { DRM_ERROR("AST 1180 modesetting not supported\n"); return -EINVAL; } + ast_state = to_ast_crtc_state(state); plane_state = crtc->primary->state; - if (plane_state && plane_state->fb) { - succ = ast_get_vbios_mode_info(plane_state->fb->format, - &state->mode, &adjusted_mode, - &vbios_mode); - if (!succ) - return -EINVAL; - } + if (!plane_state || !plane_state->fb) + return 0; + + succ = ast_get_vbios_mode_info(plane_state->fb->format, &state->mode, + &state->adjusted_mode, + &ast_state->vbios_mode_info); + if (!succ) + return -EINVAL; return 0; } @@ -820,40 +821,36 @@ static void ast_crtc_helper_atomic_flush(struct drm_crtc *crtc, struct drm_device *dev = crtc->dev; struct ast_private *ast = dev->dev_private; const struct drm_framebuffer *fb = crtc->primary->state->fb; + struct ast_crtc_state *ast_state; const struct drm_format_info *format; - struct drm_display_mode adjusted_mode; - struct ast_vbios_mode_info vbios_mode; - bool succ; + struct ast_vbios_mode_info *vbios_mode_info; + struct drm_display_mode *adjusted_mode; crtc->state->no_vblank = true; if (!fb) return; - format = fb->format; + ast_state = to_ast_crtc_state(crtc->state); - memset(&adjusted_mode, 0, sizeof(adjusted_mode)); - drm_mode_copy(&adjusted_mode, &crtc->state->adjusted_mode); - - succ = ast_get_vbios_mode_info(format, - &crtc->state->adjusted_mode, - &adjusted_mode, &vbios_mode); - if (WARN_ON_ONCE(!succ)) - return; /* BUG: didn't validate this in atomic_check() */ + format = fb->format; + vbios_mode_info = &ast_state->vbios_mode_info; ast_set_color_reg(ast, format); - ast_set_vbios_color_reg(ast, format, &vbios_mode); + ast_set_vbios_color_reg(ast, format, vbios_mode_info); if (!crtc->state->mode_changed) return; - ast_set_vbios_mode_reg(ast, &adjusted_mode, &vbios_mode); + adjusted_mode = &crtc->state->adjusted_mode; + + ast_set_vbios_mode_reg(ast, adjusted_mode, vbios_mode_info); ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa1, 0x06); - ast_set_std_reg(ast, &adjusted_mode, &vbios_mode); - ast_set_crtc_reg(ast, &adjusted_mode, &vbios_mode); - ast_set_dclk_reg(ast, &adjusted_mode, &vbios_mode); + ast_set_std_reg(ast, adjusted_mode, vbios_mode_info); + ast_set_crtc_reg(ast, adjusted_mode, vbios_mode_info); + ast_set_dclk_reg(ast, adjusted_mode, vbios_mode_info); ast_set_crtthd_reg(ast); - ast_set_sync_reg(ast, &adjusted_mode, &vbios_mode); + ast_set_sync_reg(ast, adjusted_mode, vbios_mode_info); } static void @@ -887,7 +884,7 @@ static void ast_crtc_destroy(struct drm_crtc *crtc) static struct drm_crtc_state * ast_crtc_atomic_duplicate_state(struct drm_crtc *crtc) { - struct ast_crtc_state *new_ast_state; + struct ast_crtc_state *new_ast_state, *ast_state; if (WARN_ON(!crtc->state)) return NULL; @@ -897,6 +894,11 @@ ast_crtc_atomic_duplicate_state(struct drm_crtc *crtc) return NULL; __drm_atomic_helper_crtc_duplicate_state(crtc, &new_ast_state->base); + ast_state = to_ast_crtc_state(crtc->state); + + memcpy(&new_ast_state->vbios_mode_info, &ast_state->vbios_mode_info, + sizeof(new_ast_state->vbios_mode_info)); + return &new_ast_state->base; } -- cgit From 3339fdf5742f7182d7a17fb48e2d7463f6a79580 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Mon, 2 Dec 2019 12:15:57 +0100 Subject: drm/ast: Store primary-plane format in struct ast_crtc_state Reading the primary plane's framebuffer from the CRTC's atomic_flush() function is fragile as the plane state or framebuffer can be NULL. Instead, we let the plane's atomic_check() store the framebuffer format in the CRTC state. The CRTC always receives the framebuffer format that is currently programmed, or NULL if no mode has been set yet. Signed-off-by: Thomas Zimmermann Acked-by: Gerd Hoffmann Link: https://patchwork.freedesktop.org/patch/msgid/20191202111557.15176-8-tzimmermann@suse.de --- drivers/gpu/drm/ast/ast_drv.h | 3 +++ drivers/gpu/drm/ast/ast_mode.c | 26 +++++++++++++++++--------- 2 files changed, 20 insertions(+), 9 deletions(-) (limited to 'drivers/gpu/drm/ast/ast_mode.c') diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h index 72883b5aefa7..f5d8780776ae 100644 --- a/drivers/gpu/drm/ast/ast_drv.h +++ b/drivers/gpu/drm/ast/ast_drv.h @@ -284,6 +284,9 @@ struct ast_vbios_mode_info { struct ast_crtc_state { struct drm_crtc_state base; + /* Last known format of primary plane */ + const struct drm_format_info *format; + struct ast_vbios_mode_info vbios_mode_info; }; diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index a27724832845..cde1cae073ec 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -535,6 +535,7 @@ static int ast_primary_plane_helper_atomic_check(struct drm_plane *plane, struct drm_plane_state *state) { struct drm_crtc_state *crtc_state; + struct ast_crtc_state *ast_crtc_state; int ret; if (!state->crtc) @@ -549,6 +550,13 @@ static int ast_primary_plane_helper_atomic_check(struct drm_plane *plane, if (ret) return ret; + if (!state->visible) + return 0; + + ast_crtc_state = to_ast_crtc_state(crtc_state); + + ast_crtc_state->format = state->fb->format; + return 0; } @@ -783,8 +791,8 @@ static int ast_crtc_helper_atomic_check(struct drm_crtc *crtc, struct drm_crtc_state *state) { struct ast_private *ast = crtc->dev->dev_private; - struct drm_plane_state *plane_state; struct ast_crtc_state *ast_state; + const struct drm_format_info *format; bool succ; if (ast->chip == AST1180) { @@ -793,12 +801,12 @@ static int ast_crtc_helper_atomic_check(struct drm_crtc *crtc, } ast_state = to_ast_crtc_state(state); - plane_state = crtc->primary->state; - if (!plane_state || !plane_state->fb) + format = ast_state->format; + if (!format) return 0; - succ = ast_get_vbios_mode_info(plane_state->fb->format, &state->mode, + succ = ast_get_vbios_mode_info(format, &state->mode, &state->adjusted_mode, &ast_state->vbios_mode_info); if (!succ) @@ -820,7 +828,6 @@ static void ast_crtc_helper_atomic_flush(struct drm_crtc *crtc, { struct drm_device *dev = crtc->dev; struct ast_private *ast = dev->dev_private; - const struct drm_framebuffer *fb = crtc->primary->state->fb; struct ast_crtc_state *ast_state; const struct drm_format_info *format; struct ast_vbios_mode_info *vbios_mode_info; @@ -828,12 +835,12 @@ static void ast_crtc_helper_atomic_flush(struct drm_crtc *crtc, crtc->state->no_vblank = true; - if (!fb) - return; - ast_state = to_ast_crtc_state(crtc->state); - format = fb->format; + format = ast_state->format; + if (!format) + return; + vbios_mode_info = &ast_state->vbios_mode_info; ast_set_color_reg(ast, format); @@ -896,6 +903,7 @@ ast_crtc_atomic_duplicate_state(struct drm_crtc *crtc) ast_state = to_ast_crtc_state(crtc->state); + new_ast_state->format = ast_state->format; memcpy(&new_ast_state->vbios_mode_info, &ast_state->vbios_mode_info, sizeof(new_ast_state->vbios_mode_info)); -- cgit From ebe9428b3f60fd15f6b309cf0c65a995f1732c4f Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Mon, 6 Jan 2020 13:57:43 +0100 Subject: drm/vram-helper: Remove interruptible flag from public interface The flag 'interruptible', which is passed to various functions, is always set to be false. Remove it and hard-code the value. Signed-off-by: Thomas Zimmermann Suggested-by: Daniel Vetter Reviewed-by: Daniel Vetter Acked-by: Sam Ravnborg Link: https://patchwork.freedesktop.org/patch/msgid/20200106125745.13797-7-tzimmermann@suse.de --- drivers/gpu/drm/ast/ast_mode.c | 2 +- drivers/gpu/drm/drm_gem_vram_helper.c | 17 ++++++----------- drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c | 2 +- drivers/gpu/drm/mgag200/mgag200_cursor.c | 2 +- drivers/gpu/drm/mgag200/mgag200_drv.c | 2 +- include/drm/drm_gem_vram_helper.h | 4 +--- 6 files changed, 11 insertions(+), 18 deletions(-) (limited to 'drivers/gpu/drm/ast/ast_mode.c') diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index cde1cae073ec..43572eb11ae9 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -1145,7 +1145,7 @@ static int ast_cursor_init(struct drm_device *dev) for (i = 0; i < ARRAY_SIZE(ast->cursor.gbo); ++i) { gbo = drm_gem_vram_create(dev, &dev->vram_mm->bdev, - size, 0, false); + size, 0); if (IS_ERR(gbo)) { ret = PTR_ERR(gbo); goto err_drm_gem_vram_put; diff --git a/drivers/gpu/drm/drm_gem_vram_helper.c b/drivers/gpu/drm/drm_gem_vram_helper.c index 51ee1f7bc730..bc181c0e9440 100644 --- a/drivers/gpu/drm/drm_gem_vram_helper.c +++ b/drivers/gpu/drm/drm_gem_vram_helper.c @@ -94,8 +94,7 @@ static void drm_gem_vram_placement(struct drm_gem_vram_object *gbo, static int drm_gem_vram_init(struct drm_device *dev, struct ttm_bo_device *bdev, struct drm_gem_vram_object *gbo, - size_t size, unsigned long pg_align, - bool interruptible) + size_t size, unsigned long pg_align) { int ret; size_t acc_size; @@ -112,7 +111,7 @@ static int drm_gem_vram_init(struct drm_device *dev, drm_gem_vram_placement(gbo, TTM_PL_FLAG_VRAM | TTM_PL_FLAG_SYSTEM); ret = ttm_bo_init(bdev, &gbo->bo, size, ttm_bo_type_device, - &gbo->placement, pg_align, interruptible, acc_size, + &gbo->placement, pg_align, false, acc_size, NULL, NULL, ttm_buffer_object_destroy); if (ret) goto err_drm_gem_object_release; @@ -130,7 +129,6 @@ err_drm_gem_object_release: * @bdev: the TTM BO device backing the object * @size: the buffer size in bytes * @pg_align: the buffer's alignment in multiples of the page size - * @interruptible: sleep interruptible if waiting for memory * * Returns: * A new instance of &struct drm_gem_vram_object on success, or @@ -139,8 +137,7 @@ err_drm_gem_object_release: struct drm_gem_vram_object *drm_gem_vram_create(struct drm_device *dev, struct ttm_bo_device *bdev, size_t size, - unsigned long pg_align, - bool interruptible) + unsigned long pg_align) { struct drm_gem_vram_object *gbo; int ret; @@ -149,7 +146,7 @@ struct drm_gem_vram_object *drm_gem_vram_create(struct drm_device *dev, if (!gbo) return ERR_PTR(-ENOMEM); - ret = drm_gem_vram_init(dev, bdev, gbo, size, pg_align, interruptible); + ret = drm_gem_vram_init(dev, bdev, gbo, size, pg_align); if (ret < 0) goto err_kfree; @@ -486,7 +483,6 @@ EXPORT_SYMBOL(drm_gem_vram_vunmap); * @bdev: the TTM BO device managing the buffer object * @pg_align: the buffer's alignment in multiples of the page size * @pitch_align: the scanline's alignment in powers of 2 - * @interruptible: sleep interruptible if waiting for memory * @args: the arguments as provided to \ &struct drm_driver.dumb_create * @@ -504,7 +500,6 @@ int drm_gem_vram_fill_create_dumb(struct drm_file *file, struct ttm_bo_device *bdev, unsigned long pg_align, unsigned long pitch_align, - bool interruptible, struct drm_mode_create_dumb *args) { size_t pitch, size; @@ -524,7 +519,7 @@ int drm_gem_vram_fill_create_dumb(struct drm_file *file, if (!size) return -EINVAL; - gbo = drm_gem_vram_create(dev, bdev, size, pg_align, interruptible); + gbo = drm_gem_vram_create(dev, bdev, size, pg_align); if (IS_ERR(gbo)) return PTR_ERR(gbo); @@ -620,7 +615,7 @@ int drm_gem_vram_driver_dumb_create(struct drm_file *file, return -EINVAL; return drm_gem_vram_fill_create_dumb(file, dev, &dev->vram_mm->bdev, - 0, 0, false, args); + 0, 0, args); } EXPORT_SYMBOL(drm_gem_vram_driver_dumb_create); diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c index 0af5d966a480..2f668b71fb4c 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c @@ -51,7 +51,7 @@ int hibmc_dumb_create(struct drm_file *file, struct drm_device *dev, struct drm_mode_create_dumb *args) { return drm_gem_vram_fill_create_dumb(file, dev, &dev->vram_mm->bdev, - 0, 16, false, args); + 0, 16, args); } const struct drm_mode_config_funcs hibmc_mode_funcs = { diff --git a/drivers/gpu/drm/mgag200/mgag200_cursor.c b/drivers/gpu/drm/mgag200/mgag200_cursor.c index 5444cf1573a3..dd54fd507e13 100644 --- a/drivers/gpu/drm/mgag200/mgag200_cursor.c +++ b/drivers/gpu/drm/mgag200/mgag200_cursor.c @@ -209,7 +209,7 @@ int mgag200_cursor_init(struct mga_device *mdev) for (i = 0; i < ncursors; ++i) { gbo = drm_gem_vram_create(dev, &dev->vram_mm->bdev, - size, 0, false); + size, 0); if (IS_ERR(gbo)) { ret = PTR_ERR(gbo); goto err_drm_gem_vram_put; diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.c b/drivers/gpu/drm/mgag200/mgag200_drv.c index 3473e9e9a20d..613fdc2b4b1e 100644 --- a/drivers/gpu/drm/mgag200/mgag200_drv.c +++ b/drivers/gpu/drm/mgag200/mgag200_drv.c @@ -121,7 +121,7 @@ int mgag200_driver_dumb_create(struct drm_file *file, pg_align = PFN_UP(mdev->mc.vram_size); return drm_gem_vram_fill_create_dumb(file, dev, &dev->vram_mm->bdev, - pg_align, 0, false, args); + pg_align, 0, args); } static struct drm_driver driver = { diff --git a/include/drm/drm_gem_vram_helper.h b/include/drm/drm_gem_vram_helper.h index b86d038f8a3d..219474c7d584 100644 --- a/include/drm/drm_gem_vram_helper.h +++ b/include/drm/drm_gem_vram_helper.h @@ -95,8 +95,7 @@ static inline struct drm_gem_vram_object *drm_gem_vram_of_gem( struct drm_gem_vram_object *drm_gem_vram_create(struct drm_device *dev, struct ttm_bo_device *bdev, size_t size, - unsigned long pg_align, - bool interruptible); + unsigned long pg_align); void drm_gem_vram_put(struct drm_gem_vram_object *gbo); u64 drm_gem_vram_mmap_offset(struct drm_gem_vram_object *gbo); s64 drm_gem_vram_offset(struct drm_gem_vram_object *gbo); @@ -113,7 +112,6 @@ int drm_gem_vram_fill_create_dumb(struct drm_file *file, struct ttm_bo_device *bdev, unsigned long pg_align, unsigned long pitch_align, - bool interruptible, struct drm_mode_create_dumb *args); /* -- cgit From a4d46a8e268fcd0cc4235a23d1baabfc588f66f4 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Mon, 6 Jan 2020 13:57:44 +0100 Subject: drm/vram-helper: Remove BO device from public interface TTM is an implementation detail of the VRAM helpers and therefore shouldn't be exposed to the callers. There's only one correct value for the BO device anyway, which is the one stored in the DRM device. So remove struct ttm_bo_device from the VRAM-helper interface and use the device's VRAM manager unconditionally. The GEM initializer function fails if the VRAM manager has not been initialized. Signed-off-by: Thomas Zimmermann Reviewed-by: Daniel Vetter Acked-by: Sam Ravnborg Link: https://patchwork.freedesktop.org/patch/msgid/20200106125745.13797-8-tzimmermann@suse.de --- drivers/gpu/drm/ast/ast_mode.c | 3 +-- drivers/gpu/drm/drm_gem_vram_helper.c | 18 +++++++++--------- drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c | 3 +-- drivers/gpu/drm/mgag200/mgag200_cursor.c | 3 +-- drivers/gpu/drm/mgag200/mgag200_drv.c | 3 +-- include/drm/drm_gem_vram_helper.h | 2 -- 6 files changed, 13 insertions(+), 19 deletions(-) (limited to 'drivers/gpu/drm/ast/ast_mode.c') diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index 43572eb11ae9..34608f0499eb 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -1144,8 +1144,7 @@ static int ast_cursor_init(struct drm_device *dev) size = roundup(AST_HWC_SIZE + AST_HWC_SIGNATURE_SIZE, PAGE_SIZE); for (i = 0; i < ARRAY_SIZE(ast->cursor.gbo); ++i) { - gbo = drm_gem_vram_create(dev, &dev->vram_mm->bdev, - size, 0); + gbo = drm_gem_vram_create(dev, size, 0); if (IS_ERR(gbo)) { ret = PTR_ERR(gbo); goto err_drm_gem_vram_put; diff --git a/drivers/gpu/drm/drm_gem_vram_helper.c b/drivers/gpu/drm/drm_gem_vram_helper.c index bc181c0e9440..942af7edcd0c 100644 --- a/drivers/gpu/drm/drm_gem_vram_helper.c +++ b/drivers/gpu/drm/drm_gem_vram_helper.c @@ -92,13 +92,18 @@ static void drm_gem_vram_placement(struct drm_gem_vram_object *gbo, } static int drm_gem_vram_init(struct drm_device *dev, - struct ttm_bo_device *bdev, struct drm_gem_vram_object *gbo, size_t size, unsigned long pg_align) { + struct drm_vram_mm *vmm = dev->vram_mm; + struct ttm_bo_device *bdev; int ret; size_t acc_size; + if (WARN_ONCE(!vmm, "VRAM MM not initialized")) + return -EINVAL; + bdev = &vmm->bdev; + gbo->bo.base.funcs = &drm_gem_vram_object_funcs; ret = drm_gem_object_init(dev, &gbo->bo.base, size); @@ -126,7 +131,6 @@ err_drm_gem_object_release: /** * drm_gem_vram_create() - Creates a VRAM-backed GEM object * @dev: the DRM device - * @bdev: the TTM BO device backing the object * @size: the buffer size in bytes * @pg_align: the buffer's alignment in multiples of the page size * @@ -135,7 +139,6 @@ err_drm_gem_object_release: * an ERR_PTR()-encoded error code otherwise. */ struct drm_gem_vram_object *drm_gem_vram_create(struct drm_device *dev, - struct ttm_bo_device *bdev, size_t size, unsigned long pg_align) { @@ -146,7 +149,7 @@ struct drm_gem_vram_object *drm_gem_vram_create(struct drm_device *dev, if (!gbo) return ERR_PTR(-ENOMEM); - ret = drm_gem_vram_init(dev, bdev, gbo, size, pg_align); + ret = drm_gem_vram_init(dev, gbo, size, pg_align); if (ret < 0) goto err_kfree; @@ -480,7 +483,6 @@ EXPORT_SYMBOL(drm_gem_vram_vunmap); Helper for implementing &struct drm_driver.dumb_create * @file: the DRM file * @dev: the DRM device - * @bdev: the TTM BO device managing the buffer object * @pg_align: the buffer's alignment in multiples of the page size * @pitch_align: the scanline's alignment in powers of 2 * @args: the arguments as provided to \ @@ -497,7 +499,6 @@ EXPORT_SYMBOL(drm_gem_vram_vunmap); */ int drm_gem_vram_fill_create_dumb(struct drm_file *file, struct drm_device *dev, - struct ttm_bo_device *bdev, unsigned long pg_align, unsigned long pitch_align, struct drm_mode_create_dumb *args) @@ -519,7 +520,7 @@ int drm_gem_vram_fill_create_dumb(struct drm_file *file, if (!size) return -EINVAL; - gbo = drm_gem_vram_create(dev, bdev, size, pg_align); + gbo = drm_gem_vram_create(dev, size, pg_align); if (IS_ERR(gbo)) return PTR_ERR(gbo); @@ -614,8 +615,7 @@ int drm_gem_vram_driver_dumb_create(struct drm_file *file, if (WARN_ONCE(!dev->vram_mm, "VRAM MM not initialized")) return -EINVAL; - return drm_gem_vram_fill_create_dumb(file, dev, &dev->vram_mm->bdev, - 0, 0, args); + return drm_gem_vram_fill_create_dumb(file, dev, 0, 0, args); } EXPORT_SYMBOL(drm_gem_vram_driver_dumb_create); diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c index 2f668b71fb4c..50b988fdd5cc 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c @@ -50,8 +50,7 @@ void hibmc_mm_fini(struct hibmc_drm_private *hibmc) int hibmc_dumb_create(struct drm_file *file, struct drm_device *dev, struct drm_mode_create_dumb *args) { - return drm_gem_vram_fill_create_dumb(file, dev, &dev->vram_mm->bdev, - 0, 16, args); + return drm_gem_vram_fill_create_dumb(file, dev, 0, 16, args); } const struct drm_mode_config_funcs hibmc_mode_funcs = { diff --git a/drivers/gpu/drm/mgag200/mgag200_cursor.c b/drivers/gpu/drm/mgag200/mgag200_cursor.c index dd54fd507e13..d491edd317ff 100644 --- a/drivers/gpu/drm/mgag200/mgag200_cursor.c +++ b/drivers/gpu/drm/mgag200/mgag200_cursor.c @@ -208,8 +208,7 @@ int mgag200_cursor_init(struct mga_device *mdev) return -ENOMEM; for (i = 0; i < ncursors; ++i) { - gbo = drm_gem_vram_create(dev, &dev->vram_mm->bdev, - size, 0); + gbo = drm_gem_vram_create(dev, size, 0); if (IS_ERR(gbo)) { ret = PTR_ERR(gbo); goto err_drm_gem_vram_put; diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.c b/drivers/gpu/drm/mgag200/mgag200_drv.c index 613fdc2b4b1e..ee4fb9c53d9f 100644 --- a/drivers/gpu/drm/mgag200/mgag200_drv.c +++ b/drivers/gpu/drm/mgag200/mgag200_drv.c @@ -120,8 +120,7 @@ int mgag200_driver_dumb_create(struct drm_file *file, if (mgag200_pin_bo_at_0(mdev)) pg_align = PFN_UP(mdev->mc.vram_size); - return drm_gem_vram_fill_create_dumb(file, dev, &dev->vram_mm->bdev, - pg_align, 0, args); + return drm_gem_vram_fill_create_dumb(file, dev, pg_align, 0, args); } static struct drm_driver driver = { diff --git a/include/drm/drm_gem_vram_helper.h b/include/drm/drm_gem_vram_helper.h index 219474c7d584..573e9fd109bf 100644 --- a/include/drm/drm_gem_vram_helper.h +++ b/include/drm/drm_gem_vram_helper.h @@ -93,7 +93,6 @@ static inline struct drm_gem_vram_object *drm_gem_vram_of_gem( } struct drm_gem_vram_object *drm_gem_vram_create(struct drm_device *dev, - struct ttm_bo_device *bdev, size_t size, unsigned long pg_align); void drm_gem_vram_put(struct drm_gem_vram_object *gbo); @@ -109,7 +108,6 @@ void drm_gem_vram_vunmap(struct drm_gem_vram_object *gbo, void *vaddr); int drm_gem_vram_fill_create_dumb(struct drm_file *file, struct drm_device *dev, - struct ttm_bo_device *bdev, unsigned long pg_align, unsigned long pitch_align, struct drm_mode_create_dumb *args); -- cgit