Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 33d5f513 authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge tag 'imx-drm-next-2017-03-17' of git://git.pengutronix.de/git/pza/linux into drm-next

imx-drm PRE/PRG support, deferred plane disabling, separate alpha support

- Initial support for the Prefetch Resolve Engine/Gasket on i.MX6QP,
  improving linear scanout buffer memory bandwidth utilization. This
  will in the future grow reordering support and allow direct scanout
  of Vivante tiled renderbuffers from the GPU.
- Deferred plane disabling gets rid of some busy waiting in the atomic
  plane disable and crtc disable paths that lead to wait_for_vblank
  timeouts.
- Add support for RGBA formats with a separate alpha plane, that can
  reduce memory bandwidth utilization for mostly transparent overlay
  planes by skipping color reads for completely transparent regions.
- Allow moving an active overlay plane without enforcing a modeset.
- Add 8-bit and 16-bit bayer formats to ipu_cpmem_set_image.
- Set the base address in ipu_cpmem_set_image even for invalid formats
  to increase robustness against errors.
- Use drm_plane_helper_check_state in plane atomic_check.
- Some cleanup.

* tag 'imx-drm-next-2017-03-17' of git://git.pengutronix.de/git/pza/linux: (22 commits)
  drm/imx: Remove unneeded definition for structure imx_drm_component
  drm/imx: use PRG/PRE when possible
  drm/imx: enable/disable PRG on CRTC enable/disable
  gpu: ipu-v3: only set non-zero AXI ID for IC when PRG is absent
  gpu: ipu-v3: hook up PRG unit
  gpu: ipu-v3: document valid IPUv3 compatibles and extend for i.MX6 QuadPlus
  gpu: ipu-v3: add driver for Prefetch Resolve Gasket
  gpu: ipu-v3: add DT binding for the Prefetch Resolve Gasket
  gpu: ipu-v3: add driver for Prefetch Resolve Engine
  gpu: ipu-v3: add DT binding for the Prefetch Resolve Engine
  drm/imx: ipuv3-plane: add support for separate alpha planes
  drm/imx: extend drm_plane_state_to_eba for separate channel support
  gpu: ipu-v3: add support for separate alpha channels
  drm: add RGB formats with separate alpha plane
  drm/imx: add deferred plane disabling
  drm/imx: don't wait for vblank and stop calling cleanup_planes in commit_tail
  gpu: ipu-v3: add unsynchronised DP channel disabling
  gpu: ipu-v3: remove IRQ dance on DC channel disable
  gpu: ipu-cpmem: add bayer formats to ipu_cpmem_set_image
  gpu: ipu-cpmem: set image base address even for incorrect formats
  ...
parents b7d6c8db 7d5ed292
Loading
Loading
Loading
Loading
+58 −1
Original line number Diff line number Diff line
@@ -21,13 +21,19 @@ Freescale i.MX IPUv3
====================

Required properties:
- compatible: Should be "fsl,<chip>-ipu"
- compatible: Should be "fsl,<chip>-ipu" where <chip> is one of
  - imx51
  - imx53
  - imx6q
  - imx6qp
- reg: should be register base and length as documented in the
  datasheet
- interrupts: Should contain sync interrupt and error interrupt,
  in this order.
- resets: phandle pointing to the system reset controller and
          reset line index, see reset/fsl,imx-src.txt for details
Additional required properties for fsl,imx6qp-ipu:
- fsl,prg: phandle to prg node associated with this IPU instance
Optional properties:
- port@[0-3]: Port nodes with endpoint definitions as defined in
  Documentation/devicetree/bindings/media/video-interfaces.txt.
@@ -53,6 +59,57 @@ ipu: ipu@18000000 {
	};
};

Freescale i.MX PRE (Prefetch Resolve Engine)
============================================

Required properties:
- compatible: should be "fsl,imx6qp-pre"
- reg: should be register base and length as documented in the
  datasheet
- clocks : phandle to the PRE axi clock input, as described
  in Documentation/devicetree/bindings/clock/clock-bindings.txt and
  Documentation/devicetree/bindings/clock/imx6q-clock.txt.
- clock-names: should be "axi"
- interrupts: should contain the PRE interrupt
- fsl,iram: phandle pointing to the mmio-sram device node, that should be
  used for the PRE SRAM double buffer.

example:

