diff options
author | Dave Airlie <airlied@redhat.com> | 2020-07-20 17:29:49 +1000 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2020-07-20 17:30:23 +1000 |
commit | 3ffff3c6855bda1b39eae88f3730d2baddce3bfd (patch) | |
tree | e3cb9de81d26cae157dd9d39118529d2753755c7 /drivers/gpu/drm/ast/ast_mode.c | |
parent | 1cc4af412f40bfe33f4b7e2b014a8d4b140bd8d3 (diff) | |
parent | 947fcfeac3295ff0961bb50803e0c4ae63cff65b (diff) |
Merge tag 'drm-misc-next-2020-07-16' of git://anongit.freedesktop.org/drm/drm-misc into drm-next
drm-misc-next for v5.9:
UAPI Changes:
Cross-subsystem Changes:
- Add ckoenig as dma-buf maintainer.
- Revert invalid fix for dma-fence-chain, and fix selftest.
- Add fixmes to amifb about APUS support.
- Use array3_size in fbcon_prepare_logo, and struct_size() in alloc_apertures.
- Fix leaks in neofb, fb/savage and omapfb.
- Other small fixes to fb code.
- Convert some dt bindings to schema for some panels, and fix simple-framebuffer dt example.
Core Changes:
- Add DRM_FORMAT_MOD_GENERIC_16_16_TILE as alias to DRM_FORMAT_MOD_SAMSUNG_16_16_TILE,
as it can be used more generic.
- Add support for multiple DispID extension blocks in edid.
- Use https instead of http for some of the urls.
- Use drm_* macros for logging in mipi-dsi and fb-helper.
- Further cleanup ttm_mem_reg handling.
- Remove duplicated words in comments.
Driver Changes:
- Use __drm_atomic_helper_crtc_reset in all atomic drivers.
- Add Amlogic Video FBC support to meson and fourcc to core.
- Refactor hisilicon's hibmc_drv_vdac.
- Create a TXP CRTC for vc4.
- Rework cursor support in ast.
- Fix runtime PM in STM.
- Allow bigger cursors in vkms.
- Cleanup sg handling in radeon and amdgpu, and stop creating dummy
gtt nodes with ttm fixed.
- Rework crtc handling in mgag200.
- Miscellaneous small fixes to meson, vgem, bridge/dw-hdmi,
panel/auo,b116xw03, panel/LG LB070WV8, lima, bridge/sil_sii8620,
virtio, tilcdc.
Signed-off-by: Dave Airlie <airlied@redhat.com>
From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/8b360d65-f228-9286-d247-3004156a5254@linux.intel.com
Diffstat (limited to 'drivers/gpu/drm/ast/ast_mode.c')
-rw-r--r-- | drivers/gpu/drm/ast/ast_mode.c | 322 |
1 files changed, 56 insertions, 266 deletions
diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index 510ffb497344..154cd877d9d1 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -37,6 +37,7 @@ #include <drm/drm_crtc.h> #include <drm/drm_crtc_helper.h> #include <drm/drm_fourcc.h> +#include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_gem_vram_helper.h> #include <drm/drm_plane_helper.h> #include <drm/drm_probe_helper.h> @@ -47,16 +48,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_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_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, @@ -621,56 +612,21 @@ static int ast_cursor_plane_helper_prepare_fb(struct drm_plane *plane, struct drm_plane_state *new_state) { - struct drm_device *dev = plane->dev; 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 (drm_WARN_ON_ONCE(dev, fb->width > AST_MAX_HWC_WIDTH) || - drm_WARN_ON_ONCE(dev, fb->height > AST_MAX_HWC_HEIGHT)) - return -EINVAL; /* BUG: didn't test in atomic_check() */ - - ast = to_ast_private(dev); - - 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; - } + ast = to_ast_private(plane->dev); - ret = ast_cursor_update(dst, src, fb->width, fb->height); + ret = ast_cursor_blit(ast, fb); 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 ret; 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, @@ -705,37 +661,21 @@ static void ast_cursor_plane_helper_atomic_update(struct drm_plane *plane, struct drm_plane_state *old_state) { - struct drm_device *dev = plane->dev; struct drm_plane_state *state = plane->state; - struct drm_crtc *crtc = state->crtc; struct drm_framebuffer *fb = state->fb; - struct ast_private *ast = to_ast_private(plane->dev); - struct ast_crtc *ast_crtc = to_ast_crtc(crtc); - struct drm_gem_vram_object *gbo; - s64 off; - u8 jreg; + struct ast_private *ast = plane->dev->dev_private; + unsigned int offset_x, offset_y; - ast_crtc->offset_x = AST_MAX_HWC_WIDTH - fb->width; - ast_crtc->offset_y = AST_MAX_HWC_WIDTH - fb->height; + offset_x = AST_MAX_HWC_WIDTH - fb->width; + 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 (drm_WARN_ON_ONCE(dev, 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_page_flip(ast); } - 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); + ast_cursor_show(ast, state->crtc_x, state->crtc_y, + offset_x, offset_y); } static void @@ -744,7 +684,7 @@ ast_cursor_plane_helper_atomic_disable(struct drm_plane *plane, { struct ast_private *ast = to_ast_private(plane->dev); - ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xcb, 0xfc, 0x00); + ast_cursor_hide(ast); } static const struct drm_plane_helper_funcs ast_cursor_plane_helper_funcs = { @@ -942,21 +882,22 @@ static const struct drm_crtc_funcs ast_crtc_funcs = { static int ast_crtc_init(struct drm_device *dev) { struct ast_private *ast = to_ast_private(dev); - struct ast_crtc *crtc; + struct drm_crtc *crtc; int ret; - crtc = kzalloc(sizeof(struct ast_crtc), GFP_KERNEL); + crtc = kzalloc(sizeof(*crtc), GFP_KERNEL); if (!crtc) return -ENOMEM; - ret = drm_crtc_init_with_planes(dev, &crtc->base, &ast->primary_plane, + ret = drm_crtc_init_with_planes(dev, crtc, &ast->primary_plane, &ast->cursor_plane, &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); + drm_mode_crtc_set_gamma_size(crtc, 256); + drm_crtc_helper_add(crtc, &ast_crtc_helper_funcs); + return 0; err_kfree: @@ -1129,62 +1070,48 @@ static int ast_connector_init(struct drm_device *dev) return 0; } -/* allocate cursor cache and pin at start of VRAM */ -static int ast_cursor_init(struct drm_device *dev) -{ - struct ast_private *ast = to_ast_private(dev); - size_t size, i; - struct drm_gem_vram_object *gbo; - int ret; - - 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, size, 0); - if (IS_ERR(gbo)) { - ret = PTR_ERR(gbo); - goto err_drm_gem_vram_put; - } - ret = drm_gem_vram_pin(gbo, DRM_GEM_VRAM_PL_FLAG_VRAM | - DRM_GEM_VRAM_PL_FLAG_TOPDOWN); - if (ret) { - drm_gem_vram_put(gbo); - goto err_drm_gem_vram_put; - } +/* + * Mode config + */ - ast->cursor.gbo[i] = gbo; - } +static const struct drm_mode_config_funcs ast_mode_config_funcs = { + .fb_create = drm_gem_fb_create, + .mode_valid = drm_vram_helper_mode_valid, + .atomic_check = drm_atomic_helper_check, + .atomic_commit = drm_atomic_helper_commit, +}; - return 0; +int ast_mode_config_init(struct ast_private *ast) +{ + struct drm_device *dev = ast->dev; + int ret; -err_drm_gem_vram_put: - while (i) { - --i; - gbo = ast->cursor.gbo[i]; - drm_gem_vram_unpin(gbo); - drm_gem_vram_put(gbo); - ast->cursor.gbo[i] = NULL; - } - return ret; -} + ret = ast_cursor_init(ast); + if (ret) + return ret; -static void ast_cursor_fini(struct drm_device *dev) -{ - struct ast_private *ast = to_ast_private(dev); - size_t i; - struct drm_gem_vram_object *gbo; + ret = drmm_mode_config_init(dev); + if (ret) + return ret; - for (i = 0; i < ARRAY_SIZE(ast->cursor.gbo); ++i) { - gbo = ast->cursor.gbo[i]; - drm_gem_vram_unpin(gbo); - drm_gem_vram_put(gbo); + dev->mode_config.funcs = &ast_mode_config_funcs; + dev->mode_config.min_width = 0; + dev->mode_config.min_height = 0; + dev->mode_config.preferred_depth = 24; + dev->mode_config.prefer_shadow = 1; + dev->mode_config.fb_base = pci_resource_start(ast->dev->pdev, 0); + + if (ast->chip == AST2100 || + ast->chip == AST2200 || + ast->chip == AST2300 || + ast->chip == AST2400 || + ast->chip == AST2500) { + dev->mode_config.max_width = 1920; + dev->mode_config.max_height = 2048; + } else { + dev->mode_config.max_width = 1600; + dev->mode_config.max_height = 1200; } -} - -int ast_mode_init(struct drm_device *dev) -{ - struct ast_private *ast = to_ast_private(dev); - int ret; memset(&ast->primary_plane, 0, sizeof(ast->primary_plane)); ret = drm_universal_plane_init(dev, &ast->primary_plane, 0x01, @@ -1211,17 +1138,13 @@ int ast_mode_init(struct drm_device *dev) drm_plane_helper_add(&ast->cursor_plane, &ast_cursor_plane_helper_funcs); - ast_cursor_init(dev); ast_crtc_init(dev); ast_encoder_init(dev); ast_connector_init(dev); - return 0; -} + drm_mode_config_reset(dev); -void ast_mode_fini(struct drm_device *dev) -{ - ast_cursor_fini(dev); + return 0; } static int get_clock(void *i2c_priv) @@ -1344,136 +1267,3 @@ static void ast_i2c_destroy(struct ast_i2c_chan *i2c) i2c_del_adapter(&i2c->adapter); kfree(i2c); } - -static u32 copy_cursor_image(u8 *src, u8 *dst, int width, int height) -{ - union { - u32 ul; - u8 b[4]; - } srcdata32[2], data32; - union { - u16 us; - u8 b[2]; - } data16; - u32 csum = 0; - s32 alpha_dst_delta, last_alpha_dst_delta; - u8 *srcxor, *dstxor; - int i, j; - u32 per_pixel_copy, two_pixel_copy; - - alpha_dst_delta = AST_MAX_HWC_WIDTH << 1; - last_alpha_dst_delta = alpha_dst_delta - (width << 1); - - srcxor = src; - dstxor = (u8 *)dst + last_alpha_dst_delta + (AST_MAX_HWC_HEIGHT - height) * alpha_dst_delta; - per_pixel_copy = width & 1; - two_pixel_copy = width >> 1; - - for (j = 0; j < height; j++) { - for (i = 0; i < two_pixel_copy; i++) { - srcdata32[0].ul = *((u32 *)srcxor) & 0xf0f0f0f0; - srcdata32[1].ul = *((u32 *)(srcxor + 4)) & 0xf0f0f0f0; - data32.b[0] = srcdata32[0].b[1] | (srcdata32[0].b[0] >> 4); - data32.b[1] = srcdata32[0].b[3] | (srcdata32[0].b[2] >> 4); - data32.b[2] = srcdata32[1].b[1] | (srcdata32[1].b[0] >> 4); - data32.b[3] = srcdata32[1].b[3] | (srcdata32[1].b[2] >> 4); - - writel(data32.ul, dstxor); - csum += data32.ul; - - dstxor += 4; - srcxor += 8; - - } - - for (i = 0; i < per_pixel_copy; i++) { - srcdata32[0].ul = *((u32 *)srcxor) & 0xf0f0f0f0; - data16.b[0] = srcdata32[0].b[1] | (srcdata32[0].b[0] >> 4); - data16.b[1] = srcdata32[0].b[3] | (srcdata32[0].b[2] >> 4); - writew(data16.us, dstxor); - csum += (u32)data16.us; - - dstxor += 2; - srcxor += 4; - } - dstxor += last_alpha_dst_delta; - } - return csum; -} - -static int ast_cursor_update(void *dst, void *src, unsigned int width, - unsigned int height) -{ - u32 csum; - - /* do data transfer to cursor cache */ - csum = copy_cursor_image(src, dst, width, height); - - /* write checksum + signature */ - dst += AST_HWC_SIZE; - writel(csum, dst); - writel(width, dst + AST_HWC_SIGNATURE_SizeX); - writel(height, dst + AST_HWC_SIGNATURE_SizeY); - writel(0, dst + AST_HWC_SIGNATURE_HOTSPOTX); - writel(0, dst + AST_HWC_SIGNATURE_HOTSPOTY); - - return 0; -} - -static void ast_cursor_set_base(struct ast_private *ast, u64 address) -{ - u8 addr0 = (address >> 3) & 0xff; - u8 addr1 = (address >> 11) & 0xff; - u8 addr2 = (address >> 19) & 0xff; - - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc8, addr0); - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc9, addr1); - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xca, addr2); -} - -static int ast_cursor_move(struct drm_crtc *crtc, - int x, int y) -{ - struct ast_crtc *ast_crtc = to_ast_crtc(crtc); - struct ast_private *ast = to_ast_private(crtc->dev); - struct drm_gem_vram_object *gbo; - int x_offset, y_offset; - u8 *dst, *sig; - u8 jreg; - - gbo = ast->cursor.gbo[ast->cursor.next_index]; - dst = drm_gem_vram_vmap(gbo); - if (IS_ERR(dst)) - return PTR_ERR(dst); - - sig = dst + AST_HWC_SIZE; - writel(x, sig + AST_HWC_SIGNATURE_X); - writel(y, sig + AST_HWC_SIGNATURE_Y); - - x_offset = ast_crtc->offset_x; - y_offset = ast_crtc->offset_y; - if (x < 0) { - x_offset = (-x) + ast_crtc->offset_x; - x = 0; - } - - if (y < 0) { - y_offset = (-y) + ast_crtc->offset_y; - y = 0; - } - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc2, x_offset); - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc3, y_offset); - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc4, (x & 0xff)); - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc5, ((x >> 8) & 0x0f)); - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc6, (y & 0xff)); - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc7, ((y >> 8) & 0x07)); - - /* dummy write to fire HWC */ - jreg = 0x02 | - 0x01; /* enable ARGB4444 cursor */ - ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xcb, 0xfc, jreg); - - drm_gem_vram_vunmap(gbo, dst); - - return 0; -} |