From: Zhao Junwang <zhjwpku@xxxxxxxxx> -register driver's own primary plane -use drm_crtc_init_with_planes instead drm_crtc_init -the new atomic_infrastructure needs ->mode_set_nofb callback Cc: Daniel Vetter <daniel.vetter@xxxxxxxx> Cc: Gerd Hoffmann <kraxel@xxxxxxxxxx> Cc: Matthew Garrett <mjg59@xxxxxxxxxx> Cc: Dave Airlie <airlied@xxxxxxxxxx> Signed-off-by: Zhao Junwang <zhjwpku@xxxxxxxxx> --- drivers/gpu/drm/cirrus/cirrus_drv.c | 1 - drivers/gpu/drm/cirrus/cirrus_drv.h | 3 +- drivers/gpu/drm/cirrus/cirrus_main.c | 2 +- drivers/gpu/drm/cirrus/cirrus_mode.c | 201 +++++++++++++++++++++------------- 4 files changed, 129 insertions(+), 78 deletions(-) diff --git a/drivers/gpu/drm/cirrus/cirrus_drv.c b/drivers/gpu/drm/cirrus/cirrus_drv.c index 08bd176..80f1cd2 100644 --- a/drivers/gpu/drm/cirrus/cirrus_drv.c +++ b/drivers/gpu/drm/cirrus/cirrus_drv.c @@ -40,7 +40,6 @@ static const struct pci_device_id pciidlist[] = { {0,} }; - static int cirrus_kick_out_firmware_fb(struct pci_dev *pdev) { struct apertures_struct *ap; diff --git a/drivers/gpu/drm/cirrus/cirrus_drv.h b/drivers/gpu/drm/cirrus/cirrus_drv.h index 7050615..bd1ff51 100644 --- a/drivers/gpu/drm/cirrus/cirrus_drv.h +++ b/drivers/gpu/drm/cirrus/cirrus_drv.h @@ -135,8 +135,9 @@ struct cirrus_device { resource_size_t rmmio_size; void __iomem *rmmio; - struct cirrus_mc mc; + struct cirrus_mc mc; struct cirrus_mode_info mode_info; + struct drm_plane primary; int num_crtc; int fb_mtrr; diff --git a/drivers/gpu/drm/cirrus/cirrus_main.c b/drivers/gpu/drm/cirrus/cirrus_main.c index e4b9766..d95de34 100644 --- a/drivers/gpu/drm/cirrus/cirrus_main.c +++ b/drivers/gpu/drm/cirrus/cirrus_main.c @@ -308,10 +308,10 @@ cirrus_dumb_mmap_offset(struct drm_file *file, drm_gem_object_unreference(obj); ret = 0; + out_unlock: mutex_unlock(&dev->struct_mutex); return ret; - } bool cirrus_check_framebuffer(struct cirrus_device *cdev, int width, int height, diff --git a/drivers/gpu/drm/cirrus/cirrus_mode.c b/drivers/gpu/drm/cirrus/cirrus_mode.c index 61385f2..7a7c874 100644 --- a/drivers/gpu/drm/cirrus/cirrus_mode.c +++ b/drivers/gpu/drm/cirrus/cirrus_mode.c @@ -27,6 +27,10 @@ #define PALETTE_INDEX 0x8 #define PALETTE_DATA 0x9 +static const uint32_t cirrus_primary_formats[] = { + DRM_FORMAT_RGB888, +}; + /* * This file contains setup code for the CRTC. */ @@ -126,77 +130,11 @@ static void cirrus_set_start_address(struct drm_crtc *crtc, unsigned offset) WREG_CRT(0x1d, tmp); } -/* cirrus is different - we will force move buffers out of VRAM */ -static int cirrus_crtc_do_set_base(struct drm_crtc *crtc, - struct drm_framebuffer *fb, - int x, int y, int atomic) -{ - struct cirrus_device *cdev = crtc->dev->dev_private; - struct drm_gem_object *obj; - struct cirrus_framebuffer *cirrus_fb; - struct cirrus_bo *bo; - int ret; - u64 gpu_addr; - - /* push the previous fb to system ram */ - if (!atomic && fb) { - cirrus_fb = to_cirrus_framebuffer(fb); - obj = cirrus_fb->obj; - bo = gem_to_cirrus_bo(obj); - ret = cirrus_bo_reserve(bo, false); - if (ret) - return ret; - cirrus_bo_push_sysram(bo); - cirrus_bo_unreserve(bo); - } - - cirrus_fb = to_cirrus_framebuffer(crtc->primary->fb); - obj = cirrus_fb->obj; - bo = gem_to_cirrus_bo(obj); - - ret = cirrus_bo_reserve(bo, false); - if (ret) - return ret; - - ret = cirrus_bo_pin(bo, TTM_PL_FLAG_VRAM, &gpu_addr); - if (ret) { - cirrus_bo_unreserve(bo); - return ret; - } - - if (&cdev->mode_info.gfbdev->gfb == cirrus_fb) { - /* if pushing console in kmap it */ - ret = ttm_bo_kmap(&bo->bo, 0, bo->bo.num_pages, &bo->kmap); - if (ret) - DRM_ERROR("failed to kmap fbcon\n"); - } - cirrus_bo_unreserve(bo); - - cirrus_set_start_address(crtc, (u32)gpu_addr); - return 0; -} - -static int cirrus_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, - struct drm_framebuffer *old_fb) -{ - return cirrus_crtc_do_set_base(crtc, old_fb, x, y, 0); -} - -/* - * The meat of this driver. The core passes us a mode and we have to program - * it. The modesetting here is the bare minimum required to satisfy the qemu - * emulation of this hardware, and running this against a real device is - * likely to result in an inadequately programmed mode. We've already had - * the opportunity to modify the mode, so whatever we receive here should - * be something that can be correctly programmed and displayed - */ -static int cirrus_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) +static void cirrus_crtc_mode_set_nofb(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; struct cirrus_device *cdev = dev->dev_private; + struct drm_display_mode *mode = &crtc->mode; int hsyncstart, hsyncend, htotal, hdispend; int vtotal, vdispend; int tmp; @@ -286,7 +224,7 @@ static int cirrus_crtc_mode_set(struct drm_crtc *crtc, hdr = 0xc5; break; default: - return -1; + return; } WREG_SEQ(0x7, sr07); @@ -308,11 +246,9 @@ static int cirrus_crtc_mode_set(struct drm_crtc *crtc, WREG_GFX(VGA_GFX_MISC, 0x01); WREG_HDR(hdr); - cirrus_crtc_do_set_base(crtc, old_fb, x, y, 0); /* Unblank (needed on S3 resume, vgabios doesn't do it then) */ outb(0x20, 0x3c0); - return 0; } /* @@ -373,8 +309,9 @@ static const struct drm_crtc_funcs cirrus_crtc_funcs = { static const struct drm_crtc_helper_funcs cirrus_helper_funcs = { .dpms = cirrus_crtc_dpms, .mode_fixup = cirrus_crtc_mode_fixup, - .mode_set = cirrus_crtc_mode_set, - .mode_set_base = cirrus_crtc_mode_set_base, + .mode_set = drm_helper_crtc_mode_set, + .mode_set_base = drm_helper_crtc_mode_set_base, + .mode_set_nofb = cirrus_crtc_mode_set_nofb, .prepare = cirrus_crtc_prepare, .commit = cirrus_crtc_commit, .load_lut = cirrus_crtc_load_lut, @@ -394,7 +331,8 @@ static void cirrus_crtc_init(struct drm_device *dev) if (cirrus_crtc == NULL) return; - drm_crtc_init(dev, &cirrus_crtc->base, &cirrus_crtc_funcs); + drm_crtc_init_with_planes(dev, &cirrus_crtc->base, &cdev->primary, + NULL, &cirrus_crtc_funcs); drm_mode_crtc_set_gamma_size(&cirrus_crtc->base, CIRRUS_LUT_SIZE); cdev->mode_info.crtc = cirrus_crtc; @@ -408,6 +346,119 @@ static void cirrus_crtc_init(struct drm_device *dev) drm_crtc_helper_add(&cirrus_crtc->base, &cirrus_helper_funcs); } +static int cirrus_plane_prepare_fb(struct drm_plane *plane, + struct drm_framebuffer *fb, + const struct drm_plane_state *new_state) +{ + struct cirrus_device *cdev = + container_of(plane, struct cirrus_device, primary); + struct cirrus_framebuffer *cirrus_fb; + struct drm_gem_object *obj; + struct cirrus_bo *bo; + int ret; + + cirrus_fb = to_cirrus_framebuffer(fb); + obj = cirrus_fb->obj; + bo = gem_to_cirrus_bo(obj); + + ret = cirrus_bo_reserve(bo, false); + if (ret) + return ret; + + ret = cirrus_bo_pin(bo, TTM_PL_FLAG_VRAM, NULL); + if (ret) { + cirrus_bo_unreserve(bo); + return ret; + } + + if (&cdev->mode_info.gfbdev->gfb == cirrus_fb) { + /* if pushing console in kmap it */ + ret = ttm_bo_kmap(&bo->bo, 0, bo->bo.num_pages, &bo->kmap); + if (ret) + DRM_ERROR("failed to kmap fbcon\n"); + } + cirrus_bo_unreserve(bo); + + return 0; +} + +static void cirrus_plane_cleanup_fb(struct drm_plane *plane, + struct drm_framebuffer *old_fb, + const struct drm_plane_state *old_state) +{ + struct cirrus_framebuffer *cirrus_fb; + struct drm_gem_object *obj; + struct cirrus_bo *bo; + + cirrus_fb = to_cirrus_framebuffer(old_fb); + obj = cirrus_fb->obj; + bo = gem_to_cirrus_bo(obj); + + cirrus_bo_reserve(bo, false); + cirrus_bo_push_sysram(bo); + cirrus_bo_unreserve(bo); +} + +static int cirrus_plane_atomic_check(struct drm_plane *plane, + struct drm_plane_state *plane_state) +{ + return 0; +} + +static void cirrus_plane_atomic_update(struct drm_plane *plane, + struct drm_plane_state *old_state) +{ + struct cirrus_framebuffer *cirrus_fb; + struct drm_gem_object *obj; + struct cirrus_bo *bo; + u64 gpu_addr; + + cirrus_fb = to_cirrus_framebuffer(plane->state->fb); + obj = cirrus_fb->obj; + bo = gem_to_cirrus_bo(obj); + gpu_addr = bo->bo.offset; + + cirrus_set_start_address(plane->state->crtc, (u32)gpu_addr); +} + +static void cirrus_plane_atomic_disable(struct drm_plane *plane, + struct drm_plane_state *old_state) +{ +} + +static const struct drm_plane_funcs cirrus_plane_funcs = { + .update_plane = drm_plane_helper_update, + .disable_plane = drm_plane_helper_disable, +}; + +static const struct drm_plane_helper_funcs cirrus_plane_helper_funcs = { + .prepare_fb = cirrus_plane_prepare_fb, + .cleanup_fb = cirrus_plane_cleanup_fb, + .atomic_check = cirrus_plane_atomic_check, + .atomic_update = cirrus_plane_atomic_update, + .atomic_disable = cirrus_plane_atomic_disable, +}; + +static void cirrus_plane_init(struct drm_device *dev) +{ + struct cirrus_device *cirrus = dev->dev_private; + struct drm_plane *primary = &cirrus->primary; + int r; + + r = drm_universal_plane_init(dev, primary, 0, + &cirrus_plane_funcs, + cirrus_primary_formats, + ARRAY_SIZE(cirrus_primary_formats), + DRM_PLANE_TYPE_PRIMARY); + + if (r) { + DRM_DEBUG_KMS("Failed to init primary plane.\n"); + return; + } + + drm_plane_helper_add(primary, &cirrus_plane_helper_funcs); +} + /** Sets the color ramps on behalf of fbcon */ void cirrus_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green, u16 blue, int regno) @@ -430,7 +481,6 @@ void cirrus_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green, *blue = cirrus_crtc->lut_b[regno]; } - static bool cirrus_encoder_mode_fixup(struct drm_encoder *encoder, const struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) @@ -583,6 +633,7 @@ int cirrus_modeset_init(struct cirrus_device *cdev) /* don't prefer a shadow on virt GPU */ cdev->dev->mode_config.prefer_shadow = 0; + cirrus_plane_init(cdev->dev); cirrus_crtc_init(cdev->dev); encoder = cirrus_encoder_init(cdev->dev); -- 1.7.10.4 _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/dri-devel