1 // SPDX-License-Identifier: GPL-2.0-or-later
4 * Copyright (C) 2011 Samsung Electronics Co.Ltd
6 * Joonyoung Shim <jy0922.shim@samsung.com>
7 * Inki Dae <inki.dae@samsung.com>
10 #include <linux/clk.h>
11 #include <linux/component.h>
12 #include <linux/kernel.h>
13 #include <linux/mfd/syscon.h>
15 #include <linux/platform_device.h>
16 #include <linux/pm_runtime.h>
17 #include <linux/regmap.h>
19 #include <video/of_display_timing.h>
20 #include <video/of_videomode.h>
21 #include <video/samsung_fimd.h>
23 #include <drm/drm_blend.h>
24 #include <drm/drm_fourcc.h>
25 #include <drm/drm_framebuffer.h>
26 #include <drm/drm_vblank.h>
27 #include <drm/exynos_drm.h>
29 #include "exynos_drm_crtc.h"
30 #include "exynos_drm_drv.h"
31 #include "exynos_drm_fb.h"
32 #include "exynos_drm_plane.h"
35 * FIMD stands for Fully Interactive Mobile Display and
36 * as a display controller, it transfers contents drawn on memory
37 * to a LCD Panel through Display Interfaces such as RGB or
41 #define MIN_FB_WIDTH_FOR_16WORD_BURST 128
43 /* position control register for hardware window 0, 2 ~ 4.*/
44 #define VIDOSD_A(win) (VIDOSD_BASE + 0x00 + (win) * 16)
45 #define VIDOSD_B(win) (VIDOSD_BASE + 0x04 + (win) * 16)
47 * size control register for hardware windows 0 and alpha control register
48 * for hardware windows 1 ~ 4
50 #define VIDOSD_C(win) (VIDOSD_BASE + 0x08 + (win) * 16)
51 /* size control register for hardware windows 1 ~ 2. */
52 #define VIDOSD_D(win) (VIDOSD_BASE + 0x0C + (win) * 16)
54 #define VIDWnALPHA0(win) (VIDW_ALPHA + 0x00 + (win) * 8)
55 #define VIDWnALPHA1(win) (VIDW_ALPHA + 0x04 + (win) * 8)
57 #define VIDWx_BUF_START(win, buf) (VIDW_BUF_START(buf) + (win) * 8)
58 #define VIDWx_BUF_START_S(win, buf) (VIDW_BUF_START_S(buf) + (win) * 8)
59 #define VIDWx_BUF_END(win, buf) (VIDW_BUF_END(buf) + (win) * 8)
60 #define VIDWx_BUF_SIZE(win, buf) (VIDW_BUF_SIZE(buf) + (win) * 4)
62 /* color key control register for hardware window 1 ~ 4. */
63 #define WKEYCON0_BASE(x) ((WKEYCON0 + 0x140) + ((x - 1) * 8))
64 /* color key value register for hardware window 1 ~ 4. */
65 #define WKEYCON1_BASE(x) ((WKEYCON1 + 0x140) + ((x - 1) * 8))
67 /* I80 trigger control register */
69 #define TRGMODE_ENABLE (1 << 0)
70 #define SWTRGCMD_ENABLE (1 << 1)
71 /* Exynos3250, 3472, 5260 5410, 5420 and 5422 only supported. */
72 #define HWTRGEN_ENABLE (1 << 3)
73 #define HWTRGMASK_ENABLE (1 << 4)
74 /* Exynos3250, 3472, 5260, 5420 and 5422 only supported. */
75 #define HWTRIGEN_PER_ENABLE (1 << 31)
77 /* display mode change control register except exynos4 */
78 #define VIDOUT_CON 0x000
79 #define VIDOUT_CON_F_I80_LDI0 (0x2 << 8)
81 /* I80 interface control for main LDI register */
82 #define I80IFCONFAx(x) (0x1B0 + (x) * 4)
83 #define I80IFCONFBx(x) (0x1B8 + (x) * 4)
84 #define LCD_CS_SETUP(x) ((x) << 16)
85 #define LCD_WR_SETUP(x) ((x) << 12)
86 #define LCD_WR_ACTIVE(x) ((x) << 8)
87 #define LCD_WR_HOLD(x) ((x) << 4)
88 #define I80IFEN_ENABLE (1 << 0)
90 /* FIMD has totally five hardware windows. */
93 /* HW trigger flag on i80 panel. */
94 #define I80_HW_TRG (1 << 1)
96 struct fimd_driver_data
{
97 unsigned int timing_base
;
98 unsigned int lcdblk_offset
;
99 unsigned int lcdblk_vt_shift
;
100 unsigned int lcdblk_bypass_shift
;
101 unsigned int lcdblk_mic_bypass_shift
;
102 unsigned int trg_type
;
104 unsigned int has_shadowcon
:1;
105 unsigned int has_clksel
:1;
106 unsigned int has_limited_fmt
:1;
107 unsigned int has_vidoutcon
:1;
108 unsigned int has_vtsel
:1;
109 unsigned int has_mic_bypass
:1;
110 unsigned int has_dp_clk
:1;
111 unsigned int has_hw_trigger
:1;
112 unsigned int has_trigger_per_te
:1;
113 unsigned int has_bgr_support
:1;
116 static struct fimd_driver_data s3c64xx_fimd_driver_data
= {
119 .has_limited_fmt
= 1,
122 static struct fimd_driver_data s5pv210_fimd_driver_data
= {
128 static struct fimd_driver_data exynos3_fimd_driver_data
= {
129 .timing_base
= 0x20000,
130 .lcdblk_offset
= 0x210,
131 .lcdblk_bypass_shift
= 1,
136 static struct fimd_driver_data exynos4_fimd_driver_data
= {
138 .lcdblk_offset
= 0x210,
139 .lcdblk_vt_shift
= 10,
140 .lcdblk_bypass_shift
= 1,
143 .has_bgr_support
= 1,
146 static struct fimd_driver_data exynos5_fimd_driver_data
= {
147 .timing_base
= 0x20000,
148 .lcdblk_offset
= 0x214,
149 .lcdblk_vt_shift
= 24,
150 .lcdblk_bypass_shift
= 15,
155 .has_bgr_support
= 1,
158 static struct fimd_driver_data exynos5420_fimd_driver_data
= {
159 .timing_base
= 0x20000,
160 .lcdblk_offset
= 0x214,
161 .lcdblk_vt_shift
= 24,
162 .lcdblk_bypass_shift
= 15,
163 .lcdblk_mic_bypass_shift
= 11,
169 .has_bgr_support
= 1,
172 struct fimd_context
{
174 struct drm_device
*drm_dev
;
176 struct exynos_drm_crtc
*crtc
;
177 struct exynos_drm_plane planes
[WINDOWS_NR
];
178 struct exynos_drm_plane_config configs
[WINDOWS_NR
];
182 struct regmap
*sysreg
;
183 unsigned long irq_flags
;
190 wait_queue_head_t wait_vsync_queue
;
191 atomic_t wait_vsync_event
;
192 atomic_t win_updated
;
196 const struct fimd_driver_data
*driver_data
;
197 struct drm_encoder
*encoder
;
198 struct exynos_drm_clk dp_clk
;
201 static const struct of_device_id fimd_driver_dt_match
[] = {
202 { .compatible
= "samsung,s3c6400-fimd",
203 .data
= &s3c64xx_fimd_driver_data
},
204 { .compatible
= "samsung,s5pv210-fimd",
205 .data
= &s5pv210_fimd_driver_data
},
206 { .compatible
= "samsung,exynos3250-fimd",
207 .data
= &exynos3_fimd_driver_data
},
208 { .compatible
= "samsung,exynos4210-fimd",
209 .data
= &exynos4_fimd_driver_data
},
210 { .compatible
= "samsung,exynos5250-fimd",
211 .data
= &exynos5_fimd_driver_data
},
212 { .compatible
= "samsung,exynos5420-fimd",
213 .data
= &exynos5420_fimd_driver_data
},
216 MODULE_DEVICE_TABLE(of
, fimd_driver_dt_match
);
218 static const enum drm_plane_type fimd_win_types
[WINDOWS_NR
] = {
219 DRM_PLANE_TYPE_PRIMARY
,
220 DRM_PLANE_TYPE_OVERLAY
,
221 DRM_PLANE_TYPE_OVERLAY
,
222 DRM_PLANE_TYPE_OVERLAY
,
223 DRM_PLANE_TYPE_CURSOR
,
226 static const uint32_t fimd_formats
[] = {
234 static const uint32_t fimd_extended_formats
[] = {
246 static const unsigned int capabilities
[WINDOWS_NR
] = {
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 EXYNOS_DRM_PLANE_CAP_WIN_BLEND
| EXYNOS_DRM_PLANE_CAP_PIX_BLEND
,
254 static inline void fimd_set_bits(struct fimd_context
*ctx
, u32 reg
, u32 mask
,
257 val
= (val
& mask
) | (readl(ctx
->regs
+ reg
) & ~mask
);
258 writel(val
, ctx
->regs
+ reg
);
261 static int fimd_enable_vblank(struct exynos_drm_crtc
*crtc
)
263 struct fimd_context
*ctx
= crtc
->ctx
;
269 if (!test_and_set_bit(0, &ctx
->irq_flags
)) {
270 val
= readl(ctx
->regs
+ VIDINTCON0
);
272 val
|= VIDINTCON0_INT_ENABLE
;
275 val
|= VIDINTCON0_INT_I80IFDONE
;
276 val
|= VIDINTCON0_INT_SYSMAINCON
;
277 val
&= ~VIDINTCON0_INT_SYSSUBCON
;
279 val
|= VIDINTCON0_INT_FRAME
;
281 val
&= ~VIDINTCON0_FRAMESEL0_MASK
;
282 val
|= VIDINTCON0_FRAMESEL0_FRONTPORCH
;
283 val
&= ~VIDINTCON0_FRAMESEL1_MASK
;
284 val
|= VIDINTCON0_FRAMESEL1_NONE
;
287 writel(val
, ctx
->regs
+ VIDINTCON0
);
293 static void fimd_disable_vblank(struct exynos_drm_crtc
*crtc
)
295 struct fimd_context
*ctx
= crtc
->ctx
;
301 if (test_and_clear_bit(0, &ctx
->irq_flags
)) {
302 val
= readl(ctx
->regs
+ VIDINTCON0
);
304 val
&= ~VIDINTCON0_INT_ENABLE
;
307 val
&= ~VIDINTCON0_INT_I80IFDONE
;
308 val
&= ~VIDINTCON0_INT_SYSMAINCON
;
309 val
&= ~VIDINTCON0_INT_SYSSUBCON
;
311 val
&= ~VIDINTCON0_INT_FRAME
;
313 writel(val
, ctx
->regs
+ VIDINTCON0
);
317 static void fimd_wait_for_vblank(struct exynos_drm_crtc
*crtc
)
319 struct fimd_context
*ctx
= crtc
->ctx
;
324 atomic_set(&ctx
->wait_vsync_event
, 1);
327 * wait for FIMD to signal VSYNC interrupt or return after
328 * timeout which is set to 50ms (refresh rate of 20).
330 if (!wait_event_timeout(ctx
->wait_vsync_queue
,
331 !atomic_read(&ctx
->wait_vsync_event
),
333 DRM_DEV_DEBUG_KMS(ctx
->dev
, "vblank wait timed out.\n");
336 static void fimd_enable_video_output(struct fimd_context
*ctx
, unsigned int win
,
339 u32 val
= readl(ctx
->regs
+ WINCON(win
));
342 val
|= WINCONx_ENWIN
;
344 val
&= ~WINCONx_ENWIN
;
346 writel(val
, ctx
->regs
+ WINCON(win
));
349 static void fimd_enable_shadow_channel_path(struct fimd_context
*ctx
,
353 u32 val
= readl(ctx
->regs
+ SHADOWCON
);
356 val
|= SHADOWCON_CHx_ENABLE(win
);
358 val
&= ~SHADOWCON_CHx_ENABLE(win
);
360 writel(val
, ctx
->regs
+ SHADOWCON
);
363 static int fimd_clear_channels(struct exynos_drm_crtc
*crtc
)
365 struct fimd_context
*ctx
= crtc
->ctx
;
366 unsigned int win
, ch_enabled
= 0;
369 /* Hardware is in unknown state, so ensure it gets enabled properly */
370 ret
= pm_runtime_resume_and_get(ctx
->dev
);
372 dev_err(ctx
->dev
, "failed to enable FIMD device.\n");
376 clk_prepare_enable(ctx
->bus_clk
);
377 clk_prepare_enable(ctx
->lcd_clk
);
379 /* Check if any channel is enabled. */
380 for (win
= 0; win
< WINDOWS_NR
; win
++) {
381 u32 val
= readl(ctx
->regs
+ WINCON(win
));
383 if (val
& WINCONx_ENWIN
) {
384 fimd_enable_video_output(ctx
, win
, false);
386 if (ctx
->driver_data
->has_shadowcon
)
387 fimd_enable_shadow_channel_path(ctx
, win
,
394 /* Wait for vsync, as disable channel takes effect at next vsync */
396 ctx
->suspended
= false;
398 fimd_enable_vblank(ctx
->crtc
);
399 fimd_wait_for_vblank(ctx
->crtc
);
400 fimd_disable_vblank(ctx
->crtc
);
402 ctx
->suspended
= true;
405 clk_disable_unprepare(ctx
->lcd_clk
);
406 clk_disable_unprepare(ctx
->bus_clk
);
408 pm_runtime_put(ctx
->dev
);
414 static int fimd_atomic_check(struct exynos_drm_crtc
*crtc
,
415 struct drm_crtc_state
*state
)
417 struct drm_display_mode
*mode
= &state
->adjusted_mode
;
418 struct fimd_context
*ctx
= crtc
->ctx
;
419 unsigned long ideal_clk
, lcd_rate
;
422 if (mode
->clock
== 0) {
423 DRM_DEV_ERROR(ctx
->dev
, "Mode has zero clock value.\n");
427 ideal_clk
= mode
->clock
* 1000;
431 * The frame done interrupt should be occurred prior to the
437 lcd_rate
= clk_get_rate(ctx
->lcd_clk
);
438 if (2 * lcd_rate
< ideal_clk
) {
439 DRM_DEV_ERROR(ctx
->dev
,
440 "sclk_fimd clock too low(%lu) for requested pixel clock(%lu)\n",
441 lcd_rate
, ideal_clk
);
445 /* Find the clock divider value that gets us closest to ideal_clk */
446 clkdiv
= DIV_ROUND_CLOSEST(lcd_rate
, ideal_clk
);
447 if (clkdiv
>= 0x200) {
448 DRM_DEV_ERROR(ctx
->dev
, "requested pixel clock(%lu) too low\n",
453 ctx
->clkdiv
= (clkdiv
< 0x100) ? clkdiv
: 0xff;
458 static void fimd_setup_trigger(struct fimd_context
*ctx
)
460 void __iomem
*timing_base
= ctx
->regs
+ ctx
->driver_data
->timing_base
;
461 u32 trg_type
= ctx
->driver_data
->trg_type
;
462 u32 val
= readl(timing_base
+ TRIGCON
);
464 val
&= ~(TRGMODE_ENABLE
);
466 if (trg_type
== I80_HW_TRG
) {
467 if (ctx
->driver_data
->has_hw_trigger
)
468 val
|= HWTRGEN_ENABLE
| HWTRGMASK_ENABLE
;
469 if (ctx
->driver_data
->has_trigger_per_te
)
470 val
|= HWTRIGEN_PER_ENABLE
;
472 val
|= TRGMODE_ENABLE
;
475 writel(val
, timing_base
+ TRIGCON
);
478 static void fimd_commit(struct exynos_drm_crtc
*crtc
)
480 struct fimd_context
*ctx
= crtc
->ctx
;
481 struct drm_display_mode
*mode
= &crtc
->base
.state
->adjusted_mode
;
482 const struct fimd_driver_data
*driver_data
= ctx
->driver_data
;
483 void __iomem
*timing_base
= ctx
->regs
+ driver_data
->timing_base
;
489 /* nothing to do if we haven't set the mode yet */
490 if (mode
->htotal
== 0 || mode
->vtotal
== 0)
494 val
= ctx
->i80ifcon
| I80IFEN_ENABLE
;
495 writel(val
, timing_base
+ I80IFCONFAx(0));
497 /* disable auto frame rate */
498 writel(0, timing_base
+ I80IFCONFBx(0));
500 /* set video type selection to I80 interface */
501 if (driver_data
->has_vtsel
&& ctx
->sysreg
&&
502 regmap_update_bits(ctx
->sysreg
,
503 driver_data
->lcdblk_offset
,
504 0x3 << driver_data
->lcdblk_vt_shift
,
505 0x1 << driver_data
->lcdblk_vt_shift
)) {
506 DRM_DEV_ERROR(ctx
->dev
,
507 "Failed to update sysreg for I80 i/f.\n");
511 int vsync_len
, vbpd
, vfpd
, hsync_len
, hbpd
, hfpd
;
514 /* setup polarity values */
515 vidcon1
= ctx
->vidcon1
;
516 if (mode
->flags
& DRM_MODE_FLAG_NVSYNC
)
517 vidcon1
|= VIDCON1_INV_VSYNC
;
518 if (mode
->flags
& DRM_MODE_FLAG_NHSYNC
)
519 vidcon1
|= VIDCON1_INV_HSYNC
;
520 writel(vidcon1
, ctx
->regs
+ driver_data
->timing_base
+ VIDCON1
);
522 /* setup vertical timing values. */
523 vsync_len
= mode
->crtc_vsync_end
- mode
->crtc_vsync_start
;
524 vbpd
= mode
->crtc_vtotal
- mode
->crtc_vsync_end
;
525 vfpd
= mode
->crtc_vsync_start
- mode
->crtc_vdisplay
;
527 val
= VIDTCON0_VBPD(vbpd
- 1) |
528 VIDTCON0_VFPD(vfpd
- 1) |
529 VIDTCON0_VSPW(vsync_len
- 1);
530 writel(val
, ctx
->regs
+ driver_data
->timing_base
+ VIDTCON0
);
532 /* setup horizontal timing values. */
533 hsync_len
= mode
->crtc_hsync_end
- mode
->crtc_hsync_start
;
534 hbpd
= mode
->crtc_htotal
- mode
->crtc_hsync_end
;
535 hfpd
= mode
->crtc_hsync_start
- mode
->crtc_hdisplay
;
537 val
= VIDTCON1_HBPD(hbpd
- 1) |
538 VIDTCON1_HFPD(hfpd
- 1) |
539 VIDTCON1_HSPW(hsync_len
- 1);
540 writel(val
, ctx
->regs
+ driver_data
->timing_base
+ VIDTCON1
);
543 if (driver_data
->has_vidoutcon
)
544 writel(ctx
->vidout_con
, timing_base
+ VIDOUT_CON
);
546 /* set bypass selection */
547 if (ctx
->sysreg
&& regmap_update_bits(ctx
->sysreg
,
548 driver_data
->lcdblk_offset
,
549 0x1 << driver_data
->lcdblk_bypass_shift
,
550 0x1 << driver_data
->lcdblk_bypass_shift
)) {
551 DRM_DEV_ERROR(ctx
->dev
,
552 "Failed to update sysreg for bypass setting.\n");
556 /* TODO: When MIC is enabled for display path, the lcdblk_mic_bypass
557 * bit should be cleared.
559 if (driver_data
->has_mic_bypass
&& ctx
->sysreg
&&
560 regmap_update_bits(ctx
->sysreg
,
561 driver_data
->lcdblk_offset
,
562 0x1 << driver_data
->lcdblk_mic_bypass_shift
,
563 0x1 << driver_data
->lcdblk_mic_bypass_shift
)) {
564 DRM_DEV_ERROR(ctx
->dev
,
565 "Failed to update sysreg for bypass mic.\n");
569 /* setup horizontal and vertical display size. */
570 val
= VIDTCON2_LINEVAL(mode
->vdisplay
- 1) |
571 VIDTCON2_HOZVAL(mode
->hdisplay
- 1) |
572 VIDTCON2_LINEVAL_E(mode
->vdisplay
- 1) |
573 VIDTCON2_HOZVAL_E(mode
->hdisplay
- 1);
574 writel(val
, ctx
->regs
+ driver_data
->timing_base
+ VIDTCON2
);
576 fimd_setup_trigger(ctx
);
579 * fields of register with prefix '_F' would be updated
580 * at vsync(same as dma start)
583 val
|= VIDCON0_ENVID
| VIDCON0_ENVID_F
;
585 if (ctx
->driver_data
->has_clksel
)
586 val
|= VIDCON0_CLKSEL_LCD
;
589 val
|= VIDCON0_CLKVAL_F(ctx
->clkdiv
- 1) | VIDCON0_CLKDIR
;
591 writel(val
, ctx
->regs
+ VIDCON0
);
594 static void fimd_win_set_bldeq(struct fimd_context
*ctx
, unsigned int win
,
595 unsigned int alpha
, unsigned int pixel_alpha
)
597 u32 mask
= BLENDEQ_A_FUNC_F(0xf) | BLENDEQ_B_FUNC_F(0xf);
600 switch (pixel_alpha
) {
601 case DRM_MODE_BLEND_PIXEL_NONE
:
602 case DRM_MODE_BLEND_COVERAGE
:
603 val
|= BLENDEQ_A_FUNC_F(BLENDEQ_ALPHA_A
);
604 val
|= BLENDEQ_B_FUNC_F(BLENDEQ_ONE_MINUS_ALPHA_A
);
606 case DRM_MODE_BLEND_PREMULTI
:
608 if (alpha
!= DRM_BLEND_ALPHA_OPAQUE
) {
609 val
|= BLENDEQ_A_FUNC_F(BLENDEQ_ALPHA0
);
610 val
|= BLENDEQ_B_FUNC_F(BLENDEQ_ONE_MINUS_ALPHA_A
);
612 val
|= BLENDEQ_A_FUNC_F(BLENDEQ_ONE
);
613 val
|= BLENDEQ_B_FUNC_F(BLENDEQ_ONE_MINUS_ALPHA_A
);
617 fimd_set_bits(ctx
, BLENDEQx(win
), mask
, val
);
620 static void fimd_win_set_bldmod(struct fimd_context
*ctx
, unsigned int win
,
621 unsigned int alpha
, unsigned int pixel_alpha
)
623 u32 win_alpha_l
= (alpha
>> 8) & 0xf;
624 u32 win_alpha_h
= alpha
>> 12;
627 switch (pixel_alpha
) {
628 case DRM_MODE_BLEND_PIXEL_NONE
:
630 case DRM_MODE_BLEND_COVERAGE
:
631 case DRM_MODE_BLEND_PREMULTI
:
633 val
|= WINCON1_ALPHA_SEL
;
634 val
|= WINCON1_BLD_PIX
;
635 val
|= WINCON1_ALPHA_MUL
;
638 fimd_set_bits(ctx
, WINCON(win
), WINCONx_BLEND_MODE_MASK
, val
);
641 val
= VIDISD14C_ALPHA0_R(win_alpha_h
) |
642 VIDISD14C_ALPHA0_G(win_alpha_h
) |
643 VIDISD14C_ALPHA0_B(win_alpha_h
) |
644 VIDISD14C_ALPHA1_R(0x0) |
645 VIDISD14C_ALPHA1_G(0x0) |
646 VIDISD14C_ALPHA1_B(0x0);
647 writel(val
, ctx
->regs
+ VIDOSD_C(win
));
649 val
= VIDW_ALPHA_R(win_alpha_l
) | VIDW_ALPHA_G(win_alpha_l
) |
650 VIDW_ALPHA_B(win_alpha_l
);
651 writel(val
, ctx
->regs
+ VIDWnALPHA0(win
));
653 val
= VIDW_ALPHA_R(0x0) | VIDW_ALPHA_G(0x0) |
655 writel(val
, ctx
->regs
+ VIDWnALPHA1(win
));
657 fimd_set_bits(ctx
, BLENDCON
, BLENDCON_NEW_MASK
,
658 BLENDCON_NEW_8BIT_ALPHA_VALUE
);
661 static void fimd_win_set_pixfmt(struct fimd_context
*ctx
, unsigned int win
,
662 struct drm_framebuffer
*fb
, int width
)
664 struct exynos_drm_plane
*plane
= &ctx
->planes
[win
];
665 struct exynos_drm_plane_state
*state
=
666 to_exynos_plane_state(plane
->base
.state
);
667 uint32_t pixel_format
= fb
->format
->format
;
668 unsigned int alpha
= state
->base
.alpha
;
669 u32 val
= WINCONx_ENWIN
;
670 unsigned int pixel_alpha
;
672 if (fb
->format
->has_alpha
)
673 pixel_alpha
= state
->base
.pixel_blend_mode
;
675 pixel_alpha
= DRM_MODE_BLEND_PIXEL_NONE
;
678 * In case of s3c64xx, window 0 doesn't support alpha channel.
679 * So the request format is ARGB8888 then change it to XRGB8888.
681 if (ctx
->driver_data
->has_limited_fmt
&& !win
) {
682 if (pixel_format
== DRM_FORMAT_ARGB8888
)
683 pixel_format
= DRM_FORMAT_XRGB8888
;
686 switch (pixel_format
) {
688 val
|= WINCON0_BPPMODE_8BPP_PALETTE
;
689 val
|= WINCONx_BURSTLEN_8WORD
;
690 val
|= WINCONx_BYTSWP
;
692 case DRM_FORMAT_XRGB1555
:
693 case DRM_FORMAT_XBGR1555
:
694 val
|= WINCON0_BPPMODE_16BPP_1555
;
695 val
|= WINCONx_HAWSWP
;
696 val
|= WINCONx_BURSTLEN_16WORD
;
698 case DRM_FORMAT_RGB565
:
699 case DRM_FORMAT_BGR565
:
700 val
|= WINCON0_BPPMODE_16BPP_565
;
701 val
|= WINCONx_HAWSWP
;
702 val
|= WINCONx_BURSTLEN_16WORD
;
704 case DRM_FORMAT_XRGB8888
:
705 case DRM_FORMAT_XBGR8888
:
706 val
|= WINCON0_BPPMODE_24BPP_888
;
708 val
|= WINCONx_BURSTLEN_16WORD
;
710 case DRM_FORMAT_ARGB8888
:
711 case DRM_FORMAT_ABGR8888
:
713 val
|= WINCON1_BPPMODE_25BPP_A1888
;
715 val
|= WINCONx_BURSTLEN_16WORD
;
719 switch (pixel_format
) {
720 case DRM_FORMAT_XBGR1555
:
721 case DRM_FORMAT_XBGR8888
:
722 case DRM_FORMAT_ABGR8888
:
723 case DRM_FORMAT_BGR565
:
724 writel(WIN_RGB_ORDER_REVERSE
, ctx
->regs
+ WIN_RGB_ORDER(win
));
727 writel(WIN_RGB_ORDER_FORWARD
, ctx
->regs
+ WIN_RGB_ORDER(win
));
732 * Setting dma-burst to 16Word causes permanent tearing for very small
733 * buffers, e.g. cursor buffer. Burst Mode switching which based on
734 * plane size is not recommended as plane size varies alot towards the
735 * end of the screen and rapid movement causes unstable DMA, but it is
736 * still better to change dma-burst than displaying garbage.
739 if (width
< MIN_FB_WIDTH_FOR_16WORD_BURST
) {
740 val
&= ~WINCONx_BURSTLEN_MASK
;
741 val
|= WINCONx_BURSTLEN_4WORD
;
743 fimd_set_bits(ctx
, WINCON(win
), ~WINCONx_BLEND_MODE_MASK
, val
);
745 /* hardware window 0 doesn't support alpha channel. */
747 fimd_win_set_bldmod(ctx
, win
, alpha
, pixel_alpha
);
748 fimd_win_set_bldeq(ctx
, win
, alpha
, pixel_alpha
);
752 static void fimd_win_set_colkey(struct fimd_context
*ctx
, unsigned int win
)
754 unsigned int keycon0
= 0, keycon1
= 0;
756 keycon0
= ~(WxKEYCON0_KEYBL_EN
| WxKEYCON0_KEYEN_F
|
757 WxKEYCON0_DIRCON
) | WxKEYCON0_COMPKEY(0);
759 keycon1
= WxKEYCON1_COLVAL(0xffffffff);
761 writel(keycon0
, ctx
->regs
+ WKEYCON0_BASE(win
));
762 writel(keycon1
, ctx
->regs
+ WKEYCON1_BASE(win
));
766 * fimd_shadow_protect_win() - disable updating values from shadow registers at vsync
768 * @ctx: local driver data
769 * @win: window to protect registers for
770 * @protect: 1 to protect (disable updates)
772 static void fimd_shadow_protect_win(struct fimd_context
*ctx
,
773 unsigned int win
, bool protect
)
778 * SHADOWCON/PRTCON register is used for enabling timing.
780 * for example, once only width value of a register is set,
781 * if the dma is started then fimd hardware could malfunction so
782 * with protect window setting, the register fields with prefix '_F'
783 * wouldn't be updated at vsync also but updated once unprotect window
787 if (ctx
->driver_data
->has_shadowcon
) {
789 bits
= SHADOWCON_WINx_PROTECT(win
);
792 bits
= PRTCON_PROTECT
;
795 val
= readl(ctx
->regs
+ reg
);
800 writel(val
, ctx
->regs
+ reg
);
803 static void fimd_atomic_begin(struct exynos_drm_crtc
*crtc
)
805 struct fimd_context
*ctx
= crtc
->ctx
;
811 for (i
= 0; i
< WINDOWS_NR
; i
++)
812 fimd_shadow_protect_win(ctx
, i
, true);
815 static void fimd_atomic_flush(struct exynos_drm_crtc
*crtc
)
817 struct fimd_context
*ctx
= crtc
->ctx
;
823 for (i
= 0; i
< WINDOWS_NR
; i
++)
824 fimd_shadow_protect_win(ctx
, i
, false);
826 exynos_crtc_handle_event(crtc
);
829 static void fimd_update_plane(struct exynos_drm_crtc
*crtc
,
830 struct exynos_drm_plane
*plane
)
832 struct exynos_drm_plane_state
*state
=
833 to_exynos_plane_state(plane
->base
.state
);
834 struct fimd_context
*ctx
= crtc
->ctx
;
835 struct drm_framebuffer
*fb
= state
->base
.fb
;
837 unsigned long val
, size
, offset
;
838 unsigned int last_x
, last_y
, buf_offsize
, line_size
;
839 unsigned int win
= plane
->index
;
840 unsigned int cpp
= fb
->format
->cpp
[0];
841 unsigned int pitch
= fb
->pitches
[0];
846 offset
= state
->src
.x
* cpp
;
847 offset
+= state
->src
.y
* pitch
;
849 /* buffer start address */
850 dma_addr
= exynos_drm_fb_dma_addr(fb
, 0) + offset
;
851 val
= (unsigned long)dma_addr
;
852 writel(val
, ctx
->regs
+ VIDWx_BUF_START(win
, 0));
854 /* buffer end address */
855 size
= pitch
* state
->crtc
.h
;
856 val
= (unsigned long)(dma_addr
+ size
);
857 writel(val
, ctx
->regs
+ VIDWx_BUF_END(win
, 0));
859 DRM_DEV_DEBUG_KMS(ctx
->dev
,
860 "start addr = 0x%lx, end addr = 0x%lx, size = 0x%lx\n",
861 (unsigned long)dma_addr
, val
, size
);
862 DRM_DEV_DEBUG_KMS(ctx
->dev
, "ovl_width = %d, ovl_height = %d\n",
863 state
->crtc
.w
, state
->crtc
.h
);
866 buf_offsize
= pitch
- (state
->crtc
.w
* cpp
);
867 line_size
= state
->crtc
.w
* cpp
;
868 val
= VIDW_BUF_SIZE_OFFSET(buf_offsize
) |
869 VIDW_BUF_SIZE_PAGEWIDTH(line_size
) |
870 VIDW_BUF_SIZE_OFFSET_E(buf_offsize
) |
871 VIDW_BUF_SIZE_PAGEWIDTH_E(line_size
);
872 writel(val
, ctx
->regs
+ VIDWx_BUF_SIZE(win
, 0));
875 val
= VIDOSDxA_TOPLEFT_X(state
->crtc
.x
) |
876 VIDOSDxA_TOPLEFT_Y(state
->crtc
.y
) |
877 VIDOSDxA_TOPLEFT_X_E(state
->crtc
.x
) |
878 VIDOSDxA_TOPLEFT_Y_E(state
->crtc
.y
);
879 writel(val
, ctx
->regs
+ VIDOSD_A(win
));
881 last_x
= state
->crtc
.x
+ state
->crtc
.w
;
884 last_y
= state
->crtc
.y
+ state
->crtc
.h
;
888 val
= VIDOSDxB_BOTRIGHT_X(last_x
) | VIDOSDxB_BOTRIGHT_Y(last_y
) |
889 VIDOSDxB_BOTRIGHT_X_E(last_x
) | VIDOSDxB_BOTRIGHT_Y_E(last_y
);
891 writel(val
, ctx
->regs
+ VIDOSD_B(win
));
893 DRM_DEV_DEBUG_KMS(ctx
->dev
,
894 "osd pos: tx = %d, ty = %d, bx = %d, by = %d\n",
895 state
->crtc
.x
, state
->crtc
.y
, last_x
, last_y
);
898 if (win
!= 3 && win
!= 4) {
899 u32 offset
= VIDOSD_D(win
);
901 offset
= VIDOSD_C(win
);
902 val
= state
->crtc
.w
* state
->crtc
.h
;
903 writel(val
, ctx
->regs
+ offset
);
905 DRM_DEV_DEBUG_KMS(ctx
->dev
, "osd size = 0x%x\n",
909 fimd_win_set_pixfmt(ctx
, win
, fb
, state
->src
.w
);
911 /* hardware window 0 doesn't support color key. */
913 fimd_win_set_colkey(ctx
, win
);
915 fimd_enable_video_output(ctx
, win
, true);
917 if (ctx
->driver_data
->has_shadowcon
)
918 fimd_enable_shadow_channel_path(ctx
, win
, true);
921 atomic_set(&ctx
->win_updated
, 1);
924 static void fimd_disable_plane(struct exynos_drm_crtc
*crtc
,
925 struct exynos_drm_plane
*plane
)
927 struct fimd_context
*ctx
= crtc
->ctx
;
928 unsigned int win
= plane
->index
;
933 fimd_enable_video_output(ctx
, win
, false);
935 if (ctx
->driver_data
->has_shadowcon
)
936 fimd_enable_shadow_channel_path(ctx
, win
, false);
939 static void fimd_atomic_enable(struct exynos_drm_crtc
*crtc
)
941 struct fimd_context
*ctx
= crtc
->ctx
;
946 ctx
->suspended
= false;
948 if (pm_runtime_resume_and_get(ctx
->dev
) < 0) {
949 dev_warn(ctx
->dev
, "failed to enable FIMD device.\n");
953 /* if vblank was enabled status, enable it again. */
954 if (test_and_clear_bit(0, &ctx
->irq_flags
))
955 fimd_enable_vblank(ctx
->crtc
);
957 fimd_commit(ctx
->crtc
);
960 static void fimd_atomic_disable(struct exynos_drm_crtc
*crtc
)
962 struct fimd_context
*ctx
= crtc
->ctx
;
969 * We need to make sure that all windows are disabled before we
970 * suspend that connector. Otherwise we might try to scan from
971 * a destroyed buffer later.
973 for (i
= 0; i
< WINDOWS_NR
; i
++)
974 fimd_disable_plane(crtc
, &ctx
->planes
[i
]);
976 fimd_enable_vblank(crtc
);
977 fimd_wait_for_vblank(crtc
);
978 fimd_disable_vblank(crtc
);
980 writel(0, ctx
->regs
+ VIDCON0
);
982 pm_runtime_put_sync(ctx
->dev
);
983 ctx
->suspended
= true;
986 static void fimd_trigger(struct device
*dev
)
988 struct fimd_context
*ctx
= dev_get_drvdata(dev
);
989 const struct fimd_driver_data
*driver_data
= ctx
->driver_data
;
990 void *timing_base
= ctx
->regs
+ driver_data
->timing_base
;
994 * Skips triggering if in triggering state, because multiple triggering
995 * requests can cause panel reset.
997 if (atomic_read(&ctx
->triggering
))
1000 /* Enters triggering mode */
1001 atomic_set(&ctx
->triggering
, 1);
1003 reg
= readl(timing_base
+ TRIGCON
);
1004 reg
|= (TRGMODE_ENABLE
| SWTRGCMD_ENABLE
);
1005 writel(reg
, timing_base
+ TRIGCON
);
1008 * Exits triggering mode if vblank is not enabled yet, because when the
1009 * VIDINTCON0 register is not set, it can not exit from triggering mode.
1011 if (!test_bit(0, &ctx
->irq_flags
))
1012 atomic_set(&ctx
->triggering
, 0);
1015 static void fimd_te_handler(struct exynos_drm_crtc
*crtc
)
1017 struct fimd_context
*ctx
= crtc
->ctx
;
1018 u32 trg_type
= ctx
->driver_data
->trg_type
;
1020 /* Checks the crtc is detached already from encoder */
1024 if (trg_type
== I80_HW_TRG
)
1028 * If there is a page flip request, triggers and handles the page flip
1029 * event so that current fb can be updated into panel GRAM.
1031 if (atomic_add_unless(&ctx
->win_updated
, -1, 0))
1032 fimd_trigger(ctx
->dev
);
1035 /* Wakes up vsync event queue */
1036 if (atomic_read(&ctx
->wait_vsync_event
)) {
1037 atomic_set(&ctx
->wait_vsync_event
, 0);
1038 wake_up(&ctx
->wait_vsync_queue
);
1041 if (test_bit(0, &ctx
->irq_flags
))
1042 drm_crtc_handle_vblank(&ctx
->crtc
->base
);
1045 static void fimd_dp_clock_enable(struct exynos_drm_clk
*clk
, bool enable
)
1047 struct fimd_context
*ctx
= container_of(clk
, struct fimd_context
,
1049 u32 val
= enable
? DP_MIE_CLK_DP_ENABLE
: DP_MIE_CLK_DISABLE
;
1050 writel(val
, ctx
->regs
+ DP_MIE_CLKCON
);
1053 static const struct exynos_drm_crtc_ops fimd_crtc_ops
= {
1054 .atomic_enable
= fimd_atomic_enable
,
1055 .atomic_disable
= fimd_atomic_disable
,
1056 .enable_vblank
= fimd_enable_vblank
,
1057 .disable_vblank
= fimd_disable_vblank
,
1058 .atomic_begin
= fimd_atomic_begin
,
1059 .update_plane
= fimd_update_plane
,
1060 .disable_plane
= fimd_disable_plane
,
1061 .atomic_flush
= fimd_atomic_flush
,
1062 .atomic_check
= fimd_atomic_check
,
1063 .te_handler
= fimd_te_handler
,
1066 static irqreturn_t
fimd_irq_handler(int irq
, void *dev_id
)
1068 struct fimd_context
*ctx
= (struct fimd_context
*)dev_id
;
1071 val
= readl(ctx
->regs
+ VIDINTCON1
);
1073 clear_bit
= ctx
->i80_if
? VIDINTCON1_INT_I80
: VIDINTCON1_INT_FRAME
;
1074 if (val
& clear_bit
)
1075 writel(clear_bit
, ctx
->regs
+ VIDINTCON1
);
1077 /* check the crtc is detached already from encoder */
1082 drm_crtc_handle_vblank(&ctx
->crtc
->base
);
1085 /* Exits triggering mode */
1086 atomic_set(&ctx
->triggering
, 0);
1088 /* set wait vsync event to zero and wake up queue. */
1089 if (atomic_read(&ctx
->wait_vsync_event
)) {
1090 atomic_set(&ctx
->wait_vsync_event
, 0);
1091 wake_up(&ctx
->wait_vsync_queue
);
1099 static int fimd_bind(struct device
*dev
, struct device
*master
, void *data
)
1101 struct fimd_context
*ctx
= dev_get_drvdata(dev
);
1102 struct drm_device
*drm_dev
= data
;
1103 struct exynos_drm_plane
*exynos_plane
;
1107 ctx
->drm_dev
= drm_dev
;
1109 for (i
= 0; i
< WINDOWS_NR
; i
++) {
1110 if (ctx
->driver_data
->has_bgr_support
) {
1111 ctx
->configs
[i
].pixel_formats
= fimd_extended_formats
;
1112 ctx
->configs
[i
].num_pixel_formats
= ARRAY_SIZE(fimd_extended_formats
);
1114 ctx
->configs
[i
].pixel_formats
= fimd_formats
;
1115 ctx
->configs
[i
].num_pixel_formats
= ARRAY_SIZE(fimd_formats
);
1118 ctx
->configs
[i
].zpos
= i
;
1119 ctx
->configs
[i
].type
= fimd_win_types
[i
];
1120 ctx
->configs
[i
].capabilities
= capabilities
[i
];
1121 ret
= exynos_plane_init(drm_dev
, &ctx
->planes
[i
], i
,
1127 exynos_plane
= &ctx
->planes
[DEFAULT_WIN
];
1128 ctx
->crtc
= exynos_drm_crtc_create(drm_dev
, &exynos_plane
->base
,
1129 EXYNOS_DISPLAY_TYPE_LCD
, &fimd_crtc_ops
, ctx
);
1130 if (IS_ERR(ctx
->crtc
))
1131 return PTR_ERR(ctx
->crtc
);
1133 if (ctx
->driver_data
->has_dp_clk
) {
1134 ctx
->dp_clk
.enable
= fimd_dp_clock_enable
;
1135 ctx
->crtc
->pipe_clk
= &ctx
->dp_clk
;
1139 exynos_dpi_bind(drm_dev
, ctx
->encoder
);
1141 if (is_drm_iommu_supported(drm_dev
)) {
1144 ret
= fimd_clear_channels(ctx
->crtc
);
1149 return exynos_drm_register_dma(drm_dev
, dev
, &ctx
->dma_priv
);
1152 static void fimd_unbind(struct device
*dev
, struct device
*master
,
1155 struct fimd_context
*ctx
= dev_get_drvdata(dev
);
1157 fimd_atomic_disable(ctx
->crtc
);
1159 exynos_drm_unregister_dma(ctx
->drm_dev
, ctx
->dev
, &ctx
->dma_priv
);
1162 exynos_dpi_remove(ctx
->encoder
);
1165 static const struct component_ops fimd_component_ops
= {
1167 .unbind
= fimd_unbind
,
1170 static int fimd_probe(struct platform_device
*pdev
)
1172 struct device
*dev
= &pdev
->dev
;
1173 struct fimd_context
*ctx
;
1174 struct device_node
*i80_if_timings
;
1180 ctx
= devm_kzalloc(dev
, sizeof(*ctx
), GFP_KERNEL
);
1185 ctx
->suspended
= true;
1186 ctx
->driver_data
= of_device_get_match_data(dev
);
1188 if (of_property_read_bool(dev
->of_node
, "samsung,invert-vden"))
1189 ctx
->vidcon1
|= VIDCON1_INV_VDEN
;
1190 if (of_property_read_bool(dev
->of_node
, "samsung,invert-vclk"))
1191 ctx
->vidcon1
|= VIDCON1_INV_VCLK
;
1193 i80_if_timings
= of_get_child_by_name(dev
->of_node
, "i80-if-timings");
1194 if (i80_if_timings
) {
1199 if (ctx
->driver_data
->has_vidoutcon
)
1200 ctx
->vidout_con
|= VIDOUT_CON_F_I80_LDI0
;
1202 ctx
->vidcon0
|= VIDCON0_VIDOUT_I80_LDI0
;
1204 * The user manual describes that this "DSI_EN" bit is required
1205 * to enable I80 24-bit data interface.
1207 ctx
->vidcon0
|= VIDCON0_DSI_EN
;
1209 if (of_property_read_u32(i80_if_timings
, "cs-setup", &val
))
1211 ctx
->i80ifcon
= LCD_CS_SETUP(val
);
1212 if (of_property_read_u32(i80_if_timings
, "wr-setup", &val
))
1214 ctx
->i80ifcon
|= LCD_WR_SETUP(val
);
1215 if (of_property_read_u32(i80_if_timings
, "wr-active", &val
))
1217 ctx
->i80ifcon
|= LCD_WR_ACTIVE(val
);
1218 if (of_property_read_u32(i80_if_timings
, "wr-hold", &val
))
1220 ctx
->i80ifcon
|= LCD_WR_HOLD(val
);
1222 of_node_put(i80_if_timings
);
1224 ctx
->sysreg
= syscon_regmap_lookup_by_phandle(dev
->of_node
,
1226 if (IS_ERR(ctx
->sysreg
)) {
1227 dev_warn(dev
, "failed to get system register.\n");
1231 ctx
->bus_clk
= devm_clk_get(dev
, "fimd");
1232 if (IS_ERR(ctx
->bus_clk
)) {
1233 dev_err(dev
, "failed to get bus clock\n");
1234 return PTR_ERR(ctx
->bus_clk
);
1237 ctx
->lcd_clk
= devm_clk_get(dev
, "sclk_fimd");
1238 if (IS_ERR(ctx
->lcd_clk
)) {
1239 dev_err(dev
, "failed to get lcd clock\n");
1240 return PTR_ERR(ctx
->lcd_clk
);
1243 ctx
->regs
= devm_platform_ioremap_resource(pdev
, 0);
1244 if (IS_ERR(ctx
->regs
))
1245 return PTR_ERR(ctx
->regs
);
1247 ret
= platform_get_irq_byname(pdev
, ctx
->i80_if
? "lcd_sys" : "vsync");
1251 ret
= devm_request_irq(dev
, ret
, fimd_irq_handler
, 0, "drm_fimd", ctx
);
1253 dev_err(dev
, "irq request failed.\n");
1257 init_waitqueue_head(&ctx
->wait_vsync_queue
);
1258 atomic_set(&ctx
->wait_vsync_event
, 0);
1260 platform_set_drvdata(pdev
, ctx
);
1262 ctx
->encoder
= exynos_dpi_probe(dev
);
1263 if (IS_ERR(ctx
->encoder
))
1264 return PTR_ERR(ctx
->encoder
);
1266 pm_runtime_enable(dev
);
1268 ret
= component_add(dev
, &fimd_component_ops
);
1270 goto err_disable_pm_runtime
;
1274 err_disable_pm_runtime
:
1275 pm_runtime_disable(dev
);
1280 static void fimd_remove(struct platform_device
*pdev
)
1282 pm_runtime_disable(&pdev
->dev
);
1284 component_del(&pdev
->dev
, &fimd_component_ops
);
1287 static int exynos_fimd_suspend(struct device
*dev
)
1289 struct fimd_context
*ctx
= dev_get_drvdata(dev
);
1291 clk_disable_unprepare(ctx
->lcd_clk
);
1292 clk_disable_unprepare(ctx
->bus_clk
);
1297 static int exynos_fimd_resume(struct device
*dev
)
1299 struct fimd_context
*ctx
= dev_get_drvdata(dev
);
1302 ret
= clk_prepare_enable(ctx
->bus_clk
);
1305 "Failed to prepare_enable the bus clk [%d]\n",
1310 ret
= clk_prepare_enable(ctx
->lcd_clk
);
1313 "Failed to prepare_enable the lcd clk [%d]\n",
1321 static DEFINE_RUNTIME_DEV_PM_OPS(exynos_fimd_pm_ops
, exynos_fimd_suspend
,
1322 exynos_fimd_resume
, NULL
);
1324 struct platform_driver fimd_driver
= {
1325 .probe
= fimd_probe
,
1326 .remove
= fimd_remove
,
1328 .name
= "exynos4-fb",
1329 .pm
= pm_ptr(&exynos_fimd_pm_ops
),
1330 .of_match_table
= fimd_driver_dt_match
,