From: Zhao Junwang zhjwpku@gmail.com
This patch series aim to convert DRM_CIRRUS to atomic mode-setting. This mostly reference my previous patch series on DRM_BOCHS and Gustavo Padovan;s patch series on drm/exynos.
Zhao Junwang (7): drm/cirrus: phase 1 - use the transitional helpers drm/cirrus: phase 2: wire up state reset, duplicate and destroy drm/cirrus: phase 3: atomic updates of planes drm/cirrus: add return 0 to make sure if (bo->pin_count) early_exit drm/cirrus: phase 3: use atomic .set_config helper drm/cirrus: atomic dpms support drm/cirrus: add DRIVER_ATOMIC to .driver_features
drivers/gpu/drm/cirrus/cirrus_drv.c | 3 +- drivers/gpu/drm/cirrus/cirrus_drv.h | 3 +- drivers/gpu/drm/cirrus/cirrus_main.c | 5 +- drivers/gpu/drm/cirrus/cirrus_mode.c | 299 ++++++++++++++++++++-------------- drivers/gpu/drm/cirrus/cirrus_ttm.c | 2 + 5 files changed, 187 insertions(+), 125 deletions(-)
From: Zhao Junwang zhjwpku@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@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);
From: Zhao Junwang zhjwpku@gmail.com
Set CRTC, planes and connectors to use the default implementations from the atomic helper library.
Signed-off-by: Zhao Junwang zhjwpku@gmail.com --- drivers/gpu/drm/cirrus/cirrus_mode.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
diff --git a/drivers/gpu/drm/cirrus/cirrus_mode.c b/drivers/gpu/drm/cirrus/cirrus_mode.c index 7a7c874..42a4d86 100644 --- a/drivers/gpu/drm/cirrus/cirrus_mode.c +++ b/drivers/gpu/drm/cirrus/cirrus_mode.c @@ -17,6 +17,7 @@ #include <drm/drmP.h> #include <drm/drm_crtc_helper.h> #include <drm/drm_plane_helper.h> +#include <drm/drm_atomic_helper.h>
#include <video/cirrus.h>
@@ -304,6 +305,9 @@ static const struct drm_crtc_funcs cirrus_crtc_funcs = { .gamma_set = cirrus_crtc_gamma_set, .set_config = drm_crtc_helper_set_config, .destroy = cirrus_crtc_destroy, + .reset = drm_atomic_helper_crtc_reset, + .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, };
static const struct drm_crtc_helper_funcs cirrus_helper_funcs = { @@ -429,6 +433,9 @@ static void cirrus_plane_atomic_disable(struct drm_plane *plane, static const struct drm_plane_funcs cirrus_plane_funcs = { .update_plane = drm_plane_helper_update, .disable_plane = drm_plane_helper_disable, + .reset = drm_atomic_helper_plane_reset, + .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, };
static const struct drm_plane_helper_funcs cirrus_plane_helper_funcs = { @@ -593,6 +600,9 @@ struct drm_connector_funcs cirrus_vga_connector_funcs = { .detect = cirrus_vga_detect, .fill_modes = drm_helper_probe_single_connector_modes, .destroy = cirrus_connector_destroy, + .reset = drm_atomic_helper_connector_reset, + .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, };
static struct drm_connector *cirrus_vga_init(struct drm_device *dev) @@ -648,6 +658,8 @@ int cirrus_modeset_init(struct cirrus_device *cdev) return -1; }
+ drm_mode_config_reset(cdev->dev); + drm_mode_connector_attach_encoder(connector, encoder);
ret = cirrus_fbdev_init(cdev);
From: Zhao Junwang zhjwpku@gmail.com
Now that phase 1 and 2 are complete we can switch the update/disable_plane callbacks to their atomic version
Signed-off-by: Zhao Junwang zhjwpku@gmail.com --- drivers/gpu/drm/cirrus/cirrus_main.c | 3 +++ drivers/gpu/drm/cirrus/cirrus_mode.c | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/cirrus/cirrus_main.c b/drivers/gpu/drm/cirrus/cirrus_main.c index d95de34..cfa92bc 100644 --- a/drivers/gpu/drm/cirrus/cirrus_main.c +++ b/drivers/gpu/drm/cirrus/cirrus_main.c @@ -10,6 +10,7 @@ */ #include <drm/drmP.h> #include <drm/drm_crtc_helper.h> +#include <drm/drm_atomic_helper.h>
#include "cirrus_drv.h"
@@ -82,6 +83,8 @@ cirrus_user_framebuffer_create(struct drm_device *dev,
static const struct drm_mode_config_funcs cirrus_mode_funcs = { .fb_create = cirrus_user_framebuffer_create, + .atomic_check = drm_atomic_helper_check, + .atomic_commit = drm_atomic_helper_commit, };
/* Unmap the framebuffer from the core and release the memory */ diff --git a/drivers/gpu/drm/cirrus/cirrus_mode.c b/drivers/gpu/drm/cirrus/cirrus_mode.c index 42a4d86..e8f038b 100644 --- a/drivers/gpu/drm/cirrus/cirrus_mode.c +++ b/drivers/gpu/drm/cirrus/cirrus_mode.c @@ -431,8 +431,8 @@ static void cirrus_plane_atomic_disable(struct drm_plane *plane, }
static const struct drm_plane_funcs cirrus_plane_funcs = { - .update_plane = drm_plane_helper_update, - .disable_plane = drm_plane_helper_disable, + .update_plane = drm_atomic_helper_update_plane, + .disable_plane = drm_atomic_helper_disable_plane, .reset = drm_atomic_helper_plane_reset, .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
From: Zhao Junwang zhjwpku@gmail.com
when the first modeset calls prepare_fb, bo->pin_count change from 0 to 1, then the second modeset with the same fb, that should set bo->pin_count to 2, and then when cleanup_fb was called, bo->pin_count should be 2 to 1.
But in the cirrus_bo_pin, it will set bo->pin_count = 1 at the end of the function, this results that bo->bin_count will never be larger than 1 no matter how many times cirrus_bo_pin was called.
So we need to add a condition before bo->pin_count = 1
V2: if (bo->pin_count) early_exit; do_the_real_pinning work
Signed-off-by: Zhao Junwang zhjwpku@gmail.com --- drivers/gpu/drm/cirrus/cirrus_ttm.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/drivers/gpu/drm/cirrus/cirrus_ttm.c b/drivers/gpu/drm/cirrus/cirrus_ttm.c index dfffd52..756b6d0 100644 --- a/drivers/gpu/drm/cirrus/cirrus_ttm.c +++ b/drivers/gpu/drm/cirrus/cirrus_ttm.c @@ -364,6 +364,8 @@ int cirrus_bo_pin(struct cirrus_bo *bo, u32 pl_flag, u64 *gpu_addr) bo->pin_count++; if (gpu_addr) *gpu_addr = cirrus_bo_gpu_offset(bo); + + return 0; }
cirrus_ttm_placement(bo, pl_flag);
From: Zhao Junwang zhjwpku@gmail.com
Now that phase 1 and phase 2 are completed, switch .set_config helper to use the atomic one.
-stop looking legacy crtc->primary->fb, instead we should use crtc->primary->state->fb
.prepare() calls are no more needed, remove them .mode_set() and .mode_set_base are no longer needed, remove
Signed-off-by: Zhao Junwang zhjwpku@gmail.com --- drivers/gpu/drm/cirrus/cirrus_mode.c | 28 ++++++---------------------- 1 file changed, 6 insertions(+), 22 deletions(-)
diff --git a/drivers/gpu/drm/cirrus/cirrus_mode.c b/drivers/gpu/drm/cirrus/cirrus_mode.c index e8f038b..1775864 100644 --- a/drivers/gpu/drm/cirrus/cirrus_mode.c +++ b/drivers/gpu/drm/cirrus/cirrus_mode.c @@ -208,7 +208,8 @@ static void cirrus_crtc_mode_set_nofb(struct drm_crtc *crtc) sr07 = RREG8(SEQ_DATA); sr07 &= 0xe0; hdr = 0; - switch (crtc->primary->fb->bits_per_pixel) { + + switch (crtc->primary->state->fb->bits_per_pixel) { case 8: sr07 |= 0x11; break; @@ -231,13 +232,13 @@ static void cirrus_crtc_mode_set_nofb(struct drm_crtc *crtc) WREG_SEQ(0x7, sr07);
/* Program the pitch */ - tmp = crtc->primary->fb->pitches[0] / 8; + tmp = crtc->primary->state->fb->pitches[0] / 8; WREG_CRT(VGA_CRTC_OFFSET, tmp);
/* Enable extended blanking and pitch bits, and enable full memory */ tmp = 0x22; - tmp |= (crtc->primary->fb->pitches[0] >> 7) & 0x10; - tmp |= (crtc->primary->fb->pitches[0] >> 6) & 0x40; + tmp |= (crtc->primary->state->fb->pitches[0] >> 7) & 0x10; + tmp |= (crtc->primary->state->fb->pitches[0] >> 6) & 0x40; WREG_CRT(0x1b, tmp);
/* Enable high-colour modes */ @@ -253,15 +254,6 @@ static void cirrus_crtc_mode_set_nofb(struct drm_crtc *crtc) }
/* - * This is called before a mode is programmed. A typical use might be to - * enable DPMS during the programming to avoid seeing intermediate stages, - * but that's not relevant to us - */ -static void cirrus_crtc_prepare(struct drm_crtc *crtc) -{ -} - -/* * This is called after a mode is programmed. It should reverse anything done * by the prepare function */ @@ -303,7 +295,7 @@ static void cirrus_crtc_destroy(struct drm_crtc *crtc) /* These provide the minimum set of functions required to handle a CRTC */ static const struct drm_crtc_funcs cirrus_crtc_funcs = { .gamma_set = cirrus_crtc_gamma_set, - .set_config = drm_crtc_helper_set_config, + .set_config = drm_atomic_helper_set_config, .destroy = cirrus_crtc_destroy, .reset = drm_atomic_helper_crtc_reset, .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state, @@ -313,10 +305,7 @@ 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 = 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, }; @@ -506,10 +495,6 @@ static void cirrus_encoder_dpms(struct drm_encoder *encoder, int state) return; }
-static void cirrus_encoder_prepare(struct drm_encoder *encoder) -{ -} - static void cirrus_encoder_commit(struct drm_encoder *encoder) { } @@ -525,7 +510,6 @@ static const struct drm_encoder_helper_funcs cirrus_encoder_helper_funcs = { .dpms = cirrus_encoder_dpms, .mode_fixup = cirrus_encoder_mode_fixup, .mode_set = cirrus_encoder_mode_set, - .prepare = cirrus_encoder_prepare, .commit = cirrus_encoder_commit, };
From: Zhao Junwang zhjwpku@gmail.com
Run dpms operations through the atomic interfaces. This basically removes the .dpms() callback from encoders and crtcs and use .disable and .enable to turn the crtc on and off.
use drm_atomic_helper_connector_dpms for connector
Signed-off-by: Zhao Junwang zhjwpku@gmail.com --- drivers/gpu/drm/cirrus/cirrus_mode.c | 68 +++++++++++++++++++--------------- 1 file changed, 39 insertions(+), 29 deletions(-)
diff --git a/drivers/gpu/drm/cirrus/cirrus_mode.c b/drivers/gpu/drm/cirrus/cirrus_mode.c index 1775864..e807cf0 100644 --- a/drivers/gpu/drm/cirrus/cirrus_mode.c +++ b/drivers/gpu/drm/cirrus/cirrus_mode.c @@ -55,37 +55,40 @@ static void cirrus_crtc_load_lut(struct drm_crtc *crtc) } }
-/* - * The DRM core requires DPMS functions, but they make little sense in our - * case and so are just stubs - */ +static void cirrus_crtc_enable(struct drm_crtc *crtc) +{ + struct drm_device *dev = crtc->dev; + struct cirrus_device *cdev = dev->dev_private; + u8 sr01, gr0e; + + if (crtc->enabled) + return;
-static void cirrus_crtc_dpms(struct drm_crtc *crtc, int mode) + sr01 = 0x00; + gr0e = 0x00; + + WREG8(SEQ_INDEX, 0x1); + sr01 |= RREG8(SEQ_DATA) & ~0x20; + WREG_SEQ(0x1, sr01); + + WREG8(GFX_INDEX, 0xe); + gr0e |= RREG8(GFX_DATA) & ~0x06; + WREG_GFX(0xe, gr0e); + + crtc->enabled = true; +} + +static void cirrus_crtc_disable(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; struct cirrus_device *cdev = dev->dev_private; u8 sr01, gr0e;
- switch (mode) { - case DRM_MODE_DPMS_ON: - sr01 = 0x00; - gr0e = 0x00; - break; - case DRM_MODE_DPMS_STANDBY: - sr01 = 0x20; - gr0e = 0x02; - break; - case DRM_MODE_DPMS_SUSPEND: - sr01 = 0x20; - gr0e = 0x04; - break; - case DRM_MODE_DPMS_OFF: - sr01 = 0x20; - gr0e = 0x06; - break; - default: + if (!crtc->enabled) return; - } + + sr01 = 0x20; + gr0e = 0x06;
WREG8(SEQ_INDEX, 0x1); sr01 |= RREG8(SEQ_DATA) & ~0x20; @@ -94,6 +97,8 @@ static void cirrus_crtc_dpms(struct drm_crtc *crtc, int mode) WREG8(GFX_INDEX, 0xe); gr0e |= RREG8(GFX_DATA) & ~0x06; WREG_GFX(0xe, gr0e); + + crtc->enabled = false; }
/* @@ -303,7 +308,8 @@ static const struct drm_crtc_funcs cirrus_crtc_funcs = { };
static const struct drm_crtc_helper_funcs cirrus_helper_funcs = { - .dpms = cirrus_crtc_dpms, + .disable = cirrus_crtc_disable, + .enable = cirrus_crtc_enable, .mode_fixup = cirrus_crtc_mode_fixup, .mode_set_nofb = cirrus_crtc_mode_set_nofb, .commit = cirrus_crtc_commit, @@ -490,9 +496,12 @@ static void cirrus_encoder_mode_set(struct drm_encoder *encoder, { }
-static void cirrus_encoder_dpms(struct drm_encoder *encoder, int state) +static void cirrus_encoder_enable(struct drm_encoder *encoder) +{ +} + +static void cirrus_encoder_disable(struct drm_encoder *encoder) { - return; }
static void cirrus_encoder_commit(struct drm_encoder *encoder) @@ -507,7 +516,8 @@ static void cirrus_encoder_destroy(struct drm_encoder *encoder) }
static const struct drm_encoder_helper_funcs cirrus_encoder_helper_funcs = { - .dpms = cirrus_encoder_dpms, + .enable = cirrus_encoder_enable, + .disable = cirrus_encoder_disable, .mode_fixup = cirrus_encoder_mode_fixup, .mode_set = cirrus_encoder_mode_set, .commit = cirrus_encoder_commit, @@ -580,7 +590,7 @@ struct drm_connector_helper_funcs cirrus_vga_connector_helper_funcs = { };
struct drm_connector_funcs cirrus_vga_connector_funcs = { - .dpms = drm_helper_connector_dpms, + .dpms = drm_atomic_helper_connector_dpms, .detect = cirrus_vga_detect, .fill_modes = drm_helper_probe_single_connector_modes, .destroy = cirrus_connector_destroy,
From: Zhao Junwang zhjwpku@gmail.com
Since driver is now fully atomic, we should add DRIVER_ATOMIC to .driver_features
Signed-off-by: Zhao Junwang zhjwpku@gmail.com --- drivers/gpu/drm/cirrus/cirrus_drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/cirrus/cirrus_drv.c b/drivers/gpu/drm/cirrus/cirrus_drv.c index 80f1cd2..742647b 100644 --- a/drivers/gpu/drm/cirrus/cirrus_drv.c +++ b/drivers/gpu/drm/cirrus/cirrus_drv.c @@ -130,7 +130,7 @@ static const struct file_operations cirrus_driver_fops = { #endif }; static struct drm_driver driver = { - .driver_features = DRIVER_MODESET | DRIVER_GEM, + .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC, .load = cirrus_driver_load, .unload = cirrus_driver_unload, .set_busid = drm_pci_set_busid,
[+Dave]
Hi all,
Another necro bump - second part of John's work from GSOC 2015 that did not land :-(
On 30 July 2015 at 11:08, John Hunter zhjwpku@gmail.com wrote:
From: Zhao Junwang zhjwpku@gmail.com
This patch series aim to convert DRM_CIRRUS to atomic mode-setting. This mostly reference my previous patch series on DRM_BOCHS and Gustavo Padovan;s patch series on drm/exynos.
Dave, I realise that you wrote the driver a long time ago, although you're still one of the people best familiar with it. Can you spare some time and check/ack it ?
Thanks Emil
dri-devel@lists.freedesktop.org