aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGustavo Padovan <gustavo.padovan@collabora.co.uk>2015-10-08 16:33:33 -0300
committerGustavo Padovan <gustavo.padovan@collabora.co.uk>2015-10-13 11:19:09 +0100
commit2414dfc95667254cbc6e60662473895b42a98ad0 (patch)
tree56ca3ef508915870b5d017369dce1cd9e4be58e0
parentbd2c14b5c2b7663f927da74a0fdd014d986313a0 (diff)
downloaddrm-exynos-dithering.tar.gz
WIP: fimd ditheringdithering
-rw-r--r--Documentation/devicetree/bindings/video/samsung-fimd.txt1
-rw-r--r--arch/arm/boot/dts/exynos5250-snow.dts1
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fimd.c68
-rw-r--r--include/video/samsung_fimd.h42
4 files changed, 112 insertions, 0 deletions
diff --git a/Documentation/devicetree/bindings/video/samsung-fimd.txt b/Documentation/devicetree/bindings/video/samsung-fimd.txt
index a8bbbde03e79e4..6e4dd36fd719fd 100644
--- a/Documentation/devicetree/bindings/video/samsung-fimd.txt
+++ b/Documentation/devicetree/bindings/video/samsung-fimd.txt
@@ -41,6 +41,7 @@ Optional Properties:
- power-domains: a phandle to FIMD power domain node.
- samsung,invert-vden: video enable signal is inverted
- samsung,invert-vclk: video clock signal is inverted
+- samsung,mie-dithering: enable dither for the Mobile Image Enhancement
- display-timings: timing settings for FIMD, as described in document [1].
Can be used in case timings cannot be provided otherwise
or to override timings provided by the panel.
diff --git a/arch/arm/boot/dts/exynos5250-snow.dts b/arch/arm/boot/dts/exynos5250-snow.dts
index 0720caab551111..4535596b1944de 100644
--- a/arch/arm/boot/dts/exynos5250-snow.dts
+++ b/arch/arm/boot/dts/exynos5250-snow.dts
@@ -267,6 +267,7 @@
&fimd {
status = "okay";
samsung,invert-vclk;
+ samsung,mie-dithering;
};
&hdmi {
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
index bd75c1531cac8d..7c7b021a2ec9a8 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
@@ -85,6 +85,9 @@
#define LCD_WR_HOLD(x) ((x) << 4)
#define I80IFEN_ENABLE (1 << 0)
+#define NO_DITHERING 0x00
+#define MIE_DITHERING 0x01
+
/* FIMD has totally five hardware windows. */
#define WINDOWS_NR 5
#define CURSOR_WIN 4
@@ -153,12 +156,14 @@ struct fimd_context {
struct clk *bus_clk;
struct clk *lcd_clk;
void __iomem *regs;
+ void __iomem *regs_mie;
struct regmap *sysreg;
unsigned long irq_flags;
u32 vidcon0;
u32 vidcon1;
u32 vidout_con;
u32 i80ifcon;
+ u32 dither_mode;
bool i80_if;
bool suspended;
int pipe;
@@ -376,6 +381,52 @@ static u32 fimd_calc_clkdiv(struct fimd_context *ctx,
return (clkdiv < 0x100) ? clkdiv : 0xff;
}
+static void fimd_enable_dithering(struct exynos_drm_crtc *crtc)
+{
+ struct fimd_context *ctx = crtc->ctx;
+ struct drm_display_mode *mode = &crtc->base.state->adjusted_mode;
+ int bpd, fpd, sync_len, i;
+
+ DRM_DEBUG("first\n");
+ if (ctx->dither_mode == MIE_DITHERING) {
+ writel(DP_MIE_CLK_DP_ENABLE, ctx->regs + DP_MIE_CLKCON);
+
+ writel(MIE_HRESOL(mode->crtc_hdisplay) |
+ MIE_VRESOL(mode->crtc_vdisplay) | MIE_MODE_UI,
+ ctx->regs_mie + MIE_CTRL1);
+
+ writel(MIE_WINHADDR0(0) | MIE_WINHADDR1(mode->crtc_hdisplay),
+ ctx->regs_mie + MIE_WINHADDR);
+
+ writel(MIE_WINVADDR0(0) | MIE_WINVADDR1(mode->crtc_vdisplay),
+ ctx->regs_mie + MIE_WINVADDR);
+
+ writel(PWMCLKCNT(mode->crtc_vtotal * mode->crtc_htotal /
+ (MIE_PWMCLKVAL + 1)), ctx->regs_mie + MIE_PWMCLKCNT);
+
+ bpd = mode->crtc_vtotal - mode->crtc_vsync_end;
+ fpd = mode->crtc_vsync_start - mode->crtc_vdisplay;
+ sync_len = mode->crtc_vsync_end - mode->crtc_vsync_start;
+ writel(MIE_VBPD(bpd) | MIE_VFPD(fpd) | MIE_VSPW(sync_len),
+ ctx->regs_mie + MIE_PWMVIDTCON1);
+
+ bpd = mode->crtc_htotal - mode->crtc_hsync_end;
+ fpd = mode->crtc_hsync_start - mode->crtc_hdisplay;
+ sync_len = mode->crtc_hsync_end - mode->crtc_hsync_start;
+ writel(MIE_HBPD(bpd) | MIE_HFPD(fpd) | MIE_HSPW(sync_len),
+ ctx->regs_mie + MIE_PWMVIDTCON2);
+
+ writel(MIE_DITHCON_EN | MIE_RGB6MODE,
+ ctx->regs_mie + MIE_AUXCON);
+
+ /* Bypass MIE image brightness enhancement */
+ for (i = 0; i <= 0x30; i += 4) {
+ writel(0, ctx->regs_mie + 0x100 + i);
+ writel(0, ctx->regs_mie + 0x200 + i);
+ }
+ }
+}
+
static void fimd_commit(struct exynos_drm_crtc *crtc)
{
struct fimd_context *ctx = crtc->ctx;
@@ -474,6 +525,8 @@ static void fimd_commit(struct exynos_drm_crtc *crtc)
val |= VIDCON0_CLKVAL_F(clkdiv - 1) | VIDCON0_CLKDIR;
writel(val, ctx->regs + VIDCON0);
+
+ fimd_enable_dithering(crtc);
}
@@ -795,6 +848,9 @@ static void fimd_disable(struct exynos_drm_crtc *crtc)
writel(0, ctx->regs + VIDCON0);
+ if (ctx->dither_mode == MIE_DITHERING)
+ writel(DP_MIE_CLK_DISABLE, ctx->regs + DP_MIE_CLKCON);
+
clk_disable_unprepare(ctx->lcd_clk);
clk_disable_unprepare(ctx->bus_clk);
@@ -862,6 +918,10 @@ static void fimd_dp_clock_enable(struct exynos_drm_crtc *crtc, bool enable)
struct fimd_context *ctx = crtc->ctx;
u32 val;
+ DRM_DEBUG_KMS("first\n");
+
+ return;
+
/*
* Only Exynos 5250, 5260, 5410 and 542x requires enabling DP/MIE
* clock. On these SoCs the bootloader may enable it but any
@@ -1018,6 +1078,8 @@ static int fimd_probe(struct platform_device *pdev)
ctx->vidcon1 |= VIDCON1_INV_VDEN;
if (of_property_read_bool(dev->of_node, "samsung,invert-vclk"))
ctx->vidcon1 |= VIDCON1_INV_VCLK;
+ if (of_property_read_bool(dev->of_node, "samsung,mie-dithering"))
+ ctx->dither_mode = MIE_DITHERING;
i80_if_timings = of_get_child_by_name(dev->of_node, "i80-if-timings");
if (i80_if_timings) {
@@ -1075,6 +1137,12 @@ static int fimd_probe(struct platform_device *pdev)
if (IS_ERR(ctx->regs))
return PTR_ERR(ctx->regs);
+ if (ctx->dither_mode == MIE_DITHERING) {
+ ctx->regs_mie = devm_ioremap(dev, MIE_BASE_ADDRESS, 0x400);
+ if (!ctx->regs_mie)
+ ctx->dither_mode = NO_DITHERING;
+ }
+
res = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
ctx->i80_if ? "lcd_sys" : "vsync");
if (!res) {
diff --git a/include/video/samsung_fimd.h b/include/video/samsung_fimd.h
index d8fc96ed11e9d2..9b79ad4683d6f0 100644
--- a/include/video/samsung_fimd.h
+++ b/include/video/samsung_fimd.h
@@ -475,3 +475,45 @@
#define FIMD_V8_VIDTCON2 0x20018
#define FIMD_V8_VIDTCON3 0x2001C
#define FIMD_V8_VIDCON1 0x20004
+
+/* MIE registers */
+#define MIE_BASE_ADDRESS 0x14430000
+#define MIE_CTRL1 0x0
+#define MIE_HRESOL_SHIFT 18
+#define MIE_HRESOL(x) ((x & 0xfff) << MIE_HRESOL_SHIFT)
+#define MIE_VRESOL_SHIFT 7
+#define MIE_VRESOL(x) ((x & 0x7ff) << MIE_VRESOL_SHIFT)
+#define MIE_MODE_UI (1 << 5)
+
+#define MIE_WINHADDR 0x10
+#define MIE_WINHADDR0_SHIFT 0
+#define MIE_WINHADDR1_SHIFT 20
+#define MIE_WINHADDR0(x) ((x & 0xfff) << MIE_WINHADDR0_SHIFT)
+#define MIE_WINHADDR1(x) (((x-1) & 0xfff)\
+ << MIE_WINHADDR1_SHIFT)
+
+#define MIE_WINVADDR 0x14
+#define MIE_WINVADDR0_SHIFT 0
+#define MIE_WINVADDR1_SHIFT 21
+#define MIE_WINVADDR0(x) ((x & 0x7ff) << MIE_WINVADDR0_SHIFT)
+#define MIE_WINVADDR1(x) (((x - 1) & 0x7ff)\
+ << MIE_WINVADDR1_SHIFT)
+
+#define MIE_PWMCLKCNT 0x20
+#define MIE_PWMCLKVAL 1
+#define PWMCLKCNT(x) ((x & 0x3fffff) << 4)
+
+#define MIE_PWMVIDTCON1 0x38
+#define MIE_VBPD(x) ((x - 1) << 16)
+#define MIE_VFPD(x) ((x - 1) << 8)
+#define MIE_VSPW(x) (x - 1)
+
+#define MIE_PWMVIDTCON2 0x3c
+#define MIE_HBPD(x) ((x - 1) << 16)
+#define MIE_HFPD(x) ((x - 1) << 8)
+#define MIE_HSPW(x) (x - 1)
+
+#define MIE_AUXCON 0x300
+#define MIE_DITHCON_EN 0x1
+#define MIE_RGBMODE_SHIFT 1
+#define MIE_RGB6MODE (0 << MIE_RGBMODE_SHIFT)