Skip to contentSkip to conversation

drm/tilcdc: Atomic modeset support

PATCH New Jyri Sarha 1 participant 22 messages Jun 28, 2016

Subsystems (3)
lore
Share & tools
lore

Jyri Sarha

author
#0 lore raw

v2 cover drm/tilcdc: Atomic modeset support

This series implements atomic modeset for TI's LCDC HW. The code has been tested on X-server, weston, and our kmsxx kms testing suite. The patches are based on my earlier tilcdc fixes and cleanups series [1].

I know that the tiny display pipe has been accepted for mainline and I have intention of moving lcdc on top of it at some point. However, there is just too many things I would still have to reimplemet to do it now. How to deal with different encoders, connectors and panels for example. This series should be considered as a first step towards making that move. It implements many things that are needed in simple display pipe too.

There is a lot of changes since RFC version of the series and this is not a complete list:

- Added patches
- drm/tilcdc: Fix tilcdc component master unloading
- drm/tilcdc: Make tilcdc_crtc_page_flip() work if crtc is not yet on
- drm/tilcdc: panel: Set crtc panel info at init phase
- drm/tilcdc: panel: Add atomic modeset helpers to connector funcs
- drm/tilcdc: tfp410: Set crtc panel info at init phase
- drm/tilcdc: tfp410: Add atomic modeset helpers to connector funcs
- drm/tilcdc: Enable and disable interrupts in crtc start() and stop()
- drm/tilcdc: Use drm_atomic_helper_resume/suspend()
- drm/tilcdc: Get rid of legacy dpms mechanism
- drm/tilcdc: Remove unnecessary pm_runtime_get() and *_put() calls
- drm/tilcdc: Change tilcdc_crtc_page_flip() to tilcdc_crtc_update_fb()
- At least following changes to the "old" patches
- Add mechanism to update crtc state's mode_changed if plane fb pixel_format changes
- Add tilcdc_atomic_check() for mode_config_funcs
- Leave tilcdc_crtc_mode_fixup() connected to drm_crtc_helper_funcs

[1] https://lists.freedesktop.org/archives/dri-devel/2016-June/111258.html

Jyri Sarha (21):
drm/tilcdc: Fix tilcdc component master unloading drm/tilcdc: Make tilcdc_crtc_page_flip() public drm/tilcdc: Make tilcdc_crtc_page_flip() work if crtc is not yet on drm/tilcdc: Add dummy primary plane implementation drm/tilcdc: Initialize dummy primary plane from crtc init drm/tilcdc: Add tilcdc_crtc_mode_set_nofb()
drm/tilcdc: Add tilcdc_crtc_atomic_check()
drm/tilcdc: Add atomic mode config funcs
drm/tilcdc: Add drm_mode_config_reset() call to tilcdc_load() drm/tilcdc: Set DRIVER_ATOMIC and use atomic crtc helpers drm/tilcdc: Remove obsolete crtc helper functions drm/tilcdc: Remove tilcdc_verify_fb()
drm/tilcdc: panel: Set crtc panel info at init phase drm/tilcdc: panel: Add atomic modeset helpers to connector funcs drm/tilcdc: tfp410: Set crtc panel info at init phase drm/tilcdc: tfp410: Add atomic modeset helpers to connector funcs drm/tilcdc: Enable and disable interrupts in crtc start() and stop() drm/tilcdc: Use drm_atomic_helper_resume/suspend() drm/tilcdc: Get rid of legacy dpms mechanism
drm/tilcdc: Remove unnecessary pm_runtime_get() and *_put() calls drm/tilcdc: Change tilcdc_crtc_page_flip() to tilcdc_crtc_update_fb()

 drivers/gpu/drm/tilcdc/Makefile        |   1 +
 drivers/gpu/drm/tilcdc/tilcdc_crtc.c   | 311 ++++++++++++++++-----------------
 drivers/gpu/drm/tilcdc/tilcdc_drv.c    | 210 +++++++++++-----------
 drivers/gpu/drm/tilcdc/tilcdc_drv.h    |  14 +-
 drivers/gpu/drm/tilcdc/tilcdc_panel.c  |  11 +-
 drivers/gpu/drm/tilcdc/tilcdc_plane.c  | 132 ++++++++++++++
 drivers/gpu/drm/tilcdc/tilcdc_tfp410.c |   8 +-
 7 files changed, 410 insertions(+), 277 deletions(-)
 create mode 100644 drivers/gpu/drm/tilcdc/tilcdc_plane.c
Signature · 6 lines
1.9.1

_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
author
#1 lore raw

PATCH v2 1/21 drm/tilcdc: Fix tilcdc component master unloading

Fix tilcdc component master unloading. If a subcomponent module (tda998x in this case) is unloaded before its master (tilcdc in this case), it calls drm_put_dev() and it should not be called again by the master when its module is unloaded. However component_master_del() must still be called and the check if the drm_put_dev() has been called must be in component_master_ops unbind() callback, not in platform_driver remove() callback.

---
 drivers/gpu/drm/tilcdc/tilcdc_drv.c | 22 +++++++++++++---------
 1 file changed, 13 insertions(+), 9 deletions(-)
drivers/gpu/drm/tilcdc/tilcdc_drv.c +13 -9
index 148b1ed..10fd3ee 100644
@@ -652,6 +652,12 @@ static int tilcdc_bind(struct device *dev)
 
 static void tilcdc_unbind(struct device *dev)
 {
+	struct drm_device *ddev = dev_get_drvdata(dev);
+
+	/* Check if a subcomponent has already triggered the unloading. */
+	if (!ddev->dev_private)
+		return;
+
 	drm_put_dev(dev_get_drvdata(dev));
 }
 
@@ -684,17 +690,15 @@ static int tilcdc_pdev_probe(struct platform_device *pdev)
 
 static int tilcdc_pdev_remove(struct platform_device *pdev)
 {
-	struct drm_device *ddev = dev_get_drvdata(&pdev->dev);
-	struct tilcdc_drm_private *priv = ddev->dev_private;
-
-	/* Check if a subcomponent has already triggered the unloading. */
-	if (!priv)
-		return 0;
+	int ret;
 
-	if (priv->is_componentized)
-		component_master_del(&pdev->dev, &tilcdc_comp_ops);
-	else
+	ret = tilcdc_get_external_components(&pdev->dev, NULL);
+	if (ret < 0)
+		return ret;
+	else if (ret == 0)
 		drm_put_dev(platform_get_drvdata(pdev));
+	else
+		component_master_del(&pdev->dev, &tilcdc_comp_ops);
 
 	return 0;
 }
Signature · 6 lines
1.9.1

_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
author
#2 lore raw

PATCH v2 2/21 drm/tilcdc: Make tilcdc_crtc_page_flip() public

In reply to Jyri Sarha

Make tilcdc_crtc_page_flip() public for dummy plane implementation to use.

---
 drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 2 +-
 drivers/gpu/drm/tilcdc/tilcdc_drv.h  | 4 ++++
 2 files changed, 5 insertions(+), 1 deletion(-)
drivers/gpu/drm/tilcdc/tilcdc_crtc.c +1 -1
index 80ae134..48af415 100644
@@ -165,7 +165,7 @@ static int tilcdc_verify_fb(struct drm_crtc *crtc, struct drm_framebuffer *fb)
 	return 0;
 }
 
-static int tilcdc_crtc_page_flip(struct drm_crtc *crtc,
+int tilcdc_crtc_page_flip(struct drm_crtc *crtc,
 		struct drm_framebuffer *fb,
 		struct drm_pending_vblank_event *event,
 		uint32_t page_flip_flags)
drivers/gpu/drm/tilcdc/tilcdc_drv.h +4 -0
index 3b52ce8..cd78874 100644
@@ -174,5 +174,9 @@ int tilcdc_crtc_mode_valid(struct drm_crtc *crtc, struct drm_display_mode *mode)
 int tilcdc_crtc_max_width(struct drm_crtc *crtc);
 void tilcdc_crtc_dpms(struct drm_crtc *crtc, int mode);
 int tilcdc_crtc_current_dpms_state(struct drm_crtc *crtc);
+int tilcdc_crtc_page_flip(struct drm_crtc *crtc,
+		struct drm_framebuffer *fb,
+		struct drm_pending_vblank_event *event,
+		uint32_t page_flip_flags);
 
 #endif /* __TILCDC_DRV_H__ */
Signature · 6 lines
1.9.1

_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
author
#3 lore raw

PATCH v2 3/21 drm/tilcdc: Make tilcdc_crtc_page_flip() work if crtc is not yet on

In reply to Jyri Sarha

Make tilcdc_crtc_page_flip() work if crtc is not yet on. The plane commit sometimes comes before crtc is turned on. The new framebuffer should be set to scanout also in that case, so that it is there when crtc is turned on at the end of the commit phase.

---
 drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 21 +++++++++++++--------
 1 file changed, 13 insertions(+), 8 deletions(-)
drivers/gpu/drm/tilcdc/tilcdc_crtc.c +13 -8
index 48af415..deb4f96 100644
@@ -174,8 +174,6 @@ int tilcdc_crtc_page_flip(struct drm_crtc *crtc,
 	struct drm_device *dev = crtc->dev;
 	int r;
 	unsigned long flags;
-	s64 tdiff;
-	ktime_t next_vblank;
 
 	r = tilcdc_verify_fb(crtc, fb);
 	if (r)
@@ -194,15 +192,21 @@ int tilcdc_crtc_page_flip(struct drm_crtc *crtc,
 
 	spin_lock_irqsave(&tilcdc_crtc->irq_lock, flags);
 
-	next_vblank = ktime_add_us(tilcdc_crtc->last_vblank,
-		1000000 / crtc->hwmode.vrefresh);
+	if (crtc->hwmode.vrefresh && ktime_to_ns(tilcdc_crtc->last_vblank)) {
+		ktime_t next_vblank;
+		s64 tdiff;
 
-	tdiff = ktime_to_us(ktime_sub(next_vblank, ktime_get()));
+		next_vblank = ktime_add_us(tilcdc_crtc->last_vblank,
+			1000000 / crtc->hwmode.vrefresh);
 
-	if (tdiff >= TILCDC_VBLANK_SAFETY_THRESHOLD_US)
+		tdiff = ktime_to_us(ktime_sub(next_vblank, ktime_get()));
+
+		if (tdiff < TILCDC_VBLANK_SAFETY_THRESHOLD_US)
+			tilcdc_crtc->next_fb = fb;
+	}
+
+	if (tilcdc_crtc->next_fb != fb)
 		set_scanout(crtc, fb);
-	else
-		tilcdc_crtc->next_fb = fb;
 
 	tilcdc_crtc->event = event;
 
@@ -248,6 +252,7 @@ void tilcdc_crtc_dpms(struct drm_crtc *crtc, int mode)
 		}
 
 		drm_flip_work_commit(&tilcdc_crtc->unref_work, priv->wq);
+		tilcdc_crtc->last_vblank = ktime_set(0, 0);
 	}
 }
 