pre@21c8000 {
	compatible = "fsl,imx6qp-pre";
	reg = <0x021c8000 0x1000>;
	interrupts = <GIC_SPI 90 IRQ_TYPE_EDGE_RISING>;
	clocks = <&clks IMX6QDL_CLK_PRE0>;
	clock-names = "axi";
	fsl,iram = <&ocram2>;
};

Freescale i.MX PRG (Prefetch Resolve Gasket)
============================================

Required properties:
- compatible: should be "fsl,imx6qp-prg"
- reg: should be register base and length as documented in the
  datasheet
- clocks : phandles to the PRG ipg and axi clock inputs, as described
  in Documentation/devicetree/bindings/clock/clock-bindings.txt and
  Documentation/devicetree/bindings/clock/imx6q-clock.txt.
- clock-names: should be "ipg" and "axi"
- fsl,pres: phandles to the PRE units attached to this PRG, with the fixed
  PRE as the first entry and the muxable PREs following.

example:

prg@21cc000 {
	compatible = "fsl,imx6qp-prg";
	reg = <0x021cc000 0x1000>;
	clocks = <&clks IMX6QDL_CLK_PRG0_APB>,
		 <&clks IMX6QDL_CLK_PRG0_AXI>;
	clock-names = "ipg", "axi";
	fsl,pres = <&pre1>, <&pre2>, <&pre3>;
};

Parallel display support
========================

+8 −0
Original line number Diff line number Diff line
@@ -132,6 +132,8 @@ const struct drm_format_info *__drm_format_info(u32 format)
		{ .format = DRM_FORMAT_XBGR8888,	.depth = 24, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 },
		{ .format = DRM_FORMAT_RGBX8888,	.depth = 24, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 },
		{ .format = DRM_FORMAT_BGRX8888,	.depth = 24, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 },
		{ .format = DRM_FORMAT_RGB565_A8,	.depth = 24, .num_planes = 2, .cpp = { 2, 1, 0 }, .hsub = 1, .vsub = 1 },
		{ .format = DRM_FORMAT_BGR565_A8,	.depth = 24, .num_planes = 2, .cpp = { 2, 1, 0 }, .hsub = 1, .vsub = 1 },
		{ .format = DRM_FORMAT_XRGB2101010,	.depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 },
		{ .format = DRM_FORMAT_XBGR2101010,	.depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 },
		{ .format = DRM_FORMAT_RGBX1010102,	.depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 },
@@ -144,6 +146,12 @@ const struct drm_format_info *__drm_format_info(u32 format)
		{ .format = DRM_FORMAT_ABGR8888,	.depth = 32, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 },
		{ .format = DRM_FORMAT_RGBA8888,	.depth = 32, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 },
		{ .format = DRM_FORMAT_BGRA8888,	.depth = 32, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 },
		{ .format = DRM_FORMAT_RGB888_A8,	.depth = 32, .num_planes = 2, .cpp = { 3, 1, 0 }, .hsub = 1, .vsub = 1 },
		{ .format = DRM_FORMAT_BGR888_A8,	.depth = 32, .num_planes = 2, .cpp = { 3, 1, 0 }, .hsub = 1, .vsub = 1 },
		{ .format = DRM_FORMAT_XRGB8888_A8,	.depth = 32, .num_planes = 2, .cpp = { 4, 1, 0 }, .hsub = 1, .vsub = 1 },
		{ .format = DRM_FORMAT_XBGR8888_A8,	.depth = 32, .num_planes = 2, .cpp = { 4, 1, 0 }, .hsub = 1, .vsub = 1 },
		{ .format = DRM_FORMAT_RGBX8888_A8,	.depth = 32, .num_planes = 2, .cpp = { 4, 1, 0 }, .hsub = 1, .vsub = 1 },
		{ .format = DRM_FORMAT_BGRX8888_A8,	.depth = 32, .num_planes = 2, .cpp = { 4, 1, 0 }, .hsub = 1, .vsub = 1 },
		{ .format = DRM_FORMAT_YUV410,		.depth = 0,  .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 4, .vsub = 4 },
		{ .format = DRM_FORMAT_YVU410,		.depth = 0,  .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 4, .vsub = 4 },
		{ .format = DRM_FORMAT_YUV411,		.depth = 0,  .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 4, .vsub = 1 },
