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

Commit 870a1718 authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge branch 'exynos-drm-next' of...

Merge branch 'exynos-drm-next' of git://git.kernel.org:/pub/scm/linux/kernel/git/daeinki/drm-exynos into drm-next

- Support runtime pm
  . In case of most ARM SoC, each IP has each power domain which should be
    controlled by each IP driver using runtime pm interface. So this patch
    series makes each IP driver to control its own power domain when
    drm dpms is requested.
- Support of_graph based dt binding for DP panel.
  . This patch series adds of_graph based dt binding for DP panel.
    And also it keeps backward compatibility. This includes dt binding
    patch so I got Acked-by from Krzysztof Kozlowski who is a Exynos
    SoC maintainer and from Rob Herring who is a device tree maintainer.

- Cleanup for Exynos DRM IPP enhancement.
  . This patch series is a first step for enhancing existing IPP framework
    which will integrate existing IPP functions with DRM KMS part so that
    these can be transparent to userspace. For other portion of the patch
    series, we will have more times for the review.]

* 'exynos-drm-next' of git://git.kernel.org:/pub/scm/linux/kernel/git/daeinki/drm-exynos: (29 commits)
  drm/exynos: gem: remove old unused prototypes
  drm/exynos: fimd: fix dma burst size setting for small plane size
  drm/exynos: fix clipping when scaling is enabled
  drm/exynos: mixer: use ratio precalculated in exynos_state
  drm/exynos: add generic check for plane state
  drm/exynos: introduce exynos_drm_plane_config structure
  drm/exynos: mixer: enable video overlay plane only when VP is available
  drm/exynos: mixer: use crtc->state->adjusted_mode instead of crtc->mode
  drm/exynos: introduce exynos_drm_plane_state structure
  drm/exynos: move dma_addr attribute from exynos plane to exynos fb
  drm/exynos: exynos7-decon: remove excessive check
  drm/exynos: rotator: convert to common clock framework
  drm/exynos: gsc: add device tree support and remove usage of static mappings
  drm/exynos: gsc: fix wrong pm_runtime state
  drm/exynos: gsc: prepare and unprepare gsc clock
  ARM: dts: Use OF graph for DP to panel connection in exynos5800-peach-pi
  dt-bindings: exynos-dp: update ports node binding for panel
  drm/exynos: dp: add of_graph dt binding support for panel
  drm/exynos: decon: remove unused variables
  drm/exynos: dsi: modify a error type when getting a node failed
  ...
parents b15c50be 9bac40cf
Loading
Loading
Loading
Loading
+37 −4
Original line number Diff line number Diff line
Device-Tree bindings for Samsung Exynos Embedded DisplayPort Transmitter(eDP)

DisplayPort is industry standard to accommodate the growing board adoption
of digital display technology within the PC and CE industries.
It consolidates the internal and external connection methods to reduce device
complexity and cost. It also supports necessary features for important cross
industry applications and provides performance scalability to enable the next
generation of displays that feature higher color depths, refresh rates, and
display resolutions.

eDP (embedded display port) device is compliant with Embedded DisplayPort
standard as follows,
- DisplayPort standard 1.1a for Exynos5250 and Exynos5260.
- DisplayPort standard 1.3 for Exynos5422s and Exynos5800.

eDP resides between FIMD and panel or FIMD and bridge such as LVDS.

The Exynos display port interface should be configured based on
the type of panel connected to it.

@@ -66,8 +83,15 @@ Optional properties for dp-controller:
		Hotplug detect GPIO.
			Indicates which GPIO should be used for hotplug
			detection
	-video interfaces: Device node can contain video interface port
			    nodes according to [1].
Video interfaces:
  Device node can contain video interface port nodes according to [1].
  The following are properties specific to those nodes:

  endpoint node connected to bridge or panel node:
   - remote-endpoint: specifies the endpoint in panel or bridge node.
		      This node is required in all kinds of exynos dp
		      to represent the connection between dp and bridge
		      or dp and panel.

