Commit 3ff8e509 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

Summary:
- Clean up HDMI and MIXER parts
- Clean up legacy structures specific to Exynos DRM
  . This patch series removes existing exyons_drm_display and
    exynos_drm_encoder structures specific to Exynos DRM, and
    makes them to replace with common drm_encoder structure.
    With cleanup patch, we removes exynos_drm_encoder module.
- Clean up gem, dmabuf and buffer modules
  . This patch series replaces existing Exynos DRM dmabuf codes
    with common drm prime ones, and embeds all codes of exynos_drm_buf
    into exynos_drm_gem module.
    With cleanup patch, we removes exynos_drm_buf and exynos_drm_dmabuf
    modules.
- And some fixups.

* 'exynos-drm-next' of git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos: (53 commits)
  drm/exynos: merge exynos_drm_buf.c to exynos_drm_gem.c
  drm/exynos: use prime helpers
  drm/exynos: remove function roundup_gem_size
  drm/exynos: remove function update_vm_cache_attr
  drm/exynos: remove function check_gem_flags
  drm/exynos: use ERR_PTR instead of NULL in exynos_drm_gem_init
  drm/exynos: remove unused fields of struct exynos_drm_gem_buf
  drm/exynos: stop copying sg table
  drm/exynos: remove function exynos_drm_gem_map_buf
  drm/exynos: remove mutex locking in pagefault handler
  drm/exynos: remove function convert_to_vm_err_msg
  drm/exynos: stop using sgtable in page fault handler
  drm/exynos: remove struct exynos_drm_encoder layer
  drm/exynos: fold encoder setup into exynos_drm_load()
  drm/exynos: remove exynos_drm_create_enc_conn()
  drm/exynos: remove exynos_encoder's .commit() op
  drm/exynos: remove extra call to exynos_dp_commit()
  drm/exynos: remove extra call to hdmi_commit()
  drm/exynos: remove struct exynos_drm_display
  drm/exynos: simplify calculation of possible CRTCs
  ...
parents 3be66711 2a8cb489
Loading
Loading
Loading
Loading
+3 −4
Original line number Diff line number Diff line
@@ -3,10 +3,9 @@
# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.

ccflags-y := -Iinclude/drm -Idrivers/gpu/drm/exynos
exynosdrm-y := exynos_drm_drv.o exynos_drm_encoder.o \
		exynos_drm_crtc.o exynos_drm_fbdev.o exynos_drm_fb.o \
		exynos_drm_buf.o exynos_drm_gem.o exynos_drm_core.o \
		exynos_drm_plane.o exynos_drm_dmabuf.o
exynosdrm-y := exynos_drm_drv.o exynos_drm_crtc.o exynos_drm_fbdev.o \
		exynos_drm_fb.o exynos_drm_gem.o exynos_drm_core.o \
		exynos_drm_plane.o

exynosdrm-$(CONFIG_DRM_EXYNOS_IOMMU) += exynos_drm_iommu.o
exynosdrm-$(CONFIG_DRM_EXYNOS_FIMD)	+= exynos_drm_fimd.o
+30 −35
Original line number Diff line number Diff line
@@ -152,15 +152,15 @@ static void decon_commit(struct exynos_drm_crtc *crtc)
#define OFFSIZE(x)		(((x) & 0x3fff) << 14)
#define PAGEWIDTH(x)		((x) & 0x3fff)

static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win)
static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win,
				 struct drm_framebuffer *fb)
{
	struct exynos_drm_plane *plane = &ctx->planes[win];
	unsigned long val;

	val = readl(ctx->addr + DECON_WINCONx(win));
	val &= ~WINCONx_BPPMODE_MASK;

	switch (plane->pixel_format) {
	switch (fb->pixel_format) {
	case DRM_FORMAT_XRGB1555:
		val |= WINCONx_BPPMODE_16BPP_I1555;
		val |= WINCONx_HAWSWP_F;
@@ -186,7 +186,7 @@ static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win)
		return;
	}