+22 −8
Original line number Diff line number Diff line
@@ -30,14 +30,10 @@
#include <video/imx-ipu-v3.h>

#include "imx-drm.h"
#include "ipuv3-plane.h"

#define MAX_CRTC	4

struct imx_drm_component {
	struct device_node *of_node;
	struct list_head list;
};

struct imx_drm_device {
	struct drm_device			*drm;
	unsigned int				pipes;
@@ -109,6 +105,11 @@ static int imx_drm_atomic_check(struct drm_device *dev,
	if (ret)
		return ret;

	/* Assign PRG/PRE channels and check if all constrains are satisfied. */
	ret = ipu_planes_assign_pre(dev, state);
	if (ret)
		return ret;

	return ret;
}

@@ -122,6 +123,10 @@ static const struct drm_mode_config_funcs imx_drm_mode_config_funcs = {
static void imx_drm_atomic_commit_tail(struct drm_atomic_state *state)
{
	struct drm_device *dev = state->dev;
	struct drm_plane *plane;
	struct drm_plane_state *old_plane_state;
	bool plane_disabling = false;
	int i;

	drm_atomic_helper_commit_modeset_disables(dev, state);

@@ -131,11 +136,20 @@ static void imx_drm_atomic_commit_tail(struct drm_atomic_state *state)

	drm_atomic_helper_commit_modeset_enables(dev, state);

	drm_atomic_helper_commit_hw_done(state);
	for_each_plane_in_state(state, plane, old_plane_state, i) {
		if (drm_atomic_plane_disabling(old_plane_state, plane->state))
			plane_disabling = true;
	}

	if (plane_disabling) {
		drm_atomic_helper_wait_for_vblanks(dev, state);

	drm_atomic_helper_cleanup_planes(dev, state);
		for_each_plane_in_state(state, plane, old_plane_state, i)
			ipu_plane_disable_deferred(plane);

	}

	drm_atomic_helper_commit_hw_done(state);
}

static const struct drm_mode_config_helper_funcs imx_drm_mode_config_helpers = {
+3 −0
Original line number Diff line number Diff line
@@ -39,4 +39,7 @@ int imx_drm_encoder_parse_of(struct drm_device *drm,
void imx_drm_connector_destroy(struct drm_connector *connector);
void imx_drm_encoder_destroy(struct drm_encoder *encoder);

int ipu_planes_assign_pre(struct drm_device *dev,
			  struct drm_atomic_state *state);

#endif /* _IMX_DRM_H_ */
+23 −1
Original line number Diff line number Diff line
@@ -55,11 +55,32 @@ static void ipu_crtc_enable(struct drm_crtc *crtc)
	struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc);
	struct ipu_soc *ipu = dev_get_drvdata(ipu_crtc->dev->parent);

	ipu_prg_enable(ipu);
	ipu_dc_enable(ipu);
	ipu_dc_enable_channel(ipu_crtc->dc);
	ipu_di_enable(ipu_crtc->di);
}

static void ipu_crtc_disable_planes(struct ipu_crtc *ipu_crtc,
				    struct drm_crtc_state *old_crtc_state)
{
	bool disable_partial = false;
	bool disable_full = false;
	struct drm_plane *plane;

	drm_atomic_crtc_state_for_each_plane(plane, old_crtc_state) {
		if (plane == &ipu_crtc->plane[0]->base)
			disable_full = true;
		if (&ipu_crtc->plane[1] && plane == &ipu_crtc->plane[1]->base)
			disable_partial = true;
	}

	if (disable_partial)
		ipu_plane_disable(ipu_crtc->plane[1], true);
	if (disable_full)
		ipu_plane_disable(ipu_crtc->plane[0], false);
}

static void ipu_crtc_atomic_disable(struct drm_crtc *crtc,
				    struct drm_crtc_state *old_crtc_state)
{
@@ -73,8 +94,9 @@ static void ipu_crtc_atomic_disable(struct drm_crtc *crtc,
	 * attached IDMACs will be left in undefined state, possibly hanging
	 * the IPU or even system.
	 */
	drm_atomic_helper_disable_planes_on_crtc(old_crtc_state, false);
	ipu_crtc_disable_planes(ipu_crtc, old_crtc_state);
	ipu_dc_disable(ipu);
	ipu_prg_disable(ipu);

	spin_lock_irq(&crtc->dev->event_lock);
	if (crtc->state->event) {
Loading