[PATCH 1/7] drm/cirrus: phase 1 - use the transitional helpers
John Hunter
zhjwpku at gmail.com
Thu Jul 30 03:08:52 PDT 2015
From: Zhao Junwang <zhjwpku at gmail.com>
-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
Signed-off-by: Zhao Junwang <zhjwpku at gmail.com>
---
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
More information about the dri-devel
mailing list