	DRM_DEBUG_KMS("bpp = %u\n", plane->bpp);
	DRM_DEBUG_KMS("bpp = %u\n", fb->bits_per_pixel);

	/*
	 * In case of exynos, setting dma-burst to 16Word causes permanent
@@ -196,7 +196,7 @@ static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win)
	 * movement causes unstable DMA which results into iommu crash/tear.
	 */

	if (plane->fb_width < MIN_FB_WIDTH_FOR_16WORD_BURST) {
	if (fb->width < MIN_FB_WIDTH_FOR_16WORD_BURST) {
		val &= ~WINCONx_BURSTLEN_MASK;
		val |= WINCONx_BURSTLEN_8WORD;
	}
@@ -219,17 +219,16 @@ static void decon_shadow_protect_win(struct decon_context *ctx, int win,
	writel(val, ctx->addr + DECON_SHADOWCON);
}

static void decon_win_commit(struct exynos_drm_crtc *crtc, unsigned int win)
static void decon_update_plane(struct exynos_drm_crtc *crtc,
			       struct exynos_drm_plane *plane)
{
	struct decon_context *ctx = crtc->ctx;
	struct exynos_drm_plane *plane;
	struct drm_plane_state *state = plane->base.state;
	unsigned int win = plane->zpos;
	unsigned int bpp = state->fb->bits_per_pixel >> 3;
	unsigned int pitch = state->fb->pitches[0];
	u32 val;

	if (win < 0 || win >= WINDOWS_NR)
		return;

	plane = &ctx->planes[win];

	if (ctx->suspended)
		return;

@@ -238,8 +237,8 @@ static void decon_win_commit(struct exynos_drm_crtc *crtc, unsigned int win)
	val = COORDINATE_X(plane->crtc_x) | COORDINATE_Y(plane->crtc_y);
	writel(val, ctx->addr + DECON_VIDOSDxA(win));

	val = COORDINATE_X(plane->crtc_x + plane->crtc_width - 1) |
		COORDINATE_Y(plane->crtc_y + plane->crtc_height - 1);
	val = COORDINATE_X(plane->crtc_x + plane->crtc_w - 1) |
		COORDINATE_Y(plane->crtc_y + plane->crtc_h - 1);
	writel(val, ctx->addr + DECON_VIDOSDxB(win));

	val = VIDOSD_Wx_ALPHA_R_F(0x0) | VIDOSD_Wx_ALPHA_G_F(0x0) |
@@ -252,14 +251,14 @@ static void decon_win_commit(struct exynos_drm_crtc *crtc, unsigned int win)

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

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

	val = OFFSIZE(plane->pitch - plane->crtc_width * (plane->bpp >> 3))
		| PAGEWIDTH(plane->crtc_width * (plane->bpp >> 3));
	val = OFFSIZE(pitch - plane->crtc_w * bpp)
		| PAGEWIDTH(plane->crtc_w * bpp);
	writel(val, ctx->addr + DECON_VIDW0xADD2(win));

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

	/* window enable */
	val = readl(ctx->addr + DECON_WINCONx(win));
@@ -277,17 +276,13 @@ static void decon_win_commit(struct exynos_drm_crtc *crtc, unsigned int win)
		atomic_set(&ctx->win_updated, 1);
}

static void decon_win_disable(struct exynos_drm_crtc *crtc, unsigned int win)
static void decon_disable_plane(struct exynos_drm_crtc *crtc,
				struct exynos_drm_plane *plane)
{
	struct decon_context *ctx = crtc->ctx;
	struct exynos_drm_plane *plane;
	unsigned int win = plane->zpos;
	u32 val;

	if (win < 0 || win >= WINDOWS_NR)
		return;

	plane = &ctx->planes[win];

	if (ctx->suspended)
		return;

@@ -378,7 +373,7 @@ static void decon_disable(struct exynos_drm_crtc *crtc)
	 * a destroyed buffer later.
	 */
	for (i = 0; i < WINDOWS_NR; i++)
		decon_win_disable(crtc, i);
		decon_disable_plane(crtc, &ctx->planes[i]);

	decon_swreset(ctx);

@@ -407,7 +402,7 @@ void decon_te_irq_handler(struct exynos_drm_crtc *crtc)
		writel(val, ctx->addr + DECON_TRIGCON);
	}

	drm_handle_vblank(ctx->drm_dev, ctx->pipe);
	drm_crtc_handle_vblank(&ctx->crtc->base);
}

static void decon_clear_channels(struct exynos_drm_crtc *crtc)
@@ -460,10 +455,9 @@ static struct exynos_drm_crtc_ops decon_crtc_ops = {
	.enable_vblank		= decon_enable_vblank,
	.disable_vblank		= decon_disable_vblank,
	.commit			= decon_commit,
	.win_commit		= decon_win_commit,
	.win_disable		= decon_win_disable,
	.update_plane		= decon_update_plane,
	.disable_plane		= decon_disable_plane,
	.te_handler		= decon_te_irq_handler,
	.clear_channels		= decon_clear_channels,
};

static int decon_bind(struct device *dev, struct device *master, void *data)
@@ -497,7 +491,9 @@ static int decon_bind(struct device *dev, struct device *master, void *data)
		goto err;
	}

	ret = drm_iommu_attach_device_if_possible(ctx->crtc, drm_dev, dev);
	decon_clear_channels(ctx->crtc);

	ret = drm_iommu_attach_device(drm_dev, dev);
	if (ret)
		goto err;