Signature · 6 lines
1.9.1

_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
author
#4 lore raw

PATCH v2 4/21 drm/tilcdc: Add dummy primary plane implementation

In reply to Jyri Sarha

Add dummy primary plane implementation. LCDC does not really have planes, only simple framebuffer that is mandatory. This primary plane implementation has the necessary checks for implementing simple framebuffer trough DRM plane abstraction. For setting the actual framebuffer the implementation relies on a CRTC side function.

---
 drivers/gpu/drm/tilcdc/Makefile       |   1 +
 drivers/gpu/drm/tilcdc/tilcdc_drv.h   |   2 +
 drivers/gpu/drm/tilcdc/tilcdc_plane.c | 133 ++++++++++++++++++++++++++++++++++
 3 files changed, 136 insertions(+)
 create mode 100644 drivers/gpu/drm/tilcdc/tilcdc_plane.c
drivers/gpu/drm/tilcdc/Makefile +1 -0
index deeca48..6f67517 100644
@@ -7,6 +7,7 @@ obj-$(CONFIG_DRM_TILCDC_SLAVE_COMPAT) += tilcdc_slave_compat.o \
 					 tilcdc_slave_compat.dtb.o
 
 tilcdc-y := \
+	tilcdc_plane.o \
 	tilcdc_crtc.o \
 	tilcdc_tfp410.o \
 	tilcdc_panel.o \
drivers/gpu/drm/tilcdc/tilcdc_drv.h +2 -0
index cd78874..0619c3c 100644
@@ -179,4 +179,6 @@ int tilcdc_crtc_page_flip(struct drm_crtc *crtc,
 		struct drm_pending_vblank_event *event,
 		uint32_t page_flip_flags);
 
+int tilcdc_plane_init(struct drm_device *dev, struct drm_plane *plane);
+
 #endif /* __TILCDC_DRV_H__ */
drivers/gpu/drm/tilcdc/tilcdc_plane.c new file +133 -0

133 lines not on this page · raw message

Signature · 6 lines
1.9.1

_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
author
#5 lore raw

PATCH v2 5/21 drm/tilcdc: Initialize dummy primary plane from crtc init

In reply to Jyri Sarha

Initialize dummy primary plane from crtc init.

---
 drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)
drivers/gpu/drm/tilcdc/tilcdc_crtc.c +10 -1
index deb4f96..998ef10 100644
@@ -26,6 +26,7 @@
 struct tilcdc_crtc {
 	struct drm_crtc base;
 
+	struct drm_plane primary;
 	const struct tilcdc_panel_info *info;
 	struct drm_pending_vblank_event *event;
 	int dpms;
@@ -782,6 +783,10 @@ struct drm_crtc *tilcdc_crtc_create(struct drm_device *dev)
 
 	crtc = &tilcdc_crtc->base;
 
+	ret = tilcdc_plane_init(dev, &tilcdc_crtc->primary);
+	if (ret < 0)
+		goto fail;
+
 	tilcdc_crtc->dpms = DRM_MODE_DPMS_OFF;
 	init_waitqueue_head(&tilcdc_crtc->frame_done_wq);
 
@@ -790,7 +795,11 @@ struct drm_crtc *tilcdc_crtc_create(struct drm_device *dev)
 
 	spin_lock_init(&tilcdc_crtc->irq_lock);
 
-	ret = drm_crtc_init(dev, crtc, &tilcdc_crtc_funcs);
+	ret = drm_crtc_init_with_planes(dev, crtc,
+					&tilcdc_crtc->primary,
+					NULL,
+					&tilcdc_crtc_funcs,
+					"tilcdc crtc");
 	if (ret < 0)
 		goto fail;
 
Signature · 6 lines
1.9.1

_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
author
#6 lore raw

PATCH v2 6/21 drm/tilcdc: Add tilcdc_crtc_mode_set_nofb()

In reply to Jyri Sarha

Add tilcdc_crtc_mode_set_nofb(). The mode_set_nofb() semantics do not fit well to LCDC, because of the mandatory framebuffer. However, when the primary plane is required in the check phase, it and the framebuffer can be found from the atomic state struct.

---
 drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 172 +++++++++++++++++++++++++++++++++++
 1 file changed, 172 insertions(+)
drivers/gpu/drm/tilcdc/tilcdc_crtc.c +172 -0
index 998ef10..5b692c5 100644
@@ -303,6 +303,177 @@ static void tilcdc_crtc_commit(struct drm_crtc *crtc)
 	tilcdc_crtc_dpms(crtc, DRM_MODE_DPMS_ON);
 }
 
