diff options
Diffstat (limited to 'drivers/gpu/drm/ast/ast_mode.c')
-rw-r--r-- | drivers/gpu/drm/ast/ast_mode.c | 371 |
1 files changed, 78 insertions, 293 deletions
diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index 3a3a511670c9..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, @@ -566,14 +557,15 @@ static 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_device *dev = plane->dev; + struct ast_private *ast = to_ast_private(dev); struct drm_plane_state *state = plane->state; struct drm_gem_vram_object *gbo; s64 gpu_addr; gbo = drm_gem_vram_of_gem(state->fb->obj[0]); gpu_addr = drm_gem_vram_offset(gbo); - if (WARN_ON_ONCE(gpu_addr < 0)) + if (drm_WARN_ON_ONCE(dev, gpu_addr < 0)) return; /* Bug: we didn't pin the BO to VRAM in prepare_fb. */ ast_set_offset_reg(ast, state->fb); @@ -586,7 +578,7 @@ 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; + struct ast_private *ast = to_ast_private(plane->dev); ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT, 0x1, 0xdf, 0x20); } @@ -622,53 +614,19 @@ ast_cursor_plane_helper_prepare_fb(struct drm_plane *plane, { 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 (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; + ast = to_ast_private(plane->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; - } - - 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, @@ -704,44 +662,29 @@ 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; + 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 (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_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 ast_cursor_plane_helper_atomic_disable(struct drm_plane *plane, struct drm_plane_state *old_state) { - struct ast_private *ast = plane->dev->dev_private; + 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 = { @@ -767,10 +710,7 @@ static const struct drm_plane_funcs ast_cursor_plane_funcs = { static void ast_crtc_dpms(struct drm_crtc *crtc, int mode) { - struct ast_private *ast = crtc->dev->dev_private; - - if (ast->chip == AST1180) - return; + struct ast_private *ast = to_ast_private(crtc->dev); /* TODO: Maybe control display signal generation with * Sync Enable (bit CR17.7). @@ -793,16 +733,10 @@ static void ast_crtc_dpms(struct drm_crtc *crtc, int mode) 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 ast_crtc_state *ast_state; const struct drm_format_info *format; bool succ; - if (ast->chip == AST1180) { - DRM_ERROR("AST 1180 modesetting not supported\n"); - return -EINVAL; - } - if (!state->enable) return 0; /* no mode checks if CRTC is being disabled */ @@ -824,7 +758,7 @@ static int ast_crtc_helper_atomic_check(struct drm_crtc *crtc, 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; + struct ast_private *ast = to_ast_private(crtc->dev); ast_open_key(ast); } @@ -833,7 +767,7 @@ 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; + struct ast_private *ast = to_ast_private(dev); struct ast_crtc_state *ast_state; const struct drm_format_info *format; struct ast_vbios_mode_info *vbios_mode_info; @@ -907,8 +841,9 @@ static struct drm_crtc_state * ast_crtc_atomic_duplicate_state(struct drm_crtc *crtc) { struct ast_crtc_state *new_ast_state, *ast_state; + struct drm_device *dev = crtc->dev; - if (WARN_ON(!crtc->state)) + if (drm_WARN_ON(dev, !crtc->state)) return NULL; new_ast_state = kmalloc(sizeof(*new_ast_state), GFP_KERNEL); @@ -946,22 +881,23 @@ 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; + struct ast_private *ast = to_ast_private(dev); + 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: @@ -975,7 +911,7 @@ err_kfree: static int ast_encoder_init(struct drm_device *dev) { - struct ast_private *ast = dev->dev_private; + struct ast_private *ast = to_ast_private(dev); struct drm_encoder *encoder = &ast->encoder; int ret; @@ -995,7 +931,7 @@ static int ast_encoder_init(struct drm_device *dev) static int ast_get_modes(struct drm_connector *connector) { struct ast_connector *ast_connector = to_ast_connector(connector); - struct ast_private *ast = connector->dev->dev_private; + struct ast_private *ast = to_ast_private(connector->dev); struct edid *edid; int ret; bool flags = false; @@ -1026,7 +962,7 @@ static int ast_get_modes(struct drm_connector *connector) static enum drm_mode_status ast_mode_valid(struct drm_connector *connector, struct drm_display_mode *mode) { - struct ast_private *ast = connector->dev->dev_private; + struct ast_private *ast = to_ast_private(connector->dev); int flags = MODE_NOMODE; uint32_t jtemp; @@ -1044,7 +980,7 @@ static enum drm_mode_status ast_mode_valid(struct drm_connector *connector, if ((ast->chip == AST2100) || (ast->chip == AST2200) || (ast->chip == AST2300) || (ast->chip == AST2400) || - (ast->chip == AST2500) || (ast->chip == AST1180)) { + (ast->chip == AST2500)) { if ((mode->hdisplay == 1920) && (mode->vdisplay == 1080)) return MODE_OK; @@ -1114,7 +1050,7 @@ static int ast_connector_init(struct drm_device *dev) connector = &ast_connector->base; ast_connector->i2c = ast_i2c_create(dev); if (!ast_connector->i2c) - DRM_ERROR("failed to add ddc bus for connector\n"); + drm_err(dev, "failed to add ddc bus for connector\n"); drm_connector_init_with_ddc(dev, connector, &ast_connector_funcs, @@ -1134,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 = dev->dev_private; - 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 = dev->dev_private; - 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 = dev->dev_private; - int ret; memset(&ast->primary_plane, 0, sizeof(ast->primary_plane)); ret = drm_universal_plane_init(dev, &ast->primary_plane, 0x01, @@ -1198,7 +1120,7 @@ int ast_mode_init(struct drm_device *dev) 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); + drm_err(dev, "ast: drm_universal_plane_init() failed: %d\n", ret); return ret; } drm_plane_helper_add(&ast->primary_plane, @@ -1210,29 +1132,25 @@ int ast_mode_init(struct drm_device *dev) ARRAY_SIZE(ast_cursor_plane_formats), NULL, DRM_PLANE_TYPE_CURSOR, NULL); if (ret) { - DRM_ERROR("drm_universal_plane_failed(): %d\n", ret); + drm_err(dev, "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); 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) { struct ast_i2c_chan *i2c = i2c_priv; - struct ast_private *ast = i2c->dev->dev_private; + struct ast_private *ast = to_ast_private(i2c->dev); uint32_t val, val2, count, pass; count = 0; @@ -1254,7 +1172,7 @@ static int get_clock(void *i2c_priv) static int get_data(void *i2c_priv) { struct ast_i2c_chan *i2c = i2c_priv; - struct ast_private *ast = i2c->dev->dev_private; + struct ast_private *ast = to_ast_private(i2c->dev); uint32_t val, val2, count, pass; count = 0; @@ -1276,7 +1194,7 @@ static int get_data(void *i2c_priv) static void set_clock(void *i2c_priv, int clock) { struct ast_i2c_chan *i2c = i2c_priv; - struct ast_private *ast = i2c->dev->dev_private; + struct ast_private *ast = to_ast_private(i2c->dev); int i; u8 ujcrb7, jtemp; @@ -1292,7 +1210,7 @@ static void set_clock(void *i2c_priv, int clock) static void set_data(void *i2c_priv, int data) { struct ast_i2c_chan *i2c = i2c_priv; - struct ast_private *ast = i2c->dev->dev_private; + struct ast_private *ast = to_ast_private(i2c->dev); int i; u8 ujcrb7, jtemp; @@ -1332,7 +1250,7 @@ static struct ast_i2c_chan *ast_i2c_create(struct drm_device *dev) i2c->bit.getscl = get_clock; ret = i2c_bit_add_bus(&i2c->adapter); if (ret) { - DRM_ERROR("Failed to register bit i2c\n"); + drm_err(dev, "Failed to register bit i2c\n"); goto out_free; } @@ -1349,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 = crtc->dev->dev_private; - 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; -} |