[1]: Documentation/devicetree/bindings/media/video-interfaces.txt

@@ -111,9 +135,18 @@ Board Specific portion:
		};

		ports {
			port@0 {
			port {
				dp_out: endpoint {
					remote-endpoint = <&bridge_in>;
					remote-endpoint = <&dp_in>;
				};
			};
		};

		panel {
			...
			port {
				dp_in: endpoint {
					remote-endpoint = <&dp_out>;
				};
			};
		};
+4 −0
Original line number Diff line number Diff line
@@ -7,6 +7,10 @@ Required properties:
- reg: should contain G-Scaler physical address location and length.
- interrupts: should contain G-Scaler interrupt number

Optional properties:
- samsung,sysreg: handle to syscon used to control the system registers to
  set writeback input and destination

Example:

gsc_0:  gsc@0x13e00000 {
+14 −1
Original line number Diff line number Diff line
@@ -122,6 +122,12 @@
		compatible = "auo,b133htn01";
		power-supply = <&tps65090_fet6>;
		backlight = <&backlight>;

		port {
			panel_in: endpoint {
				remote-endpoint = <&dp_out>;
			};
		};
	};

	mmc1_pwrseq: mmc1_pwrseq {
@@ -148,7 +154,14 @@
	samsung,link-rate = <0x0a>;
	samsung,lane-count = <2>;
	samsung,hpd-gpio = <&gpx2 6 GPIO_ACTIVE_HIGH>;
	panel = <&panel>;

	ports {
		port {
			dp_out: endpoint {
				remote-endpoint = <&panel_in>;
			};
		};
	};
};

&fimd {
+1 −1
Original line number Diff line number Diff line
@@ -118,7 +118,7 @@ config DRM_EXYNOS_ROTATOR

config DRM_EXYNOS_GSC
	bool "GScaler"
	depends on DRM_EXYNOS_IPP && ARCH_EXYNOS5 && !ARCH_MULTIPLATFORM
	depends on DRM_EXYNOS_IPP && ARCH_EXYNOS5 && !VIDEO_SAMSUNG_EXYNOS_GSC
	help
	  Choose this option if you want to use Exynos GSC for DRM.

+69 −35
Original line number Diff line number Diff line
@@ -21,11 +21,11 @@

#include "exynos_drm_drv.h"
#include "exynos_drm_crtc.h"
#include "exynos_drm_fb.h"
#include "exynos_drm_plane.h"
#include "exynos_drm_iommu.h"

#define WINDOWS_NR	3
#define CURSOR_WIN	2
#define MIN_FB_WIDTH_FOR_16WORD_BURST	128

static const char * const decon_clks_name[] = {
@@ -56,6 +56,7 @@ struct decon_context {
	struct drm_device		*drm_dev;
	struct exynos_drm_crtc		*crtc;
	struct exynos_drm_plane		planes[WINDOWS_NR];
	struct exynos_drm_plane_config	configs[WINDOWS_NR];
	void __iomem			*addr;
	struct clk			*clks[ARRAY_SIZE(decon_clks_name)];
	int				pipe;
@@ -71,6 +72,12 @@ static const uint32_t decon_formats[] = {
	DRM_FORMAT_ARGB8888,
};

static const enum drm_plane_type decon_win_types[WINDOWS_NR] = {
	DRM_PLANE_TYPE_PRIMARY,
	DRM_PLANE_TYPE_OVERLAY,
	DRM_PLANE_TYPE_CURSOR,
};

static inline void decon_set_bits(struct decon_context *ctx, u32 reg, u32 mask,
				  u32 val)
{
@@ -259,21 +266,24 @@ static void decon_atomic_begin(struct exynos_drm_crtc *crtc,
static void decon_update_plane(struct exynos_drm_crtc *crtc,
			       struct exynos_drm_plane *plane)
{
	struct exynos_drm_plane_state *state =
				to_exynos_plane_state(plane->base.state);
	struct decon_context *ctx = crtc->ctx;
	struct drm_plane_state *state = plane->base.state;
	struct drm_framebuffer *fb = state->base.fb;
	unsigned int win = plane->zpos;
	unsigned int bpp = state->fb->bits_per_pixel >> 3;
	unsigned int pitch = state->fb->pitches[0];
	unsigned int bpp = fb->bits_per_pixel >> 3;
	unsigned int pitch = fb->pitches[0];
	dma_addr_t dma_addr = exynos_drm_fb_dma_addr(fb, 0);
	u32 val;

	if (test_bit(BIT_SUSPENDED, &ctx->flags))
		return;

	val = COORDINATE_X(plane->crtc_x) | COORDINATE_Y(plane->crtc_y);
	val = COORDINATE_X(state->crtc.x) | COORDINATE_Y(state->crtc.y);
	writel(val, ctx->addr + DECON_VIDOSDxA(win));

	val = COORDINATE_X(plane->crtc_x + plane->crtc_w - 1) |
		COORDINATE_Y(plane->crtc_y + plane->crtc_h - 1);
	val = COORDINATE_X(state->crtc.x + state->crtc.w - 1) |
		COORDINATE_Y(state->crtc.y + state->crtc.h - 1);
	writel(val, ctx->addr + DECON_VIDOSDxB(win));

	val = VIDOSD_Wx_ALPHA_R_F(0x0) | VIDOSD_Wx_ALPHA_G_F(0x0) |
@@ -284,20 +294,20 @@ static void decon_update_plane(struct exynos_drm_crtc *crtc,
		VIDOSD_Wx_ALPHA_B_F(0x0);
	writel(val, ctx->addr + DECON_VIDOSDxD(win));

	writel(plane->dma_addr[0], ctx->addr + DECON_VIDW0xADD0B0(win));
	writel(dma_addr, ctx->addr + DECON_VIDW0xADD0B0(win));

	val = plane->dma_addr[0] + pitch * plane->crtc_h;
	val = dma_addr + pitch * state->src.h;
	writel(val, ctx->addr + DECON_VIDW0xADD1B0(win));

	if (ctx->out_type != IFTYPE_HDMI)
		val = BIT_VAL(pitch - plane->crtc_w * bpp, 27, 14)
			| BIT_VAL(plane->crtc_w * bpp, 13, 0);
		val = BIT_VAL(pitch - state->crtc.w * bpp, 27, 14)
			| BIT_VAL(state->crtc.w * bpp, 13, 0);
	else
		val = BIT_VAL(pitch - plane->crtc_w * bpp, 29, 15)
			| BIT_VAL(plane->crtc_w * bpp, 14, 0);
		val = BIT_VAL(pitch - state->crtc.w * bpp, 29, 15)
			| BIT_VAL(state->crtc.w * bpp, 14, 0);
	writel(val, ctx->addr + DECON_VIDW0xADD2(win));

	decon_win_set_pixfmt(ctx, win, state->fb);
	decon_win_set_pixfmt(ctx, win, fb);

	/* window enable */
	decon_set_bits(ctx, DECON_WINCONx(win), WINCONx_ENWIN_F, ~0);
@@ -377,20 +387,12 @@ static void decon_swreset(struct decon_context *ctx)
static void decon_enable(struct exynos_drm_crtc *crtc)
{
	struct decon_context *ctx = crtc->ctx;
	int ret;
	int i;

	if (!test_and_clear_bit(BIT_SUSPENDED, &ctx->flags))
		return;

	pm_runtime_get_sync(ctx->dev);

	for (i = 0; i < ARRAY_SIZE(decon_clks_name); i++) {
		ret = clk_prepare_enable(ctx->clks[i]);
		if (ret < 0)
			goto err;
	}

	set_bit(BIT_CLKS_ENABLED, &ctx->flags);

	/* if vblank was enabled status, enable it again. */
@@ -399,11 +401,6 @@ static void decon_enable(struct exynos_drm_crtc *crtc)

	decon_commit(ctx->crtc);

	return;
err:
	while (--i >= 0)
		clk_disable_unprepare(ctx->clks[i]);

	set_bit(BIT_SUSPENDED, &ctx->flags);
}

@@ -425,9 +422,6 @@ static void decon_disable(struct exynos_drm_crtc *crtc)

	decon_swreset(ctx);

	for (i = 0; i < ARRAY_SIZE(decon_clks_name); i++)
		clk_disable_unprepare(ctx->clks[i]);

	clear_bit(BIT_CLKS_ENABLED, &ctx->flags);

	pm_runtime_put_sync(ctx->dev);
@@ -478,7 +472,6 @@ static void decon_clear_channels(struct exynos_drm_crtc *crtc)
static struct exynos_drm_crtc_ops decon_crtc_ops = {
	.enable			= decon_enable,
	.disable		= decon_disable,
	.commit			= decon_commit,
	.enable_vblank		= decon_enable_vblank,
	.disable_vblank		= decon_disable_vblank,
	.atomic_begin		= decon_atomic_begin,
@@ -495,7 +488,6 @@ static int decon_bind(struct device *dev, struct device *master, void *data)
	struct exynos_drm_private *priv = drm_dev->dev_private;
	struct exynos_drm_plane *exynos_plane;
	enum exynos_drm_output_type out_type;
	enum drm_plane_type type;
	unsigned int win;
	int ret;

@@ -505,10 +497,13 @@ static int decon_bind(struct device *dev, struct device *master, void *data)
	for (win = ctx->first_win; win < WINDOWS_NR; win++) {
		int tmp = (win == ctx->first_win) ? 0 : win;

		type = exynos_plane_get_type(tmp, CURSOR_WIN);
		ctx->configs[win].pixel_formats = decon_formats;
		ctx->configs[win].num_pixel_formats = ARRAY_SIZE(decon_formats);
		ctx->configs[win].zpos = win;
		ctx->configs[win].type = decon_win_types[tmp];

		ret = exynos_plane_init(drm_dev, &ctx->planes[win],
				1 << ctx->pipe, type, decon_formats,
				ARRAY_SIZE(decon_formats), win);
					1 << ctx->pipe, &ctx->configs[win]);
		if (ret)
			return ret;
	}
@@ -581,6 +576,44 @@ static irqreturn_t decon_irq_handler(int irq, void *dev_id)
	return IRQ_HANDLED;
}

#ifdef CONFIG_PM
static int exynos5433_decon_suspend(struct device *dev)
{
	struct decon_context *ctx = dev_get_drvdata(dev);
	int i;

	for (i = 0; i < ARRAY_SIZE(decon_clks_name); i++)
		clk_disable_unprepare(ctx->clks[i]);

	return 0;
}

static int exynos5433_decon_resume(struct device *dev)
{
	struct decon_context *ctx = dev_get_drvdata(dev);
	int i, ret;

	for (i = 0; i < ARRAY_SIZE(decon_clks_name); i++) {
		ret = clk_prepare_enable(ctx->clks[i]);
		if (ret < 0)
			goto err;
	}

	return 0;

err:
	while (--i >= 0)
		clk_disable_unprepare(ctx->clks[i]);

	return ret;
}
#endif

static const struct dev_pm_ops exynos5433_decon_pm_ops = {
	SET_RUNTIME_PM_OPS(exynos5433_decon_suspend, exynos5433_decon_resume,
			   NULL)
};

static const struct of_device_id exynos5433_decon_driver_dt_match[] = {
	{
		.compatible = "samsung,exynos5433-decon",
@@ -684,6 +717,7 @@ struct platform_driver exynos5433_decon_driver = {
	.remove		= exynos5433_decon_remove,
	.driver		= {
		.name	= "exynos5433-decon",
		.pm	= &exynos5433_decon_pm_ops,
		.of_match_table = exynos5433_decon_driver_dt_match,
	},
};
Loading