+static void tilcdc_crtc_mode_set_nofb(struct drm_crtc *crtc)
+{
+	struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
+	struct drm_device *dev = crtc->dev;
+	struct tilcdc_drm_private *priv = dev->dev_private;
+	const struct tilcdc_panel_info *info = tilcdc_crtc->info;
+	uint32_t reg, hbp, hfp, hsw, vbp, vfp, vsw;
+	struct drm_display_mode *mode = &crtc->state->adjusted_mode;
+	struct drm_framebuffer *fb = crtc->primary->state->fb;
+
+	if (WARN_ON(!info))
+		return;
+
+	if (WARN_ON(!fb))
+		return;
+
+	pm_runtime_get_sync(dev->dev);
+
+	/* Configure the Burst Size and fifo threshold of DMA: */
+	reg = tilcdc_read(dev, LCDC_DMA_CTRL_REG) & ~0x00000770;
+	switch (info->dma_burst_sz) {
+	case 1:
+		reg |= LCDC_DMA_BURST_SIZE(LCDC_DMA_BURST_1);
+		break;
+	case 2:
+		reg |= LCDC_DMA_BURST_SIZE(LCDC_DMA_BURST_2);
+		break;
+	case 4:
+		reg |= LCDC_DMA_BURST_SIZE(LCDC_DMA_BURST_4);
+		break;
+	case 8:
+		reg |= LCDC_DMA_BURST_SIZE(LCDC_DMA_BURST_8);
+		break;
+	case 16:
+		reg |= LCDC_DMA_BURST_SIZE(LCDC_DMA_BURST_16);
+		break;
+	default:
+		dev_err(dev->dev, "invalid burst size\n");
+		return;
+	}
+	reg |= (info->fifo_th << 8);
+	tilcdc_write(dev, LCDC_DMA_CTRL_REG, reg);
+
+	/* Configure timings: */
+	hbp = mode->htotal - mode->hsync_end;
+	hfp = mode->hsync_start - mode->hdisplay;
+	hsw = mode->hsync_end - mode->hsync_start;
+	vbp = mode->vtotal - mode->vsync_end;
+	vfp = mode->vsync_start - mode->vdisplay;
+	vsw = mode->vsync_end - mode->vsync_start;
+
+	DBG("%dx%d, hbp=%u, hfp=%u, hsw=%u, vbp=%u, vfp=%u, vsw=%u",
+	    mode->hdisplay, mode->vdisplay, hbp, hfp, hsw, vbp, vfp, vsw);
+
+	/* Set AC Bias Period and Number of Transitions per Interrupt: */
+	reg = tilcdc_read(dev, LCDC_RASTER_TIMING_2_REG) & ~0x000fff00;
+	reg |= LCDC_AC_BIAS_FREQUENCY(info->ac_bias) |
+		LCDC_AC_BIAS_TRANSITIONS_PER_INT(info->ac_bias_intrpt);
+
+	/*
+	 * subtract one from hfp, hbp, hsw because the hardware uses
+	 * a value of 0 as 1
+	 */
+	if (priv->rev == 2) {
+		/* clear bits we're going to set */
+		reg &= ~0x78000033;
+		reg |= ((hfp-1) & 0x300) >> 8;
+		reg |= ((hbp-1) & 0x300) >> 4;
+		reg |= ((hsw-1) & 0x3c0) << 21;
+	}
+	tilcdc_write(dev, LCDC_RASTER_TIMING_2_REG, reg);
+
+	reg = (((mode->hdisplay >> 4) - 1) << 4) |
+		(((hbp-1) & 0xff) << 24) |
+		(((hfp-1) & 0xff) << 16) |
+		(((hsw-1) & 0x3f) << 10);
+	if (priv->rev == 2)
+		reg |= (((mode->hdisplay >> 4) - 1) & 0x40) >> 3;
+	tilcdc_write(dev, LCDC_RASTER_TIMING_0_REG, reg);
+
+	reg = ((mode->vdisplay - 1) & 0x3ff) |
+		((vbp & 0xff) << 24) |
+		((vfp & 0xff) << 16) |
+		(((vsw-1) & 0x3f) << 10);
+	tilcdc_write(dev, LCDC_RASTER_TIMING_1_REG, reg);
+
+	/*
+	 * be sure to set Bit 10 for the V2 LCDC controller,
+	 * otherwise limited to 1024 pixels width, stopping
+	 * 1920x1080 being supported.
+	 */
+	if (priv->rev == 2) {
+		if ((mode->vdisplay - 1) & 0x400) {
+			tilcdc_set(dev, LCDC_RASTER_TIMING_2_REG,
+				LCDC_LPP_B10);
+		} else {
+			tilcdc_clear(dev, LCDC_RASTER_TIMING_2_REG,
+				LCDC_LPP_B10);
+		}
+	}
+
+	/* Configure display type: */
+	reg = tilcdc_read(dev, LCDC_RASTER_CTRL_REG) &
+		~(LCDC_TFT_MODE | LCDC_MONO_8BIT_MODE | LCDC_MONOCHROME_MODE |
+		  LCDC_V2_TFT_24BPP_MODE | LCDC_V2_TFT_24BPP_UNPACK |
+		  0x000ff000 /* Palette Loading Delay bits */);
+	reg |= LCDC_TFT_MODE; /* no monochrome/passive support */
+	if (info->tft_alt_mode)
+		reg |= LCDC_TFT_ALT_ENABLE;
+	if (priv->rev == 2) {
+		unsigned int depth, bpp;
+
+		drm_fb_get_bpp_depth(fb->pixel_format, &depth, &bpp);
+		switch (bpp) {
+		case 16:
+			break;
+		case 32:
+			reg |= LCDC_V2_TFT_24BPP_UNPACK;
+			/* fallthrough */
+		case 24:
+			reg |= LCDC_V2_TFT_24BPP_MODE;
+			break;
+		default:
+			dev_err(dev->dev, "invalid pixel format\n");
+			return;
+		}
+	}
+	reg |= info->fdd < 12;
+	tilcdc_write(dev, LCDC_RASTER_CTRL_REG, reg);
+
+	if (info->invert_pxl_clk)
+		tilcdc_set(dev, LCDC_RASTER_TIMING_2_REG, LCDC_INVERT_PIXEL_CLOCK);
+	else
+		tilcdc_clear(dev, LCDC_RASTER_TIMING_2_REG, LCDC_INVERT_PIXEL_CLOCK);
+
+	if (info->sync_ctrl)
+		tilcdc_set(dev, LCDC_RASTER_TIMING_2_REG, LCDC_SYNC_CTRL);
+	else
+		tilcdc_clear(dev, LCDC_RASTER_TIMING_2_REG, LCDC_SYNC_CTRL);
+
+	if (info->sync_edge)
+		tilcdc_set(dev, LCDC_RASTER_TIMING_2_REG, LCDC_SYNC_EDGE);
+	else
+		tilcdc_clear(dev, LCDC_RASTER_TIMING_2_REG, LCDC_SYNC_EDGE);
+
+	if (mode->flags & DRM_MODE_FLAG_NHSYNC)
+		tilcdc_set(dev, LCDC_RASTER_TIMING_2_REG, LCDC_INVERT_HSYNC);
+	else
+		tilcdc_clear(dev, LCDC_RASTER_TIMING_2_REG, LCDC_INVERT_HSYNC);
+
+	if (mode->flags & DRM_MODE_FLAG_NVSYNC)
+		tilcdc_set(dev, LCDC_RASTER_TIMING_2_REG, LCDC_INVERT_VSYNC);
+	else
+		tilcdc_clear(dev, LCDC_RASTER_TIMING_2_REG, LCDC_INVERT_VSYNC);
+
+	if (info->raster_order)
+		tilcdc_set(dev, LCDC_RASTER_CTRL_REG, LCDC_RASTER_ORDER);
+	else
+		tilcdc_clear(dev, LCDC_RASTER_CTRL_REG, LCDC_RASTER_ORDER);
+
+	drm_framebuffer_reference(fb);
+
+	set_scanout(crtc, fb);
+
+	tilcdc_crtc_update_clk(crtc);
+
+	pm_runtime_put_sync(dev->dev);
+
+	crtc->hwmode = crtc->state->adjusted_mode;
+}
+
 static int tilcdc_crtc_mode_set(struct drm_crtc *crtc,
 		struct drm_display_mode *mode,
 		struct drm_display_mode *adjusted_mode,
@@ -519,6 +690,7 @@ static const struct drm_crtc_helper_funcs tilcdc_crtc_helper_funcs = {
 		.commit         = tilcdc_crtc_commit,
 		.mode_set       = tilcdc_crtc_mode_set,
 		.mode_set_base  = tilcdc_crtc_mode_set_base,
+		.mode_set_nofb	= tilcdc_crtc_mode_set_nofb,
 };
 
 int tilcdc_crtc_max_width(struct drm_crtc *crtc)
Signature · 6 lines
1.9.1

_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
author
#7 lore raw

PATCH v2 7/21 drm/tilcdc: Add tilcdc_crtc_atomic_check()

In reply to Jyri Sarha

Add tilcdc_crtc_atomic_check(). Checks the display mode validity and the presence of the mandatory primary plane.

The drm_crtc_helper_funcs mode_fixup() callback is left untouched and the check function does no try to do its job on purpose, despite what the mode_fixup() callback's documentations suggests.

The plane's check() callback needs to set drm_crtc_state's ->mode_changed to true if the pixel format for the framebuffer changes. Because of this drm_mode_config_funcs atomic_check() callback needs to call drm_atomic_helper_check_modeset() once more after it has called drm_atomic_helper_check_planes(). If the fixing of the adjusted_mode would be done in drm_crtc_helper_funcs atomic_check() callback, it would get over written by the extra drm_atomic_helper_check_modeset() call.

---
 drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)
drivers/gpu/drm/tilcdc/tilcdc_crtc.c +27 -0
index 5b692c5..4787e4a 100644
@@ -474,6 +474,32 @@ static void tilcdc_crtc_mode_set_nofb(struct drm_crtc *crtc)
 	crtc->hwmode = crtc->state->adjusted_mode;
 }
 
