37
37
38
38
#define WINDOWS_NR 2
39
39
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
+
40
58
struct decon_context {
41
59
struct device * dev ;
42
60
struct drm_device * drm_dev ;
@@ -55,11 +73,19 @@ struct decon_context {
55
73
wait_queue_head_t wait_vsync_queue ;
56
74
atomic_t wait_vsync_event ;
57
75
76
+ const struct decon_data * data ;
58
77
struct drm_encoder * encoder ;
59
78
};
60
79
61
80
static 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
+ },
63
89
{},
64
90
};
65
91
MODULE_DEVICE_TABLE (of , decon_driver_dt_match );
@@ -81,10 +107,31 @@ static const enum drm_plane_type decon_win_types[WINDOWS_NR] = {
81
107
DRM_PLANE_TYPE_CURSOR ,
82
108
};
83
109
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 )
85
119
{
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
+ }
87
132
133
+ static void decon_wait_for_vblank (struct decon_context * ctx )
134
+ {
88
135
if (ctx -> suspended )
89
136
return ;
90
137
@@ -100,33 +147,41 @@ static void decon_wait_for_vblank(struct exynos_drm_crtc *crtc)
100
147
DRM_DEV_DEBUG_KMS (ctx -> dev , "vblank wait timed out.\n" );
101
148
}
102
149
103
- static void decon_clear_channels (struct exynos_drm_crtc * crtc )
150
+ static void decon_clear_channels (struct decon_context * ctx )
104
151
{
105
- struct decon_context * ctx = crtc -> ctx ;
106
152
unsigned int win , ch_enabled = 0 ;
153
+ u32 val ;
107
154
108
155
/* Check if any channel is enabled. */
109
156
for (win = 0 ; win < WINDOWS_NR ; win ++ ) {
110
- u32 val = readl (ctx -> regs + WINCON (win ));
157
+ val = readl (ctx -> regs + WINCON (win ));
111
158
112
159
if (val & WINCONx_ENWIN ) {
160
+ decon_shadow_protect_win (ctx , win , true);
161
+
113
162
val &= ~WINCONx_ENWIN ;
114
163
writel (val , ctx -> regs + WINCON (win ));
115
164
ch_enabled = 1 ;
165
+
166
+ decon_shadow_protect_win (ctx , win , false);
116
167
}
117
168
}
118
169
170
+ val = readl (ctx -> regs + DECON_UPDATE );
171
+ val |= DECON_UPDATE_STANDALONE_F ;
172
+ writel (val , ctx -> regs + DECON_UPDATE );
173
+
119
174
/* Wait for vsync, as disable channel takes effect at next vsync */
120
175
if (ch_enabled )
121
- decon_wait_for_vblank (ctx -> crtc );
176
+ decon_wait_for_vblank (ctx );
122
177
}
123
178
124
179
static int decon_ctx_initialize (struct decon_context * ctx ,
125
180
struct drm_device * drm_dev )
126
181
{
127
182
ctx -> drm_dev = drm_dev ;
128
183
129
- decon_clear_channels (ctx -> crtc );
184
+ decon_clear_channels (ctx );
130
185
131
186
return exynos_drm_register_dma (drm_dev , ctx -> dev , & ctx -> dma_priv );
132
187
}
@@ -140,7 +195,7 @@ static void decon_ctx_remove(struct decon_context *ctx)
140
195
static u32 decon_calc_clkdiv (struct decon_context * ctx ,
141
196
const struct drm_display_mode * mode )
142
197
{
143
- unsigned long ideal_clk = mode -> clock ;
198
+ unsigned long ideal_clk = mode -> clock * 1000 ;
144
199
u32 clkdiv ;
145
200
146
201
/* 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,
263
318
{
264
319
unsigned long val ;
265
320
int padding ;
321
+ unsigned int shift = ctx -> data -> wincon_burstlen_shift ;
266
322
267
323
val = readl (ctx -> regs + WINCON (win ));
268
324
val &= ~WINCONx_BPPMODE_MASK ;
269
325
270
326
switch (fb -> format -> format ) {
271
327
case DRM_FORMAT_RGB565 :
272
328
val |= WINCONx_BPPMODE_16BPP_565 ;
273
- val |= WINCONx_BURSTLEN_16WORD ;
329
+ val |= WINCONx_BURSTLEN_16WORD ( shift ) ;
274
330
break ;
275
331
case DRM_FORMAT_XRGB8888 :
276
332
val |= WINCONx_BPPMODE_24BPP_xRGB ;
277
- val |= WINCONx_BURSTLEN_16WORD ;
333
+ val |= WINCONx_BURSTLEN_16WORD ( shift ) ;
278
334
break ;
279
335
case DRM_FORMAT_XBGR8888 :
280
336
val |= WINCONx_BPPMODE_24BPP_xBGR ;
281
- val |= WINCONx_BURSTLEN_16WORD ;
337
+ val |= WINCONx_BURSTLEN_16WORD ( shift ) ;
282
338
break ;
283
339
case DRM_FORMAT_RGBX8888 :
284
340
val |= WINCONx_BPPMODE_24BPP_RGBx ;
285
- val |= WINCONx_BURSTLEN_16WORD ;
341
+ val |= WINCONx_BURSTLEN_16WORD ( shift ) ;
286
342
break ;
287
343
case DRM_FORMAT_BGRX8888 :
288
344
val |= WINCONx_BPPMODE_24BPP_BGRx ;
289
- val |= WINCONx_BURSTLEN_16WORD ;
345
+ val |= WINCONx_BURSTLEN_16WORD ( shift ) ;
290
346
break ;
291
347
case DRM_FORMAT_ARGB8888 :
292
348
val |= WINCONx_BPPMODE_32BPP_ARGB | WINCONx_BLD_PIX |
293
349
WINCONx_ALPHA_SEL ;
294
- val |= WINCONx_BURSTLEN_16WORD ;
350
+ val |= WINCONx_BURSTLEN_16WORD ( shift ) ;
295
351
break ;
296
352
case DRM_FORMAT_ABGR8888 :
297
353
val |= WINCONx_BPPMODE_32BPP_ABGR | WINCONx_BLD_PIX |
298
354
WINCONx_ALPHA_SEL ;
299
- val |= WINCONx_BURSTLEN_16WORD ;
355
+ val |= WINCONx_BURSTLEN_16WORD ( shift ) ;
300
356
break ;
301
357
case DRM_FORMAT_RGBA8888 :
302
358
val |= WINCONx_BPPMODE_32BPP_RGBA | WINCONx_BLD_PIX |
303
359
WINCONx_ALPHA_SEL ;
304
- val |= WINCONx_BURSTLEN_16WORD ;
360
+ val |= WINCONx_BURSTLEN_16WORD ( shift ) ;
305
361
break ;
306
362
case DRM_FORMAT_BGRA8888 :
307
363
default :
308
364
val |= WINCONx_BPPMODE_32BPP_BGRA | WINCONx_BLD_PIX |
309
365
WINCONx_ALPHA_SEL ;
310
- val |= WINCONx_BURSTLEN_16WORD ;
366
+ val |= WINCONx_BURSTLEN_16WORD ( shift ) ;
311
367
break ;
312
368
}
313
369
@@ -323,8 +379,8 @@ static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win,
323
379
324
380
padding = (fb -> pitches [0 ] / fb -> format -> cpp [0 ]) - fb -> width ;
325
381
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 ) ;
328
384
}
329
385
330
386
writel (val , ctx -> regs + WINCON (win ));
@@ -343,28 +399,6 @@ static void decon_win_set_colkey(struct decon_context *ctx, unsigned int win)
343
399
writel (keycon1 , ctx -> regs + WKEYCON1_BASE (win ));
344
400
}
345
401
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
-
368
402
static void decon_atomic_begin (struct exynos_drm_crtc * crtc )
369
403
{
370
404
struct decon_context * ctx = crtc -> ctx ;
@@ -391,6 +425,7 @@ static void decon_update_plane(struct exynos_drm_crtc *crtc,
391
425
unsigned int win = plane -> index ;
392
426
unsigned int cpp = fb -> format -> cpp [0 ];
393
427
unsigned int pitch = fb -> pitches [0 ];
428
+ unsigned int vidw_addr0_base = ctx -> data -> vidw_buf_start_base ;
394
429
395
430
if (ctx -> suspended )
396
431
return ;
@@ -407,7 +442,7 @@ static void decon_update_plane(struct exynos_drm_crtc *crtc,
407
442
408
443
/* buffer start address */
409
444
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 ));
411
446
412
447
padding = (pitch / cpp ) - fb -> width ;
413
448
@@ -689,6 +724,7 @@ static int decon_probe(struct platform_device *pdev)
689
724
690
725
ctx -> dev = dev ;
691
726
ctx -> suspended = true;
727
+ ctx -> data = of_device_get_match_data (dev );
692
728
693
729
i80_if_timings = of_get_child_by_name (dev -> of_node , "i80-if-timings" );
694
730
if (i80_if_timings )
0 commit comments