aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2017-08-28 20:37:36 -0400
committerDave Airlie <airlied@redhat.com>2017-08-28 20:37:36 -0400
commit7ebdb0dd52404907b8eac2bab476b43a8b8aa9f1 (patch)
treed54244823f1c17fc60c018d0aee0ccd53f49e1ba
parent095e2d04f9fa88a7c6923734ab4162833ff4f230 (diff)
parent5b7b1b7fa10145c014750b09ff4cf31ac4e1843a (diff)
Merge tag 'exynos-drm-next-for-v4.14' of git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos into drm-next
Summary: - Provide NV12MT pixel format support of Mixer driver in generic way. - Refactor Exynos KMS drivers . Refactoring to panel detection way . Refactoring to setting up possible_crtcs . Refactoring to video and command mode support - Some cleanups * tag 'exynos-drm-next-for-v4.14' of git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos: drm/exynos: simplify set_pixfmt() in DECON and FIMD drivers drm/exynos: consistent use of cpp drm/exynos: mixer: remove src offset from mixer_graph_buffer() drm/exynos: mixer: simplify mixer_graph_buffer() drm/exynos: mixer: simplify vp_video_buffer() drm/exynos: mixer: enable NV12MT support for the video plane drm/exynos: mixer: fix chroma comment in vp_video_buffer() arm64: dts: exynos: remove i80-if-timings nodes dt-bindings: exynos5433-decon: remove i80-if-timings property drm/exynos/decon5433: use mode info stored in CRTC to detect i80 mode drm/exynos: add mode_valid callback to exynos_drm drm/exynos/decon5433: refactor irq requesting code drm/exynos/mic: use mode info stored in CRTC to detect i80 mode drm/exynos/dsi: propagate info about command mode from panel drm/exynos/dsi: refactor panel detection logic drm/exynos: use helper to set possible crtcs drm/exynos/decon5433: use readl_poll_timeout helpers
-rw-r--r--Documentation/devicetree/bindings/display/exynos/exynos5433-decon.txt12
-rw-r--r--arch/arm64/boot/dts/exynos/exynos5433-tm2-common.dtsi6
-rw-r--r--drivers/gpu/drm/exynos/exynos5433_drm_decon.c124
-rw-r--r--drivers/gpu/drm/exynos/exynos7_drm_decon.c13
-rw-r--r--drivers/gpu/drm/exynos/exynos_dp.c15
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_core.c1
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_crtc.c33
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_crtc.h10
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_dpi.c12
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_drv.h5
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_dsi.c218
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fb.c2
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fimd.c16
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_mic.c44
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_plane.c27
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_vidi.c15
-rw-r--r--drivers/gpu/drm/exynos/exynos_hdmi.c25
-rw-r--r--drivers/gpu/drm/exynos/exynos_mixer.c48
18 files changed, 299 insertions, 327 deletions
diff --git a/Documentation/devicetree/bindings/display/exynos/exynos5433-decon.txt b/Documentation/devicetree/bindings/display/exynos/exynos5433-decon.txt
index 549c538b38a5..fc2588292a68 100644
--- a/Documentation/devicetree/bindings/display/exynos/exynos5433-decon.txt
+++ b/Documentation/devicetree/bindings/display/exynos/exynos5433-decon.txt
@@ -25,12 +25,6 @@ Required properties:
25 size-cells must 1 and 0, respectively. 25 size-cells must 1 and 0, respectively.
26- port: contains an endpoint node which is connected to the endpoint in the mic 26- port: contains an endpoint node which is connected to the endpoint in the mic
27 node. The reg value muset be 0. 27 node. The reg value muset be 0.
28- i80-if-timings: specify whether the panel which is connected to decon uses
29 i80 lcd interface or mipi video interface. This node contains
30 no timing information as that of fimd does. Because there is
31 no register in decon to specify i80 interface timing value,
32 it is not needed, but make it remain to use same kind of node
33 in fimd and exynos7 decon.
34 28
35Example: 29Example:
36SoC specific DT entry: 30SoC specific DT entry:
@@ -59,9 +53,3 @@ decon: decon@13800000 {
59 }; 53 };
60 }; 54 };
61}; 55};
62
63Board specific DT entry:
64&decon {
65 i80-if-timings {
66 };
67};
diff --git a/arch/arm64/boot/dts/exynos/exynos5433-tm2-common.dtsi b/arch/arm64/boot/dts/exynos/exynos5433-tm2-common.dtsi
index e2b0da2c0bc7..105b2938082f 100644
--- a/arch/arm64/boot/dts/exynos/exynos5433-tm2-common.dtsi
+++ b/arch/arm64/boot/dts/exynos/exynos5433-tm2-common.dtsi
@@ -280,9 +280,6 @@
280 280
281&decon { 281&decon {
282 status = "okay"; 282 status = "okay";
283
284 i80-if-timings {
285 };
286}; 283};
287 284
288&decon_tv { 285&decon_tv {
@@ -1116,9 +1113,6 @@
1116 1113
1117&mic { 1114&mic {
1118 status = "okay"; 1115 status = "okay";
1119
1120 i80-if-timings {
1121 };
1122}; 1116};
1123 1117
1124&pmu_system_controller { 1118&pmu_system_controller {
diff --git a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c
index 5792ca88ab7a..730b8d9db187 100644
--- a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c
+++ b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c
@@ -13,6 +13,7 @@
13#include <linux/platform_device.h> 13#include <linux/platform_device.h>
14#include <linux/clk.h> 14#include <linux/clk.h>
15#include <linux/component.h> 15#include <linux/component.h>
16#include <linux/iopoll.h>
16#include <linux/mfd/syscon.h> 17#include <linux/mfd/syscon.h>
17#include <linux/of_device.h> 18#include <linux/of_device.h>
18#include <linux/of_gpio.h> 19#include <linux/of_gpio.h>
@@ -33,9 +34,8 @@
33#define WINDOWS_NR 3 34#define WINDOWS_NR 3
34#define MIN_FB_WIDTH_FOR_16WORD_BURST 128 35#define MIN_FB_WIDTH_FOR_16WORD_BURST 128
35 36
36#define IFTYPE_I80 (1 << 0) 37#define I80_HW_TRG (1 << 0)
37#define I80_HW_TRG (1 << 1) 38#define IFTYPE_HDMI (1 << 1)
38#define IFTYPE_HDMI (1 << 2)
39 39
40static const char * const decon_clks_name[] = { 40static const char * const decon_clks_name[] = {
41 "pclk", 41 "pclk",
@@ -57,6 +57,8 @@ struct decon_context {
57 struct regmap *sysreg; 57 struct regmap *sysreg;
58 struct clk *clks[ARRAY_SIZE(decon_clks_name)]; 58 struct clk *clks[ARRAY_SIZE(decon_clks_name)];
59 unsigned int irq; 59 unsigned int irq;
60 unsigned int irq_vsync;
61 unsigned int irq_lcd_sys;
60 unsigned int te_irq; 62 unsigned int te_irq;
61 unsigned long out_type; 63 unsigned long out_type;
62 int first_win; 64 int first_win;
@@ -90,7 +92,7 @@ static int decon_enable_vblank(struct exynos_drm_crtc *crtc)
90 u32 val; 92 u32 val;
91 93
92 val = VIDINTCON0_INTEN; 94 val = VIDINTCON0_INTEN;
93 if (ctx->out_type & IFTYPE_I80) 95 if (crtc->i80_mode)
94 val |= VIDINTCON0_FRAMEDONE; 96 val |= VIDINTCON0_FRAMEDONE;
95 else 97 else
96 val |= VIDINTCON0_INTFRMEN | VIDINTCON0_FRAMESEL_FP; 98 val |= VIDINTCON0_INTFRMEN | VIDINTCON0_FRAMESEL_FP;
@@ -139,7 +141,7 @@ static u32 decon_get_frame_count(struct decon_context *ctx, bool end)
139 141
140 switch (status & (VIDCON1_VSTATUS_MASK | VIDCON1_I80_ACTIVE)) { 142 switch (status & (VIDCON1_VSTATUS_MASK | VIDCON1_I80_ACTIVE)) {
141 case VIDCON1_VSTATUS_VS: 143 case VIDCON1_VSTATUS_VS:
142 if (!(ctx->out_type & IFTYPE_I80)) 144 if (!(ctx->crtc->i80_mode))
143 --frm; 145 --frm;
144 break; 146 break;
145 case VIDCON1_VSTATUS_BP: 147 case VIDCON1_VSTATUS_BP:
@@ -166,7 +168,7 @@ static u32 decon_get_vblank_counter(struct exynos_drm_crtc *crtc)
166 168
167static void decon_setup_trigger(struct decon_context *ctx) 169static void decon_setup_trigger(struct decon_context *ctx)
168{ 170{
169 if (!(ctx->out_type & (IFTYPE_I80 | I80_HW_TRG))) 171 if (!ctx->crtc->i80_mode && !(ctx->out_type & I80_HW_TRG))
170 return; 172 return;
171 173
172 if (!(ctx->out_type & I80_HW_TRG)) { 174 if (!(ctx->out_type & I80_HW_TRG)) {
@@ -206,7 +208,7 @@ static void decon_commit(struct exynos_drm_crtc *crtc)
206 val = VIDOUT_LCD_ON; 208 val = VIDOUT_LCD_ON;
207 if (interlaced) 209 if (interlaced)
208 val |= VIDOUT_INTERLACE_EN_F; 210 val |= VIDOUT_INTERLACE_EN_F;
209 if (ctx->out_type & IFTYPE_I80) { 211 if (crtc->i80_mode) {
210 val |= VIDOUT_COMMAND_IF; 212 val |= VIDOUT_COMMAND_IF;
211 } else { 213 } else {
212 val |= VIDOUT_RGB_IF; 214 val |= VIDOUT_RGB_IF;
@@ -222,7 +224,7 @@ static void decon_commit(struct exynos_drm_crtc *crtc)
222 VIDTCON2_HOZVAL(m->hdisplay - 1); 224 VIDTCON2_HOZVAL(m->hdisplay - 1);
223 writel(val, ctx->addr + DECON_VIDTCON2); 225 writel(val, ctx->addr + DECON_VIDTCON2);
224 226
225 if (!(ctx->out_type & IFTYPE_I80)) { 227 if (!crtc->i80_mode) {
226 int vbp = m->crtc_vtotal - m->crtc_vsync_end; 228 int vbp = m->crtc_vtotal - m->crtc_vsync_end;
227 int vfp = m->crtc_vsync_start - m->crtc_vdisplay; 229 int vfp = m->crtc_vsync_start - m->crtc_vdisplay;
228 230
@@ -277,16 +279,14 @@ static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win,
277 val |= WINCONx_BURSTLEN_16WORD; 279 val |= WINCONx_BURSTLEN_16WORD;
278 break; 280 break;
279 case DRM_FORMAT_ARGB8888: 281 case DRM_FORMAT_ARGB8888:
282 default:
280 val |= WINCONx_BPPMODE_32BPP_A8888; 283 val |= WINCONx_BPPMODE_32BPP_A8888;
281 val |= WINCONx_WSWP_F | WINCONx_BLD_PIX_F | WINCONx_ALPHA_SEL_F; 284 val |= WINCONx_WSWP_F | WINCONx_BLD_PIX_F | WINCONx_ALPHA_SEL_F;
282 val |= WINCONx_BURSTLEN_16WORD; 285 val |= WINCONx_BURSTLEN_16WORD;
283 break; 286 break;
284 default:
285 DRM_ERROR("Proper pixel format is not set\n");
286 return;
287 } 287 }
288 288
289 DRM_DEBUG_KMS("bpp = %u\n", fb->format->cpp[0] * 8); 289 DRM_DEBUG_KMS("cpp = %u\n", fb->format->cpp[0]);
290 290
291 /* 291 /*
292 * In case of exynos, setting dma-burst to 16Word causes permanent 292 * In case of exynos, setting dma-burst to 16Word causes permanent
@@ -329,7 +329,7 @@ static void decon_update_plane(struct exynos_drm_crtc *crtc,
329 struct decon_context *ctx = crtc->ctx; 329 struct decon_context *ctx = crtc->ctx;
330 struct drm_framebuffer *fb = state->base.fb; 330 struct drm_framebuffer *fb = state->base.fb;
331 unsigned int win = plane->index; 331 unsigned int win = plane->index;
332 unsigned int bpp = fb->format->cpp[0]; 332 unsigned int cpp = fb->format->cpp[0];
333 unsigned int pitch = fb->pitches[0]; 333 unsigned int pitch = fb->pitches[0];
334 dma_addr_t dma_addr = exynos_drm_fb_dma_addr(fb, 0); 334 dma_addr_t dma_addr = exynos_drm_fb_dma_addr(fb, 0);
335 u32 val; 335 u32 val;
@@ -365,11 +365,11 @@ static void decon_update_plane(struct exynos_drm_crtc *crtc,
365 writel(val, ctx->addr + DECON_VIDW0xADD1B0(win)); 365 writel(val, ctx->addr + DECON_VIDW0xADD1B0(win));
366 366
367 if (!(ctx->out_type & IFTYPE_HDMI)) 367 if (!(ctx->out_type & IFTYPE_HDMI))
368 val = BIT_VAL(pitch - state->crtc.w * bpp, 27, 14) 368 val = BIT_VAL(pitch - state->crtc.w * cpp, 27, 14)
369 | BIT_VAL(state->crtc.w * bpp, 13, 0); 369 | BIT_VAL(state->crtc.w * cpp, 13, 0);
370 else 370 else
371 val = BIT_VAL(pitch - state->crtc.w * bpp, 29, 15) 371 val = BIT_VAL(pitch - state->crtc.w * cpp, 29, 15)
372 | BIT_VAL(state->crtc.w * bpp, 14, 0); 372 | BIT_VAL(state->crtc.w * cpp, 14, 0);
373 writel(val, ctx->addr + DECON_VIDW0xADD2(win)); 373 writel(val, ctx->addr + DECON_VIDW0xADD2(win));
374 374
375 decon_win_set_pixfmt(ctx, win, fb); 375 decon_win_set_pixfmt(ctx, win, fb);
@@ -407,24 +407,19 @@ static void decon_atomic_flush(struct exynos_drm_crtc *crtc)
407 407
408static void decon_swreset(struct decon_context *ctx) 408static void decon_swreset(struct decon_context *ctx)
409{ 409{
410 unsigned int tries;
411 unsigned long flags; 410 unsigned long flags;
411 u32 val;
412 int ret;
412 413
413 writel(0, ctx->addr + DECON_VIDCON0); 414 writel(0, ctx->addr + DECON_VIDCON0);
414 for (tries = 2000; tries; --tries) { 415 readl_poll_timeout(ctx->addr + DECON_VIDCON0, val,
415 if (~readl(ctx->addr + DECON_VIDCON0) & VIDCON0_STOP_STATUS) 416 ~val & VIDCON0_STOP_STATUS, 12, 20000);
416 break;
417 udelay(10);
418 }
419 417
420 writel(VIDCON0_SWRESET, ctx->addr + DECON_VIDCON0); 418 writel(VIDCON0_SWRESET, ctx->addr + DECON_VIDCON0);
421 for (tries = 2000; tries; --tries) { 419 ret = readl_poll_timeout(ctx->addr + DECON_VIDCON0, val,
422 if (~readl(ctx->addr + DECON_VIDCON0) & VIDCON0_SWRESET) 420 ~val & VIDCON0_SWRESET, 12, 20000);
423 break;
424 udelay(10);
425 }
426 421
427 WARN(tries == 0, "failed to software reset DECON\n"); 422 WARN(ret < 0, "failed to software reset DECON\n");
428 423
429 spin_lock_irqsave(&ctx->vblank_lock, flags); 424 spin_lock_irqsave(&ctx->vblank_lock, flags);
430 ctx->frame_id = 0; 425 ctx->frame_id = 0;
@@ -515,6 +510,22 @@ err:
515 clk_disable_unprepare(ctx->clks[i]); 510 clk_disable_unprepare(ctx->clks[i]);
516} 511}
517 512
513static enum drm_mode_status decon_mode_valid(struct exynos_drm_crtc *crtc,
514 const struct drm_display_mode *mode)
515{
516 struct decon_context *ctx = crtc->ctx;
517
518 ctx->irq = crtc->i80_mode ? ctx->irq_lcd_sys : ctx->irq_vsync;
519
520 if (ctx->irq)
521 return MODE_OK;
522
523 dev_info(ctx->dev, "Sink requires %s mode, but appropriate interrupt is not provided.\n",
524 crtc->i80_mode ? "command" : "video");
525
526 return MODE_BAD;
527}
528
518static const struct exynos_drm_crtc_ops decon_crtc_ops = { 529static const struct exynos_drm_crtc_ops decon_crtc_ops = {
519 .enable = decon_enable, 530 .enable = decon_enable,
520 .disable = decon_disable, 531 .disable = decon_disable,
@@ -524,6 +535,7 @@ static const struct exynos_drm_crtc_ops decon_crtc_ops = {
524 .atomic_begin = decon_atomic_begin, 535 .atomic_begin = decon_atomic_begin,
525 .update_plane = decon_update_plane, 536 .update_plane = decon_update_plane,
526 .disable_plane = decon_disable_plane, 537 .disable_plane = decon_disable_plane,
538 .mode_valid = decon_mode_valid,
527 .atomic_flush = decon_atomic_flush, 539 .atomic_flush = decon_atomic_flush,
528}; 540};
529 541
@@ -674,19 +686,22 @@ static const struct of_device_id exynos5433_decon_driver_dt_match[] = {
674MODULE_DEVICE_TABLE(of, exynos5433_decon_driver_dt_match); 686MODULE_DEVICE_TABLE(of, exynos5433_decon_driver_dt_match);
675 687
676static int decon_conf_irq(struct decon_context *ctx, const char *name, 688static int decon_conf_irq(struct decon_context *ctx, const char *name,
677 irq_handler_t handler, unsigned long int flags, bool required) 689 irq_handler_t handler, unsigned long int flags)
678{ 690{
679 struct platform_device *pdev = to_platform_device(ctx->dev); 691 struct platform_device *pdev = to_platform_device(ctx->dev);
680 int ret, irq = platform_get_irq_byname(pdev, name); 692 int ret, irq = platform_get_irq_byname(pdev, name);
681 693
682 if (irq < 0) { 694 if (irq < 0) {
683 if (irq == -EPROBE_DEFER) 695 switch (irq) {
696 case -EPROBE_DEFER:
684 return irq; 697 return irq;
685 if (required) 698 case -ENODATA:
686 dev_err(ctx->dev, "cannot get %s IRQ\n", name); 699 case -ENXIO:
687 else 700 return 0;
688 irq = 0; 701 default:
689 return irq; 702 dev_err(ctx->dev, "IRQ %s get failed, %d\n", name, irq);
703 return irq;
704 }
690 } 705 }
691 irq_set_status_flags(irq, IRQ_NOAUTOEN); 706 irq_set_status_flags(irq, IRQ_NOAUTOEN);
692 ret = devm_request_irq(ctx->dev, irq, handler, flags, "drm_decon", ctx); 707 ret = devm_request_irq(ctx->dev, irq, handler, flags, "drm_decon", ctx);
@@ -714,11 +729,8 @@ static int exynos5433_decon_probe(struct platform_device *pdev)
714 ctx->out_type = (unsigned long)of_device_get_match_data(dev); 729 ctx->out_type = (unsigned long)of_device_get_match_data(dev);
715 spin_lock_init(&ctx->vblank_lock); 730 spin_lock_init(&ctx->vblank_lock);
716 731
717 if (ctx->out_type & IFTYPE_HDMI) { 732 if (ctx->out_type & IFTYPE_HDMI)
718 ctx->first_win = 1; 733 ctx->first_win = 1;
719 } else if (of_get_child_by_name(dev->of_node, "i80-if-timings")) {
720 ctx->out_type |= IFTYPE_I80;
721 }
722 734
723 for (i = 0; i < ARRAY_SIZE(decon_clks_name); i++) { 735 for (i = 0; i < ARRAY_SIZE(decon_clks_name); i++) {
724 struct clk *clk; 736 struct clk *clk;
@@ -742,25 +754,23 @@ static int exynos5433_decon_probe(struct platform_device *pdev)
742 return PTR_ERR(ctx->addr); 754 return PTR_ERR(ctx->addr);
743 } 755 }
744 756
745 if (ctx->out_type & IFTYPE_I80) { 757 ret = decon_conf_irq(ctx, "vsync", decon_irq_handler, 0);
746 ret = decon_conf_irq(ctx, "lcd_sys", decon_irq_handler, 0, true); 758 if (ret < 0)
747 if (ret < 0) 759 return ret;
748 return ret; 760 ctx->irq_vsync = ret;
749 ctx->irq = ret;
750 761
751 ret = decon_conf_irq(ctx, "te", decon_te_irq_handler, 762 ret = decon_conf_irq(ctx, "lcd_sys", decon_irq_handler, 0);
752 IRQF_TRIGGER_RISING, false); 763 if (ret < 0)
753 if (ret < 0) 764 return ret;
754 return ret; 765 ctx->irq_lcd_sys = ret;
755 if (ret) { 766
756 ctx->te_irq = ret; 767 ret = decon_conf_irq(ctx, "te", decon_te_irq_handler,
757 ctx->out_type &= ~I80_HW_TRG; 768 IRQF_TRIGGER_RISING);
758 } 769 if (ret < 0)
759 } else {
760 ret = decon_conf_irq(ctx, "vsync", decon_irq_handler, 0, true);
761 if (ret < 0)
762 return ret; 770 return ret;
763 ctx->irq = ret; 771 if (ret) {
772 ctx->te_irq = ret;
773 ctx->out_type &= ~I80_HW_TRG;
764 } 774 }
765 775
766 if (ctx->out_type & I80_HW_TRG) { 776 if (ctx->out_type & I80_HW_TRG) {
diff --git a/drivers/gpu/drm/exynos/exynos7_drm_decon.c b/drivers/gpu/drm/exynos/exynos7_drm_decon.c
index 3e88269fdc2e..615efcf7782a 100644
--- a/drivers/gpu/drm/exynos/exynos7_drm_decon.c
+++ b/drivers/gpu/drm/exynos/exynos7_drm_decon.c
@@ -309,19 +309,14 @@ static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win,
309 val |= WINCONx_BURSTLEN_16WORD; 309 val |= WINCONx_BURSTLEN_16WORD;
310 break; 310 break;
311 case DRM_FORMAT_BGRA8888: 311 case DRM_FORMAT_BGRA8888:
312 default:
312 val |= WINCONx_BPPMODE_32BPP_BGRA | WINCONx_BLD_PIX | 313 val |= WINCONx_BPPMODE_32BPP_BGRA | WINCONx_BLD_PIX |
313 WINCONx_ALPHA_SEL; 314 WINCONx_ALPHA_SEL;
314 val |= WINCONx_BURSTLEN_16WORD; 315 val |= WINCONx_BURSTLEN_16WORD;
315 break; 316 break;
316 default:
317 DRM_DEBUG_KMS("invalid pixel size so using unpacked 24bpp.\n");
318
319 val |= WINCONx_BPPMODE_24BPP_xRGB;
320 val |= WINCONx_BURSTLEN_16WORD;
321 break;
322 } 317 }
323 318
324 DRM_DEBUG_KMS("bpp = %d\n", fb->format->cpp[0] * 8); 319 DRM_DEBUG_KMS("cpp = %d\n", fb->format->cpp[0]);
325 320
326 /* 321 /*
327 * In case of exynos, setting dma-burst to 16Word causes permanent 322 * In case of exynos, setting dma-burst to 16Word causes permanent
@@ -398,7 +393,7 @@ static void decon_update_plane(struct exynos_drm_crtc *crtc,
398 unsigned int last_x; 393 unsigned int last_x;
399 unsigned int last_y; 394 unsigned int last_y;
400 unsigned int win = plane->index; 395 unsigned int win = plane->index;
401 unsigned int bpp = fb->format->cpp[0]; 396 unsigned int cpp = fb->format->cpp[0];
402 unsigned int pitch = fb->pitches[0]; 397 unsigned int pitch = fb->pitches[0];
403 398
404 if (ctx->suspended) 399 if (ctx->suspended)
@@ -418,7 +413,7 @@ static void decon_update_plane(struct exynos_drm_crtc *crtc,
418 val = (unsigned long)exynos_drm_fb_dma_addr(fb, 0); 413 val = (unsigned long)exynos_drm_fb_dma_addr(fb, 0);
419 writel(val, ctx->regs + VIDW_BUF_START(win)); 414 writel(val, ctx->regs + VIDW_BUF_START(win));
420 415
421 padding = (pitch / bpp) - fb->width; 416 padding = (pitch / cpp) - fb->width;
422 417
423 /* buffer size */ 418 /* buffer size */
424 writel(fb->width + padding, ctx->regs + VIDW_WHOLE_X(win)); 419 writel(fb->width + padding, ctx->regs + VIDW_WHOLE_X(win));
diff --git a/drivers/gpu/drm/exynos/exynos_dp.c b/drivers/gpu/drm/exynos/exynos_dp.c
index 385537b726a6..39629e7a80b9 100644
--- a/drivers/gpu/drm/exynos/exynos_dp.c
+++ b/drivers/gpu/drm/exynos/exynos_dp.c
@@ -155,7 +155,7 @@ static int exynos_dp_bind(struct device *dev, struct device *master, void *data)
155 struct exynos_dp_device *dp = dev_get_drvdata(dev); 155 struct exynos_dp_device *dp = dev_get_drvdata(dev);
156 struct drm_encoder *encoder = &dp->encoder; 156 struct drm_encoder *encoder = &dp->encoder;
157 struct drm_device *drm_dev = data; 157 struct drm_device *drm_dev = data;
158 int pipe, ret; 158 int ret;
159 159
160 /* 160 /*
161 * Just like the probe function said, we don't need the 161 * Just like the probe function said, we don't need the
@@ -179,20 +179,15 @@ static int exynos_dp_bind(struct device *dev, struct device *master, void *data)
179 return ret; 179 return ret;
180 } 180 }
181 181
182 pipe = exynos_drm_crtc_get_pipe_from_type(drm_dev,
183 EXYNOS_DISPLAY_TYPE_LCD);
184 if (pipe < 0)
185 return pipe;
186
187 encoder->possible_crtcs = 1 << pipe;
188
189 DRM_DEBUG_KMS("possible_crtcs = 0x%x\n", encoder->possible_crtcs);
190
191 drm_encoder_init(drm_dev, encoder, &exynos_dp_encoder_funcs, 182 drm_encoder_init(drm_dev, encoder, &exynos_dp_encoder_funcs,
192 DRM_MODE_ENCODER_TMDS, NULL); 183 DRM_MODE_ENCODER_TMDS, NULL);
193 184
194 drm_encoder_helper_add(encoder, &exynos_dp_encoder_helper_funcs); 185 drm_encoder_helper_add(encoder, &exynos_dp_encoder_helper_funcs);
195 186
187 ret = exynos_drm_set_possible_crtcs(encoder, EXYNOS_DISPLAY_TYPE_LCD);
188 if (ret < 0)
189 return ret;
190
196 dp->plat_data.encoder = encoder; 191 dp->plat_data.encoder = encoder;
197 192
198 return analogix_dp_bind(dev, dp->drm_dev, &dp->plat_data); 193 return analogix_dp_bind(dev, dp->drm_dev, &dp->plat_data);
diff --git a/drivers/gpu/drm/exynos/exynos_drm_core.c b/drivers/gpu/drm/exynos/exynos_drm_core.c
index edbd98ff293e..b0c0621fcdf7 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_core.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_core.c
@@ -13,6 +13,7 @@
13 */ 13 */
14 14
15#include <drm/drmP.h> 15#include <drm/drmP.h>
16
16#include "exynos_drm_drv.h" 17#include "exynos_drm_drv.h"
17#include "exynos_drm_crtc.h" 18#include "exynos_drm_crtc.h"
18 19
diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
index c37078fbe0ea..6ce0821590df 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
@@ -16,6 +16,7 @@
16#include <drm/drm_crtc_helper.h> 16#include <drm/drm_crtc_helper.h>
17#include <drm/drm_atomic.h> 17#include <drm/drm_atomic.h>
18#include <drm/drm_atomic_helper.h> 18#include <drm/drm_atomic_helper.h>
19#include <drm/drm_encoder.h>
19 20
20#include "exynos_drm_crtc.h" 21#include "exynos_drm_crtc.h"
21#include "exynos_drm_drv.h" 22#include "exynos_drm_drv.h"
@@ -83,7 +84,19 @@ static void exynos_crtc_atomic_flush(struct drm_crtc *crtc,
83 exynos_crtc->ops->atomic_flush(exynos_crtc); 84 exynos_crtc->ops->atomic_flush(exynos_crtc);
84} 85}
85 86
87static enum drm_mode_status exynos_crtc_mode_valid(struct drm_crtc *crtc,
88 const struct drm_display_mode *mode)
89{
90 struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
91
92 if (exynos_crtc->ops->mode_valid)
93 return exynos_crtc->ops->mode_valid(exynos_crtc, mode);
94
95 return MODE_OK;
96}
97
86static const struct drm_crtc_helper_funcs exynos_crtc_helper_funcs = { 98static const struct drm_crtc_helper_funcs exynos_crtc_helper_funcs = {
99 .mode_valid = exynos_crtc_mode_valid,
87 .atomic_check = exynos_crtc_atomic_check, 100 .atomic_check = exynos_crtc_atomic_check,
88 .atomic_begin = exynos_crtc_atomic_begin, 101 .atomic_begin = exynos_crtc_atomic_begin,
89 .atomic_flush = exynos_crtc_atomic_flush, 102 .atomic_flush = exynos_crtc_atomic_flush,
@@ -191,16 +204,30 @@ err_crtc:
191 return ERR_PTR(ret); 204 return ERR_PTR(ret);
192} 205}
193 206
194int exynos_drm_crtc_get_pipe_from_type(struct drm_device *drm_dev, 207struct exynos_drm_crtc *exynos_drm_crtc_get_by_type(struct drm_device *drm_dev,
195 enum exynos_drm_output_type out_type) 208 enum exynos_drm_output_type out_type)
196{ 209{
197 struct drm_crtc *crtc; 210 struct drm_crtc *crtc;
198 211
199 drm_for_each_crtc(crtc, drm_dev) 212 drm_for_each_crtc(crtc, drm_dev)
200 if (to_exynos_crtc(crtc)->type == out_type) 213 if (to_exynos_crtc(crtc)->type == out_type)
201 return drm_crtc_index(crtc); 214 return to_exynos_crtc(crtc);
202 215
203 return -EPERM; 216 return ERR_PTR(-EPERM);
217}
218
219int exynos_drm_set_possible_crtcs(struct drm_encoder *encoder,
220 enum exynos_drm_output_type out_type)
221{
222 struct exynos_drm_crtc *crtc = exynos_drm_crtc_get_by_type(encoder->dev,
223 out_type);
224
225 if (IS_ERR(crtc))
226 return PTR_ERR(crtc);
227
228 encoder->possible_crtcs = drm_crtc_mask(&crtc->base);
229
230 return 0;
204} 231}
205 232
206void exynos_drm_crtc_te_handler(struct drm_crtc *crtc) 233void exynos_drm_crtc_te_handler(struct drm_crtc *crtc)
diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.h b/drivers/gpu/drm/exynos/exynos_drm_crtc.h
index ef58b64e3d2d..dec446109e6c 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_crtc.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.h
@@ -15,21 +15,25 @@
15#ifndef _EXYNOS_DRM_CRTC_H_ 15#ifndef _EXYNOS_DRM_CRTC_H_
16#define _EXYNOS_DRM_CRTC_H_ 16#define _EXYNOS_DRM_CRTC_H_
17 17
18
18#include "exynos_drm_drv.h" 19#include "exynos_drm_drv.h"
19 20
20struct exynos_drm_crtc *exynos_drm_crtc_create(struct drm_device *drm_dev, 21struct exynos_drm_crtc *exynos_drm_crtc_create(struct drm_device *drm_dev,
21 struct drm_plane *plane, 22 struct drm_plane *plane,
22 enum exynos_drm_output_type type, 23 enum exynos_drm_output_type out_type,
23 const struct exynos_drm_crtc_ops *ops, 24 const struct exynos_drm_crtc_ops *ops,
24 void *context); 25 void *context);
25void exynos_drm_crtc_wait_pending_update(struct exynos_drm_crtc *exynos_crtc); 26void exynos_drm_crtc_wait_pending_update(struct exynos_drm_crtc *exynos_crtc);
26void exynos_drm_crtc_finish_update(struct exynos_drm_crtc *exynos_crtc, 27void exynos_drm_crtc_finish_update(struct exynos_drm_crtc *exynos_crtc,
27 struct exynos_drm_plane *exynos_plane); 28 struct exynos_drm_plane *exynos_plane);
28 29
29/* This function gets pipe value to crtc device matched with out_type. */ 30/* This function gets crtc device matched with out_type. */
30int exynos_drm_crtc_get_pipe_from_type(struct drm_device *drm_dev, 31struct exynos_drm_crtc *exynos_drm_crtc_get_by_type(struct drm_device *drm_dev,
31 enum exynos_drm_output_type out_type); 32 enum exynos_drm_output_type out_type);
32 33
34int exynos_drm_set_possible_crtcs(struct drm_encoder *encoder,
35 enum exynos_drm_output_type out_type);
36
33/* 37/*
34 * This function calls the crtc device(manager)'s te_handler() callback 38 * This function calls the crtc device(manager)'s te_handler() callback
35 * to trigger to transfer video image at the tearing effect synchronization 39 * to trigger to transfer video image at the tearing effect synchronization
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dpi.c b/drivers/gpu/drm/exynos/exynos_drm_dpi.c
index 76d80e5de521..66945e0dc57f 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_dpi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_dpi.c
@@ -202,19 +202,15 @@ int exynos_dpi_bind(struct drm_device *dev, struct drm_encoder *encoder)
202{ 202{
203 int ret; 203 int ret;
204 204
205 ret = exynos_drm_crtc_get_pipe_from_type(dev, EXYNOS_DISPLAY_TYPE_LCD);
206 if (ret < 0)
207 return ret;
208
209 encoder->possible_crtcs = 1 << ret;
210
211 DRM_DEBUG_KMS("possible_crtcs = 0x%x\n", encoder->possible_crtcs);
212
213 drm_encoder_init(dev, encoder, &exynos_dpi_encoder_funcs, 205 drm_encoder_init(dev, encoder, &exynos_dpi_encoder_funcs,
214 DRM_MODE_ENCODER_TMDS, NULL); 206 DRM_MODE_ENCODER_TMDS, NULL);
215 207
216 drm_encoder_helper_add(encoder, &exynos_dpi_encoder_helper_funcs); 208 drm_encoder_helper_add(encoder, &exynos_dpi_encoder_helper_funcs);
217 209
210 ret = exynos_drm_set_possible_crtcs(encoder, EXYNOS_DISPLAY_TYPE_LCD);
211 if (ret < 0)
212 return ret;
213
218 ret = exynos_dpi_create_connector(encoder); 214 ret = exynos_dpi_create_connector(encoder);
219 if (ret) { 215 if (ret) {
220 DRM_ERROR("failed to create connector ret = %d\n", ret); 216 DRM_ERROR("failed to create connector ret = %d\n", ret);
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h
index a93de321706b..cf131c2aa23e 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h
@@ -91,6 +91,7 @@ struct exynos_drm_plane {
91#define EXYNOS_DRM_PLANE_CAP_DOUBLE (1 << 0) 91#define EXYNOS_DRM_PLANE_CAP_DOUBLE (1 << 0)
92#define EXYNOS_DRM_PLANE_CAP_SCALE (1 << 1) 92#define EXYNOS_DRM_PLANE_CAP_SCALE (1 << 1)
93#define EXYNOS_DRM_PLANE_CAP_ZPOS (1 << 2) 93#define EXYNOS_DRM_PLANE_CAP_ZPOS (1 << 2)
94#define EXYNOS_DRM_PLANE_CAP_TILE (1 << 3)
94 95
95/* 96/*
96 * Exynos DRM plane configuration structure. 97 * Exynos DRM plane configuration structure.
@@ -117,6 +118,7 @@ struct exynos_drm_plane_config {
117 * @disable: disable the device 118 * @disable: disable the device
118 * @enable_vblank: specific driver callback for enabling vblank interrupt. 119 * @enable_vblank: specific driver callback for enabling vblank interrupt.
119 * @disable_vblank: specific driver callback for disabling vblank interrupt. 120 * @disable_vblank: specific driver callback for disabling vblank interrupt.
121 * @mode_valid: specific driver callback for mode validation
120 * @atomic_check: validate state 122 * @atomic_check: validate state
121 * @atomic_begin: prepare device to receive an update 123 * @atomic_begin: prepare device to receive an update
122 * @atomic_flush: mark the end of device update 124 * @atomic_flush: mark the end of device update
@@ -132,6 +134,8 @@ struct exynos_drm_crtc_ops {
132 int (*enable_vblank)(struct exynos_drm_crtc *crtc); 134 int (*enable_vblank)(struct exynos_drm_crtc *crtc);
133 void (*disable_vblank)(struct exynos_drm_crtc *crtc); 135 void (*disable_vblank)(struct exynos_drm_crtc *crtc);
134 u32 (*get_vblank_counter)(struct exynos_drm_crtc *crtc); 136 u32 (*get_vblank_counter)(struct exynos_drm_crtc *crtc);
137 enum drm_mode_status (*mode_valid)(struct exynos_drm_crtc *crtc,
138 const struct drm_display_mode *mode);
135 int (*atomic_check)(struct exynos_drm_crtc *crtc, 139 int (*atomic_check)(struct exynos_drm_crtc *crtc,
136 struct drm_crtc_state *state); 140 struct drm_crtc_state *state);
137 void (*atomic_begin)(struct exynos_drm_crtc *crtc); 141 void (*atomic_begin)(struct exynos_drm_crtc *crtc);
@@ -162,6 +166,7 @@ struct exynos_drm_crtc {
162 const struct exynos_drm_crtc_ops *ops; 166 const struct exynos_drm_crtc_ops *ops;
163 void *ctx; 167 void *ctx;
164 struct exynos_drm_clk *pipe_clk; 168 struct exynos_drm_clk *pipe_clk;
169 bool i80_mode : 1;
165}; 170};
166 171
167static inline void exynos_drm_pipe_clk_enable(struct exynos_drm_crtc *crtc, 172static inline void exynos_drm_pipe_clk_enable(struct exynos_drm_crtc *crtc,
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
index c399dc9b325f..7904ffa9abfb 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
@@ -254,7 +254,6 @@ struct exynos_dsi {
254 struct drm_encoder encoder; 254 struct drm_encoder encoder;
255 struct mipi_dsi_host dsi_host; 255 struct mipi_dsi_host dsi_host;
256 struct drm_connector connector; 256 struct drm_connector connector;
257 struct device_node *panel_node;
258 struct drm_panel *panel; 257 struct drm_panel *panel;
259 struct device *dev; 258 struct device *dev;
260 259
@@ -1329,12 +1328,13 @@ static int exynos_dsi_init(struct exynos_dsi *dsi)
1329 return 0; 1328 return 0;
1330} 1329}
1331 1330
1332static int exynos_dsi_register_te_irq(struct exynos_dsi *dsi) 1331static int exynos_dsi_register_te_irq(struct exynos_dsi *dsi,
1332 struct device *panel)
1333{ 1333{
1334 int ret; 1334 int ret;
1335 int te_gpio_irq; 1335 int te_gpio_irq;
1336 1336
1337 dsi->te_gpio = of_get_named_gpio(dsi->panel_node, "te-gpios", 0); 1337 dsi->te_gpio = of_get_named_gpio(panel->of_node, "te-gpios", 0);
1338 if (dsi->te_gpio == -ENOENT) 1338 if (dsi->te_gpio == -ENOENT)
1339 return 0; 1339 return 0;
1340 1340
@@ -1374,85 +1374,6 @@ static void exynos_dsi_unregister_te_irq(struct exynos_dsi *dsi)
1374 } 1374 }
1375} 1375}
1376 1376
1377static int exynos_dsi_host_attach(struct mipi_dsi_host *host,
1378 struct mipi_dsi_device *device)
1379{
1380 struct exynos_dsi *dsi = host_to_dsi(host);
1381
1382 dsi->lanes = device->lanes;
1383 dsi->format = device->format;
1384 dsi->mode_flags = device->mode_flags;
1385 dsi->panel_node = device->dev.of_node;
1386
1387 /*
1388 * This is a temporary solution and should be made by more generic way.
1389 *
1390 * If attached panel device is for command mode one, dsi should register
1391 * TE interrupt handler.
1392 */
1393 if (!(dsi->mode_flags & MIPI_DSI_MODE_VIDEO)) {
1394 int ret = exynos_dsi_register_te_irq(dsi);
1395
1396 if (ret)
1397 return ret;
1398 }
1399
1400 if (dsi->connector.dev)
1401 drm_helper_hpd_irq_event(dsi->connector.dev);
1402
1403 return 0;
1404}
1405
1406static int exynos_dsi_host_detach(struct mipi_dsi_host *host,
1407 struct mipi_dsi_device *device)
1408{
1409 struct exynos_dsi *dsi = host_to_dsi(host);
1410
1411 exynos_dsi_unregister_te_irq(dsi);
1412
1413 dsi->panel_node = NULL;
1414
1415 if (dsi->connector.dev)
1416 drm_helper_hpd_irq_event(dsi->connector.dev);
1417
1418 return 0;
1419}
1420
1421static ssize_t exynos_dsi_host_transfer(struct mipi_dsi_host *host,
1422 const struct mipi_dsi_msg *msg)
1423{
1424 struct exynos_dsi *dsi = host_to_dsi(host);
1425 struct exynos_dsi_transfer xfer;
1426 int ret;
1427
1428 if (!(dsi->state & DSIM_STATE_ENABLED))
1429 return -EINVAL;
1430
1431 if (!(dsi->state & DSIM_STATE_INITIALIZED)) {
1432 ret = exynos_dsi_init(dsi);
1433 if (ret)
1434 return ret;
1435 dsi->state |= DSIM_STATE_INITIALIZED;
1436 }
1437
1438 ret = mipi_dsi_create_packet(&xfer.packet, msg);
1439 if (ret < 0)
1440 return ret;
1441
1442 xfer.rx_len = msg->rx_len;
1443 xfer.rx_payload = msg->rx_buf;
1444 xfer.flags = msg->flags;
1445
1446 ret = exynos_dsi_transfer(dsi, &xfer);
1447 return (ret < 0) ? ret : xfer.rx_done;
1448}
1449
1450static const struct mipi_dsi_host_ops exynos_dsi_ops = {
1451 .attach = exynos_dsi_host_attach,
1452 .detach = exynos_dsi_host_detach,
1453 .transfer = exynos_dsi_host_transfer,
1454};
1455
1456static void exynos_dsi_enable(struct drm_encoder *encoder) 1377static void exynos_dsi_enable(struct drm_encoder *encoder)
1457{ 1378{
1458 struct exynos_dsi *dsi = encoder_to_dsi(encoder); 1379 struct exynos_dsi *dsi = encoder_to_dsi(encoder);
@@ -1508,25 +1429,7 @@ static void exynos_dsi_disable(struct drm_encoder *encoder)
1508static enum drm_connector_status 1429static enum drm_connector_status
1509exynos_dsi_detect(struct drm_connector *connector, bool force) 1430exynos_dsi_detect(struct drm_connector *connector, bool force)
1510{ 1431{
1511 struct exynos_dsi *dsi = connector_to_dsi(connector); 1432 return connector->status;
1512
1513 if (!dsi->panel) {
1514 dsi->panel = of_drm_find_panel(dsi->panel_node);
1515 if (dsi->panel)
1516 drm_panel_attach(dsi->panel, &dsi->connector);
1517 } else if (!dsi->panel_node) {
1518 struct drm_encoder *encoder;
1519
1520 encoder = platform_get_drvdata(to_platform_device(dsi->dev));
1521 exynos_dsi_disable(encoder);
1522 drm_panel_detach(dsi->panel);
1523 dsi->panel = NULL;
1524 }
1525
1526 if (dsi->panel)
1527 return connector_status_connected;
1528
1529 return connector_status_disconnected;
1530} 1433}
1531 1434
1532static void exynos_dsi_connector_destroy(struct drm_connector *connector) 1435static void exynos_dsi_connector_destroy(struct drm_connector *connector)
@@ -1575,6 +1478,7 @@ static int exynos_dsi_create_connector(struct drm_encoder *encoder)
1575 return ret; 1478 return ret;
1576 } 1479 }
1577 1480
1481 connector->status = connector_status_disconnected;
1578 drm_connector_helper_add(connector, &exynos_dsi_connector_helper_funcs); 1482 drm_connector_helper_add(connector, &exynos_dsi_connector_helper_funcs);
1579 drm_mode_connector_attach_encoder(connector, encoder); 1483 drm_mode_connector_attach_encoder(connector, encoder);
1580 1484
@@ -1611,6 +1515,105 @@ static const struct drm_encoder_funcs exynos_dsi_encoder_funcs = {
1611 1515
1612MODULE_DEVICE_TABLE(of, exynos_dsi_of_match); 1516MODULE_DEVICE_TABLE(of, exynos_dsi_of_match);
1613 1517
1518static int exynos_dsi_host_attach(struct mipi_dsi_host *host,
1519 struct mipi_dsi_device *device)
1520{
1521 struct exynos_dsi *dsi = host_to_dsi(host);
1522 struct drm_device *drm = dsi->connector.dev;
1523
1524 /*
1525 * This is a temporary solution and should be made by more generic way.
1526 *
1527 * If attached panel device is for command mode one, dsi should register
1528 * TE interrupt handler.
1529 */
1530 if (!(device->mode_flags & MIPI_DSI_MODE_VIDEO)) {
1531 int ret = exynos_dsi_register_te_irq(dsi, &device->dev);
1532 if (ret)
1533 return ret;
1534 }
1535
1536 mutex_lock(&drm->mode_config.mutex);
1537
1538 dsi->lanes = device->lanes;
1539 dsi->format = device->format;
1540 dsi->mode_flags = device->mode_flags;
1541 dsi->panel = of_drm_find_panel(device->dev.of_node);
1542 if (dsi->panel) {
1543 drm_panel_attach(dsi->panel, &dsi->connector);
1544 dsi->connector.status = connector_status_connected;
1545 }
1546 exynos_drm_crtc_get_by_type(drm, EXYNOS_DISPLAY_TYPE_LCD)->i80_mode =
1547 !(dsi->mode_flags & MIPI_DSI_MODE_VIDEO);
1548
1549 mutex_unlock(&drm->mode_config.mutex);
1550
1551 if (drm->mode_config.poll_enabled)
1552 drm_kms_helper_hotplug_event(drm);
1553
1554 return 0;
1555}
1556
1557static int exynos_dsi_host_detach(struct mipi_dsi_host *host,
1558 struct mipi_dsi_device *device)
1559{
1560 struct exynos_dsi *dsi = host_to_dsi(host);
1561 struct drm_device *drm = dsi->connector.dev;
1562
1563 mutex_lock(&drm->mode_config.mutex);
1564
1565 if (dsi->panel) {
1566 exynos_dsi_disable(&dsi->encoder);
1567 drm_panel_detach(dsi->panel);
1568 dsi->panel = NULL;
1569 dsi->connector.status = connector_status_disconnected;
1570 }
1571
1572 mutex_unlock(&drm->mode_config.mutex);
1573
1574 if (drm->mode_config.poll_enabled)
1575 drm_kms_helper_hotplug_event(drm);
1576
1577 exynos_dsi_unregister_te_irq(dsi);
1578
1579 return 0;
1580}
1581
1582static ssize_t exynos_dsi_host_transfer(struct mipi_dsi_host *host,
1583 const struct mipi_dsi_msg *msg)
1584{
1585 struct exynos_dsi *dsi = host_to_dsi(host);
1586 struct exynos_dsi_transfer xfer;
1587 int ret;
1588
1589 if (!(dsi->state & DSIM_STATE_ENABLED))
1590 return -EINVAL;
1591
1592 if (!(dsi->state & DSIM_STATE_INITIALIZED)) {
1593 ret = exynos_dsi_init(dsi);
1594 if (ret)
1595 return ret;
1596 dsi->state |= DSIM_STATE_INITIALIZED;
1597 }
1598
1599 ret = mipi_dsi_create_packet(&xfer.packet, msg);
1600 if (ret < 0)
1601 return ret;
1602
1603 xfer.rx_len = msg->rx_len;
1604 xfer.rx_payload = msg->rx_buf;
1605 xfer.flags = msg->flags;
1606
1607 ret = exynos_dsi_transfer(dsi, &xfer);
1608 return (ret < 0) ? ret : xfer.rx_done;
1609}
1610
1611static const struct mipi_dsi_host_ops exynos_dsi_ops = {
1612 .attach = exynos_dsi_host_attach,
1613 .detach = exynos_dsi_host_detach,
1614 .transfer = exynos_dsi_host_transfer,
1615};
1616
1614static int exynos_dsi_of_read_u32(const struct device_node *np, 1617static int exynos_dsi_of_read_u32(const struct device_node *np,
1615 const char *propname, u32 *out_value) 1618 const char *propname, u32 *out_value)
1616{ 1619{
@@ -1662,20 +1665,15 @@ static int exynos_dsi_bind(struct device *dev, struct device *master,
1662 struct drm_bridge *bridge; 1665 struct drm_bridge *bridge;
1663 int ret; 1666 int ret;
1664 1667
1665 ret = exynos_drm_crtc_get_pipe_from_type(drm_dev,
1666 EXYNOS_DISPLAY_TYPE_LCD);
1667 if (ret < 0)
1668 return ret;
1669
1670 encoder->possible_crtcs = 1 << ret;
1671
1672 DRM_DEBUG_KMS("possible_crtcs = 0x%x\n", encoder->possible_crtcs);
1673
1674 drm_encoder_init(drm_dev, encoder, &exynos_dsi_encoder_funcs, 1668 drm_encoder_init(drm_dev, encoder, &exynos_dsi_encoder_funcs,
1675 DRM_MODE_ENCODER_TMDS, NULL); 1669 DRM_MODE_ENCODER_TMDS, NULL);
1676 1670
1677 drm_encoder_helper_add(encoder, &exynos_dsi_encoder_helper_funcs); 1671 drm_encoder_helper_add(encoder, &exynos_dsi_encoder_helper_funcs);
1678 1672
1673 ret = exynos_drm_set_possible_crtcs(encoder, EXYNOS_DISPLAY_TYPE_LCD);
1674 if (ret < 0)
1675 return ret;
1676
1679 ret = exynos_dsi_create_connector(encoder); 1677 ret = exynos_dsi_create_connector(encoder);
1680 if (ret) { 1678 if (ret) {
1681 DRM_ERROR("failed to create connector ret = %d\n", ret); 1679 DRM_ERROR("failed to create connector ret = %d\n", ret);
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fb.c b/drivers/gpu/drm/exynos/exynos_drm_fb.c
index 6592f50d460a..8208df56a88f 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fb.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fb.c
@@ -225,4 +225,6 @@ void exynos_drm_mode_config_init(struct drm_device *dev)
225 225
226 dev->mode_config.funcs = &exynos_drm_mode_config_funcs; 226 dev->mode_config.funcs = &exynos_drm_mode_config_funcs;
227 dev->mode_config.helper_private = &exynos_drm_mode_config_helpers; 227 dev->mode_config.helper_private = &exynos_drm_mode_config_helpers;
228
229 dev->mode_config.allow_fb_modifiers = true;
228} 230}
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
index 60f93cad6643..d42ae2bc3e56 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
@@ -583,18 +583,12 @@ static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win,
583 val |= WINCONx_BURSTLEN_16WORD; 583 val |= WINCONx_BURSTLEN_16WORD;
584 break; 584 break;
585 case DRM_FORMAT_ARGB8888: 585 case DRM_FORMAT_ARGB8888:
586 default:
586 val |= WINCON1_BPPMODE_25BPP_A1888 587 val |= WINCON1_BPPMODE_25BPP_A1888
587 | WINCON1_BLD_PIX | WINCON1_ALPHA_SEL; 588 | WINCON1_BLD_PIX | WINCON1_ALPHA_SEL;
588 val |= WINCONx_WSWP; 589 val |= WINCONx_WSWP;
589 val |= WINCONx_BURSTLEN_16WORD; 590 val |= WINCONx_BURSTLEN_16WORD;
590 break; 591 break;
591 default:
592 DRM_DEBUG_KMS("invalid pixel size so using unpacked 24bpp.\n");
593
594 val |= WINCON0_BPPMODE_24BPP_888;
595 val |= WINCONx_WSWP;
596 val |= WINCONx_BURSTLEN_16WORD;
597 break;
598 } 592 }
599 593
600 /* 594 /*
@@ -718,13 +712,13 @@ static void fimd_update_plane(struct exynos_drm_crtc *crtc,
718 unsigned long val, size, offset; 712 unsigned long val, size, offset;
719 unsigned int last_x, last_y, buf_offsize, line_size; 713 unsigned int last_x, last_y, buf_offsize, line_size;
720 unsigned int win = plane->index; 714 unsigned int win = plane->index;
721 unsigned int bpp = fb->format->cpp[0]; 715 unsigned int cpp = fb->format->cpp[0];
722 unsigned int pitch = fb->pitches[0]; 716 unsigned int pitch = fb->pitches[0];
723 717
724 if (ctx->suspended) 718 if (ctx->suspended)
725 return; 719 return;
726 720
727 offset = state->src.x * bpp; 721 offset = state->src.x * cpp;
728 offset += state->src.y * pitch; 722 offset += state->src.y * pitch;
729 723
730 /* buffer start address */ 724 /* buffer start address */
@@ -743,8 +737,8 @@ static void fimd_update_plane(struct exynos_drm_crtc *crtc,
743 state->crtc.w, state->crtc.h); 737 state->crtc.w, state->crtc.h);
744 738
745 /* buffer size */ 739 /* buffer size */
746 buf_offsize = pitch - (state->crtc.w * bpp); 740 buf_offsize = pitch - (state->crtc.w * cpp);
747 line_size = state->crtc.w * bpp; 741 line_size = state->crtc.w * cpp;
748 val = VIDW_BUF_SIZE_OFFSET(buf_offsize) | 742 val = VIDW_BUF_SIZE_OFFSET(buf_offsize) |
749 VIDW_BUF_SIZE_PAGEWIDTH(line_size) | 743 VIDW_BUF_SIZE_PAGEWIDTH(line_size) |
750 VIDW_BUF_SIZE_OFFSET_E(buf_offsize) | 744 VIDW_BUF_SIZE_OFFSET_E(buf_offsize) |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_mic.c b/drivers/gpu/drm/exynos/exynos_drm_mic.c
index 16bbee897e0d..ba4a32b132ba 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_mic.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_mic.c
@@ -21,9 +21,12 @@
21#include <linux/component.h> 21#include <linux/component.h>
22#include <linux/pm_runtime.h> 22#include <linux/pm_runtime.h>
23#include <drm/drmP.h> 23#include <drm/drmP.h>
24#include <drm/drm_encoder.h>
24#include <linux/mfd/syscon.h> 25#include <linux/mfd/syscon.h>
25#include <linux/regmap.h> 26#include <linux/regmap.h>
26 27
28#include "exynos_drm_drv.h"
29
27/* Sysreg registers for MIC */ 30/* Sysreg registers for MIC */
28#define DSD_CFG_MUX 0x1004 31#define DSD_CFG_MUX 0x1004
29#define MIC0_RGB_MUX (1 << 0) 32#define MIC0_RGB_MUX (1 << 0)
@@ -85,12 +88,6 @@
85 88
86#define MIC_BS_SIZE_2D(x) ((x) & 0x3fff) 89#define MIC_BS_SIZE_2D(x) ((x) & 0x3fff)
87 90
88enum {
89 ENDPOINT_DECON_NODE,
90 ENDPOINT_DSI_NODE,
91 NUM_ENDPOINTS
92};
93
94static char *clk_names[] = { "pclk_mic0", "sclk_rgb_vclk_to_mic0" }; 91static char *clk_names[] = { "pclk_mic0", "sclk_rgb_vclk_to_mic0" };
95#define NUM_CLKS ARRAY_SIZE(clk_names) 92#define NUM_CLKS ARRAY_SIZE(clk_names)
96static DEFINE_MUTEX(mic_mutex); 93static DEFINE_MUTEX(mic_mutex);
@@ -229,36 +226,6 @@ static void mic_set_reg_on(struct exynos_mic *mic, bool enable)
229 writel(reg, mic->reg + MIC_OP); 226 writel(reg, mic->reg + MIC_OP);
230} 227}
231 228
232static int parse_dt(struct exynos_mic *mic)
233{
234 int ret = 0, i, j;
235 struct device_node *remote_node;
236 struct device_node *nodes[3];
237
238 /*
239 * The order of endpoints does matter.
240 * The first node must be for decon and the second one must be for dsi.
241 */
242 for (i = 0, j = 0; i < NUM_ENDPOINTS; i++) {
243 remote_node = of_graph_get_remote_node(mic->dev->of_node, i, 0);
244 if (!remote_node) {
245 ret = -EPIPE;
246 goto exit;
247 }
248 nodes[j++] = remote_node;
249
250 if (i == ENDPOINT_DECON_NODE &&
251 of_get_child_by_name(remote_node, "i80-if-timings"))
252 mic->i80_mode = 1;
253 }
254
255exit:
256 while (--j > -1)
257 of_node_put(nodes[j]);
258
259 return ret;
260}
261
262static void mic_disable(struct drm_bridge *bridge) { } 229static void mic_disable(struct drm_bridge *bridge) { }
263 230
264static void mic_post_disable(struct drm_bridge *bridge) 231static void mic_post_disable(struct drm_bridge *bridge)
@@ -286,6 +253,7 @@ static void mic_mode_set(struct drm_bridge *bridge,
286 253
287 mutex_lock(&mic_mutex); 254 mutex_lock(&mic_mutex);
288 drm_display_mode_to_videomode(mode, &mic->vm); 255 drm_display_mode_to_videomode(mode, &mic->vm);
256 mic->i80_mode = to_exynos_crtc(bridge->encoder->crtc)->i80_mode;
289 mutex_unlock(&mic_mutex); 257 mutex_unlock(&mic_mutex);
290} 258}
291 259
@@ -417,10 +385,6 @@ static int exynos_mic_probe(struct platform_device *pdev)
417 385
418 mic->dev = dev; 386 mic->dev = dev;
419 387
420 ret = parse_dt(mic);
421 if (ret)
422 goto err;
423
424 ret = of_address_to_resource(dev->of_node, 0, &res); 388 ret = of_address_to_resource(dev->of_node, 0, &res);
425 if (ret) { 389 if (ret) {
426 DRM_ERROR("mic: Failed to get mem region for MIC\n"); 390 DRM_ERROR("mic: Failed to get mem region for MIC\n");
diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c
index 8de74009dee4..d2a90dae5c71 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_plane.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c
@@ -179,6 +179,29 @@ static struct drm_plane_funcs exynos_plane_funcs = {
179}; 179};
180 180
181static int 181static int
182exynos_drm_plane_check_format(const struct exynos_drm_plane_config *config,
183 struct exynos_drm_plane_state *state)
184{
185 struct drm_framebuffer *fb = state->base.fb;
186
187 switch (fb->modifier) {
188 case DRM_FORMAT_MOD_SAMSUNG_64_32_TILE:
189 if (!(config->capabilities & EXYNOS_DRM_PLANE_CAP_TILE))
190 return -ENOTSUPP;
191 break;
192
193 case DRM_FORMAT_MOD_LINEAR:
194 break;
195
196 default:
197 DRM_ERROR("unsupported pixel format modifier");
198 return -ENOTSUPP;
199 }
200
201 return 0;
202}
203
204static int
182exynos_drm_plane_check_size(const struct exynos_drm_plane_config *config, 205exynos_drm_plane_check_size(const struct exynos_drm_plane_config *config,
183 struct exynos_drm_plane_state *state) 206 struct exynos_drm_plane_state *state)
184{ 207{
@@ -222,6 +245,10 @@ static int exynos_plane_atomic_check(struct drm_plane *plane,
222 /* translate state into exynos_state */ 245 /* translate state into exynos_state */
223 exynos_plane_mode_set(exynos_state); 246 exynos_plane_mode_set(exynos_state);
224 247
248 ret = exynos_drm_plane_check_format(exynos_plane->config, exynos_state);
249 if (ret)
250 return ret;
251
225 ret = exynos_drm_plane_check_size(exynos_plane->config, exynos_state); 252 ret = exynos_drm_plane_check_size(exynos_plane->config, exynos_state);
226 return ret; 253 return ret;
227} 254}
diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
index 9186a654c3b5..53e03f8af3d5 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
@@ -381,7 +381,7 @@ static int vidi_bind(struct device *dev, struct device *master, void *data)
381 struct exynos_drm_plane *exynos_plane; 381 struct exynos_drm_plane *exynos_plane;
382 struct exynos_drm_plane_config plane_config = { 0 }; 382 struct exynos_drm_plane_config plane_config = { 0 };
383 unsigned int i; 383 unsigned int i;
384 int pipe, ret; 384 int ret;
385 385
386 ctx->drm_dev = drm_dev; 386 ctx->drm_dev = drm_dev;
387 387
@@ -406,20 +406,15 @@ static int vidi_bind(struct device *dev, struct device *master, void *data)
406 return PTR_ERR(ctx->crtc); 406 return PTR_ERR(ctx->crtc);
407 } 407 }
408 408
409 pipe = exynos_drm_crtc_get_pipe_from_type(drm_dev,
410 EXYNOS_DISPLAY_TYPE_VIDI);
411 if (pipe < 0)
412 return pipe;
413
414 encoder->possible_crtcs = 1 << pipe;
415
416 DRM_DEBUG_KMS("possible_crtcs = 0x%x\n", encoder->possible_crtcs);
417
418 drm_encoder_init(drm_dev, encoder, &exynos_vidi_encoder_funcs, 409 drm_encoder_init(drm_dev, encoder, &exynos_vidi_encoder_funcs,
419 DRM_MODE_ENCODER_TMDS, NULL); 410 DRM_MODE_ENCODER_TMDS, NULL);
420 411
421 drm_encoder_helper_add(encoder, &exynos_vidi_encoder_helper_funcs); 412 drm_encoder_helper_add(encoder, &exynos_vidi_encoder_helper_funcs);
422 413
414 ret = exynos_drm_set_possible_crtcs(encoder, EXYNOS_DISPLAY_TYPE_VIDI);
415 if (ret < 0)
416 return ret;
417
423 ret = vidi_create_connector(encoder); 418 ret = vidi_create_connector(encoder);
424 if (ret) { 419 if (ret) {
425 DRM_ERROR("failed to create connector ret = %d\n", ret); 420 DRM_ERROR("failed to create connector ret = %d\n", ret);
diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c
index d70eeb8c5f75..214fa5e51963 100644
--- a/drivers/gpu/drm/exynos/exynos_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
@@ -1697,32 +1697,25 @@ static int hdmi_bind(struct device *dev, struct device *master, void *data)
1697 struct drm_device *drm_dev = data; 1697 struct drm_device *drm_dev = data;
1698 struct hdmi_context *hdata = dev_get_drvdata(dev); 1698 struct hdmi_context *hdata = dev_get_drvdata(dev);
1699 struct drm_encoder *encoder = &hdata->encoder; 1699 struct drm_encoder *encoder = &hdata->encoder;
1700 struct exynos_drm_crtc *exynos_crtc; 1700 struct exynos_drm_crtc *crtc;
1701 struct drm_crtc *crtc; 1701 int ret;
1702 int ret, pipe;
1703 1702
1704 hdata->drm_dev = drm_dev; 1703 hdata->drm_dev = drm_dev;
1705 1704
1706 pipe = exynos_drm_crtc_get_pipe_from_type(drm_dev,
1707 EXYNOS_DISPLAY_TYPE_HDMI);
1708 if (pipe < 0)
1709 return pipe;
1710
1711 hdata->phy_clk.enable = hdmiphy_clk_enable; 1705 hdata->phy_clk.enable = hdmiphy_clk_enable;
1712 1706
1713 crtc = drm_crtc_from_index(drm_dev, pipe);
1714 exynos_crtc = to_exynos_crtc(crtc);
1715 exynos_crtc->pipe_clk = &hdata->phy_clk;
1716
1717 encoder->possible_crtcs = 1 << pipe;
1718
1719 DRM_DEBUG_KMS("possible_crtcs = 0x%x\n", encoder->possible_crtcs);
1720
1721 drm_encoder_init(drm_dev, encoder, &exynos_hdmi_encoder_funcs, 1707 drm_encoder_init(drm_dev, encoder, &exynos_hdmi_encoder_funcs,
1722 DRM_MODE_ENCODER_TMDS, NULL); 1708 DRM_MODE_ENCODER_TMDS, NULL);
1723 1709
1724 drm_encoder_helper_add(encoder, &exynos_hdmi_encoder_helper_funcs); 1710 drm_encoder_helper_add(encoder, &exynos_hdmi_encoder_helper_funcs);
1725 1711
1712 ret = exynos_drm_set_possible_crtcs(encoder, EXYNOS_DISPLAY_TYPE_HDMI);
1713 if (ret < 0)
1714 return ret;
1715
1716 crtc = exynos_drm_crtc_get_by_type(drm_dev, EXYNOS_DISPLAY_TYPE_HDMI);
1717 crtc->pipe_clk = &hdata->phy_clk;
1718
1726 ret = hdmi_create_connector(encoder); 1719 ret = hdmi_create_connector(encoder);
1727 if (ret) { 1720 if (ret) {
1728 DRM_ERROR("failed to create connector ret = %d\n", ret); 1721 DRM_ERROR("failed to create connector ret = %d\n", ret);
diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c
index a998a8dd783c..002755415e00 100644
--- a/drivers/gpu/drm/exynos/exynos_mixer.c
+++ b/drivers/gpu/drm/exynos/exynos_mixer.c
@@ -148,7 +148,8 @@ static const struct exynos_drm_plane_config plane_configs[MIXER_WIN_NR] = {
148 .pixel_formats = vp_formats, 148 .pixel_formats = vp_formats,
149 .num_pixel_formats = ARRAY_SIZE(vp_formats), 149 .num_pixel_formats = ARRAY_SIZE(vp_formats),
150 .capabilities = EXYNOS_DRM_PLANE_CAP_SCALE | 150 .capabilities = EXYNOS_DRM_PLANE_CAP_SCALE |
151 EXYNOS_DRM_PLANE_CAP_ZPOS, 151 EXYNOS_DRM_PLANE_CAP_ZPOS |
152 EXYNOS_DRM_PLANE_CAP_TILE,
152 }, 153 },
153}; 154};
154 155
@@ -483,29 +484,18 @@ static void vp_video_buffer(struct mixer_context *ctx,
483 unsigned int priority = state->base.normalized_zpos + 1; 484 unsigned int priority = state->base.normalized_zpos + 1;
484 unsigned long flags; 485 unsigned long flags;
485 dma_addr_t luma_addr[2], chroma_addr[2]; 486 dma_addr_t luma_addr[2], chroma_addr[2];
486 bool tiled_mode = false; 487 bool is_tiled, is_nv21;
487 bool crcb_mode = false;
488 u32 val; 488 u32 val;
489 489
490 switch (fb->format->format) { 490 is_nv21 = (fb->format->format == DRM_FORMAT_NV21);
491 case DRM_FORMAT_NV12: 491 is_tiled = (fb->modifier == DRM_FORMAT_MOD_SAMSUNG_64_32_TILE);
492 crcb_mode = false;
493 break;
494 case DRM_FORMAT_NV21:
495 crcb_mode = true;
496 break;
497 default:
498 DRM_ERROR("pixel format for vp is wrong [%d].\n",
499 fb->format->format);
500 return;
501 }
502 492
503 luma_addr[0] = exynos_drm_fb_dma_addr(fb, 0); 493 luma_addr[0] = exynos_drm_fb_dma_addr(fb, 0);
504 chroma_addr[0] = exynos_drm_fb_dma_addr(fb, 1); 494 chroma_addr[0] = exynos_drm_fb_dma_addr(fb, 1);
505 495
506 if (mode->flags & DRM_MODE_FLAG_INTERLACE) { 496 if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
507 __set_bit(MXR_BIT_INTERLACE, &ctx->flags); 497 __set_bit(MXR_BIT_INTERLACE, &ctx->flags);
508 if (tiled_mode) { 498 if (is_tiled) {
509 luma_addr[1] = luma_addr[0] + 0x40; 499 luma_addr[1] = luma_addr[0] + 0x40;
510 chroma_addr[1] = chroma_addr[0] + 0x40; 500 chroma_addr[1] = chroma_addr[0] + 0x40;
511 } else { 501 } else {
@@ -525,14 +515,14 @@ static void vp_video_buffer(struct mixer_context *ctx,
525 vp_reg_writemask(res, VP_MODE, val, VP_MODE_LINE_SKIP); 515 vp_reg_writemask(res, VP_MODE, val, VP_MODE_LINE_SKIP);
526 516
527 /* setup format */ 517 /* setup format */
528 val = (crcb_mode ? VP_MODE_NV21 : VP_MODE_NV12); 518 val = (is_nv21 ? VP_MODE_NV21 : VP_MODE_NV12);
529 val |= (tiled_mode ? VP_MODE_MEM_TILED : VP_MODE_MEM_LINEAR); 519 val |= (is_tiled ? VP_MODE_MEM_TILED : VP_MODE_MEM_LINEAR);
530 vp_reg_writemask(res, VP_MODE, val, VP_MODE_FMT_MASK); 520 vp_reg_writemask(res, VP_MODE, val, VP_MODE_FMT_MASK);
531 521
532 /* setting size of input image */ 522 /* setting size of input image */
533 vp_reg_write(res, VP_IMG_SIZE_Y, VP_IMG_HSIZE(fb->pitches[0]) | 523 vp_reg_write(res, VP_IMG_SIZE_Y, VP_IMG_HSIZE(fb->pitches[0]) |
534 VP_IMG_VSIZE(fb->height)); 524 VP_IMG_VSIZE(fb->height));
535 /* chroma height has to reduced by 2 to avoid chroma distorions */ 525 /* chroma plane for NV12/NV21 is half the height of the luma plane */
536 vp_reg_write(res, VP_IMG_SIZE_C, VP_IMG_HSIZE(fb->pitches[0]) | 526 vp_reg_write(res, VP_IMG_SIZE_C, VP_IMG_HSIZE(fb->pitches[0]) |
537 VP_IMG_VSIZE(fb->height / 2)); 527 VP_IMG_VSIZE(fb->height / 2));
538 528
@@ -594,7 +584,7 @@ static void mixer_graph_buffer(struct mixer_context *ctx,
594 unsigned long flags; 584 unsigned long flags;
595 unsigned int win = plane->index; 585 unsigned int win = plane->index;
596 unsigned int x_ratio = 0, y_ratio = 0; 586 unsigned int x_ratio = 0, y_ratio = 0;
597 unsigned int src_x_offset, src_y_offset, dst_x_offset, dst_y_offset; 587 unsigned int dst_x_offset, dst_y_offset;
598 dma_addr_t dma_addr; 588 dma_addr_t dma_addr;
599 unsigned int fmt; 589 unsigned int fmt;
600 u32 val; 590 u32 val;
@@ -616,12 +606,9 @@ static void mixer_graph_buffer(struct mixer_context *ctx,
616 606
617 case DRM_FORMAT_XRGB8888: 607 case DRM_FORMAT_XRGB8888:
618 case DRM_FORMAT_ARGB8888: 608 case DRM_FORMAT_ARGB8888:
609 default:
619 fmt = MXR_FORMAT_ARGB8888; 610 fmt = MXR_FORMAT_ARGB8888;
620 break; 611 break;
621
622 default:
623 DRM_DEBUG_KMS("pixelformat unsupported by mixer\n");
624 return;
625 } 612 }
626 613
627 /* ratio is already checked by common plane code */ 614 /* ratio is already checked by common plane code */
@@ -631,12 +618,10 @@ static void mixer_graph_buffer(struct mixer_context *ctx,
631 dst_x_offset = state->crtc.x; 618 dst_x_offset = state->crtc.x;
632 dst_y_offset = state->crtc.y; 619 dst_y_offset = state->crtc.y;
633 620
634 /* converting dma address base and source offset */ 621 /* translate dma address base s.t. the source image offset is zero */
635 dma_addr = exynos_drm_fb_dma_addr(fb, 0) 622 dma_addr = exynos_drm_fb_dma_addr(fb, 0)
636 + (state->src.x * fb->format->cpp[0]) 623 + (state->src.x * fb->format->cpp[0])
637 + (state->src.y * fb->pitches[0]); 624 + (state->src.y * fb->pitches[0]);
638 src_x_offset = 0;
639 src_y_offset = 0;
640 625
641 if (mode->flags & DRM_MODE_FLAG_INTERLACE) 626 if (mode->flags & DRM_MODE_FLAG_INTERLACE)
642 __set_bit(MXR_BIT_INTERLACE, &ctx->flags); 627 __set_bit(MXR_BIT_INTERLACE, &ctx->flags);
@@ -667,11 +652,6 @@ static void mixer_graph_buffer(struct mixer_context *ctx,
667 val |= MXR_GRP_WH_V_SCALE(y_ratio); 652 val |= MXR_GRP_WH_V_SCALE(y_ratio);
668 mixer_reg_write(res, MXR_GRAPHIC_WH(win), val); 653 mixer_reg_write(res, MXR_GRAPHIC_WH(win), val);
669 654
670 /* setup offsets in source image */
671 val = MXR_GRP_SXY_SX(src_x_offset);
672 val |= MXR_GRP_SXY_SY(src_y_offset);
673 mixer_reg_write(res, MXR_GRAPHIC_SXY(win), val);
674
675 /* setup offsets in display image */ 655 /* setup offsets in display image */
676 val = MXR_GRP_DXY_DX(dst_x_offset); 656 val = MXR_GRP_DXY_DX(dst_x_offset);
677 val |= MXR_GRP_DXY_DY(dst_y_offset); 657 val |= MXR_GRP_DXY_DY(dst_y_offset);
@@ -748,6 +728,10 @@ static void mixer_win_reset(struct mixer_context *ctx)
748 if (test_bit(MXR_BIT_VP_ENABLED, &ctx->flags)) 728 if (test_bit(MXR_BIT_VP_ENABLED, &ctx->flags))
749 mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_VP_ENABLE); 729 mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_VP_ENABLE);
750 730
731 /* set all source image offsets to zero */
732 mixer_reg_write(res, MXR_GRAPHIC_SXY(0), 0);
733 mixer_reg_write(res, MXR_GRAPHIC_SXY(1), 0);
734
751 spin_unlock_irqrestore(&res->reg_slock, flags); 735 spin_unlock_irqrestore(&res->reg_slock, flags);
752} 736}
753 737