+static int tilcdc_crtc_atomic_check(struct drm_crtc *crtc,
+				    struct drm_crtc_state *state)
+{
+	struct drm_display_mode *mode = &state->mode;
+	int ret;
+
+	/* If we are not active we don't care */
+	if (!state->active)
+		return 0;
+
+	if (state->state->planes[0].ptr != crtc->primary ||
+	    state->state->planes[0].state == NULL ||
+	    state->state->planes[0].state->crtc != crtc) {
+		dev_dbg(crtc->dev->dev, "CRTC primary plane must be present");
+		return -EINVAL;
+	}
+
+	ret = tilcdc_crtc_mode_valid(crtc, mode);
+	if (ret) {
+		dev_dbg(crtc->dev->dev, "Mode \"%s\" not valid", mode->name);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
 static int tilcdc_crtc_mode_set(struct drm_crtc *crtc,
 		struct drm_display_mode *mode,
 		struct drm_display_mode *adjusted_mode,
@@ -690,6 +716,7 @@ static const struct drm_crtc_helper_funcs tilcdc_crtc_helper_funcs = {
 		.commit         = tilcdc_crtc_commit,
 		.mode_set       = tilcdc_crtc_mode_set,
 		.mode_set_base  = tilcdc_crtc_mode_set_base,
+		.atomic_check	= tilcdc_crtc_atomic_check,
 		.mode_set_nofb	= tilcdc_crtc_mode_set_nofb,
 };
 
Signature · 6 lines
1.9.1

_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
author
#8 lore raw

PATCH v2 8/21 drm/tilcdc: Add atomic mode config funcs

In reply to Jyri Sarha

Add atomic mode config funcs. The atomic_commit implementation is a copy-paste from drm_atomic_helper_commit(), leaving out the async test. The similar copy-paste implementation appears to be used in many other drivers too. The standard drm_atomic_helper_check() is used for checking.

The drm_atomic_helper_check() can not be used in drm_mode_config_funcs atomic_check() callback because the plane's check implementation may update crtc state's ->mode_changed flag. Because of this the drm_atomic_helper_check_modeset() has to be called once more after drm_atomic_helper_check_planes() (see drm_atomic_helper_check_modeset() documentation).

---
 drivers/gpu/drm/tilcdc/tilcdc_drv.c | 71 +++++++++++++++++++++++++++++++++++++
 1 file changed, 71 insertions(+)
drivers/gpu/drm/tilcdc/tilcdc_drv.c +71 -0
index 10fd3ee..c431870 100644
@@ -20,6 +20,8 @@
 #include <linux/component.h>
 #include <linux/pinctrl/consumer.h>
 #include <linux/suspend.h>
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
 
 #include "tilcdc_drv.h"
 #include "tilcdc_regs.h"
@@ -59,9 +61,78 @@ static void tilcdc_fb_output_poll_changed(struct drm_device *dev)
 	drm_fbdev_cma_hotplug_event(priv->fbdev);
 }
 
+int tilcdc_atomic_check(struct drm_device *dev,
+			struct drm_atomic_state *state)
+{
+	int ret;
+
+	ret = drm_atomic_helper_check_modeset(dev, state);
+	if (ret)
+		return ret;
+
+	ret = drm_atomic_helper_check_planes(dev, state);
+	if (ret)
+		return ret;
+
+	/*
+	 * tilcdc ->atomic_check can update ->mode_changed if pixel format
+	 * changes, hence will we check modeset changes again.
+	 */
+	ret = drm_atomic_helper_check_modeset(dev, state);
+	if (ret)
+		return ret;
+
+	return ret;
+}
+
+static int tilcdc_commit(struct drm_device *dev,
+		  struct drm_atomic_state *state,
+		  bool async)
+{
+	int ret;
+
+	ret = drm_atomic_helper_prepare_planes(dev, state);
+	if (ret)
+		return ret;
+
+	drm_atomic_helper_swap_state(dev, state);
+
+	/*
+	 * Everything below can be run asynchronously without the need to grab
+	 * any modeset locks at all under one condition: It must be guaranteed
+	 * that the asynchronous work has either been cancelled (if the driver
+	 * supports it, which at least requires that the framebuffers get
+	 * cleaned up with drm_atomic_helper_cleanup_planes()) or completed
+	 * before the new state gets committed on the software side with
+	 * drm_atomic_helper_swap_state().
+	 *
+	 * This scheme allows new atomic state updates to be prepared and
+	 * checked in parallel to the asynchronous completion of the previous
+	 * update. Which is important since compositors need to figure out the
+	 * composition of the next frame right after having submitted the
+	 * current layout.
+	 */
+
+	drm_atomic_helper_commit_modeset_disables(dev, state);
+
+	drm_atomic_helper_commit_planes(dev, state, false);
+
+	drm_atomic_helper_commit_modeset_enables(dev, state);
+
+	drm_atomic_helper_wait_for_vblanks(dev, state);
+
+	drm_atomic_helper_cleanup_planes(dev, state);
+
+	drm_atomic_state_free(state);
+
+	return 0;
+}
+
 static const struct drm_mode_config_funcs mode_config_funcs = {
 	.fb_create = tilcdc_fb_create,
 	.output_poll_changed = tilcdc_fb_output_poll_changed,
+	.atomic_check = tilcdc_atomic_check,
+	.atomic_commit = tilcdc_commit,
 };
 
 static int modeset_init(struct drm_device *dev)
Signature · 6 lines
1.9.1

_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
author
#9 lore raw

PATCH v2 9/21 drm/tilcdc: Add drm_mode_config_reset() call to tilcdc_load()

In reply to Jyri Sarha

Add drm_mode_config_reset() call to tilcdc_load(). This is need to initialize atomic state variables at load time.

---
 drivers/gpu/drm/tilcdc/tilcdc_drv.c | 3 +++
 1 file changed, 3 insertions(+)
drivers/gpu/drm/tilcdc/tilcdc_drv.c +3 -0
index c431870..6299433 100644
@@ -366,6 +366,9 @@ static int tilcdc_load(struct drm_device *dev, unsigned long flags)
 	}
 
 	drm_helper_disable_unused_functions(dev);
+
+	drm_mode_config_reset(dev);
+
 	priv->fbdev = drm_fbdev_cma_init(dev, bpp,
 			dev->mode_config.num_crtc,
 			dev->mode_config.num_connector);
Signature · 6 lines
1.9.1

_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
author
#10 lore raw

PATCH v2 10/21 drm/tilcdc: Set DRIVER_ATOMIC and use atomic crtc helpers

In reply to Jyri Sarha

Set DRIVER_ATOMIC and use atomic helpers and rename commit and prepare crtc helpers to enable and disable. This makes the final jump to mode setting, but there is lot of obsolete code to clean up.

---
 drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 20 +++++++++++++-------
 drivers/gpu/drm/tilcdc/tilcdc_drv.c  |  2 +-
 2 files changed, 14 insertions(+), 8 deletions(-)
drivers/gpu/drm/tilcdc/tilcdc_crtc.c +13 -7
index 4787e4a..defde99 100644
@@ -17,6 +17,7 @@
 
 #include "drm_flip_work.h"
 #include <drm/drm_plane_helper.h>
+#include <drm/drm_atomic_helper.h>
 
 #include "tilcdc_drv.h"
 #include "tilcdc_regs.h"
@@ -293,12 +294,12 @@ static bool tilcdc_crtc_mode_fixup(struct drm_crtc *crtc,
 	return true;
 }
 
-static void tilcdc_crtc_prepare(struct drm_crtc *crtc)
+static void tilcdc_crtc_disable(struct drm_crtc *crtc)
 {
 	tilcdc_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
 }
 
-static void tilcdc_crtc_commit(struct drm_crtc *crtc)
+static void tilcdc_crtc_enable(struct drm_crtc *crtc)
 {
 	tilcdc_crtc_dpms(crtc, DRM_MODE_DPMS_ON);
 }
@@ -704,18 +705,23 @@ static int tilcdc_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
 }
 
 static const struct drm_crtc_funcs tilcdc_crtc_funcs = {
-		.destroy        = tilcdc_crtc_destroy,
-		.set_config     = drm_crtc_helper_set_config,
-		.page_flip      = tilcdc_crtc_page_flip,
+	.destroy        = tilcdc_crtc_destroy,
+	.set_config     = drm_atomic_helper_set_config,
+	.page_flip      = drm_atomic_helper_page_flip,
+	.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 tilcdc_crtc_helper_funcs = {
 		.dpms           = tilcdc_crtc_dpms,
 		.mode_fixup     = tilcdc_crtc_mode_fixup,
-		.prepare        = tilcdc_crtc_prepare,
-		.commit         = tilcdc_crtc_commit,
+		.prepare        = tilcdc_crtc_disable,
+		.commit         = tilcdc_crtc_enable,
 		.mode_set       = tilcdc_crtc_mode_set,
 		.mode_set_base  = tilcdc_crtc_mode_set_base,
+		.enable		= tilcdc_crtc_enable,
+		.disable	= tilcdc_crtc_disable,
 		.atomic_check	= tilcdc_crtc_atomic_check,
 		.mode_set_nofb	= tilcdc_crtc_mode_set_nofb,
 };
drivers/gpu/drm/tilcdc/tilcdc_drv.c +1 -1
index 6299433..28928c4 100644
@@ -611,7 +611,7 @@ static const struct file_operations fops = {
 
 static struct drm_driver tilcdc_driver = {
 	.driver_features    = (DRIVER_HAVE_IRQ | DRIVER_GEM | DRIVER_MODESET |
-			       DRIVER_PRIME),
+			       DRIVER_PRIME | DRIVER_ATOMIC),
 	.load               = tilcdc_load,
 	.unload             = tilcdc_unload,
 	.lastclose          = tilcdc_lastclose,
Signature · 6 lines
1.9.1

_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
author
#11 lore raw

PATCH v2 11/21 drm/tilcdc: Remove obsolete crtc helper functions

In reply to Jyri Sarha

Remove obsolete crtc helper functions. These are not needed when atomic modeset is used.

Note that the drm_crtc_helper_funcs mode_fixup() is still needed. The crtc's check() callback can not do its job here.

The plane's check() callback needs to set drm_crtc_state's ->mode_changed to true if the pixel format for the framebuffer changes. Because of this drm_mode_config_funcs atomic_check() callback needs to call drm_atomic_helper_check_modeset() once more after it has called drm_atomic_helper_check_planes(). If the fixing of the adjusted_mode would be done in drm_crtc_helper_funcs atomic_check() callback, it would get over written by the extra drm_atomic_helper_check_modeset() call.

---
 drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 208 -----------------------------------
 1 file changed, 208 deletions(-)
drivers/gpu/drm/tilcdc/tilcdc_crtc.c +0 -208
index defde99..f10d549 100644
@@ -501,209 +501,6 @@ static int tilcdc_crtc_atomic_check(struct drm_crtc *crtc,
 	return 0;
 }
 
-static int tilcdc_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)
-{
-	struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
-	struct drm_device *dev = crtc->dev;
-	struct tilcdc_drm_private *priv = dev->dev_private;
-	const struct tilcdc_panel_info *info = tilcdc_crtc->info;
-	uint32_t reg, hbp, hfp, hsw, vbp, vfp, vsw;
-	int ret;
-
-	ret = tilcdc_crtc_mode_valid(crtc, mode);
-	if (WARN_ON(ret))
-		return ret;
-
-	if (WARN_ON(!info))
-		return -EINVAL;
-
-	ret = tilcdc_verify_fb(crtc, crtc->primary->fb);
-	if (ret)
-		return ret;
-
-	pm_runtime_get_sync(dev->dev);
-
-	/* Configure the Burst Size and fifo threshold of DMA: */
-	reg = tilcdc_read(dev, LCDC_DMA_CTRL_REG) & ~0x00000770;
-	switch (info->dma_burst_sz) {
-	case 1:
-		reg |= LCDC_DMA_BURST_SIZE(LCDC_DMA_BURST_1);
-		break;
-	case 2:
-		reg |= LCDC_DMA_BURST_SIZE(LCDC_DMA_BURST_2);
-		break;
-	case 4:
-		reg |= LCDC_DMA_BURST_SIZE(LCDC_DMA_BURST_4);
-		break;
-	case 8:
-		reg |= LCDC_DMA_BURST_SIZE(LCDC_DMA_BURST_8);
-		break;
-	case 16:
-		reg |= LCDC_DMA_BURST_SIZE(LCDC_DMA_BURST_16);
-		break;
-	default:
-		return -EINVAL;
-	}
-	reg |= (info->fifo_th << 8);
-	tilcdc_write(dev, LCDC_DMA_CTRL_REG, reg);
-
-	/* Configure timings: */
-	hbp = mode->htotal - mode->hsync_end;
-	hfp = mode->hsync_start - mode->hdisplay;
-	hsw = mode->hsync_end - mode->hsync_start;
-	vbp = mode->vtotal - mode->vsync_end;
-	vfp = mode->vsync_start - mode->vdisplay;
-	vsw = mode->vsync_end - mode->vsync_start;
-
-	DBG("%dx%d, hbp=%u, hfp=%u, hsw=%u, vbp=%u, vfp=%u, vsw=%u",
-			mode->hdisplay, mode->vdisplay, hbp, hfp, hsw, vbp, vfp, vsw);
-
-	/* Configure the AC Bias Period and Number of Transitions per Interrupt: */
-	reg = tilcdc_read(dev, LCDC_RASTER_TIMING_2_REG) & ~0x000fff00;
-	reg |= LCDC_AC_BIAS_FREQUENCY(info->ac_bias) |
-		LCDC_AC_BIAS_TRANSITIONS_PER_INT(info->ac_bias_intrpt);
-
-	/*
-	 * subtract one from hfp, hbp, hsw because the hardware uses
-	 * a value of 0 as 1
-	 */
-	if (priv->rev == 2) {
-		/* clear bits we're going to set */
-		reg &= ~0x78000033;
-		reg |= ((hfp-1) & 0x300) >> 8;
-		reg |= ((hbp-1) & 0x300) >> 4;
-		reg |= ((hsw-1) & 0x3c0) << 21;
-	}
-	tilcdc_write(dev, LCDC_RASTER_TIMING_2_REG, reg);
-
-	reg = (((mode->hdisplay >> 4) - 1) << 4) |
-		(((hbp-1) & 0xff) << 24) |
-		(((hfp-1) & 0xff) << 16) |
-		(((hsw-1) & 0x3f) << 10);
-	if (priv->rev == 2)
-		reg |= (((mode->hdisplay >> 4) - 1) & 0x40) >> 3;
-	tilcdc_write(dev, LCDC_RASTER_TIMING_0_REG, reg);
-
-	reg = ((mode->vdisplay - 1) & 0x3ff) |
-		((vbp & 0xff) << 24) |
-		((vfp & 0xff) << 16) |
-		(((vsw-1) & 0x3f) << 10);
-	tilcdc_write(dev, LCDC_RASTER_TIMING_1_REG, reg);
-
-	/*
-	 * be sure to set Bit 10 for the V2 LCDC controller,
-	 * otherwise limited to 1024 pixels width, stopping
-	 * 1920x1080 being suppoted.
-	 */
-	if (priv->rev == 2) {
-		if ((mode->vdisplay - 1) & 0x400) {
-			tilcdc_set(dev, LCDC_RASTER_TIMING_2_REG,
-				LCDC_LPP_B10);
-		} else {
-			tilcdc_clear(dev, LCDC_RASTER_TIMING_2_REG,
-				LCDC_LPP_B10);
-		}
-	}
-
-	/* Configure display type: */
-	reg = tilcdc_read(dev, LCDC_RASTER_CTRL_REG) &
-		~(LCDC_TFT_MODE | LCDC_MONO_8BIT_MODE | LCDC_MONOCHROME_MODE |
-			LCDC_V2_TFT_24BPP_MODE | LCDC_V2_TFT_24BPP_UNPACK | 0x000ff000);
-	reg |= LCDC_TFT_MODE; /* no monochrome/passive support */
-	if (info->tft_alt_mode)
-		reg |= LCDC_TFT_ALT_ENABLE;
-	if (priv->rev == 2) {
-		unsigned int depth, bpp;
-
-		drm_fb_get_bpp_depth(crtc->primary->fb->pixel_format, &depth, &bpp);
-		switch (bpp) {
-		case 16:
-			break;
-		case 32:
-			reg |= LCDC_V2_TFT_24BPP_UNPACK;
-			/* fallthrough */
-		case 24:
-			reg |= LCDC_V2_TFT_24BPP_MODE;
-			break;
-		default:
-			dev_err(dev->dev, "invalid pixel format\n");
-			return -EINVAL;
-		}
-	}
-	reg |= info->fdd < 12;
-	tilcdc_write(dev, LCDC_RASTER_CTRL_REG, reg);
-
-	if (info->invert_pxl_clk)
-		tilcdc_set(dev, LCDC_RASTER_TIMING_2_REG, LCDC_INVERT_PIXEL_CLOCK);
-	else
-		tilcdc_clear(dev, LCDC_RASTER_TIMING_2_REG, LCDC_INVERT_PIXEL_CLOCK);
-
-	if (info->sync_ctrl)
-		tilcdc_set(dev, LCDC_RASTER_TIMING_2_REG, LCDC_SYNC_CTRL);
-	else
-		tilcdc_clear(dev, LCDC_RASTER_TIMING_2_REG, LCDC_SYNC_CTRL);
-
-	if (info->sync_edge)
-		tilcdc_set(dev, LCDC_RASTER_TIMING_2_REG, LCDC_SYNC_EDGE);
-	else
-		tilcdc_clear(dev, LCDC_RASTER_TIMING_2_REG, LCDC_SYNC_EDGE);
-
-	/*
-	 * use value from adjusted_mode here as this might have been
-	 * changed as part of the fixup for slave encoders to solve the
-	 * issue where tilcdc timings are not VESA compliant
-	 */
-	if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC)
-		tilcdc_set(dev, LCDC_RASTER_TIMING_2_REG, LCDC_INVERT_HSYNC);
-	else
-		tilcdc_clear(dev, LCDC_RASTER_TIMING_2_REG, LCDC_INVERT_HSYNC);
-
-	if (mode->flags & DRM_MODE_FLAG_NVSYNC)
-		tilcdc_set(dev, LCDC_RASTER_TIMING_2_REG, LCDC_INVERT_VSYNC);
-	else
-		tilcdc_clear(dev, LCDC_RASTER_TIMING_2_REG, LCDC_INVERT_VSYNC);
-
-	if (info->raster_order)
-		tilcdc_set(dev, LCDC_RASTER_CTRL_REG, LCDC_RASTER_ORDER);
-	else
-		tilcdc_clear(dev, LCDC_RASTER_CTRL_REG, LCDC_RASTER_ORDER);
-
-	drm_framebuffer_reference(crtc->primary->fb);
-
-	set_scanout(crtc, crtc->primary->fb);
-
-	tilcdc_crtc_update_clk(crtc);
-
-	pm_runtime_put_sync(dev->dev);
-
-	return 0;
-}
-
-static int tilcdc_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
-		struct drm_framebuffer *old_fb)
-{
-	struct drm_device *dev = crtc->dev;
-	int r;
-
-	r = tilcdc_verify_fb(crtc, crtc->primary->fb);
-	if (r)
-		return r;
-
-	drm_framebuffer_reference(crtc->primary->fb);
-
-	pm_runtime_get_sync(dev->dev);
-
-	set_scanout(crtc, crtc->primary->fb);
-
-	pm_runtime_put_sync(dev->dev);
-
-	return 0;
-}
-
 static const struct drm_crtc_funcs tilcdc_crtc_funcs = {
 	.destroy        = tilcdc_crtc_destroy,
 	.set_config     = drm_atomic_helper_set_config,
@@ -714,12 +511,7 @@ static const struct drm_crtc_funcs tilcdc_crtc_funcs = {
 };
 
 static const struct drm_crtc_helper_funcs tilcdc_crtc_helper_funcs = {
-		.dpms           = tilcdc_crtc_dpms,
 		.mode_fixup     = tilcdc_crtc_mode_fixup,
-		.prepare        = tilcdc_crtc_disable,
-		.commit         = tilcdc_crtc_enable,
-		.mode_set       = tilcdc_crtc_mode_set,
-		.mode_set_base  = tilcdc_crtc_mode_set_base,
 		.enable		= tilcdc_crtc_enable,
 		.disable	= tilcdc_crtc_disable,
 		.atomic_check	= tilcdc_crtc_atomic_check,
Signature · 6 lines
1.9.1

_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
author
#12 lore raw

PATCH v2 12/21 drm/tilcdc: Remove tilcdc_verify_fb()

In reply to Jyri Sarha

Remove tilcdc_verify_fb(). The tilcdc_verify_fb() function is not needed because the same checks are implemented in tilcdc_plane_atomic_check().

---
 drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 21 ---------------------
 1 file changed, 21 deletions(-)
drivers/gpu/drm/tilcdc/tilcdc_crtc.c +0 -21
index f10d549..05b1d14 100644
@@ -151,22 +151,6 @@ static void tilcdc_crtc_destroy(struct drm_crtc *crtc)
 	drm_flip_work_cleanup(&tilcdc_crtc->unref_work);
 }
 
-static int tilcdc_verify_fb(struct drm_crtc *crtc, struct drm_framebuffer *fb)
-{
-	struct drm_device *dev = crtc->dev;
-	unsigned int depth, bpp;
-
-	drm_fb_get_bpp_depth(fb->pixel_format, &depth, &bpp);
-
-	if (fb->pitches[0] != crtc->mode.hdisplay * bpp / 8) {
-		dev_err(dev->dev,
-			"Invalid pitch: fb and crtc widths must be the same");
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
 int tilcdc_crtc_page_flip(struct drm_crtc *crtc,
 		struct drm_framebuffer *fb,
 		struct drm_pending_vblank_event *event,
@@ -174,13 +158,8 @@ int tilcdc_crtc_page_flip(struct drm_crtc *crtc,
 {
 	struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
 	struct drm_device *dev = crtc->dev;
-	int r;
 	unsigned long flags;
 
-	r = tilcdc_verify_fb(crtc, fb);
-	if (r)
-		return r;
-
 	if (tilcdc_crtc->event) {
 		dev_err(dev->dev, "already pending page flip!\n");
 		return -EBUSY;
Signature · 6 lines
1.9.1

_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
author
#13 lore raw

PATCH v2 13/21 drm/tilcdc: panel: Set crtc panel info at init phase

In reply to Jyri Sarha

Set crtc panel info at init phase. Setting it at prepare callback does it multiple times for no good reason and it also too late when atomic modeset is used.

---
 drivers/gpu/drm/tilcdc/tilcdc_panel.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/gpu/drm/tilcdc/tilcdc_panel.c +3 -2
index ff7774c..9874881 100644
@@ -64,9 +64,7 @@ static void panel_encoder_dpms(struct drm_encoder *encoder, int mode)
 
 static void panel_encoder_prepare(struct drm_encoder *encoder)
 {
-	struct panel_encoder *panel_encoder = to_panel_encoder(encoder);
 	panel_encoder_dpms(encoder, DRM_MODE_DPMS_OFF);
-	tilcdc_crtc_set_panel_info(encoder->crtc, panel_encoder->mod->info);
 }
 
 static void panel_encoder_commit(struct drm_encoder *encoder)
@@ -268,6 +266,9 @@ static int panel_modeset_init(struct tilcdc_module *mod, struct drm_device *dev)
 	priv->encoders[priv->num_encoders++] = encoder;
 	priv->connectors[priv->num_connectors++] = connector;
 
+	tilcdc_crtc_set_panel_info(priv->crtc,
+				   to_panel_encoder(encoder)->mod->info);
+
 	return 0;
 }
 
Signature · 6 lines
1.9.1

_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
author
#14 lore raw

PATCH v2 14/21 drm/tilcdc: panel: Add atomic modeset helpers to connector funcs

In reply to Jyri Sarha

Add atomic modeset helpers to panel connector funcs. Property handling related helpers, atomic reset helper, and new dpms helper is needed in connector for atomic modeseting to work. The default helper functions are enough.

---
 drivers/gpu/drm/tilcdc/tilcdc_panel.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)
drivers/gpu/drm/tilcdc/tilcdc_panel.c +5 -1
index 9874881..4ac1d25 100644
@@ -22,6 +22,7 @@
 #include <video/display_timing.h>
 #include <video/of_display_timing.h>
 #include <video/videomode.h>
+#include <drm/drm_atomic_helper.h>
 
 #include "tilcdc_drv.h"
 
@@ -194,9 +195,12 @@ static struct drm_encoder *panel_connector_best_encoder(
 
 static const struct drm_connector_funcs panel_connector_funcs = {
 	.destroy            = panel_connector_destroy,
-	.dpms               = drm_helper_connector_dpms,
+	.dpms               = drm_atomic_helper_connector_dpms,
 	.detect             = panel_connector_detect,
 	.fill_modes         = drm_helper_probe_single_connector_modes,
+	.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 const struct drm_connector_helper_funcs panel_connector_helper_funcs = {
Signature · 6 lines
1.9.1

_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
author
#15 lore raw

PATCH v2 15/21 drm/tilcdc: tfp410: Set crtc panel info at init phase

In reply to Jyri Sarha

Set crtc panel info at init phase. Setting it at prepare callback does it multiple times for no good reason and it also too late when atomic modeset is used.

---
 drivers/gpu/drm/tilcdc/tilcdc_tfp410.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/tilcdc/tilcdc_tfp410.c +1 -1
index 6b8c5b3..21f6485 100644
@@ -75,7 +75,6 @@ static void tfp410_encoder_dpms(struct drm_encoder *encoder, int mode)
 static void tfp410_encoder_prepare(struct drm_encoder *encoder)
 {
 	tfp410_encoder_dpms(encoder, DRM_MODE_DPMS_OFF);
-	tilcdc_crtc_set_panel_info(encoder->crtc, &dvi_info);
 }
 
 static void tfp410_encoder_commit(struct drm_encoder *encoder)
@@ -276,6 +275,7 @@ static int tfp410_modeset_init(struct tilcdc_module *mod, struct drm_device *dev
 	priv->encoders[priv->num_encoders++] = encoder;
 	priv->connectors[priv->num_connectors++] = connector;
 
+	tilcdc_crtc_set_panel_info(priv->crtc, &dvi_info);
 	return 0;
 }
 
Signature · 6 lines
1.9.1

_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
author
#16 lore raw

PATCH v2 16/21 drm/tilcdc: tfp410: Add atomic modeset helpers to connector funcs

In reply to Jyri Sarha

Add atomic modeset helpers to tfp410 connector funcs. Property handling related helpers, atomic reset helper, and new dpms helper is needed in connector for atomic modeseting to work. The default helper functions are enough.

---
 drivers/gpu/drm/tilcdc/tilcdc_tfp410.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)
drivers/gpu/drm/tilcdc/tilcdc_tfp410.c +5 -1
index 21f6485..741c7b5 100644
@@ -20,6 +20,7 @@
 #include <linux/of_gpio.h>
 #include <linux/pinctrl/pinmux.h>
 #include <linux/pinctrl/consumer.h>
+#include <drm/drm_atomic_helper.h>
 
 #include "tilcdc_drv.h"
 
@@ -200,9 +201,12 @@ static struct drm_encoder *tfp410_connector_best_encoder(
 
 static const struct drm_connector_funcs tfp410_connector_funcs = {
 	.destroy            = tfp410_connector_destroy,
-	.dpms               = drm_helper_connector_dpms,
+	.dpms               = drm_atomic_helper_connector_dpms,
 	.detect             = tfp410_connector_detect,
 	.fill_modes         = drm_helper_probe_single_connector_modes,
+	.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 const struct drm_connector_helper_funcs tfp410_connector_helper_funcs = {
Signature · 6 lines
1.9.1

_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
author
#17 lore raw

PATCH v2 17/21 drm/tilcdc: Enable and disable interrupts in crtc start() and stop()

In reply to Jyri Sarha

Enable and disable interrupts in crtc start() and stop(). None of the interrupts can fire if CRTC is disabled, so it is cleaner - when considering suspend/resume code etc. - to enable the interrupts in when CRTC is turned on and to disable them when CRTC is turned off.

---
 drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 39 +++++++++++++++++++++++++++++
 drivers/gpu/drm/tilcdc/tilcdc_drv.c  | 48 ------------------------------------
 2 files changed, 39 insertions(+), 48 deletions(-)
drivers/gpu/drm/tilcdc/tilcdc_crtc.c +39 -0
index 05b1d14..f699818 100644
@@ -89,6 +89,41 @@ static void set_scanout(struct drm_crtc *crtc, struct drm_framebuffer *fb)
 	tilcdc_crtc->curr_fb = fb;
 }
 
+static void tilcdc_crtc_enable_irqs(struct drm_device *dev)
+{
+	struct tilcdc_drm_private *priv = dev->dev_private;
+
+	tilcdc_clear_irqstatus(dev, 0xffffffff);
+
+	if (priv->rev == 1) {
+		tilcdc_set(dev, LCDC_RASTER_CTRL_REG,
+			LCDC_V1_UNDERFLOW_INT_ENA);
+	} else {
+		tilcdc_write(dev, LCDC_INT_ENABLE_SET_REG,
+			LCDC_V2_UNDERFLOW_INT_ENA |
+			LCDC_V2_END_OF_FRAME0_INT_ENA |
+			LCDC_FRAME_DONE | LCDC_SYNC_LOST);
+	}
+}
+
+static void tilcdc_crtc_disable_irqs(struct drm_device *dev)
+{
+	struct tilcdc_drm_private *priv = dev->dev_private;
+
+	/* disable irqs that we might have enabled: */
+	if (priv->rev == 1) {
+		tilcdc_clear(dev, LCDC_RASTER_CTRL_REG,
+			LCDC_V1_UNDERFLOW_INT_ENA | LCDC_V1_PL_INT_ENA);
+		tilcdc_clear(dev, LCDC_DMA_CTRL_REG,
+			LCDC_V1_END_OF_FRAME_INT_ENA);
+	} else {
+		tilcdc_write(dev, LCDC_INT_ENABLE_CLR_REG,
+			LCDC_V2_UNDERFLOW_INT_ENA | LCDC_V2_PL_INT_ENA |
+			LCDC_V2_END_OF_FRAME0_INT_ENA |
+			LCDC_FRAME_DONE | LCDC_SYNC_LOST);
+	}
+}
+
 static void reset(struct drm_crtc *crtc)
 {
 	struct drm_device *dev = crtc->dev;
@@ -108,6 +143,8 @@ static void start(struct drm_crtc *crtc)
 
 	reset(crtc);
 
+	tilcdc_crtc_enable_irqs(dev);
+
 	tilcdc_clear(dev, LCDC_DMA_CTRL_REG, LCDC_DUAL_FRAME_BUFFER_ENABLE);
 	tilcdc_set(dev, LCDC_RASTER_CTRL_REG, LCDC_PALETTE_LOAD_MODE(DATA_ONLY));
 	tilcdc_set(dev, LCDC_RASTER_CTRL_REG, LCDC_RASTER_ENABLE);
@@ -138,6 +175,8 @@ static void stop(struct drm_crtc *crtc)
 	}
 
 	drm_crtc_vblank_off(crtc);
+
+	tilcdc_crtc_disable_irqs(dev);
 }
 
 static void tilcdc_crtc_destroy(struct drm_crtc *crtc)
drivers/gpu/drm/tilcdc/tilcdc_drv.c +0 -48

81 lines not on this page · raw message

Signature · 6 lines
1.9.1

_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
author
#18 lore raw

PATCH v2 18/21 drm/tilcdc: Use drm_atomic_helper_resume/suspend()

In reply to Jyri Sarha

Use drm_atomic_helper_resume/suspend() and get rid off all obsolete code register level context restoring code.

---
 drivers/gpu/drm/tilcdc/tilcdc_drv.c | 56 +++++--------------------------------
 drivers/gpu/drm/tilcdc/tilcdc_drv.h |  6 ++--
 2 files changed, 9 insertions(+), 53 deletions(-)
drivers/gpu/drm/tilcdc/tilcdc_drv.c +7 -49
index f0d1599..fc24aba 100644
@@ -215,8 +215,6 @@ static int tilcdc_unload(struct drm_device *dev)
 	return 0;
 }
 
-static size_t tilcdc_num_regs(void);
-
 static int tilcdc_load(struct drm_device *dev, unsigned long flags)
 {
 	struct platform_device *pdev = dev->platformdev;
@@ -228,11 +226,7 @@ static int tilcdc_load(struct drm_device *dev, unsigned long flags)
 	int ret;
 
 	priv = devm_kzalloc(dev->dev, sizeof(*priv), GFP_KERNEL);
-	if (priv)
-		priv->saved_register =
-			devm_kcalloc(dev->dev, tilcdc_num_regs(),
-				     sizeof(*priv->saved_register), GFP_KERNEL);
-	if (!priv || !priv->saved_register) {
+	if (!priv) {
 		dev_err(dev->dev, "failed to allocate private data\n");
 		return -ENOMEM;
 	}
@@ -439,7 +433,7 @@ static void tilcdc_disable_vblank(struct drm_device *dev, unsigned int pipe)
 	return;
 }
 
-#if defined(CONFIG_DEBUG_FS) || defined(CONFIG_PM_SLEEP)
+#if defined(CONFIG_DEBUG_FS)
 static const struct {
 	const char *name;
 	uint8_t  rev;
@@ -470,15 +464,6 @@ static const struct {
 #undef REG
 };
 
-static size_t tilcdc_num_regs(void)
-{
-	return ARRAY_SIZE(registers);
-}
-#else
-static size_t tilcdc_num_regs(void)
-{
-	return 0;
-}
 #endif
 
 #ifdef CONFIG_DEBUG_FS
@@ -611,29 +596,12 @@ static int tilcdc_pm_suspend(struct device *dev)
 {
 	struct drm_device *ddev = dev_get_drvdata(dev);
 	struct tilcdc_drm_private *priv = ddev->dev_private;
-	unsigned i, n = 0;
 
-	drm_kms_helper_poll_disable(ddev);
+	priv->saved_state = drm_atomic_helper_suspend(ddev);
 
 	/* Select sleep pin state */
 	pinctrl_pm_select_sleep_state(dev);
 
-	if (pm_runtime_suspended(dev)) {
-		priv->ctx_valid = false;
-		return 0;
-	}
-
-	/* Disable the LCDC controller, to avoid locking up the PRCM */
-	priv->saved_dpms_state = tilcdc_crtc_current_dpms_state(priv->crtc);
-	tilcdc_crtc_dpms(priv->crtc, DRM_MODE_DPMS_OFF);
-
-	/* Save register state: */
-	for (i = 0; i < ARRAY_SIZE(registers); i++)
-		if (registers[i].save && (priv->rev >= registers[i].rev))
-			priv->saved_register[n++] = tilcdc_read(ddev, registers[i].reg);
-
-	priv->ctx_valid = true;
-
 	return 0;
 }
 
@@ -641,25 +609,15 @@ static int tilcdc_pm_resume(struct device *dev)
 {
 	struct drm_device *ddev = dev_get_drvdata(dev);
 	struct tilcdc_drm_private *priv = ddev->dev_private;
-	unsigned i, n = 0;
+	int ret = 0;
 
 	/* Select default pin state */
 	pinctrl_pm_select_default_state(dev);
 
-	if (priv->ctx_valid == true) {
-		/* Restore register state: */
-		for (i = 0; i < ARRAY_SIZE(registers); i++)
-			if (registers[i].save &&
-			    (priv->rev >= registers[i].rev))
-				tilcdc_write(ddev, registers[i].reg,
-					     priv->saved_register[n++]);
-	}
+	if (priv->saved_state)
+		ret = drm_atomic_helper_resume(ddev, priv->saved_state);
 
-	tilcdc_crtc_dpms(priv->crtc, priv->saved_dpms_state);
-
-	drm_kms_helper_poll_enable(ddev);
-
-	return 0;
+	return ret;
 }
 #endif
 
drivers/gpu/drm/tilcdc/tilcdc_drv.h +2 -4
index 0619c3c..5e645ce 100644
@@ -65,10 +65,8 @@ struct tilcdc_drm_private {
 	 */
 	uint32_t max_width;
 
-	/* register contents saved across suspend/resume: */
-	u32 *saved_register;
-	int saved_dpms_state;
-	bool ctx_valid;
+	/* The context for pm susped/resume cycle is stored here */
+	struct drm_atomic_state *saved_state;
 
 #ifdef CONFIG_CPU_FREQ
 	struct notifier_block freq_transition;
Signature · 6 lines
1.9.1

_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
author
#19 lore raw

PATCH v2 19/21 drm/tilcdc: Get rid of legacy dpms mechanism

In reply to Jyri Sarha

Get rid of legacy dpms mechanism. This simplifies the code quite a bit. The old start() and stop() functions become tilcdc_crtc_enable() and *_disable(). The functions are added with all the necessary mechanisms from the old dpms function and they are used directly as the crtc helper enable() and disable() callbacks.

---
 drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 109 ++++++++++++++---------------------
 drivers/gpu/drm/tilcdc/tilcdc_drv.c  |   8 ++-
 drivers/gpu/drm/tilcdc/tilcdc_drv.h  |   3 +-
 3 files changed, 50 insertions(+), 70 deletions(-)
drivers/gpu/drm/tilcdc/tilcdc_crtc.c +42 -67
index f699818..783cb17 100644
@@ -30,7 +30,7 @@ struct tilcdc_crtc {
 	struct drm_plane primary;
 	const struct tilcdc_panel_info *info;
 	struct drm_pending_vblank_event *event;
-	int dpms;
+	bool enabled;
 	wait_queue_head_t frame_done_wq;
 	bool frame_done;
 	spinlock_t irq_lock;
@@ -137,9 +137,15 @@ static void reset(struct drm_crtc *crtc)
 	tilcdc_clear(dev, LCDC_CLK_RESET_REG, LCDC_CLK_MAIN_RESET);
 }
 
-static void start(struct drm_crtc *crtc)
+static void tilcdc_crtc_enable(struct drm_crtc *crtc)
 {
 	struct drm_device *dev = crtc->dev;
+	struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
+
+	if (tilcdc_crtc->enabled)
+		return;
+
+	pm_runtime_get_sync(dev->dev);
 
 	reset(crtc);
 
@@ -150,14 +156,19 @@ static void start(struct drm_crtc *crtc)
 	tilcdc_set(dev, LCDC_RASTER_CTRL_REG, LCDC_RASTER_ENABLE);
 
 	drm_crtc_vblank_on(crtc);
+
+	tilcdc_crtc->enabled = true;
 }
 
-static void stop(struct drm_crtc *crtc)
+void tilcdc_crtc_disable(struct drm_crtc *crtc)
 {
 	struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
 	struct drm_device *dev = crtc->dev;
 	struct tilcdc_drm_private *priv = dev->dev_private;
 
+	if (!tilcdc_crtc->enabled)
+		return;
+
 	tilcdc_crtc->frame_done = false;
 	tilcdc_clear(dev, LCDC_RASTER_CTRL_REG, LCDC_RASTER_ENABLE);
 
@@ -177,13 +188,37 @@ static void stop(struct drm_crtc *crtc)
 	drm_crtc_vblank_off(crtc);
 
 	tilcdc_crtc_disable_irqs(dev);
+
+	pm_runtime_put_sync(dev->dev);
+
+	if (tilcdc_crtc->next_fb) {
+		drm_flip_work_queue(&tilcdc_crtc->unref_work,
+				    tilcdc_crtc->next_fb);
+		tilcdc_crtc->next_fb = NULL;
+	}
+
+	if (tilcdc_crtc->curr_fb) {
+		drm_flip_work_queue(&tilcdc_crtc->unref_work,
+				    tilcdc_crtc->curr_fb);
+		tilcdc_crtc->curr_fb = NULL;
+	}
+
+	drm_flip_work_commit(&tilcdc_crtc->unref_work, priv->wq);
+	tilcdc_crtc->last_vblank = ktime_set(0, 0);
+
+	tilcdc_crtc->enabled = false;
+}
+
+static bool tilcdc_crtc_is_on(struct drm_crtc *crtc)
+{
+	return crtc->state && crtc->state->enable && crtc->state->active;
 }
 
 static void tilcdc_crtc_destroy(struct drm_crtc *crtc)
 {
 	struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
 
-	tilcdc_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
+	tilcdc_crtc_disable(crtc);
 
 	of_node_put(crtc->port);
 	drm_crtc_cleanup(crtc);
@@ -237,52 +272,6 @@ int tilcdc_crtc_page_flip(struct drm_crtc *crtc,
 	return 0;
 }
 
-void tilcdc_crtc_dpms(struct drm_crtc *crtc, int mode)
-{
-	struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
-	struct drm_device *dev = crtc->dev;
-	struct tilcdc_drm_private *priv = dev->dev_private;
-
-	/* we really only care about on or off: */
-	if (mode != DRM_MODE_DPMS_ON)
-		mode = DRM_MODE_DPMS_OFF;
-
-	if (tilcdc_crtc->dpms == mode)
-		return;
-
-	tilcdc_crtc->dpms = mode;
-
-	if (mode == DRM_MODE_DPMS_ON) {
-		pm_runtime_get_sync(dev->dev);
-		start(crtc);
-	} else {
-		stop(crtc);
-		pm_runtime_put_sync(dev->dev);
-
-		if (tilcdc_crtc->next_fb) {
-			drm_flip_work_queue(&tilcdc_crtc->unref_work,
-					    tilcdc_crtc->next_fb);
-			tilcdc_crtc->next_fb = NULL;
-		}
-
-		if (tilcdc_crtc->curr_fb) {
-			drm_flip_work_queue(&tilcdc_crtc->unref_work,
-					    tilcdc_crtc->curr_fb);
-			tilcdc_crtc->curr_fb = NULL;
-		}
-
-		drm_flip_work_commit(&tilcdc_crtc->unref_work, priv->wq);
-		tilcdc_crtc->last_vblank = ktime_set(0, 0);
-	}
-}
-
-int tilcdc_crtc_current_dpms_state(struct drm_crtc *crtc)
-{
-	struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
-
-	return tilcdc_crtc->dpms;
-}
-
 static bool tilcdc_crtc_mode_fixup(struct drm_crtc *crtc,
 		const struct drm_display_mode *mode,
 		struct drm_display_mode *adjusted_mode)
@@ -312,16 +301,6 @@ static bool tilcdc_crtc_mode_fixup(struct drm_crtc *crtc,
 	return true;
 }
 
-static void tilcdc_crtc_disable(struct drm_crtc *crtc)
-{
-	tilcdc_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
-}
-
-static void tilcdc_crtc_enable(struct drm_crtc *crtc)
-{
-	tilcdc_crtc_dpms(crtc, DRM_MODE_DPMS_ON);
-}
-
 static void tilcdc_crtc_mode_set_nofb(struct drm_crtc *crtc)
 {
 	struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
@@ -655,18 +634,15 @@ void tilcdc_crtc_set_simulate_vesa_sync(struct drm_crtc *crtc,
 
 void tilcdc_crtc_update_clk(struct drm_crtc *crtc)
 {
-	struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
 	struct drm_device *dev = crtc->dev;
 	struct tilcdc_drm_private *priv = dev->dev_private;
-	int dpms = tilcdc_crtc->dpms;
 	unsigned long lcd_clk;
 	const unsigned clkdiv = 2; /* using a fixed divider of 2 */
 	int ret;
 
 	pm_runtime_get_sync(dev->dev);
 
-	if (dpms == DRM_MODE_DPMS_ON)
-		tilcdc_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
+	tilcdc_crtc_disable(crtc);
 
 	/* mode.clock is in KHz, set_rate wants parameter in Hz */
 	ret = clk_set_rate(priv->clk, crtc->mode.clock * 1000 * clkdiv);
@@ -690,8 +666,8 @@ void tilcdc_crtc_update_clk(struct drm_crtc *crtc)
 				LCDC_V2_DMA_CLK_EN | LCDC_V2_LIDD_CLK_EN |
 				LCDC_V2_CORE_CLK_EN);
 
-	if (dpms == DRM_MODE_DPMS_ON)
-		tilcdc_crtc_dpms(crtc, DRM_MODE_DPMS_ON);
+	if (tilcdc_crtc_is_on(crtc))
+		tilcdc_crtc_enable(crtc);
 
 out:
 	pm_runtime_put_sync(dev->dev);
@@ -802,7 +778,6 @@ struct drm_crtc *tilcdc_crtc_create(struct drm_device *dev)
 	if (ret < 0)
 		goto fail;
 
-	tilcdc_crtc->dpms = DRM_MODE_DPMS_OFF;
 	init_waitqueue_head(&tilcdc_crtc->frame_done_wq);
 
 	drm_flip_work_init(&tilcdc_crtc->unref_work,
drivers/gpu/drm/tilcdc/tilcdc_drv.c +7 -1
index fc24aba..fd61740 100644
@@ -113,12 +113,18 @@ static int tilcdc_commit(struct drm_device *dev,
 	 * current layout.
 	 */
 
+	/* Keep HW on while we commit the state. */
+	pm_runtime_get_sync(dev->dev);
+
 	drm_atomic_helper_commit_modeset_disables(dev, state);
 
 	drm_atomic_helper_commit_planes(dev, state, false);
 
 	drm_atomic_helper_commit_modeset_enables(dev, state);
 
+	/* Now HW should remain on if need becase the crtc is enabled */
+	pm_runtime_put_sync(dev->dev);
+
 	drm_atomic_helper_wait_for_vblanks(dev, state);
 
 	drm_atomic_helper_cleanup_planes(dev, state);
@@ -183,7 +189,7 @@ static int tilcdc_unload(struct drm_device *dev)
 {
 	struct tilcdc_drm_private *priv = dev->dev_private;
 
-	tilcdc_crtc_dpms(priv->crtc, DRM_MODE_DPMS_OFF);
+	tilcdc_crtc_disable(priv->crtc);
 
 	tilcdc_remove_external_encoders(dev);
 
drivers/gpu/drm/tilcdc/tilcdc_drv.h +1 -2
index 5e645ce..a02eb373 100644
@@ -170,8 +170,7 @@ void tilcdc_crtc_set_simulate_vesa_sync(struct drm_crtc *crtc,
 					bool simulate_vesa_sync);
 int tilcdc_crtc_mode_valid(struct drm_crtc *crtc, struct drm_display_mode *mode);
 int tilcdc_crtc_max_width(struct drm_crtc *crtc);
-void tilcdc_crtc_dpms(struct drm_crtc *crtc, int mode);
-int tilcdc_crtc_current_dpms_state(struct drm_crtc *crtc);
+void tilcdc_crtc_disable(struct drm_crtc *crtc);
 int tilcdc_crtc_page_flip(struct drm_crtc *crtc,
 		struct drm_framebuffer *fb,
 		struct drm_pending_vblank_event *event,
Signature · 6 lines
1.9.1

_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
author
#20 lore raw

PATCH v2 20/21 drm/tilcdc: Remove unnecessary pm_runtime_get() and *_put() calls

In reply to Jyri Sarha

Remove unnecessary pm_runtime_get() and *_put() calls from commit phase callbacks. Those calls are not needed since we have the whole commit phase between pm_runtime_get_sync() and pm_runtime_put_sync().

---
 drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 8 --------
 1 file changed, 8 deletions(-)
drivers/gpu/drm/tilcdc/tilcdc_crtc.c +0 -8
index 783cb17..3573bfa 100644
@@ -243,8 +243,6 @@ int tilcdc_crtc_page_flip(struct drm_crtc *crtc,
 
 	crtc->primary->fb = fb;
 
-	pm_runtime_get_sync(dev->dev);
-
 	spin_lock_irqsave(&tilcdc_crtc->irq_lock, flags);
 
 	if (crtc->hwmode.vrefresh && ktime_to_ns(tilcdc_crtc->last_vblank)) {
@@ -267,8 +265,6 @@ int tilcdc_crtc_page_flip(struct drm_crtc *crtc,
 
 	spin_unlock_irqrestore(&tilcdc_crtc->irq_lock, flags);
 
-	pm_runtime_put_sync(dev->dev);
-
 	return 0;
 }
 
@@ -317,8 +313,6 @@ static void tilcdc_crtc_mode_set_nofb(struct drm_crtc *crtc)
 	if (WARN_ON(!fb))
 		return;
 
-	pm_runtime_get_sync(dev->dev);
-
 	/* Configure the Burst Size and fifo threshold of DMA: */
 	reg = tilcdc_read(dev, LCDC_DMA_CTRL_REG) & ~0x00000770;
 	switch (info->dma_burst_sz) {
@@ -467,8 +461,6 @@ static void tilcdc_crtc_mode_set_nofb(struct drm_crtc *crtc)
 
 	tilcdc_crtc_update_clk(crtc);
 
-	pm_runtime_put_sync(dev->dev);
-
 	crtc->hwmode = crtc->state->adjusted_mode;
 }
 
Signature · 6 lines
1.9.1

_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
author
#21 lore raw

PATCH v2 21/21 drm/tilcdc: Change tilcdc_crtc_page_flip() to tilcdc_crtc_update_fb()

In reply to Jyri Sarha

Change tilcdc_crtc_page_flip() to tilcdc_crtc_update_fb(). The function is not used as a page_flip() callback anymore so it is only confusing to call it that anymore. The function should only be used by dummy primary plane commit() callback.

---
 drivers/gpu/drm/tilcdc/tilcdc_crtc.c  | 5 ++---
 drivers/gpu/drm/tilcdc/tilcdc_drv.h   | 5 ++---
 drivers/gpu/drm/tilcdc/tilcdc_plane.c | 5 ++---
 3 files changed, 6 insertions(+), 9 deletions(-)
drivers/gpu/drm/tilcdc/tilcdc_crtc.c +2 -3
index 3573bfa..15aefd6 100644
@@ -225,10 +225,9 @@ static void tilcdc_crtc_destroy(struct drm_crtc *crtc)
 	drm_flip_work_cleanup(&tilcdc_crtc->unref_work);
 }
 
-int tilcdc_crtc_page_flip(struct drm_crtc *crtc,
+int tilcdc_crtc_update_fb(struct drm_crtc *crtc,
 		struct drm_framebuffer *fb,
-		struct drm_pending_vblank_event *event,
-		uint32_t page_flip_flags)
+		struct drm_pending_vblank_event *event)
 {
 	struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
 	struct drm_device *dev = crtc->dev;
drivers/gpu/drm/tilcdc/tilcdc_drv.h +2 -3
index a02eb373..13001df 100644
@@ -171,10 +171,9 @@ void tilcdc_crtc_set_simulate_vesa_sync(struct drm_crtc *crtc,
 int tilcdc_crtc_mode_valid(struct drm_crtc *crtc, struct drm_display_mode *mode);
 int tilcdc_crtc_max_width(struct drm_crtc *crtc);
 void tilcdc_crtc_disable(struct drm_crtc *crtc);
-int tilcdc_crtc_page_flip(struct drm_crtc *crtc,
+int tilcdc_crtc_update_fb(struct drm_crtc *crtc,
 		struct drm_framebuffer *fb,
-		struct drm_pending_vblank_event *event,
-		uint32_t page_flip_flags);
+		struct drm_pending_vblank_event *event);
 
 int tilcdc_plane_init(struct drm_device *dev, struct drm_plane *plane);
 
drivers/gpu/drm/tilcdc/tilcdc_plane.c +2 -3
index d5635d6..41911e3 100644
@@ -101,10 +101,9 @@ static void tilcdc_plane_atomic_update(struct drm_plane *plane,
 	if (WARN_ON(!state->fb || !state->crtc->state))
 		return;
 
-	tilcdc_crtc_page_flip(state->crtc,
+	tilcdc_crtc_update_fb(state->crtc,
 			      state->fb,
-			      state->crtc->state->event,
-			      0);
+			      state->crtc->state->event);
 }
 
 static const struct drm_plane_helper_funcs plane_helper_funcs = {
Signature · 6 lines
1.9.1

_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel