3737
3838#define WINDOWS_NR 2
3939
40+ struct decon_data {
41+ unsigned int vidw_buf_start_base ;
42+ unsigned int shadowcon_win_protect_shift ;
43+ unsigned int wincon_burstlen_shift ;
44+ };
45+
46+ static struct decon_data exynos7_decon_data = {
47+ .vidw_buf_start_base = 0x80 ,
48+ .shadowcon_win_protect_shift = 10 ,
49+ .wincon_burstlen_shift = 11 ,
50+ };
51+
52+ static struct decon_data exynos7870_decon_data = {
53+ .vidw_buf_start_base = 0x880 ,
54+ .shadowcon_win_protect_shift = 8 ,
55+ .wincon_burstlen_shift = 10 ,
56+ };
57+
4058struct decon_context {
4159 struct device * dev ;
4260 struct drm_device * drm_dev ;
@@ -55,11 +73,19 @@ struct decon_context {
5573 wait_queue_head_t wait_vsync_queue ;
5674 atomic_t wait_vsync_event ;
5775
76+ const struct decon_data * data ;
5877 struct drm_encoder * encoder ;
5978};
6079
6180static const struct of_device_id decon_driver_dt_match [] = {
62- {.compatible = "samsung,exynos7-decon" },
81+ {
82+ .compatible = "samsung,exynos7-decon" ,
83+ .data = & exynos7_decon_data ,
84+ },
85+ {
86+ .compatible = "samsung,exynos7870-decon" ,
87+ .data = & exynos7870_decon_data ,
88+ },
6389 {},
6490};
6591MODULE_DEVICE_TABLE (of , decon_driver_dt_match );
@@ -81,10 +107,31 @@ static const enum drm_plane_type decon_win_types[WINDOWS_NR] = {
81107 DRM_PLANE_TYPE_CURSOR ,
82108};
83109
84- static void decon_wait_for_vblank (struct exynos_drm_crtc * crtc )
110+ /**
111+ * decon_shadow_protect_win() - disable updating values from shadow registers at vsync
112+ *
113+ * @ctx: display and enhancement controller context
114+ * @win: window to protect registers for
115+ * @protect: 1 to protect (disable updates)
116+ */
117+ static void decon_shadow_protect_win (struct decon_context * ctx ,
118+ unsigned int win , bool protect )
85119{
86- struct decon_context * ctx = crtc -> ctx ;
120+ u32 bits , val ;
121+ unsigned int shift = ctx -> data -> shadowcon_win_protect_shift ;
122+
123+ bits = SHADOWCON_WINx_PROTECT (shift , win );
124+
125+ val = readl (ctx -> regs + SHADOWCON );
126+ if (protect )
127+ val |= bits ;
128+ else
129+ val &= ~bits ;
130+ writel (val , ctx -> regs + SHADOWCON );
131+ }
87132
133+ static void decon_wait_for_vblank (struct decon_context * ctx )
134+ {
88135 if (ctx -> suspended )
89136 return ;
90137
@@ -100,33 +147,41 @@ static void decon_wait_for_vblank(struct exynos_drm_crtc *crtc)
100147 DRM_DEV_DEBUG_KMS (ctx -> dev , "vblank wait timed out.\n" );
101148}
102149
103- static void decon_clear_channels (struct exynos_drm_crtc * crtc )
150+ static void decon_clear_channels (struct decon_context * ctx )
104151{
105- struct decon_context * ctx = crtc -> ctx ;
106152 unsigned int win , ch_enabled = 0 ;
153+ u32 val ;
107154
108155 /* Check if any channel is enabled. */
109156 for (win = 0 ; win < WINDOWS_NR ; win ++ ) {
110- u32 val = readl (ctx -> regs + WINCON (win ));
157+ val = readl (ctx -> regs + WINCON (win ));
111158
112159 if (val & WINCONx_ENWIN ) {
160+ decon_shadow_protect_win (ctx , win , true);
161+
113162 val &= ~WINCONx_ENWIN ;
114163 writel (val , ctx -> regs + WINCON (win ));
115164 ch_enabled = 1 ;
165+
166+ decon_shadow_protect_win (ctx , win , false);
116167 }
117168 }
118169
170+ val = readl (ctx -> regs + DECON_UPDATE );
171+ val |= DECON_UPDATE_STANDALONE_F ;
172+ writel (val , ctx -> regs + DECON_UPDATE );
173+
119174 /* Wait for vsync, as disable channel takes effect at next vsync */
120175 if (ch_enabled )
121- decon_wait_for_vblank (ctx -> crtc );
176+ decon_wait_for_vblank (ctx );
122177}
123178
124179static int decon_ctx_initialize (struct decon_context * ctx ,
125180 struct drm_device * drm_dev )
126181{
127182 ctx -> drm_dev = drm_dev ;
128183
129- decon_clear_channels (ctx -> crtc );
184+ decon_clear_channels (ctx );
130185
131186 return exynos_drm_register_dma (drm_dev , ctx -> dev , & ctx -> dma_priv );
132187}
@@ -140,7 +195,7 @@ static void decon_ctx_remove(struct decon_context *ctx)
140195static u32 decon_calc_clkdiv (struct decon_context * ctx ,
141196 const struct drm_display_mode * mode )
142197{
143- unsigned long ideal_clk = mode -> clock ;
198+ unsigned long ideal_clk = mode -> clock * 1000 ;
144199 u32 clkdiv ;
145200
146201 /* Find the clock divider value that gets us closest to ideal_clk */
@@ -263,51 +318,52 @@ static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win,
263318{
264319 unsigned long val ;
265320 int padding ;
321+ unsigned int shift = ctx -> data -> wincon_burstlen_shift ;
266322
267323 val = readl (ctx -> regs + WINCON (win ));
268324 val &= ~WINCONx_BPPMODE_MASK ;
269325
270326 switch (fb -> format -> format ) {
271327 case DRM_FORMAT_RGB565 :
272328 val |= WINCONx_BPPMODE_16BPP_565 ;
273- val |= WINCONx_BURSTLEN_16WORD ;
329+ val |= WINCONx_BURSTLEN_16WORD ( shift ) ;
274330 break ;
275331 case DRM_FORMAT_XRGB8888 :
276332 val |= WINCONx_BPPMODE_24BPP_xRGB ;
277- val |= WINCONx_BURSTLEN_16WORD ;
333+ val |= WINCONx_BURSTLEN_16WORD ( shift ) ;
278334 break ;
279335 case DRM_FORMAT_XBGR8888 :
280336 val |= WINCONx_BPPMODE_24BPP_xBGR ;
281- val |= WINCONx_BURSTLEN_16WORD ;
337+ val |= WINCONx_BURSTLEN_16WORD ( shift ) ;
282338 break ;
283339 case DRM_FORMAT_RGBX8888 :
284340 val |= WINCONx_BPPMODE_24BPP_RGBx ;
285- val |= WINCONx_BURSTLEN_16WORD ;
341+ val |= WINCONx_BURSTLEN_16WORD ( shift ) ;
286342 break ;
287343 case DRM_FORMAT_BGRX8888 :
288344 val |= WINCONx_BPPMODE_24BPP_BGRx ;
289- val |= WINCONx_BURSTLEN_16WORD ;
345+ val |= WINCONx_BURSTLEN_16WORD ( shift ) ;
290346 break ;
291347 case DRM_FORMAT_ARGB8888 :
292348 val |= WINCONx_BPPMODE_32BPP_ARGB | WINCONx_BLD_PIX |
293349 WINCONx_ALPHA_SEL ;
294- val |= WINCONx_BURSTLEN_16WORD ;
350+ val |= WINCONx_BURSTLEN_16WORD ( shift ) ;
295351 break ;
296352 case DRM_FORMAT_ABGR8888 :
297353 val |= WINCONx_BPPMODE_32BPP_ABGR | WINCONx_BLD_PIX |
298354 WINCONx_ALPHA_SEL ;
299- val |= WINCONx_BURSTLEN_16WORD ;
355+ val |= WINCONx_BURSTLEN_16WORD ( shift ) ;
300356 break ;
301357 case DRM_FORMAT_RGBA8888 :
302358 val |= WINCONx_BPPMODE_32BPP_RGBA | WINCONx_BLD_PIX |
303359 WINCONx_ALPHA_SEL ;
304- val |= WINCONx_BURSTLEN_16WORD ;
360+ val |= WINCONx_BURSTLEN_16WORD ( shift ) ;
305361 break ;
306362 case DRM_FORMAT_BGRA8888 :
307363 default :
308364 val |= WINCONx_BPPMODE_32BPP_BGRA | WINCONx_BLD_PIX |
309365 WINCONx_ALPHA_SEL ;
310- val |= WINCONx_BURSTLEN_16WORD ;
366+ val |= WINCONx_BURSTLEN_16WORD ( shift ) ;
311367 break ;
312368 }
313369
@@ -323,8 +379,8 @@ static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win,
323379
324380 padding = (fb -> pitches [0 ] / fb -> format -> cpp [0 ]) - fb -> width ;
325381 if (fb -> width + padding < MIN_FB_WIDTH_FOR_16WORD_BURST ) {
326- val &= ~WINCONx_BURSTLEN_MASK ;
327- val |= WINCONx_BURSTLEN_8WORD ;
382+ val &= ~WINCONx_BURSTLEN_MASK ( shift ) ;
383+ val |= WINCONx_BURSTLEN_8WORD ( shift ) ;
328384 }
329385
330386 writel (val , ctx -> regs + WINCON (win ));
@@ -343,28 +399,6 @@ static void decon_win_set_colkey(struct decon_context *ctx, unsigned int win)
343399 writel (keycon1 , ctx -> regs + WKEYCON1_BASE (win ));
344400}
345401
346- /**
347- * decon_shadow_protect_win() - disable updating values from shadow registers at vsync
348- *
349- * @ctx: display and enhancement controller context
350- * @win: window to protect registers for
351- * @protect: 1 to protect (disable updates)
352- */
353- static void decon_shadow_protect_win (struct decon_context * ctx ,
354- unsigned int win , bool protect )
355- {
356- u32 bits , val ;
357-
358- bits = SHADOWCON_WINx_PROTECT (win );
359-
360- val = readl (ctx -> regs + SHADOWCON );
361- if (protect )
362- val |= bits ;
363- else
364- val &= ~bits ;
365- writel (val , ctx -> regs + SHADOWCON );
366- }
367-
368402static void decon_atomic_begin (struct exynos_drm_crtc * crtc )
369403{
370404 struct decon_context * ctx = crtc -> ctx ;
@@ -391,6 +425,7 @@ static void decon_update_plane(struct exynos_drm_crtc *crtc,
391425 unsigned int win = plane -> index ;
392426 unsigned int cpp = fb -> format -> cpp [0 ];
393427 unsigned int pitch = fb -> pitches [0 ];
428+ unsigned int vidw_addr0_base = ctx -> data -> vidw_buf_start_base ;
394429
395430 if (ctx -> suspended )
396431 return ;
@@ -407,7 +442,7 @@ static void decon_update_plane(struct exynos_drm_crtc *crtc,
407442
408443 /* buffer start address */
409444 val = (unsigned long )exynos_drm_fb_dma_addr (fb , 0 );
410- writel (val , ctx -> regs + VIDW_BUF_START (win ));
445+ writel (val , ctx -> regs + VIDW_BUF_START (vidw_addr0_base , win ));
411446
412447 padding = (pitch / cpp ) - fb -> width ;
413448
@@ -689,6 +724,7 @@ static int decon_probe(struct platform_device *pdev)
689724
690725 ctx -> dev = dev ;
691726 ctx -> suspended = true;
727+ ctx -> data = of_device_get_match_data (dev );
692728
693729 i80_if_timings = of_get_child_by_name (dev -> of_node , "i80-if-timings" );
694730 if (i80_if_timings )
0 commit comments