@@ -514,7 +510,6 @@ static void decon_unbind(struct device *dev, struct device *master, void *data)
	decon_disable(ctx->crtc);

	/* detach this sub driver from iommu mapping if supported. */
	if (is_drm_iommu_supported(ctx->drm_dev))
	drm_iommu_detach_device(ctx->drm_dev, ctx->dev);
}

@@ -533,7 +528,7 @@ static irqreturn_t decon_vsync_irq_handler(int irq, void *dev_id)

	val = readl(ctx->addr + DECON_VIDINTCON1);
	if (val & VIDINTCON1_INTFRMPEND) {
		drm_handle_vblank(ctx->drm_dev, ctx->pipe);
		drm_crtc_handle_vblank(&ctx->crtc->base);

		/* clear */
		writel(VIDINTCON1_INTFRMPEND, ctx->addr + DECON_VIDINTCON1);
@@ -553,7 +548,7 @@ static irqreturn_t decon_lcd_sys_irq_handler(int irq, void *dev_id)

	val = readl(ctx->addr + DECON_VIDINTCON1);
	if (val & VIDINTCON1_INTFRMDONEPEND) {
		exynos_drm_crtc_finish_pageflip(ctx->drm_dev, ctx->pipe);
		exynos_drm_crtc_finish_pageflip(ctx->crtc);

		/* clear */
		writel(VIDINTCON1_INTFRMDONEPEND,
+43 −51
Original line number Diff line number Diff line
@@ -61,7 +61,7 @@ struct decon_context {
	atomic_t			wait_vsync_event;

	struct exynos_drm_panel_info panel;
	struct exynos_drm_display *display;
	struct drm_encoder *encoder;
};

static const struct of_device_id decon_driver_dt_match[] = {
@@ -126,7 +126,9 @@ static int decon_ctx_initialize(struct decon_context *ctx,
	ctx->drm_dev = drm_dev;
	ctx->pipe = priv->pipe++;

	ret = drm_iommu_attach_device_if_possible(ctx->crtc, drm_dev, ctx->dev);
	decon_clear_channels(ctx->crtc);

	ret = drm_iommu_attach_device(drm_dev, ctx->dev);
	if (ret)
		priv->pipe--;

@@ -136,7 +138,6 @@ static int decon_ctx_initialize(struct decon_context *ctx,
static void decon_ctx_remove(struct decon_context *ctx)
{
	/* detach this sub driver from iommu mapping if supported. */
	if (is_drm_iommu_supported(ctx->drm_dev))
	drm_iommu_detach_device(ctx->drm_dev, ctx->dev);
}

@@ -271,16 +272,16 @@ static void decon_disable_vblank(struct exynos_drm_crtc *crtc)
	}
}

static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win)
static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win,
				 struct drm_framebuffer *fb)
{
	struct exynos_drm_plane *plane = &ctx->planes[win];
	unsigned long val;
	int padding;

	val = readl(ctx->regs + WINCON(win));
	val &= ~WINCONx_BPPMODE_MASK;

	switch (plane->pixel_format) {
	switch (fb->pixel_format) {
	case DRM_FORMAT_RGB565:
		val |= WINCONx_BPPMODE_16BPP_565;
		val |= WINCONx_BURSTLEN_16WORD;
@@ -329,7 +330,7 @@ static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win)
		break;
	}

	DRM_DEBUG_KMS("bpp = %d\n", plane->bpp);
	DRM_DEBUG_KMS("bpp = %d\n", fb->bits_per_pixel);

	/*
	 * In case of exynos, setting dma-burst to 16Word causes permanent
@@ -339,8 +340,8 @@ static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win)
	 * movement causes unstable DMA which results into iommu crash/tear.
	 */

	padding = (plane->pitch / (plane->bpp >> 3)) - plane->fb_width;
	if (plane->fb_width + padding < MIN_FB_WIDTH_FOR_16WORD_BURST) {
	padding = (fb->pitches[0] / (fb->bits_per_pixel >> 3)) - fb->width;
	if (fb->width + padding < MIN_FB_WIDTH_FOR_16WORD_BURST) {
		val &= ~WINCONx_BURSTLEN_MASK;
		val |= WINCONx_BURSTLEN_8WORD;
	}
@@ -382,23 +383,19 @@ static void decon_shadow_protect_win(struct decon_context *ctx,
	writel(val, ctx->regs + SHADOWCON);
}

static void decon_win_commit(struct exynos_drm_crtc *crtc, unsigned int win)
static void decon_update_plane(struct exynos_drm_crtc *crtc,
			       struct exynos_drm_plane *plane)
{
	struct decon_context *ctx = crtc->ctx;
	struct drm_display_mode *mode = &crtc->base.state->adjusted_mode;
	struct exynos_drm_plane *plane;
	struct drm_plane_state *state = plane->base.state;
	int padding;
	unsigned long val, alpha;
	unsigned int last_x;
	unsigned int last_y;

	if (ctx->suspended)
		return;

	if (win < 0 || win >= WINDOWS_NR)
		return;

	plane = &ctx->planes[win];
	unsigned int win = plane->zpos;
	unsigned int bpp = state->fb->bits_per_pixel >> 3;
	unsigned int pitch = state->fb->pitches[0];

	if (ctx->suspended)
		return;
@@ -420,11 +417,11 @@ static void decon_win_commit(struct exynos_drm_crtc *crtc, unsigned int win)
	val = (unsigned long)plane->dma_addr[0];
	writel(val, ctx->regs + VIDW_BUF_START(win));

	padding = (plane->pitch / (plane->bpp >> 3)) - plane->fb_width;
	padding = (pitch / bpp) - state->fb->width;

	/* buffer size */
	writel(plane->fb_width + padding, ctx->regs + VIDW_WHOLE_X(win));
	writel(plane->fb_height, ctx->regs + VIDW_WHOLE_Y(win));
	writel(state->fb->width + padding, ctx->regs + VIDW_WHOLE_X(win));
	writel(state->fb->height, ctx->regs + VIDW_WHOLE_Y(win));

	/* offset from the start of the buffer to read */
	writel(plane->src_x, ctx->regs + VIDW_OFFSET_X(win));
@@ -433,25 +430,25 @@ static void decon_win_commit(struct exynos_drm_crtc *crtc, unsigned int win)
	DRM_DEBUG_KMS("start addr = 0x%lx\n",
			(unsigned long)val);
	DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n",
			plane->crtc_width, plane->crtc_height);
			plane->crtc_w, plane->crtc_h);

	/*
	 * OSD position.
	 * In case the window layout goes of LCD layout, DECON fails.
	 */
	if ((plane->crtc_x + plane->crtc_width) > mode->hdisplay)
		plane->crtc_x = mode->hdisplay - plane->crtc_width;
	if ((plane->crtc_y + plane->crtc_height) > mode->vdisplay)
		plane->crtc_y = mode->vdisplay - plane->crtc_height;
	if ((plane->crtc_x + plane->crtc_w) > mode->hdisplay)
		plane->crtc_x = mode->hdisplay - plane->crtc_w;
	if ((plane->crtc_y + plane->crtc_h) > mode->vdisplay)
		plane->crtc_y = mode->vdisplay - plane->crtc_h;

	val = VIDOSDxA_TOPLEFT_X(plane->crtc_x) |
		VIDOSDxA_TOPLEFT_Y(plane->crtc_y);
	writel(val, ctx->regs + VIDOSD_A(win));

	last_x = plane->crtc_x + plane->crtc_width;
	last_x = plane->crtc_x + plane->crtc_w;
	if (last_x)
		last_x--;
	last_y = plane->crtc_y + plane->crtc_height;
	last_y = plane->crtc_y + plane->crtc_h;
	if (last_y)
		last_y--;

@@ -475,7 +472,7 @@ static void decon_win_commit(struct exynos_drm_crtc *crtc, unsigned int win)

	writel(alpha, ctx->regs + VIDOSD_D(win));

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

	/* hardware window 0 doesn't support color key. */
	if (win != 0)
@@ -495,17 +492,13 @@ static void decon_win_commit(struct exynos_drm_crtc *crtc, unsigned int win)
	writel(val, ctx->regs + DECON_UPDATE);
}

static void decon_win_disable(struct exynos_drm_crtc *crtc, unsigned int win)
static void decon_disable_plane(struct exynos_drm_crtc *crtc,
				struct exynos_drm_plane *plane)
{
	struct decon_context *ctx = crtc->ctx;
	struct exynos_drm_plane *plane;
	unsigned int win = plane->zpos;
	u32 val;

	if (win < 0 || win >= WINDOWS_NR)
		return;

	plane = &ctx->planes[win];

	if (ctx->suspended)
		return;

@@ -601,7 +594,7 @@ static void decon_disable(struct exynos_drm_crtc *crtc)
	 * a destroyed buffer later.
	 */
	for (i = 0; i < WINDOWS_NR; i++)
		decon_win_disable(crtc, i);
		decon_disable_plane(crtc, &ctx->planes[i]);

	clk_disable_unprepare(ctx->vclk);
	clk_disable_unprepare(ctx->eclk);
@@ -621,9 +614,8 @@ static const struct exynos_drm_crtc_ops decon_crtc_ops = {
	.enable_vblank = decon_enable_vblank,
	.disable_vblank = decon_disable_vblank,
	.wait_for_vblank = decon_wait_for_vblank,
	.win_commit = decon_win_commit,
	.win_disable = decon_win_disable,
	.clear_channels = decon_clear_channels,
	.update_plane = decon_update_plane,
	.disable_plane = decon_disable_plane,
};


@@ -643,8 +635,8 @@ static irqreturn_t decon_irq_handler(int irq, void *dev_id)
		goto out;

	if (!ctx->i80_if) {
		drm_handle_vblank(ctx->drm_dev, ctx->pipe);
		exynos_drm_crtc_finish_pageflip(ctx->drm_dev, ctx->pipe);
		drm_crtc_handle_vblank(&ctx->crtc->base);
		exynos_drm_crtc_finish_pageflip(ctx->crtc);

		/* set wait vsync event to zero and wake up queue. */
		if (atomic_read(&ctx->wait_vsync_event)) {
@@ -689,8 +681,8 @@ static int decon_bind(struct device *dev, struct device *master, void *data)
		return PTR_ERR(ctx->crtc);
	}

	if (ctx->display)
		exynos_drm_create_enc_conn(drm_dev, ctx->display);
	if (ctx->encoder)
		exynos_dpi_bind(drm_dev, ctx->encoder);

	return 0;

@@ -703,8 +695,8 @@ static void decon_unbind(struct device *dev, struct device *master,

	decon_disable(ctx->crtc);

	if (ctx->display)
		exynos_dpi_remove(ctx->display);
	if (ctx->encoder)
		exynos_dpi_remove(ctx->encoder);

	decon_ctx_remove(ctx);
}
@@ -789,9 +781,9 @@ static int decon_probe(struct platform_device *pdev)

	platform_set_drvdata(pdev, ctx);

	ctx->display = exynos_dpi_probe(dev);
	if (IS_ERR(ctx->display)) {
		ret = PTR_ERR(ctx->display);
	ctx->encoder = exynos_dpi_probe(dev);
	if (IS_ERR(ctx->encoder)) {
		ret = PTR_ERR(ctx->encoder);
		goto err_iounmap;
	}

+67 −56
Original line number Diff line number Diff line
@@ -32,19 +32,20 @@
#include <drm/drm_panel.h>

#include "exynos_dp_core.h"
#include "exynos_drm_crtc.h"

#define ctx_from_connector(c)	container_of(c, struct exynos_dp_device, \
					connector)

static inline struct exynos_drm_crtc *dp_to_crtc(struct exynos_dp_device *dp)
{
	return to_exynos_crtc(dp->encoder->crtc);
	return to_exynos_crtc(dp->encoder.crtc);
}

static inline struct exynos_dp_device *
display_to_dp(struct exynos_drm_display *d)
static inline struct exynos_dp_device *encoder_to_dp(
						struct drm_encoder *e)
{
	return container_of(d, struct exynos_dp_device, display);
	return container_of(e, struct exynos_dp_device, encoder);
}

struct bridge_init {
@@ -795,9 +796,6 @@ static int exynos_dp_config_video(struct exynos_dp_device *dp)
	/* Configure video slave mode */
	exynos_dp_enable_video_master(dp, 0);

	/* Enable video */
	exynos_dp_start_video(dp);

	timeout_loop = 0;

	for (;;) {
@@ -891,9 +889,9 @@ static void exynos_dp_hotplug(struct work_struct *work)
		drm_helper_hpd_irq_event(dp->drm_dev);
}

static void exynos_dp_commit(struct exynos_drm_display *display)
static void exynos_dp_commit(struct drm_encoder *encoder)
{
	struct exynos_dp_device *dp = display_to_dp(display);
	struct exynos_dp_device *dp = encoder_to_dp(encoder);
	int ret;

	/* Keep the panel disabled while we configure video */
@@ -938,6 +936,9 @@ static void exynos_dp_commit(struct exynos_drm_display *display)
		if (drm_panel_enable(dp->panel))
			DRM_ERROR("failed to enable the panel\n");
	}

	/* Enable video */
	exynos_dp_start_video(dp);
}

static enum drm_connector_status exynos_dp_detect(
@@ -994,7 +995,7 @@ static struct drm_encoder *exynos_dp_best_encoder(
{
	struct exynos_dp_device *dp = ctx_from_connector(connector);

	return dp->encoder;
	return &dp->encoder;
}

static struct drm_connector_helper_funcs exynos_dp_connector_helper_funcs = {
@@ -1019,15 +1020,12 @@ static int exynos_drm_attach_lcd_bridge(struct exynos_dp_device *dp,
	return 0;
}

static int exynos_dp_create_connector(struct exynos_drm_display *display,
				struct drm_encoder *encoder)
static int exynos_dp_create_connector(struct drm_encoder *encoder)
{
	struct exynos_dp_device *dp = display_to_dp(display);
	struct exynos_dp_device *dp = encoder_to_dp(encoder);
	struct drm_connector *connector = &dp->connector;
	int ret;

	dp->encoder = encoder;

	/* Pre-empt DP connector creation if there's a bridge */
	if (dp->bridge) {
		ret = exynos_drm_attach_lcd_bridge(dp, encoder);
@@ -1054,20 +1052,22 @@ static int exynos_dp_create_connector(struct exynos_drm_display *display,
	return ret;
}

static void exynos_dp_phy_init(struct exynos_dp_device *dp)
static bool exynos_dp_mode_fixup(struct drm_encoder *encoder,
				 const struct drm_display_mode *mode,
				 struct drm_display_mode *adjusted_mode)
{
	if (dp->phy)
		phy_power_on(dp->phy);
	return true;
}

static void exynos_dp_phy_exit(struct exynos_dp_device *dp)
static void exynos_dp_mode_set(struct drm_encoder *encoder,
			       struct drm_display_mode *mode,
			       struct drm_display_mode *adjusted_mode)
{
	if (dp->phy)
		phy_power_off(dp->phy);
}

static void exynos_dp_poweron(struct exynos_dp_device *dp)
static void exynos_dp_enable(struct drm_encoder *encoder)
{
	struct exynos_dp_device *dp = encoder_to_dp(encoder);
	struct exynos_drm_crtc *crtc = dp_to_crtc(dp);

	if (dp->dpms_mode == DRM_MODE_DPMS_ON)
@@ -1084,14 +1084,17 @@ static void exynos_dp_poweron(struct exynos_dp_device *dp)
		crtc->ops->clock_enable(dp_to_crtc(dp), true);

	clk_prepare_enable(dp->clock);
	exynos_dp_phy_init(dp);
	phy_power_on(dp->phy);
	exynos_dp_init_dp(dp);
	enable_irq(dp->irq);
	exynos_dp_commit(&dp->display);
	exynos_dp_commit(&dp->encoder);

	dp->dpms_mode = DRM_MODE_DPMS_ON;
}

static void exynos_dp_poweroff(struct exynos_dp_device *dp)
static void exynos_dp_disable(struct drm_encoder *encoder)
{
	struct exynos_dp_device *dp = encoder_to_dp(encoder);
	struct exynos_drm_crtc *crtc = dp_to_crtc(dp);

	if (dp->dpms_mode != DRM_MODE_DPMS_ON)
@@ -1106,7 +1109,7 @@ static void exynos_dp_poweroff(struct exynos_dp_device *dp)

	disable_irq(dp->irq);
	flush_work(&dp->hotplug_work);
	exynos_dp_phy_exit(dp);
	phy_power_off(dp->phy);
	clk_disable_unprepare(dp->clock);

	if (crtc->ops->clock_enable)
@@ -1116,31 +1119,19 @@ static void exynos_dp_poweroff(struct exynos_dp_device *dp)
		if (drm_panel_unprepare(dp->panel))
			DRM_ERROR("failed to turnoff the panel\n");
	}
}

static void exynos_dp_dpms(struct exynos_drm_display *display, int mode)
{
	struct exynos_dp_device *dp = display_to_dp(display);

	switch (mode) {
	case DRM_MODE_DPMS_ON:
		exynos_dp_poweron(dp);
		break;
	case DRM_MODE_DPMS_STANDBY:
	case DRM_MODE_DPMS_SUSPEND:
	case DRM_MODE_DPMS_OFF:
		exynos_dp_poweroff(dp);
		break;
	default:
		break;
	}
	dp->dpms_mode = mode;
	dp->dpms_mode = DRM_MODE_DPMS_OFF;
}

static struct exynos_drm_display_ops exynos_dp_display_ops = {
	.create_connector = exynos_dp_create_connector,
	.dpms = exynos_dp_dpms,
	.commit = exynos_dp_commit,
static struct drm_encoder_helper_funcs exynos_dp_encoder_helper_funcs = {
	.mode_fixup = exynos_dp_mode_fixup,
	.mode_set = exynos_dp_mode_set,
	.enable = exynos_dp_enable,
	.disable = exynos_dp_disable,
};

static struct drm_encoder_funcs exynos_dp_encoder_funcs = {
	.destroy = drm_encoder_cleanup,
};

static struct video_info *exynos_dp_dt_parse_pdata(struct device *dev)
@@ -1219,9 +1210,10 @@ static int exynos_dp_bind(struct device *dev, struct device *master, void *data)
	struct exynos_dp_device *dp = dev_get_drvdata(dev);
	struct platform_device *pdev = to_platform_device(dev);
	struct drm_device *drm_dev = data;
	struct drm_encoder *encoder = &dp->encoder;
	struct resource *res;
	unsigned int irq_flags;
	int ret = 0;
	int pipe, ret = 0;

	dp->dev = &pdev->dev;
	dp->dpms_mode = DRM_MODE_DPMS_OFF;
@@ -1297,7 +1289,7 @@ static int exynos_dp_bind(struct device *dev, struct device *master, void *data)

	INIT_WORK(&dp->hotplug_work, exynos_dp_hotplug);

	exynos_dp_phy_init(dp);
	phy_power_on(dp->phy);

	exynos_dp_init_dp(dp);

@@ -1311,7 +1303,28 @@ static int exynos_dp_bind(struct device *dev, struct device *master, void *data)

	dp->drm_dev = drm_dev;

	return exynos_drm_create_enc_conn(drm_dev, &dp->display);
	pipe = exynos_drm_crtc_get_pipe_from_type(drm_dev,
						  EXYNOS_DISPLAY_TYPE_LCD);
	if (pipe < 0)
		return pipe;

	encoder->possible_crtcs = 1 << pipe;

	DRM_DEBUG_KMS("possible_crtcs = 0x%x\n", encoder->possible_crtcs);

	drm_encoder_init(drm_dev, encoder, &exynos_dp_encoder_funcs,
			 DRM_MODE_ENCODER_TMDS);

	drm_encoder_helper_add(encoder, &exynos_dp_encoder_helper_funcs);

	ret = exynos_dp_create_connector(encoder);
	if (ret) {
		DRM_ERROR("failed to create connector ret = %d\n", ret);
		drm_encoder_cleanup(encoder);
		return ret;
	}

	return 0;
}

static void exynos_dp_unbind(struct device *dev, struct device *master,
@@ -1319,7 +1332,7 @@ static void exynos_dp_unbind(struct device *dev, struct device *master,
{
	struct exynos_dp_device *dp = dev_get_drvdata(dev);

	exynos_dp_dpms(&dp->display, DRM_MODE_DPMS_OFF);
	exynos_dp_disable(&dp->encoder);
}

static const struct component_ops exynos_dp_ops = {
@@ -1338,8 +1351,6 @@ static int exynos_dp_probe(struct platform_device *pdev)
	if (!dp)
		return -ENOMEM;

	dp->display.type = EXYNOS_DISPLAY_TYPE_LCD;
	dp->display.ops = &exynos_dp_display_ops;
	platform_set_drvdata(pdev, dp);

	panel_node = of_parse_phandle(dev->of_node, "panel", 0);
@@ -1377,7 +1388,7 @@ static int exynos_dp_suspend(struct device *dev)
{
	struct exynos_dp_device *dp = dev_get_drvdata(dev);

	exynos_dp_dpms(&dp->display, DRM_MODE_DPMS_OFF);
	exynos_dp_disable(&dp->encoder);
	return 0;
}

@@ -1385,7 +1396,7 @@ static int exynos_dp_resume(struct device *dev)
{
	struct exynos_dp_device *dp = dev_get_drvdata(dev);

	exynos_dp_dpms(&dp->display, DRM_MODE_DPMS_ON);
	exynos_dp_enable(&dp->encoder);
	return 0;
}
#endif
+1 −2
Original line number Diff line number Diff line
@@ -147,11 +147,10 @@ struct link_train {
};

struct exynos_dp_device {
	struct exynos_drm_display display;
	struct drm_encoder	encoder;
	struct device		*dev;
	struct drm_device	*drm_dev;
	struct drm_connector	connector;
	struct drm_encoder	*encoder;
	struct drm_panel	*panel;
	struct drm_bridge	*bridge;
	struct clk		*clock;
Loading