cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

exynos_drm_fimd.c (34873B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/* exynos_drm_fimd.c
      3 *
      4 * Copyright (C) 2011 Samsung Electronics Co.Ltd
      5 * Authors:
      6 *	Joonyoung Shim <jy0922.shim@samsung.com>
      7 *	Inki Dae <inki.dae@samsung.com>
      8 */
      9
     10#include <linux/clk.h>
     11#include <linux/component.h>
     12#include <linux/kernel.h>
     13#include <linux/mfd/syscon.h>
     14#include <linux/of.h>
     15#include <linux/of_device.h>
     16#include <linux/platform_device.h>
     17#include <linux/pm_runtime.h>
     18#include <linux/regmap.h>
     19
     20#include <video/of_display_timing.h>
     21#include <video/of_videomode.h>
     22#include <video/samsung_fimd.h>
     23
     24#include <drm/drm_fourcc.h>
     25#include <drm/drm_vblank.h>
     26#include <drm/exynos_drm.h>
     27
     28#include "exynos_drm_crtc.h"
     29#include "exynos_drm_drv.h"
     30#include "exynos_drm_fb.h"
     31#include "exynos_drm_plane.h"
     32
     33/*
     34 * FIMD stands for Fully Interactive Mobile Display and
     35 * as a display controller, it transfers contents drawn on memory
     36 * to a LCD Panel through Display Interfaces such as RGB or
     37 * CPU Interface.
     38 */
     39
     40#define MIN_FB_WIDTH_FOR_16WORD_BURST 128
     41
     42/* position control register for hardware window 0, 2 ~ 4.*/
     43#define VIDOSD_A(win)		(VIDOSD_BASE + 0x00 + (win) * 16)
     44#define VIDOSD_B(win)		(VIDOSD_BASE + 0x04 + (win) * 16)
     45/*
     46 * size control register for hardware windows 0 and alpha control register
     47 * for hardware windows 1 ~ 4
     48 */
     49#define VIDOSD_C(win)		(VIDOSD_BASE + 0x08 + (win) * 16)
     50/* size control register for hardware windows 1 ~ 2. */
     51#define VIDOSD_D(win)		(VIDOSD_BASE + 0x0C + (win) * 16)
     52
     53#define VIDWnALPHA0(win)	(VIDW_ALPHA + 0x00 + (win) * 8)
     54#define VIDWnALPHA1(win)	(VIDW_ALPHA + 0x04 + (win) * 8)
     55
     56#define VIDWx_BUF_START(win, buf)	(VIDW_BUF_START(buf) + (win) * 8)
     57#define VIDWx_BUF_START_S(win, buf)	(VIDW_BUF_START_S(buf) + (win) * 8)
     58#define VIDWx_BUF_END(win, buf)		(VIDW_BUF_END(buf) + (win) * 8)
     59#define VIDWx_BUF_SIZE(win, buf)	(VIDW_BUF_SIZE(buf) + (win) * 4)
     60
     61/* color key control register for hardware window 1 ~ 4. */
     62#define WKEYCON0_BASE(x)		((WKEYCON0 + 0x140) + ((x - 1) * 8))
     63/* color key value register for hardware window 1 ~ 4. */
     64#define WKEYCON1_BASE(x)		((WKEYCON1 + 0x140) + ((x - 1) * 8))
     65
     66/* I80 trigger control register */
     67#define TRIGCON				0x1A4
     68#define TRGMODE_ENABLE			(1 << 0)
     69#define SWTRGCMD_ENABLE			(1 << 1)
     70/* Exynos3250, 3472, 5260 5410, 5420 and 5422 only supported. */
     71#define HWTRGEN_ENABLE			(1 << 3)
     72#define HWTRGMASK_ENABLE		(1 << 4)
     73/* Exynos3250, 3472, 5260, 5420 and 5422 only supported. */
     74#define HWTRIGEN_PER_ENABLE		(1 << 31)
     75
     76/* display mode change control register except exynos4 */
     77#define VIDOUT_CON			0x000
     78#define VIDOUT_CON_F_I80_LDI0		(0x2 << 8)
     79
     80/* I80 interface control for main LDI register */
     81#define I80IFCONFAx(x)			(0x1B0 + (x) * 4)
     82#define I80IFCONFBx(x)			(0x1B8 + (x) * 4)
     83#define LCD_CS_SETUP(x)			((x) << 16)
     84#define LCD_WR_SETUP(x)			((x) << 12)
     85#define LCD_WR_ACTIVE(x)		((x) << 8)
     86#define LCD_WR_HOLD(x)			((x) << 4)
     87#define I80IFEN_ENABLE			(1 << 0)
     88
     89/* FIMD has totally five hardware windows. */
     90#define WINDOWS_NR	5
     91
     92/* HW trigger flag on i80 panel. */
     93#define I80_HW_TRG     (1 << 1)
     94
     95struct fimd_driver_data {
     96	unsigned int timing_base;
     97	unsigned int lcdblk_offset;
     98	unsigned int lcdblk_vt_shift;
     99	unsigned int lcdblk_bypass_shift;
    100	unsigned int lcdblk_mic_bypass_shift;
    101	unsigned int trg_type;
    102
    103	unsigned int has_shadowcon:1;
    104	unsigned int has_clksel:1;
    105	unsigned int has_limited_fmt:1;
    106	unsigned int has_vidoutcon:1;
    107	unsigned int has_vtsel:1;
    108	unsigned int has_mic_bypass:1;
    109	unsigned int has_dp_clk:1;
    110	unsigned int has_hw_trigger:1;
    111	unsigned int has_trigger_per_te:1;
    112	unsigned int has_bgr_support:1;
    113};
    114
    115static struct fimd_driver_data s3c64xx_fimd_driver_data = {
    116	.timing_base = 0x0,
    117	.has_clksel = 1,
    118	.has_limited_fmt = 1,
    119};
    120
    121static struct fimd_driver_data s5pv210_fimd_driver_data = {
    122	.timing_base = 0x0,
    123	.has_shadowcon = 1,
    124	.has_clksel = 1,
    125};
    126
    127static struct fimd_driver_data exynos3_fimd_driver_data = {
    128	.timing_base = 0x20000,
    129	.lcdblk_offset = 0x210,
    130	.lcdblk_bypass_shift = 1,
    131	.has_shadowcon = 1,
    132	.has_vidoutcon = 1,
    133};
    134
    135static struct fimd_driver_data exynos4_fimd_driver_data = {
    136	.timing_base = 0x0,
    137	.lcdblk_offset = 0x210,
    138	.lcdblk_vt_shift = 10,
    139	.lcdblk_bypass_shift = 1,
    140	.has_shadowcon = 1,
    141	.has_vtsel = 1,
    142	.has_bgr_support = 1,
    143};
    144
    145static struct fimd_driver_data exynos5_fimd_driver_data = {
    146	.timing_base = 0x20000,
    147	.lcdblk_offset = 0x214,
    148	.lcdblk_vt_shift = 24,
    149	.lcdblk_bypass_shift = 15,
    150	.has_shadowcon = 1,
    151	.has_vidoutcon = 1,
    152	.has_vtsel = 1,
    153	.has_dp_clk = 1,
    154	.has_bgr_support = 1,
    155};
    156
    157static struct fimd_driver_data exynos5420_fimd_driver_data = {
    158	.timing_base = 0x20000,
    159	.lcdblk_offset = 0x214,
    160	.lcdblk_vt_shift = 24,
    161	.lcdblk_bypass_shift = 15,
    162	.lcdblk_mic_bypass_shift = 11,
    163	.has_shadowcon = 1,
    164	.has_vidoutcon = 1,
    165	.has_vtsel = 1,
    166	.has_mic_bypass = 1,
    167	.has_dp_clk = 1,
    168	.has_bgr_support = 1,
    169};
    170
    171struct fimd_context {
    172	struct device			*dev;
    173	struct drm_device		*drm_dev;
    174	void				*dma_priv;
    175	struct exynos_drm_crtc		*crtc;
    176	struct exynos_drm_plane		planes[WINDOWS_NR];
    177	struct exynos_drm_plane_config	configs[WINDOWS_NR];
    178	struct clk			*bus_clk;
    179	struct clk			*lcd_clk;
    180	void __iomem			*regs;
    181	struct regmap			*sysreg;
    182	unsigned long			irq_flags;
    183	u32				vidcon0;
    184	u32				vidcon1;
    185	u32				vidout_con;
    186	u32				i80ifcon;
    187	bool				i80_if;
    188	bool				suspended;
    189	wait_queue_head_t		wait_vsync_queue;
    190	atomic_t			wait_vsync_event;
    191	atomic_t			win_updated;
    192	atomic_t			triggering;
    193	u32				clkdiv;
    194
    195	const struct fimd_driver_data *driver_data;
    196	struct drm_encoder *encoder;
    197	struct exynos_drm_clk		dp_clk;
    198};
    199
    200static const struct of_device_id fimd_driver_dt_match[] = {
    201	{ .compatible = "samsung,s3c6400-fimd",
    202	  .data = &s3c64xx_fimd_driver_data },
    203	{ .compatible = "samsung,s5pv210-fimd",
    204	  .data = &s5pv210_fimd_driver_data },
    205	{ .compatible = "samsung,exynos3250-fimd",
    206	  .data = &exynos3_fimd_driver_data },
    207	{ .compatible = "samsung,exynos4210-fimd",
    208	  .data = &exynos4_fimd_driver_data },
    209	{ .compatible = "samsung,exynos5250-fimd",
    210	  .data = &exynos5_fimd_driver_data },
    211	{ .compatible = "samsung,exynos5420-fimd",
    212	  .data = &exynos5420_fimd_driver_data },
    213	{},
    214};
    215MODULE_DEVICE_TABLE(of, fimd_driver_dt_match);
    216
    217static const enum drm_plane_type fimd_win_types[WINDOWS_NR] = {
    218	DRM_PLANE_TYPE_PRIMARY,
    219	DRM_PLANE_TYPE_OVERLAY,
    220	DRM_PLANE_TYPE_OVERLAY,
    221	DRM_PLANE_TYPE_OVERLAY,
    222	DRM_PLANE_TYPE_CURSOR,
    223};
    224
    225static const uint32_t fimd_formats[] = {
    226	DRM_FORMAT_C8,
    227	DRM_FORMAT_XRGB1555,
    228	DRM_FORMAT_RGB565,
    229	DRM_FORMAT_XRGB8888,
    230	DRM_FORMAT_ARGB8888,
    231};
    232
    233static const uint32_t fimd_extended_formats[] = {
    234	DRM_FORMAT_C8,
    235	DRM_FORMAT_XRGB1555,
    236	DRM_FORMAT_XBGR1555,
    237	DRM_FORMAT_RGB565,
    238	DRM_FORMAT_BGR565,
    239	DRM_FORMAT_XRGB8888,
    240	DRM_FORMAT_XBGR8888,
    241	DRM_FORMAT_ARGB8888,
    242	DRM_FORMAT_ABGR8888,
    243};
    244
    245static const unsigned int capabilities[WINDOWS_NR] = {
    246	0,
    247	EXYNOS_DRM_PLANE_CAP_WIN_BLEND | EXYNOS_DRM_PLANE_CAP_PIX_BLEND,
    248	EXYNOS_DRM_PLANE_CAP_WIN_BLEND | EXYNOS_DRM_PLANE_CAP_PIX_BLEND,
    249	EXYNOS_DRM_PLANE_CAP_WIN_BLEND | EXYNOS_DRM_PLANE_CAP_PIX_BLEND,
    250	EXYNOS_DRM_PLANE_CAP_WIN_BLEND | EXYNOS_DRM_PLANE_CAP_PIX_BLEND,
    251};
    252
    253static inline void fimd_set_bits(struct fimd_context *ctx, u32 reg, u32 mask,
    254				 u32 val)
    255{
    256	val = (val & mask) | (readl(ctx->regs + reg) & ~mask);
    257	writel(val, ctx->regs + reg);
    258}
    259
    260static int fimd_enable_vblank(struct exynos_drm_crtc *crtc)
    261{
    262	struct fimd_context *ctx = crtc->ctx;
    263	u32 val;
    264
    265	if (ctx->suspended)
    266		return -EPERM;
    267
    268	if (!test_and_set_bit(0, &ctx->irq_flags)) {
    269		val = readl(ctx->regs + VIDINTCON0);
    270
    271		val |= VIDINTCON0_INT_ENABLE;
    272
    273		if (ctx->i80_if) {
    274			val |= VIDINTCON0_INT_I80IFDONE;
    275			val |= VIDINTCON0_INT_SYSMAINCON;
    276			val &= ~VIDINTCON0_INT_SYSSUBCON;
    277		} else {
    278			val |= VIDINTCON0_INT_FRAME;
    279
    280			val &= ~VIDINTCON0_FRAMESEL0_MASK;
    281			val |= VIDINTCON0_FRAMESEL0_FRONTPORCH;
    282			val &= ~VIDINTCON0_FRAMESEL1_MASK;
    283			val |= VIDINTCON0_FRAMESEL1_NONE;
    284		}
    285
    286		writel(val, ctx->regs + VIDINTCON0);
    287	}
    288
    289	return 0;
    290}
    291
    292static void fimd_disable_vblank(struct exynos_drm_crtc *crtc)
    293{
    294	struct fimd_context *ctx = crtc->ctx;
    295	u32 val;
    296
    297	if (ctx->suspended)
    298		return;
    299
    300	if (test_and_clear_bit(0, &ctx->irq_flags)) {
    301		val = readl(ctx->regs + VIDINTCON0);
    302
    303		val &= ~VIDINTCON0_INT_ENABLE;
    304
    305		if (ctx->i80_if) {
    306			val &= ~VIDINTCON0_INT_I80IFDONE;
    307			val &= ~VIDINTCON0_INT_SYSMAINCON;
    308			val &= ~VIDINTCON0_INT_SYSSUBCON;
    309		} else
    310			val &= ~VIDINTCON0_INT_FRAME;
    311
    312		writel(val, ctx->regs + VIDINTCON0);
    313	}
    314}
    315
    316static void fimd_wait_for_vblank(struct exynos_drm_crtc *crtc)
    317{
    318	struct fimd_context *ctx = crtc->ctx;
    319
    320	if (ctx->suspended)
    321		return;
    322
    323	atomic_set(&ctx->wait_vsync_event, 1);
    324
    325	/*
    326	 * wait for FIMD to signal VSYNC interrupt or return after
    327	 * timeout which is set to 50ms (refresh rate of 20).
    328	 */
    329	if (!wait_event_timeout(ctx->wait_vsync_queue,
    330				!atomic_read(&ctx->wait_vsync_event),
    331				HZ/20))
    332		DRM_DEV_DEBUG_KMS(ctx->dev, "vblank wait timed out.\n");
    333}
    334
    335static void fimd_enable_video_output(struct fimd_context *ctx, unsigned int win,
    336					bool enable)
    337{
    338	u32 val = readl(ctx->regs + WINCON(win));
    339
    340	if (enable)
    341		val |= WINCONx_ENWIN;
    342	else
    343		val &= ~WINCONx_ENWIN;
    344
    345	writel(val, ctx->regs + WINCON(win));
    346}
    347
    348static void fimd_enable_shadow_channel_path(struct fimd_context *ctx,
    349						unsigned int win,
    350						bool enable)
    351{
    352	u32 val = readl(ctx->regs + SHADOWCON);
    353
    354	if (enable)
    355		val |= SHADOWCON_CHx_ENABLE(win);
    356	else
    357		val &= ~SHADOWCON_CHx_ENABLE(win);
    358
    359	writel(val, ctx->regs + SHADOWCON);
    360}
    361
    362static int fimd_clear_channels(struct exynos_drm_crtc *crtc)
    363{
    364	struct fimd_context *ctx = crtc->ctx;
    365	unsigned int win, ch_enabled = 0;
    366	int ret;
    367
    368	/* Hardware is in unknown state, so ensure it gets enabled properly */
    369	ret = pm_runtime_resume_and_get(ctx->dev);
    370	if (ret < 0) {
    371		dev_err(ctx->dev, "failed to enable FIMD device.\n");
    372		return ret;
    373	}
    374
    375	clk_prepare_enable(ctx->bus_clk);
    376	clk_prepare_enable(ctx->lcd_clk);
    377
    378	/* Check if any channel is enabled. */
    379	for (win = 0; win < WINDOWS_NR; win++) {
    380		u32 val = readl(ctx->regs + WINCON(win));
    381
    382		if (val & WINCONx_ENWIN) {
    383			fimd_enable_video_output(ctx, win, false);
    384
    385			if (ctx->driver_data->has_shadowcon)
    386				fimd_enable_shadow_channel_path(ctx, win,
    387								false);
    388
    389			ch_enabled = 1;
    390		}
    391	}
    392
    393	/* Wait for vsync, as disable channel takes effect at next vsync */
    394	if (ch_enabled) {
    395		ctx->suspended = false;
    396
    397		fimd_enable_vblank(ctx->crtc);
    398		fimd_wait_for_vblank(ctx->crtc);
    399		fimd_disable_vblank(ctx->crtc);
    400
    401		ctx->suspended = true;
    402	}
    403
    404	clk_disable_unprepare(ctx->lcd_clk);
    405	clk_disable_unprepare(ctx->bus_clk);
    406
    407	pm_runtime_put(ctx->dev);
    408
    409	return 0;
    410}
    411
    412
    413static int fimd_atomic_check(struct exynos_drm_crtc *crtc,
    414		struct drm_crtc_state *state)
    415{
    416	struct drm_display_mode *mode = &state->adjusted_mode;
    417	struct fimd_context *ctx = crtc->ctx;
    418	unsigned long ideal_clk, lcd_rate;
    419	u32 clkdiv;
    420
    421	if (mode->clock == 0) {
    422		DRM_DEV_ERROR(ctx->dev, "Mode has zero clock value.\n");
    423		return -EINVAL;
    424	}
    425
    426	ideal_clk = mode->clock * 1000;
    427
    428	if (ctx->i80_if) {
    429		/*
    430		 * The frame done interrupt should be occurred prior to the
    431		 * next TE signal.
    432		 */
    433		ideal_clk *= 2;
    434	}
    435
    436	lcd_rate = clk_get_rate(ctx->lcd_clk);
    437	if (2 * lcd_rate < ideal_clk) {
    438		DRM_DEV_ERROR(ctx->dev,
    439			      "sclk_fimd clock too low(%lu) for requested pixel clock(%lu)\n",
    440			      lcd_rate, ideal_clk);
    441		return -EINVAL;
    442	}
    443
    444	/* Find the clock divider value that gets us closest to ideal_clk */
    445	clkdiv = DIV_ROUND_CLOSEST(lcd_rate, ideal_clk);
    446	if (clkdiv >= 0x200) {
    447		DRM_DEV_ERROR(ctx->dev, "requested pixel clock(%lu) too low\n",
    448			      ideal_clk);
    449		return -EINVAL;
    450	}
    451
    452	ctx->clkdiv = (clkdiv < 0x100) ? clkdiv : 0xff;
    453
    454	return 0;
    455}
    456
    457static void fimd_setup_trigger(struct fimd_context *ctx)
    458{
    459	void __iomem *timing_base = ctx->regs + ctx->driver_data->timing_base;
    460	u32 trg_type = ctx->driver_data->trg_type;
    461	u32 val = readl(timing_base + TRIGCON);
    462
    463	val &= ~(TRGMODE_ENABLE);
    464
    465	if (trg_type == I80_HW_TRG) {
    466		if (ctx->driver_data->has_hw_trigger)
    467			val |= HWTRGEN_ENABLE | HWTRGMASK_ENABLE;
    468		if (ctx->driver_data->has_trigger_per_te)
    469			val |= HWTRIGEN_PER_ENABLE;
    470	} else {
    471		val |= TRGMODE_ENABLE;
    472	}
    473
    474	writel(val, timing_base + TRIGCON);
    475}
    476
    477static void fimd_commit(struct exynos_drm_crtc *crtc)
    478{
    479	struct fimd_context *ctx = crtc->ctx;
    480	struct drm_display_mode *mode = &crtc->base.state->adjusted_mode;
    481	const struct fimd_driver_data *driver_data = ctx->driver_data;
    482	void *timing_base = ctx->regs + driver_data->timing_base;
    483	u32 val;
    484
    485	if (ctx->suspended)
    486		return;
    487
    488	/* nothing to do if we haven't set the mode yet */
    489	if (mode->htotal == 0 || mode->vtotal == 0)
    490		return;
    491
    492	if (ctx->i80_if) {
    493		val = ctx->i80ifcon | I80IFEN_ENABLE;
    494		writel(val, timing_base + I80IFCONFAx(0));
    495
    496		/* disable auto frame rate */
    497		writel(0, timing_base + I80IFCONFBx(0));
    498
    499		/* set video type selection to I80 interface */
    500		if (driver_data->has_vtsel && ctx->sysreg &&
    501				regmap_update_bits(ctx->sysreg,
    502					driver_data->lcdblk_offset,
    503					0x3 << driver_data->lcdblk_vt_shift,
    504					0x1 << driver_data->lcdblk_vt_shift)) {
    505			DRM_DEV_ERROR(ctx->dev,
    506				      "Failed to update sysreg for I80 i/f.\n");
    507			return;
    508		}
    509	} else {
    510		int vsync_len, vbpd, vfpd, hsync_len, hbpd, hfpd;
    511		u32 vidcon1;
    512
    513		/* setup polarity values */
    514		vidcon1 = ctx->vidcon1;
    515		if (mode->flags & DRM_MODE_FLAG_NVSYNC)
    516			vidcon1 |= VIDCON1_INV_VSYNC;
    517		if (mode->flags & DRM_MODE_FLAG_NHSYNC)
    518			vidcon1 |= VIDCON1_INV_HSYNC;
    519		writel(vidcon1, ctx->regs + driver_data->timing_base + VIDCON1);
    520
    521		/* setup vertical timing values. */
    522		vsync_len = mode->crtc_vsync_end - mode->crtc_vsync_start;
    523		vbpd = mode->crtc_vtotal - mode->crtc_vsync_end;
    524		vfpd = mode->crtc_vsync_start - mode->crtc_vdisplay;
    525
    526		val = VIDTCON0_VBPD(vbpd - 1) |
    527			VIDTCON0_VFPD(vfpd - 1) |
    528			VIDTCON0_VSPW(vsync_len - 1);
    529		writel(val, ctx->regs + driver_data->timing_base + VIDTCON0);
    530
    531		/* setup horizontal timing values.  */
    532		hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start;
    533		hbpd = mode->crtc_htotal - mode->crtc_hsync_end;
    534		hfpd = mode->crtc_hsync_start - mode->crtc_hdisplay;
    535
    536		val = VIDTCON1_HBPD(hbpd - 1) |
    537			VIDTCON1_HFPD(hfpd - 1) |
    538			VIDTCON1_HSPW(hsync_len - 1);
    539		writel(val, ctx->regs + driver_data->timing_base + VIDTCON1);
    540	}
    541
    542	if (driver_data->has_vidoutcon)
    543		writel(ctx->vidout_con, timing_base + VIDOUT_CON);
    544
    545	/* set bypass selection */
    546	if (ctx->sysreg && regmap_update_bits(ctx->sysreg,
    547				driver_data->lcdblk_offset,
    548				0x1 << driver_data->lcdblk_bypass_shift,
    549				0x1 << driver_data->lcdblk_bypass_shift)) {
    550		DRM_DEV_ERROR(ctx->dev,
    551			      "Failed to update sysreg for bypass setting.\n");
    552		return;
    553	}
    554
    555	/* TODO: When MIC is enabled for display path, the lcdblk_mic_bypass
    556	 * bit should be cleared.
    557	 */
    558	if (driver_data->has_mic_bypass && ctx->sysreg &&
    559	    regmap_update_bits(ctx->sysreg,
    560				driver_data->lcdblk_offset,
    561				0x1 << driver_data->lcdblk_mic_bypass_shift,
    562				0x1 << driver_data->lcdblk_mic_bypass_shift)) {
    563		DRM_DEV_ERROR(ctx->dev,
    564			      "Failed to update sysreg for bypass mic.\n");
    565		return;
    566	}
    567
    568	/* setup horizontal and vertical display size. */
    569	val = VIDTCON2_LINEVAL(mode->vdisplay - 1) |
    570	       VIDTCON2_HOZVAL(mode->hdisplay - 1) |
    571	       VIDTCON2_LINEVAL_E(mode->vdisplay - 1) |
    572	       VIDTCON2_HOZVAL_E(mode->hdisplay - 1);
    573	writel(val, ctx->regs + driver_data->timing_base + VIDTCON2);
    574
    575	fimd_setup_trigger(ctx);
    576
    577	/*
    578	 * fields of register with prefix '_F' would be updated
    579	 * at vsync(same as dma start)
    580	 */
    581	val = ctx->vidcon0;
    582	val |= VIDCON0_ENVID | VIDCON0_ENVID_F;
    583
    584	if (ctx->driver_data->has_clksel)
    585		val |= VIDCON0_CLKSEL_LCD;
    586
    587	if (ctx->clkdiv > 1)
    588		val |= VIDCON0_CLKVAL_F(ctx->clkdiv - 1) | VIDCON0_CLKDIR;
    589
    590	writel(val, ctx->regs + VIDCON0);
    591}
    592
    593static void fimd_win_set_bldeq(struct fimd_context *ctx, unsigned int win,
    594			       unsigned int alpha, unsigned int pixel_alpha)
    595{
    596	u32 mask = BLENDEQ_A_FUNC_F(0xf) | BLENDEQ_B_FUNC_F(0xf);
    597	u32 val = 0;
    598
    599	switch (pixel_alpha) {
    600	case DRM_MODE_BLEND_PIXEL_NONE:
    601	case DRM_MODE_BLEND_COVERAGE:
    602		val |= BLENDEQ_A_FUNC_F(BLENDEQ_ALPHA_A);
    603		val |= BLENDEQ_B_FUNC_F(BLENDEQ_ONE_MINUS_ALPHA_A);
    604		break;
    605	case DRM_MODE_BLEND_PREMULTI:
    606	default:
    607		if (alpha != DRM_BLEND_ALPHA_OPAQUE) {
    608			val |= BLENDEQ_A_FUNC_F(BLENDEQ_ALPHA0);
    609			val |= BLENDEQ_B_FUNC_F(BLENDEQ_ONE_MINUS_ALPHA_A);
    610		} else {
    611			val |= BLENDEQ_A_FUNC_F(BLENDEQ_ONE);
    612			val |= BLENDEQ_B_FUNC_F(BLENDEQ_ONE_MINUS_ALPHA_A);
    613		}
    614		break;
    615	}
    616	fimd_set_bits(ctx, BLENDEQx(win), mask, val);
    617}
    618
    619static void fimd_win_set_bldmod(struct fimd_context *ctx, unsigned int win,
    620				unsigned int alpha, unsigned int pixel_alpha)
    621{
    622	u32 win_alpha_l = (alpha >> 8) & 0xf;
    623	u32 win_alpha_h = alpha >> 12;
    624	u32 val = 0;
    625
    626	switch (pixel_alpha) {
    627	case DRM_MODE_BLEND_PIXEL_NONE:
    628		break;
    629	case DRM_MODE_BLEND_COVERAGE:
    630	case DRM_MODE_BLEND_PREMULTI:
    631	default:
    632		val |= WINCON1_ALPHA_SEL;
    633		val |= WINCON1_BLD_PIX;
    634		val |= WINCON1_ALPHA_MUL;
    635		break;
    636	}
    637	fimd_set_bits(ctx, WINCON(win), WINCONx_BLEND_MODE_MASK, val);
    638
    639	/* OSD alpha */
    640	val = VIDISD14C_ALPHA0_R(win_alpha_h) |
    641		VIDISD14C_ALPHA0_G(win_alpha_h) |
    642		VIDISD14C_ALPHA0_B(win_alpha_h) |
    643		VIDISD14C_ALPHA1_R(0x0) |
    644		VIDISD14C_ALPHA1_G(0x0) |
    645		VIDISD14C_ALPHA1_B(0x0);
    646	writel(val, ctx->regs + VIDOSD_C(win));
    647
    648	val = VIDW_ALPHA_R(win_alpha_l) | VIDW_ALPHA_G(win_alpha_l) |
    649		VIDW_ALPHA_B(win_alpha_l);
    650	writel(val, ctx->regs + VIDWnALPHA0(win));
    651
    652	val = VIDW_ALPHA_R(0x0) | VIDW_ALPHA_G(0x0) |
    653		VIDW_ALPHA_B(0x0);
    654	writel(val, ctx->regs + VIDWnALPHA1(win));
    655
    656	fimd_set_bits(ctx, BLENDCON, BLENDCON_NEW_MASK,
    657			BLENDCON_NEW_8BIT_ALPHA_VALUE);
    658}
    659
    660static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win,
    661				struct drm_framebuffer *fb, int width)
    662{
    663	struct exynos_drm_plane plane = ctx->planes[win];
    664	struct exynos_drm_plane_state *state =
    665		to_exynos_plane_state(plane.base.state);
    666	uint32_t pixel_format = fb->format->format;
    667	unsigned int alpha = state->base.alpha;
    668	u32 val = WINCONx_ENWIN;
    669	unsigned int pixel_alpha;
    670
    671	if (fb->format->has_alpha)
    672		pixel_alpha = state->base.pixel_blend_mode;
    673	else
    674		pixel_alpha = DRM_MODE_BLEND_PIXEL_NONE;
    675
    676	/*
    677	 * In case of s3c64xx, window 0 doesn't support alpha channel.
    678	 * So the request format is ARGB8888 then change it to XRGB8888.
    679	 */
    680	if (ctx->driver_data->has_limited_fmt && !win) {
    681		if (pixel_format == DRM_FORMAT_ARGB8888)
    682			pixel_format = DRM_FORMAT_XRGB8888;
    683	}
    684
    685	switch (pixel_format) {
    686	case DRM_FORMAT_C8:
    687		val |= WINCON0_BPPMODE_8BPP_PALETTE;
    688		val |= WINCONx_BURSTLEN_8WORD;
    689		val |= WINCONx_BYTSWP;
    690		break;
    691	case DRM_FORMAT_XRGB1555:
    692	case DRM_FORMAT_XBGR1555:
    693		val |= WINCON0_BPPMODE_16BPP_1555;
    694		val |= WINCONx_HAWSWP;
    695		val |= WINCONx_BURSTLEN_16WORD;
    696		break;
    697	case DRM_FORMAT_RGB565:
    698	case DRM_FORMAT_BGR565:
    699		val |= WINCON0_BPPMODE_16BPP_565;
    700		val |= WINCONx_HAWSWP;
    701		val |= WINCONx_BURSTLEN_16WORD;
    702		break;
    703	case DRM_FORMAT_XRGB8888:
    704	case DRM_FORMAT_XBGR8888:
    705		val |= WINCON0_BPPMODE_24BPP_888;
    706		val |= WINCONx_WSWP;
    707		val |= WINCONx_BURSTLEN_16WORD;
    708		break;
    709	case DRM_FORMAT_ARGB8888:
    710	case DRM_FORMAT_ABGR8888:
    711	default:
    712		val |= WINCON1_BPPMODE_25BPP_A1888;
    713		val |= WINCONx_WSWP;
    714		val |= WINCONx_BURSTLEN_16WORD;
    715		break;
    716	}
    717
    718	switch (pixel_format) {
    719	case DRM_FORMAT_XBGR1555:
    720	case DRM_FORMAT_XBGR8888:
    721	case DRM_FORMAT_ABGR8888:
    722	case DRM_FORMAT_BGR565:
    723		writel(WIN_RGB_ORDER_REVERSE, ctx->regs + WIN_RGB_ORDER(win));
    724		break;
    725	default:
    726		writel(WIN_RGB_ORDER_FORWARD, ctx->regs + WIN_RGB_ORDER(win));
    727		break;
    728	}
    729
    730	/*
    731	 * Setting dma-burst to 16Word causes permanent tearing for very small
    732	 * buffers, e.g. cursor buffer. Burst Mode switching which based on
    733	 * plane size is not recommended as plane size varies alot towards the
    734	 * end of the screen and rapid movement causes unstable DMA, but it is
    735	 * still better to change dma-burst than displaying garbage.
    736	 */
    737
    738	if (width < MIN_FB_WIDTH_FOR_16WORD_BURST) {
    739		val &= ~WINCONx_BURSTLEN_MASK;
    740		val |= WINCONx_BURSTLEN_4WORD;
    741	}
    742	fimd_set_bits(ctx, WINCON(win), ~WINCONx_BLEND_MODE_MASK, val);
    743
    744	/* hardware window 0 doesn't support alpha channel. */
    745	if (win != 0) {
    746		fimd_win_set_bldmod(ctx, win, alpha, pixel_alpha);
    747		fimd_win_set_bldeq(ctx, win, alpha, pixel_alpha);
    748	}
    749}
    750
    751static void fimd_win_set_colkey(struct fimd_context *ctx, unsigned int win)
    752{
    753	unsigned int keycon0 = 0, keycon1 = 0;
    754
    755	keycon0 = ~(WxKEYCON0_KEYBL_EN | WxKEYCON0_KEYEN_F |
    756			WxKEYCON0_DIRCON) | WxKEYCON0_COMPKEY(0);
    757
    758	keycon1 = WxKEYCON1_COLVAL(0xffffffff);
    759
    760	writel(keycon0, ctx->regs + WKEYCON0_BASE(win));
    761	writel(keycon1, ctx->regs + WKEYCON1_BASE(win));
    762}
    763
    764/**
    765 * fimd_shadow_protect_win() - disable updating values from shadow registers at vsync
    766 *
    767 * @ctx: local driver data
    768 * @win: window to protect registers for
    769 * @protect: 1 to protect (disable updates)
    770 */
    771static void fimd_shadow_protect_win(struct fimd_context *ctx,
    772				    unsigned int win, bool protect)
    773{
    774	u32 reg, bits, val;
    775
    776	/*
    777	 * SHADOWCON/PRTCON register is used for enabling timing.
    778	 *
    779	 * for example, once only width value of a register is set,
    780	 * if the dma is started then fimd hardware could malfunction so
    781	 * with protect window setting, the register fields with prefix '_F'
    782	 * wouldn't be updated at vsync also but updated once unprotect window
    783	 * is set.
    784	 */
    785
    786	if (ctx->driver_data->has_shadowcon) {
    787		reg = SHADOWCON;
    788		bits = SHADOWCON_WINx_PROTECT(win);
    789	} else {
    790		reg = PRTCON;
    791		bits = PRTCON_PROTECT;
    792	}
    793
    794	val = readl(ctx->regs + reg);
    795	if (protect)
    796		val |= bits;
    797	else
    798		val &= ~bits;
    799	writel(val, ctx->regs + reg);
    800}
    801
    802static void fimd_atomic_begin(struct exynos_drm_crtc *crtc)
    803{
    804	struct fimd_context *ctx = crtc->ctx;
    805	int i;
    806
    807	if (ctx->suspended)
    808		return;
    809
    810	for (i = 0; i < WINDOWS_NR; i++)
    811		fimd_shadow_protect_win(ctx, i, true);
    812}
    813
    814static void fimd_atomic_flush(struct exynos_drm_crtc *crtc)
    815{
    816	struct fimd_context *ctx = crtc->ctx;
    817	int i;
    818
    819	if (ctx->suspended)
    820		return;
    821
    822	for (i = 0; i < WINDOWS_NR; i++)
    823		fimd_shadow_protect_win(ctx, i, false);
    824
    825	exynos_crtc_handle_event(crtc);
    826}
    827
    828static void fimd_update_plane(struct exynos_drm_crtc *crtc,
    829			      struct exynos_drm_plane *plane)
    830{
    831	struct exynos_drm_plane_state *state =
    832				to_exynos_plane_state(plane->base.state);
    833	struct fimd_context *ctx = crtc->ctx;
    834	struct drm_framebuffer *fb = state->base.fb;
    835	dma_addr_t dma_addr;
    836	unsigned long val, size, offset;
    837	unsigned int last_x, last_y, buf_offsize, line_size;
    838	unsigned int win = plane->index;
    839	unsigned int cpp = fb->format->cpp[0];
    840	unsigned int pitch = fb->pitches[0];
    841
    842	if (ctx->suspended)
    843		return;
    844
    845	offset = state->src.x * cpp;
    846	offset += state->src.y * pitch;
    847
    848	/* buffer start address */
    849	dma_addr = exynos_drm_fb_dma_addr(fb, 0) + offset;
    850	val = (unsigned long)dma_addr;
    851	writel(val, ctx->regs + VIDWx_BUF_START(win, 0));
    852
    853	/* buffer end address */
    854	size = pitch * state->crtc.h;
    855	val = (unsigned long)(dma_addr + size);
    856	writel(val, ctx->regs + VIDWx_BUF_END(win, 0));
    857
    858	DRM_DEV_DEBUG_KMS(ctx->dev,
    859			  "start addr = 0x%lx, end addr = 0x%lx, size = 0x%lx\n",
    860			  (unsigned long)dma_addr, val, size);
    861	DRM_DEV_DEBUG_KMS(ctx->dev, "ovl_width = %d, ovl_height = %d\n",
    862			  state->crtc.w, state->crtc.h);
    863
    864	/* buffer size */
    865	buf_offsize = pitch - (state->crtc.w * cpp);
    866	line_size = state->crtc.w * cpp;
    867	val = VIDW_BUF_SIZE_OFFSET(buf_offsize) |
    868		VIDW_BUF_SIZE_PAGEWIDTH(line_size) |
    869		VIDW_BUF_SIZE_OFFSET_E(buf_offsize) |
    870		VIDW_BUF_SIZE_PAGEWIDTH_E(line_size);
    871	writel(val, ctx->regs + VIDWx_BUF_SIZE(win, 0));
    872
    873	/* OSD position */
    874	val = VIDOSDxA_TOPLEFT_X(state->crtc.x) |
    875		VIDOSDxA_TOPLEFT_Y(state->crtc.y) |
    876		VIDOSDxA_TOPLEFT_X_E(state->crtc.x) |
    877		VIDOSDxA_TOPLEFT_Y_E(state->crtc.y);
    878	writel(val, ctx->regs + VIDOSD_A(win));
    879
    880	last_x = state->crtc.x + state->crtc.w;
    881	if (last_x)
    882		last_x--;
    883	last_y = state->crtc.y + state->crtc.h;
    884	if (last_y)
    885		last_y--;
    886
    887	val = VIDOSDxB_BOTRIGHT_X(last_x) | VIDOSDxB_BOTRIGHT_Y(last_y) |
    888		VIDOSDxB_BOTRIGHT_X_E(last_x) | VIDOSDxB_BOTRIGHT_Y_E(last_y);
    889
    890	writel(val, ctx->regs + VIDOSD_B(win));
    891
    892	DRM_DEV_DEBUG_KMS(ctx->dev,
    893			  "osd pos: tx = %d, ty = %d, bx = %d, by = %d\n",
    894			  state->crtc.x, state->crtc.y, last_x, last_y);
    895
    896	/* OSD size */
    897	if (win != 3 && win != 4) {
    898		u32 offset = VIDOSD_D(win);
    899		if (win == 0)
    900			offset = VIDOSD_C(win);
    901		val = state->crtc.w * state->crtc.h;
    902		writel(val, ctx->regs + offset);
    903
    904		DRM_DEV_DEBUG_KMS(ctx->dev, "osd size = 0x%x\n",
    905				  (unsigned int)val);
    906	}
    907
    908	fimd_win_set_pixfmt(ctx, win, fb, state->src.w);
    909
    910	/* hardware window 0 doesn't support color key. */
    911	if (win != 0)
    912		fimd_win_set_colkey(ctx, win);
    913
    914	fimd_enable_video_output(ctx, win, true);
    915
    916	if (ctx->driver_data->has_shadowcon)
    917		fimd_enable_shadow_channel_path(ctx, win, true);
    918
    919	if (ctx->i80_if)
    920		atomic_set(&ctx->win_updated, 1);
    921}
    922
    923static void fimd_disable_plane(struct exynos_drm_crtc *crtc,
    924			       struct exynos_drm_plane *plane)
    925{
    926	struct fimd_context *ctx = crtc->ctx;
    927	unsigned int win = plane->index;
    928
    929	if (ctx->suspended)
    930		return;
    931
    932	fimd_enable_video_output(ctx, win, false);
    933
    934	if (ctx->driver_data->has_shadowcon)
    935		fimd_enable_shadow_channel_path(ctx, win, false);
    936}
    937
    938static void fimd_atomic_enable(struct exynos_drm_crtc *crtc)
    939{
    940	struct fimd_context *ctx = crtc->ctx;
    941
    942	if (!ctx->suspended)
    943		return;
    944
    945	ctx->suspended = false;
    946
    947	if (pm_runtime_resume_and_get(ctx->dev) < 0) {
    948		dev_warn(ctx->dev, "failed to enable FIMD device.\n");
    949		return;
    950	}
    951
    952	/* if vblank was enabled status, enable it again. */
    953	if (test_and_clear_bit(0, &ctx->irq_flags))
    954		fimd_enable_vblank(ctx->crtc);
    955
    956	fimd_commit(ctx->crtc);
    957}
    958
    959static void fimd_atomic_disable(struct exynos_drm_crtc *crtc)
    960{
    961	struct fimd_context *ctx = crtc->ctx;
    962	int i;
    963
    964	if (ctx->suspended)
    965		return;
    966
    967	/*
    968	 * We need to make sure that all windows are disabled before we
    969	 * suspend that connector. Otherwise we might try to scan from
    970	 * a destroyed buffer later.
    971	 */
    972	for (i = 0; i < WINDOWS_NR; i++)
    973		fimd_disable_plane(crtc, &ctx->planes[i]);
    974
    975	fimd_enable_vblank(crtc);
    976	fimd_wait_for_vblank(crtc);
    977	fimd_disable_vblank(crtc);
    978
    979	writel(0, ctx->regs + VIDCON0);
    980
    981	pm_runtime_put_sync(ctx->dev);
    982	ctx->suspended = true;
    983}
    984
    985static void fimd_trigger(struct device *dev)
    986{
    987	struct fimd_context *ctx = dev_get_drvdata(dev);
    988	const struct fimd_driver_data *driver_data = ctx->driver_data;
    989	void *timing_base = ctx->regs + driver_data->timing_base;
    990	u32 reg;
    991
    992	 /*
    993	  * Skips triggering if in triggering state, because multiple triggering
    994	  * requests can cause panel reset.
    995	  */
    996	if (atomic_read(&ctx->triggering))
    997		return;
    998
    999	/* Enters triggering mode */
   1000	atomic_set(&ctx->triggering, 1);
   1001
   1002	reg = readl(timing_base + TRIGCON);
   1003	reg |= (TRGMODE_ENABLE | SWTRGCMD_ENABLE);
   1004	writel(reg, timing_base + TRIGCON);
   1005
   1006	/*
   1007	 * Exits triggering mode if vblank is not enabled yet, because when the
   1008	 * VIDINTCON0 register is not set, it can not exit from triggering mode.
   1009	 */
   1010	if (!test_bit(0, &ctx->irq_flags))
   1011		atomic_set(&ctx->triggering, 0);
   1012}
   1013
   1014static void fimd_te_handler(struct exynos_drm_crtc *crtc)
   1015{
   1016	struct fimd_context *ctx = crtc->ctx;
   1017	u32 trg_type = ctx->driver_data->trg_type;
   1018
   1019	/* Checks the crtc is detached already from encoder */
   1020	if (!ctx->drm_dev)
   1021		return;
   1022
   1023	if (trg_type == I80_HW_TRG)
   1024		goto out;
   1025
   1026	/*
   1027	 * If there is a page flip request, triggers and handles the page flip
   1028	 * event so that current fb can be updated into panel GRAM.
   1029	 */
   1030	if (atomic_add_unless(&ctx->win_updated, -1, 0))
   1031		fimd_trigger(ctx->dev);
   1032
   1033out:
   1034	/* Wakes up vsync event queue */
   1035	if (atomic_read(&ctx->wait_vsync_event)) {
   1036		atomic_set(&ctx->wait_vsync_event, 0);
   1037		wake_up(&ctx->wait_vsync_queue);
   1038	}
   1039
   1040	if (test_bit(0, &ctx->irq_flags))
   1041		drm_crtc_handle_vblank(&ctx->crtc->base);
   1042}
   1043
   1044static void fimd_dp_clock_enable(struct exynos_drm_clk *clk, bool enable)
   1045{
   1046	struct fimd_context *ctx = container_of(clk, struct fimd_context,
   1047						dp_clk);
   1048	u32 val = enable ? DP_MIE_CLK_DP_ENABLE : DP_MIE_CLK_DISABLE;
   1049	writel(val, ctx->regs + DP_MIE_CLKCON);
   1050}
   1051
   1052static const struct exynos_drm_crtc_ops fimd_crtc_ops = {
   1053	.atomic_enable = fimd_atomic_enable,
   1054	.atomic_disable = fimd_atomic_disable,
   1055	.enable_vblank = fimd_enable_vblank,
   1056	.disable_vblank = fimd_disable_vblank,
   1057	.atomic_begin = fimd_atomic_begin,
   1058	.update_plane = fimd_update_plane,
   1059	.disable_plane = fimd_disable_plane,
   1060	.atomic_flush = fimd_atomic_flush,
   1061	.atomic_check = fimd_atomic_check,
   1062	.te_handler = fimd_te_handler,
   1063};
   1064
   1065static irqreturn_t fimd_irq_handler(int irq, void *dev_id)
   1066{
   1067	struct fimd_context *ctx = (struct fimd_context *)dev_id;
   1068	u32 val, clear_bit;
   1069
   1070	val = readl(ctx->regs + VIDINTCON1);
   1071
   1072	clear_bit = ctx->i80_if ? VIDINTCON1_INT_I80 : VIDINTCON1_INT_FRAME;
   1073	if (val & clear_bit)
   1074		writel(clear_bit, ctx->regs + VIDINTCON1);
   1075
   1076	/* check the crtc is detached already from encoder */
   1077	if (!ctx->drm_dev)
   1078		goto out;
   1079
   1080	if (!ctx->i80_if)
   1081		drm_crtc_handle_vblank(&ctx->crtc->base);
   1082
   1083	if (ctx->i80_if) {
   1084		/* Exits triggering mode */
   1085		atomic_set(&ctx->triggering, 0);
   1086	} else {
   1087		/* set wait vsync event to zero and wake up queue. */
   1088		if (atomic_read(&ctx->wait_vsync_event)) {
   1089			atomic_set(&ctx->wait_vsync_event, 0);
   1090			wake_up(&ctx->wait_vsync_queue);
   1091		}
   1092	}
   1093
   1094out:
   1095	return IRQ_HANDLED;
   1096}
   1097
   1098static int fimd_bind(struct device *dev, struct device *master, void *data)
   1099{
   1100	struct fimd_context *ctx = dev_get_drvdata(dev);
   1101	struct drm_device *drm_dev = data;
   1102	struct exynos_drm_plane *exynos_plane;
   1103	unsigned int i;
   1104	int ret;
   1105
   1106	ctx->drm_dev = drm_dev;
   1107
   1108	for (i = 0; i < WINDOWS_NR; i++) {
   1109		if (ctx->driver_data->has_bgr_support) {
   1110			ctx->configs[i].pixel_formats = fimd_extended_formats;
   1111			ctx->configs[i].num_pixel_formats = ARRAY_SIZE(fimd_extended_formats);
   1112		} else {
   1113			ctx->configs[i].pixel_formats = fimd_formats;
   1114			ctx->configs[i].num_pixel_formats = ARRAY_SIZE(fimd_formats);
   1115		}
   1116
   1117		ctx->configs[i].zpos = i;
   1118		ctx->configs[i].type = fimd_win_types[i];
   1119		ctx->configs[i].capabilities = capabilities[i];
   1120		ret = exynos_plane_init(drm_dev, &ctx->planes[i], i,
   1121					&ctx->configs[i]);
   1122		if (ret)
   1123			return ret;
   1124	}
   1125
   1126	exynos_plane = &ctx->planes[DEFAULT_WIN];
   1127	ctx->crtc = exynos_drm_crtc_create(drm_dev, &exynos_plane->base,
   1128			EXYNOS_DISPLAY_TYPE_LCD, &fimd_crtc_ops, ctx);
   1129	if (IS_ERR(ctx->crtc))
   1130		return PTR_ERR(ctx->crtc);
   1131
   1132	if (ctx->driver_data->has_dp_clk) {
   1133		ctx->dp_clk.enable = fimd_dp_clock_enable;
   1134		ctx->crtc->pipe_clk = &ctx->dp_clk;
   1135	}
   1136
   1137	if (ctx->encoder)
   1138		exynos_dpi_bind(drm_dev, ctx->encoder);
   1139
   1140	if (is_drm_iommu_supported(drm_dev)) {
   1141		int ret;
   1142
   1143		ret = fimd_clear_channels(ctx->crtc);
   1144		if (ret < 0)
   1145			return ret;
   1146	}
   1147
   1148	return exynos_drm_register_dma(drm_dev, dev, &ctx->dma_priv);
   1149}
   1150
   1151static void fimd_unbind(struct device *dev, struct device *master,
   1152			void *data)
   1153{
   1154	struct fimd_context *ctx = dev_get_drvdata(dev);
   1155
   1156	fimd_atomic_disable(ctx->crtc);
   1157
   1158	exynos_drm_unregister_dma(ctx->drm_dev, ctx->dev, &ctx->dma_priv);
   1159
   1160	if (ctx->encoder)
   1161		exynos_dpi_remove(ctx->encoder);
   1162}
   1163
   1164static const struct component_ops fimd_component_ops = {
   1165	.bind	= fimd_bind,
   1166	.unbind = fimd_unbind,
   1167};
   1168
   1169static int fimd_probe(struct platform_device *pdev)
   1170{
   1171	struct device *dev = &pdev->dev;
   1172	struct fimd_context *ctx;
   1173	struct device_node *i80_if_timings;
   1174	int ret;
   1175
   1176	if (!dev->of_node)
   1177		return -ENODEV;
   1178
   1179	ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
   1180	if (!ctx)
   1181		return -ENOMEM;
   1182
   1183	ctx->dev = dev;
   1184	ctx->suspended = true;
   1185	ctx->driver_data = of_device_get_match_data(dev);
   1186
   1187	if (of_property_read_bool(dev->of_node, "samsung,invert-vden"))
   1188		ctx->vidcon1 |= VIDCON1_INV_VDEN;
   1189	if (of_property_read_bool(dev->of_node, "samsung,invert-vclk"))
   1190		ctx->vidcon1 |= VIDCON1_INV_VCLK;
   1191
   1192	i80_if_timings = of_get_child_by_name(dev->of_node, "i80-if-timings");
   1193	if (i80_if_timings) {
   1194		u32 val;
   1195
   1196		ctx->i80_if = true;
   1197
   1198		if (ctx->driver_data->has_vidoutcon)
   1199			ctx->vidout_con |= VIDOUT_CON_F_I80_LDI0;
   1200		else
   1201			ctx->vidcon0 |= VIDCON0_VIDOUT_I80_LDI0;
   1202		/*
   1203		 * The user manual describes that this "DSI_EN" bit is required
   1204		 * to enable I80 24-bit data interface.
   1205		 */
   1206		ctx->vidcon0 |= VIDCON0_DSI_EN;
   1207
   1208		if (of_property_read_u32(i80_if_timings, "cs-setup", &val))
   1209			val = 0;
   1210		ctx->i80ifcon = LCD_CS_SETUP(val);
   1211		if (of_property_read_u32(i80_if_timings, "wr-setup", &val))
   1212			val = 0;
   1213		ctx->i80ifcon |= LCD_WR_SETUP(val);
   1214		if (of_property_read_u32(i80_if_timings, "wr-active", &val))
   1215			val = 1;
   1216		ctx->i80ifcon |= LCD_WR_ACTIVE(val);
   1217		if (of_property_read_u32(i80_if_timings, "wr-hold", &val))
   1218			val = 0;
   1219		ctx->i80ifcon |= LCD_WR_HOLD(val);
   1220	}
   1221	of_node_put(i80_if_timings);
   1222
   1223	ctx->sysreg = syscon_regmap_lookup_by_phandle(dev->of_node,
   1224							"samsung,sysreg");
   1225	if (IS_ERR(ctx->sysreg)) {
   1226		dev_warn(dev, "failed to get system register.\n");
   1227		ctx->sysreg = NULL;
   1228	}
   1229
   1230	ctx->bus_clk = devm_clk_get(dev, "fimd");
   1231	if (IS_ERR(ctx->bus_clk)) {
   1232		dev_err(dev, "failed to get bus clock\n");
   1233		return PTR_ERR(ctx->bus_clk);
   1234	}
   1235
   1236	ctx->lcd_clk = devm_clk_get(dev, "sclk_fimd");
   1237	if (IS_ERR(ctx->lcd_clk)) {
   1238		dev_err(dev, "failed to get lcd clock\n");
   1239		return PTR_ERR(ctx->lcd_clk);
   1240	}
   1241
   1242	ctx->regs = devm_platform_ioremap_resource(pdev, 0);
   1243	if (IS_ERR(ctx->regs))
   1244		return PTR_ERR(ctx->regs);
   1245
   1246	ret = platform_get_irq_byname(pdev, ctx->i80_if ? "lcd_sys" : "vsync");
   1247	if (ret < 0)
   1248		return ret;
   1249
   1250	ret = devm_request_irq(dev, ret, fimd_irq_handler, 0, "drm_fimd", ctx);
   1251	if (ret) {
   1252		dev_err(dev, "irq request failed.\n");
   1253		return ret;
   1254	}
   1255
   1256	init_waitqueue_head(&ctx->wait_vsync_queue);
   1257	atomic_set(&ctx->wait_vsync_event, 0);
   1258
   1259	platform_set_drvdata(pdev, ctx);
   1260
   1261	ctx->encoder = exynos_dpi_probe(dev);
   1262	if (IS_ERR(ctx->encoder))
   1263		return PTR_ERR(ctx->encoder);
   1264
   1265	pm_runtime_enable(dev);
   1266
   1267	ret = component_add(dev, &fimd_component_ops);
   1268	if (ret)
   1269		goto err_disable_pm_runtime;
   1270
   1271	return ret;
   1272
   1273err_disable_pm_runtime:
   1274	pm_runtime_disable(dev);
   1275
   1276	return ret;
   1277}
   1278
   1279static int fimd_remove(struct platform_device *pdev)
   1280{
   1281	pm_runtime_disable(&pdev->dev);
   1282
   1283	component_del(&pdev->dev, &fimd_component_ops);
   1284
   1285	return 0;
   1286}
   1287
   1288#ifdef CONFIG_PM
   1289static int exynos_fimd_suspend(struct device *dev)
   1290{
   1291	struct fimd_context *ctx = dev_get_drvdata(dev);
   1292
   1293	clk_disable_unprepare(ctx->lcd_clk);
   1294	clk_disable_unprepare(ctx->bus_clk);
   1295
   1296	return 0;
   1297}
   1298
   1299static int exynos_fimd_resume(struct device *dev)
   1300{
   1301	struct fimd_context *ctx = dev_get_drvdata(dev);
   1302	int ret;
   1303
   1304	ret = clk_prepare_enable(ctx->bus_clk);
   1305	if (ret < 0) {
   1306		DRM_DEV_ERROR(dev,
   1307			      "Failed to prepare_enable the bus clk [%d]\n",
   1308			      ret);
   1309		return ret;
   1310	}
   1311
   1312	ret = clk_prepare_enable(ctx->lcd_clk);
   1313	if  (ret < 0) {
   1314		DRM_DEV_ERROR(dev,
   1315			      "Failed to prepare_enable the lcd clk [%d]\n",
   1316			      ret);
   1317		return ret;
   1318	}
   1319
   1320	return 0;
   1321}
   1322#endif
   1323
   1324static const struct dev_pm_ops exynos_fimd_pm_ops = {
   1325	SET_RUNTIME_PM_OPS(exynos_fimd_suspend, exynos_fimd_resume, NULL)
   1326	SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
   1327				pm_runtime_force_resume)
   1328};
   1329
   1330struct platform_driver fimd_driver = {
   1331	.probe		= fimd_probe,
   1332	.remove		= fimd_remove,
   1333	.driver		= {
   1334		.name	= "exynos4-fb",
   1335		.owner	= THIS_MODULE,
   1336		.pm	= &exynos_fimd_pm_ops,
   1337		.of_match_table = fimd_driver_dt_match,
   1338	},
   1339};