3bc01a6b5e95cb7bb44ad9adb0a1de85f7832f1c
[GitHub/LineageOS/android_kernel_samsung_universal7580.git] / drivers / gpu / drm / exynos / exynos_mixer.c
1 /*
2 * Copyright (C) 2011 Samsung Electronics Co.Ltd
3 * Authors:
4 * Seung-Woo Kim <sw0312.kim@samsung.com>
5 * Inki Dae <inki.dae@samsung.com>
6 * Joonyoung Shim <jy0922.shim@samsung.com>
7 *
8 * Based on drivers/media/video/s5p-tv/mixer_reg.c
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the
12 * Free Software Foundation; either version 2 of the License, or (at your
13 * option) any later version.
14 *
15 */
16
17 #include "drmP.h"
18
19 #include "regs-mixer.h"
20 #include "regs-vp.h"
21
22 #include <linux/kernel.h>
23 #include <linux/spinlock.h>
24 #include <linux/wait.h>
25 #include <linux/i2c.h>
26 #include <linux/module.h>
27 #include <linux/platform_device.h>
28 #include <linux/interrupt.h>
29 #include <linux/irq.h>
30 #include <linux/delay.h>
31 #include <linux/pm_runtime.h>
32 #include <linux/clk.h>
33 #include <linux/regulator/consumer.h>
34
35 #include <drm/exynos_drm.h>
36
37 #include "exynos_drm_drv.h"
38 #include "exynos_drm_hdmi.h"
39
40 #define get_mixer_context(dev) platform_get_drvdata(to_platform_device(dev))
41
42 struct hdmi_win_data {
43 dma_addr_t dma_addr;
44 void __iomem *vaddr;
45 dma_addr_t chroma_dma_addr;
46 void __iomem *chroma_vaddr;
47 uint32_t pixel_format;
48 unsigned int bpp;
49 unsigned int crtc_x;
50 unsigned int crtc_y;
51 unsigned int crtc_width;
52 unsigned int crtc_height;
53 unsigned int fb_x;
54 unsigned int fb_y;
55 unsigned int fb_width;
56 unsigned int fb_height;
57 unsigned int mode_width;
58 unsigned int mode_height;
59 unsigned int scan_flags;
60 };
61
62 struct mixer_resources {
63 int irq;
64 void __iomem *mixer_regs;
65 void __iomem *vp_regs;
66 spinlock_t reg_slock;
67 struct clk *mixer;
68 struct clk *vp;
69 struct clk *sclk_mixer;
70 struct clk *sclk_hdmi;
71 struct clk *sclk_dac;
72 };
73
74 struct mixer_context {
75 struct device *dev;
76 int pipe;
77 bool interlace;
78 bool powered;
79 u32 int_en;
80
81 struct mutex mixer_mutex;
82 struct mixer_resources mixer_res;
83 struct hdmi_win_data win_data[MIXER_WIN_NR];
84 };
85
86 static const u8 filter_y_horiz_tap8[] = {
87 0, -1, -1, -1, -1, -1, -1, -1,
88 -1, -1, -1, -1, -1, 0, 0, 0,
89 0, 2, 4, 5, 6, 6, 6, 6,
90 6, 5, 5, 4, 3, 2, 1, 1,
91 0, -6, -12, -16, -18, -20, -21, -20,
92 -20, -18, -16, -13, -10, -8, -5, -2,
93 127, 126, 125, 121, 114, 107, 99, 89,
94 79, 68, 57, 46, 35, 25, 16, 8,
95 };
96
97 static const u8 filter_y_vert_tap4[] = {
98 0, -3, -6, -8, -8, -8, -8, -7,
99 -6, -5, -4, -3, -2, -1, -1, 0,
100 127, 126, 124, 118, 111, 102, 92, 81,
101 70, 59, 48, 37, 27, 19, 11, 5,
102 0, 5, 11, 19, 27, 37, 48, 59,
103 70, 81, 92, 102, 111, 118, 124, 126,
104 0, 0, -1, -1, -2, -3, -4, -5,
105 -6, -7, -8, -8, -8, -8, -6, -3,
106 };
107
108 static const u8 filter_cr_horiz_tap4[] = {
109 0, -3, -6, -8, -8, -8, -8, -7,
110 -6, -5, -4, -3, -2, -1, -1, 0,
111 127, 126, 124, 118, 111, 102, 92, 81,
112 70, 59, 48, 37, 27, 19, 11, 5,
113 };
114
115 static inline u32 vp_reg_read(struct mixer_resources *res, u32 reg_id)
116 {
117 return readl(res->vp_regs + reg_id);
118 }
119
120 static inline void vp_reg_write(struct mixer_resources *res, u32 reg_id,
121 u32 val)
122 {
123 writel(val, res->vp_regs + reg_id);
124 }
125
126 static inline void vp_reg_writemask(struct mixer_resources *res, u32 reg_id,
127 u32 val, u32 mask)
128 {
129 u32 old = vp_reg_read(res, reg_id);
130
131 val = (val & mask) | (old & ~mask);
132 writel(val, res->vp_regs + reg_id);
133 }
134
135 static inline u32 mixer_reg_read(struct mixer_resources *res, u32 reg_id)
136 {
137 return readl(res->mixer_regs + reg_id);
138 }
139
140 static inline void mixer_reg_write(struct mixer_resources *res, u32 reg_id,
141 u32 val)
142 {
143 writel(val, res->mixer_regs + reg_id);
144 }
145
146 static inline void mixer_reg_writemask(struct mixer_resources *res,
147 u32 reg_id, u32 val, u32 mask)
148 {
149 u32 old = mixer_reg_read(res, reg_id);
150
151 val = (val & mask) | (old & ~mask);
152 writel(val, res->mixer_regs + reg_id);
153 }
154
155 static void mixer_regs_dump(struct mixer_context *ctx)
156 {
157 #define DUMPREG(reg_id) \
158 do { \
159 DRM_DEBUG_KMS(#reg_id " = %08x\n", \
160 (u32)readl(ctx->mixer_res.mixer_regs + reg_id)); \
161 } while (0)
162
163 DUMPREG(MXR_STATUS);
164 DUMPREG(MXR_CFG);
165 DUMPREG(MXR_INT_EN);
166 DUMPREG(MXR_INT_STATUS);
167
168 DUMPREG(MXR_LAYER_CFG);
169 DUMPREG(MXR_VIDEO_CFG);
170
171 DUMPREG(MXR_GRAPHIC0_CFG);
172 DUMPREG(MXR_GRAPHIC0_BASE);
173 DUMPREG(MXR_GRAPHIC0_SPAN);
174 DUMPREG(MXR_GRAPHIC0_WH);
175 DUMPREG(MXR_GRAPHIC0_SXY);
176 DUMPREG(MXR_GRAPHIC0_DXY);
177
178 DUMPREG(MXR_GRAPHIC1_CFG);
179 DUMPREG(MXR_GRAPHIC1_BASE);
180 DUMPREG(MXR_GRAPHIC1_SPAN);
181 DUMPREG(MXR_GRAPHIC1_WH);
182 DUMPREG(MXR_GRAPHIC1_SXY);
183 DUMPREG(MXR_GRAPHIC1_DXY);
184 #undef DUMPREG
185 }
186
187 static void vp_regs_dump(struct mixer_context *ctx)
188 {
189 #define DUMPREG(reg_id) \
190 do { \
191 DRM_DEBUG_KMS(#reg_id " = %08x\n", \
192 (u32) readl(ctx->mixer_res.vp_regs + reg_id)); \
193 } while (0)
194
195 DUMPREG(VP_ENABLE);
196 DUMPREG(VP_SRESET);
197 DUMPREG(VP_SHADOW_UPDATE);
198 DUMPREG(VP_FIELD_ID);
199 DUMPREG(VP_MODE);
200 DUMPREG(VP_IMG_SIZE_Y);
201 DUMPREG(VP_IMG_SIZE_C);
202 DUMPREG(VP_PER_RATE_CTRL);
203 DUMPREG(VP_TOP_Y_PTR);
204 DUMPREG(VP_BOT_Y_PTR);
205 DUMPREG(VP_TOP_C_PTR);
206 DUMPREG(VP_BOT_C_PTR);
207 DUMPREG(VP_ENDIAN_MODE);
208 DUMPREG(VP_SRC_H_POSITION);
209 DUMPREG(VP_SRC_V_POSITION);
210 DUMPREG(VP_SRC_WIDTH);
211 DUMPREG(VP_SRC_HEIGHT);
212 DUMPREG(VP_DST_H_POSITION);
213 DUMPREG(VP_DST_V_POSITION);
214 DUMPREG(VP_DST_WIDTH);
215 DUMPREG(VP_DST_HEIGHT);
216 DUMPREG(VP_H_RATIO);
217 DUMPREG(VP_V_RATIO);
218
219 #undef DUMPREG
220 }
221
222 static inline void vp_filter_set(struct mixer_resources *res,
223 int reg_id, const u8 *data, unsigned int size)
224 {
225 /* assure 4-byte align */
226 BUG_ON(size & 3);
227 for (; size; size -= 4, reg_id += 4, data += 4) {
228 u32 val = (data[0] << 24) | (data[1] << 16) |
229 (data[2] << 8) | data[3];
230 vp_reg_write(res, reg_id, val);
231 }
232 }
233
234 static void vp_default_filter(struct mixer_resources *res)
235 {
236 vp_filter_set(res, VP_POLY8_Y0_LL,
237 filter_y_horiz_tap8, sizeof filter_y_horiz_tap8);
238 vp_filter_set(res, VP_POLY4_Y0_LL,
239 filter_y_vert_tap4, sizeof filter_y_vert_tap4);
240 vp_filter_set(res, VP_POLY4_C0_LL,
241 filter_cr_horiz_tap4, sizeof filter_cr_horiz_tap4);
242 }
243
244 static void mixer_vsync_set_update(struct mixer_context *ctx, bool enable)
245 {
246 struct mixer_resources *res = &ctx->mixer_res;
247
248 /* block update on vsync */
249 mixer_reg_writemask(res, MXR_STATUS, enable ?
250 MXR_STATUS_SYNC_ENABLE : 0, MXR_STATUS_SYNC_ENABLE);
251
252 vp_reg_write(res, VP_SHADOW_UPDATE, enable ?
253 VP_SHADOW_UPDATE_ENABLE : 0);
254 }
255
256 static void mixer_cfg_scan(struct mixer_context *ctx, unsigned int height)
257 {
258 struct mixer_resources *res = &ctx->mixer_res;
259 u32 val;
260
261 /* choosing between interlace and progressive mode */
262 val = (ctx->interlace ? MXR_CFG_SCAN_INTERLACE :
263 MXR_CFG_SCAN_PROGRASSIVE);
264
265 /* choosing between porper HD and SD mode */
266 if (height == 480)
267 val |= MXR_CFG_SCAN_NTSC | MXR_CFG_SCAN_SD;
268 else if (height == 576)
269 val |= MXR_CFG_SCAN_PAL | MXR_CFG_SCAN_SD;
270 else if (height == 720)
271 val |= MXR_CFG_SCAN_HD_720 | MXR_CFG_SCAN_HD;
272 else if (height == 1080)
273 val |= MXR_CFG_SCAN_HD_1080 | MXR_CFG_SCAN_HD;
274 else
275 val |= MXR_CFG_SCAN_HD_720 | MXR_CFG_SCAN_HD;
276
277 mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_SCAN_MASK);
278 }
279
280 static void mixer_cfg_rgb_fmt(struct mixer_context *ctx, unsigned int height)
281 {
282 struct mixer_resources *res = &ctx->mixer_res;
283 u32 val;
284
285 if (height == 480) {
286 val = MXR_CFG_RGB601_0_255;
287 } else if (height == 576) {
288 val = MXR_CFG_RGB601_0_255;
289 } else if (height == 720) {
290 val = MXR_CFG_RGB709_16_235;
291 mixer_reg_write(res, MXR_CM_COEFF_Y,
292 (1 << 30) | (94 << 20) | (314 << 10) |
293 (32 << 0));
294 mixer_reg_write(res, MXR_CM_COEFF_CB,
295 (972 << 20) | (851 << 10) | (225 << 0));
296 mixer_reg_write(res, MXR_CM_COEFF_CR,
297 (225 << 20) | (820 << 10) | (1004 << 0));
298 } else if (height == 1080) {
299 val = MXR_CFG_RGB709_16_235;
300 mixer_reg_write(res, MXR_CM_COEFF_Y,
301 (1 << 30) | (94 << 20) | (314 << 10) |
302 (32 << 0));
303 mixer_reg_write(res, MXR_CM_COEFF_CB,
304 (972 << 20) | (851 << 10) | (225 << 0));
305 mixer_reg_write(res, MXR_CM_COEFF_CR,
306 (225 << 20) | (820 << 10) | (1004 << 0));
307 } else {
308 val = MXR_CFG_RGB709_16_235;
309 mixer_reg_write(res, MXR_CM_COEFF_Y,
310 (1 << 30) | (94 << 20) | (314 << 10) |
311 (32 << 0));
312 mixer_reg_write(res, MXR_CM_COEFF_CB,
313 (972 << 20) | (851 << 10) | (225 << 0));
314 mixer_reg_write(res, MXR_CM_COEFF_CR,
315 (225 << 20) | (820 << 10) | (1004 << 0));
316 }
317
318 mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_RGB_FMT_MASK);
319 }
320
321 static void mixer_cfg_layer(struct mixer_context *ctx, int win, bool enable)
322 {
323 struct mixer_resources *res = &ctx->mixer_res;
324 u32 val = enable ? ~0 : 0;
325
326 switch (win) {
327 case 0:
328 mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP0_ENABLE);
329 break;
330 case 1:
331 mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP1_ENABLE);
332 break;
333 case 2:
334 vp_reg_writemask(res, VP_ENABLE, val, VP_ENABLE_ON);
335 mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_VP_ENABLE);
336 break;
337 }
338 }
339
340 static void mixer_run(struct mixer_context *ctx)
341 {
342 struct mixer_resources *res = &ctx->mixer_res;
343
344 mixer_reg_writemask(res, MXR_STATUS, ~0, MXR_STATUS_REG_RUN);
345
346 mixer_regs_dump(ctx);
347 }
348
349 static void vp_video_buffer(struct mixer_context *ctx, int win)
350 {
351 struct mixer_resources *res = &ctx->mixer_res;
352 unsigned long flags;
353 struct hdmi_win_data *win_data;
354 unsigned int full_width, full_height, width, height;
355 unsigned int x_ratio, y_ratio;
356 unsigned int src_x_offset, src_y_offset, dst_x_offset, dst_y_offset;
357 unsigned int mode_width, mode_height;
358 unsigned int buf_num;
359 dma_addr_t luma_addr[2], chroma_addr[2];
360 bool tiled_mode = false;
361 bool crcb_mode = false;
362 u32 val;
363
364 win_data = &ctx->win_data[win];
365
366 switch (win_data->pixel_format) {
367 case DRM_FORMAT_NV12MT:
368 tiled_mode = true;
369 case DRM_FORMAT_NV12M:
370 crcb_mode = false;
371 buf_num = 2;
372 break;
373 /* TODO: single buffer format NV12, NV21 */
374 default:
375 /* ignore pixel format at disable time */
376 if (!win_data->dma_addr)
377 break;
378
379 DRM_ERROR("pixel format for vp is wrong [%d].\n",
380 win_data->pixel_format);
381 return;
382 }
383
384 full_width = win_data->fb_width;
385 full_height = win_data->fb_height;
386 width = win_data->crtc_width;
387 height = win_data->crtc_height;
388 mode_width = win_data->mode_width;
389 mode_height = win_data->mode_height;
390
391 /* scaling feature: (src << 16) / dst */
392 x_ratio = (width << 16) / width;
393 y_ratio = (height << 16) / height;
394
395 src_x_offset = win_data->fb_x;
396 src_y_offset = win_data->fb_y;
397 dst_x_offset = win_data->crtc_x;
398 dst_y_offset = win_data->crtc_y;
399
400 if (buf_num == 2) {
401 luma_addr[0] = win_data->dma_addr;
402 chroma_addr[0] = win_data->chroma_dma_addr;
403 } else {
404 luma_addr[0] = win_data->dma_addr;
405 chroma_addr[0] = win_data->dma_addr
406 + (full_width * full_height);
407 }
408
409 if (win_data->scan_flags & DRM_MODE_FLAG_INTERLACE) {
410 ctx->interlace = true;
411 if (tiled_mode) {
412 luma_addr[1] = luma_addr[0] + 0x40;
413 chroma_addr[1] = chroma_addr[0] + 0x40;
414 } else {
415 luma_addr[1] = luma_addr[0] + full_width;
416 chroma_addr[1] = chroma_addr[0] + full_width;
417 }
418 } else {
419 ctx->interlace = false;
420 luma_addr[1] = 0;
421 chroma_addr[1] = 0;
422 }
423
424 spin_lock_irqsave(&res->reg_slock, flags);
425 mixer_vsync_set_update(ctx, false);
426
427 /* interlace or progressive scan mode */
428 val = (ctx->interlace ? ~0 : 0);
429 vp_reg_writemask(res, VP_MODE, val, VP_MODE_LINE_SKIP);
430
431 /* setup format */
432 val = (crcb_mode ? VP_MODE_NV21 : VP_MODE_NV12);
433 val |= (tiled_mode ? VP_MODE_MEM_TILED : VP_MODE_MEM_LINEAR);
434 vp_reg_writemask(res, VP_MODE, val, VP_MODE_FMT_MASK);
435
436 /* setting size of input image */
437 vp_reg_write(res, VP_IMG_SIZE_Y, VP_IMG_HSIZE(full_width) |
438 VP_IMG_VSIZE(full_height));
439 /* chroma height has to reduced by 2 to avoid chroma distorions */
440 vp_reg_write(res, VP_IMG_SIZE_C, VP_IMG_HSIZE(full_width) |
441 VP_IMG_VSIZE(full_height / 2));
442
443 vp_reg_write(res, VP_SRC_WIDTH, width);
444 vp_reg_write(res, VP_SRC_HEIGHT, height);
445 vp_reg_write(res, VP_SRC_H_POSITION,
446 VP_SRC_H_POSITION_VAL(src_x_offset));
447 vp_reg_write(res, VP_SRC_V_POSITION, src_y_offset);
448
449 vp_reg_write(res, VP_DST_WIDTH, width);
450 vp_reg_write(res, VP_DST_H_POSITION, dst_x_offset);
451 if (ctx->interlace) {
452 vp_reg_write(res, VP_DST_HEIGHT, height / 2);
453 vp_reg_write(res, VP_DST_V_POSITION, dst_y_offset / 2);
454 } else {
455 vp_reg_write(res, VP_DST_HEIGHT, height);
456 vp_reg_write(res, VP_DST_V_POSITION, dst_y_offset);
457 }
458
459 vp_reg_write(res, VP_H_RATIO, x_ratio);
460 vp_reg_write(res, VP_V_RATIO, y_ratio);
461
462 vp_reg_write(res, VP_ENDIAN_MODE, VP_ENDIAN_MODE_LITTLE);
463
464 /* set buffer address to vp */
465 vp_reg_write(res, VP_TOP_Y_PTR, luma_addr[0]);
466 vp_reg_write(res, VP_BOT_Y_PTR, luma_addr[1]);
467 vp_reg_write(res, VP_TOP_C_PTR, chroma_addr[0]);
468 vp_reg_write(res, VP_BOT_C_PTR, chroma_addr[1]);
469
470 mixer_cfg_scan(ctx, mode_height);
471 mixer_cfg_rgb_fmt(ctx, mode_height);
472 mixer_cfg_layer(ctx, win, true);
473 mixer_run(ctx);
474
475 mixer_vsync_set_update(ctx, true);
476 spin_unlock_irqrestore(&res->reg_slock, flags);
477
478 vp_regs_dump(ctx);
479 }
480
481 static void mixer_graph_buffer(struct mixer_context *ctx, int win)
482 {
483 struct mixer_resources *res = &ctx->mixer_res;
484 unsigned long flags;
485 struct hdmi_win_data *win_data;
486 unsigned int full_width, width, height;
487 unsigned int x_ratio, y_ratio;
488 unsigned int src_x_offset, src_y_offset, dst_x_offset, dst_y_offset;
489 unsigned int mode_width, mode_height;
490 dma_addr_t dma_addr;
491 unsigned int fmt;
492 u32 val;
493
494 win_data = &ctx->win_data[win];
495
496 #define RGB565 4
497 #define ARGB1555 5
498 #define ARGB4444 6
499 #define ARGB8888 7
500
501 switch (win_data->bpp) {
502 case 16:
503 fmt = ARGB4444;
504 break;
505 case 32:
506 fmt = ARGB8888;
507 break;
508 default:
509 fmt = ARGB8888;
510 }
511
512 dma_addr = win_data->dma_addr;
513 full_width = win_data->fb_width;
514 width = win_data->crtc_width;
515 height = win_data->crtc_height;
516 mode_width = win_data->mode_width;
517 mode_height = win_data->mode_height;
518
519 /* 2x scaling feature */
520 x_ratio = 0;
521 y_ratio = 0;
522
523 src_x_offset = win_data->fb_x;
524 src_y_offset = win_data->fb_y;
525 dst_x_offset = win_data->crtc_x;
526 dst_y_offset = win_data->crtc_y;
527
528 /* converting dma address base and source offset */
529 dma_addr = dma_addr
530 + (src_x_offset * win_data->bpp >> 3)
531 + (src_y_offset * full_width * win_data->bpp >> 3);
532 src_x_offset = 0;
533 src_y_offset = 0;
534
535 if (win_data->scan_flags & DRM_MODE_FLAG_INTERLACE)
536 ctx->interlace = true;
537 else
538 ctx->interlace = false;
539
540 spin_lock_irqsave(&res->reg_slock, flags);
541 mixer_vsync_set_update(ctx, false);
542
543 /* setup format */
544 mixer_reg_writemask(res, MXR_GRAPHIC_CFG(win),
545 MXR_GRP_CFG_FORMAT_VAL(fmt), MXR_GRP_CFG_FORMAT_MASK);
546
547 /* setup geometry */
548 mixer_reg_write(res, MXR_GRAPHIC_SPAN(win), full_width);
549
550 val = MXR_GRP_WH_WIDTH(width);
551 val |= MXR_GRP_WH_HEIGHT(height);
552 val |= MXR_GRP_WH_H_SCALE(x_ratio);
553 val |= MXR_GRP_WH_V_SCALE(y_ratio);
554 mixer_reg_write(res, MXR_GRAPHIC_WH(win), val);
555
556 /* setup offsets in source image */
557 val = MXR_GRP_SXY_SX(src_x_offset);
558 val |= MXR_GRP_SXY_SY(src_y_offset);
559 mixer_reg_write(res, MXR_GRAPHIC_SXY(win), val);
560
561 /* setup offsets in display image */
562 val = MXR_GRP_DXY_DX(dst_x_offset);
563 val |= MXR_GRP_DXY_DY(dst_y_offset);
564 mixer_reg_write(res, MXR_GRAPHIC_DXY(win), val);
565
566 /* set buffer address to mixer */
567 mixer_reg_write(res, MXR_GRAPHIC_BASE(win), dma_addr);
568
569 mixer_cfg_scan(ctx, mode_height);
570 mixer_cfg_rgb_fmt(ctx, mode_height);
571 mixer_cfg_layer(ctx, win, true);
572 mixer_run(ctx);
573
574 mixer_vsync_set_update(ctx, true);
575 spin_unlock_irqrestore(&res->reg_slock, flags);
576 }
577
578 static void vp_win_reset(struct mixer_context *ctx)
579 {
580 struct mixer_resources *res = &ctx->mixer_res;
581 int tries = 100;
582
583 vp_reg_write(res, VP_SRESET, VP_SRESET_PROCESSING);
584 for (tries = 100; tries; --tries) {
585 /* waiting until VP_SRESET_PROCESSING is 0 */
586 if (~vp_reg_read(res, VP_SRESET) & VP_SRESET_PROCESSING)
587 break;
588 mdelay(10);
589 }
590 WARN(tries == 0, "failed to reset Video Processor\n");
591 }
592
593 static void mixer_win_reset(struct mixer_context *ctx)
594 {
595 struct mixer_resources *res = &ctx->mixer_res;
596 unsigned long flags;
597 u32 val; /* value stored to register */
598
599 spin_lock_irqsave(&res->reg_slock, flags);
600 mixer_vsync_set_update(ctx, false);
601
602 mixer_reg_writemask(res, MXR_CFG, MXR_CFG_DST_HDMI, MXR_CFG_DST_MASK);
603
604 /* set output in RGB888 mode */
605 mixer_reg_writemask(res, MXR_CFG, MXR_CFG_OUT_RGB888, MXR_CFG_OUT_MASK);
606
607 /* 16 beat burst in DMA */
608 mixer_reg_writemask(res, MXR_STATUS, MXR_STATUS_16_BURST,
609 MXR_STATUS_BURST_MASK);
610
611 /* setting default layer priority: layer1 > layer0 > video
612 * because typical usage scenario would be
613 * layer1 - OSD
614 * layer0 - framebuffer
615 * video - video overlay
616 */
617 val = MXR_LAYER_CFG_GRP1_VAL(3);
618 val |= MXR_LAYER_CFG_GRP0_VAL(2);
619 val |= MXR_LAYER_CFG_VP_VAL(1);
620 mixer_reg_write(res, MXR_LAYER_CFG, val);
621
622 /* setting background color */
623 mixer_reg_write(res, MXR_BG_COLOR0, 0x008080);
624 mixer_reg_write(res, MXR_BG_COLOR1, 0x008080);
625 mixer_reg_write(res, MXR_BG_COLOR2, 0x008080);
626
627 /* setting graphical layers */
628
629 val = MXR_GRP_CFG_COLOR_KEY_DISABLE; /* no blank key */
630 val |= MXR_GRP_CFG_WIN_BLEND_EN;
631 val |= MXR_GRP_CFG_ALPHA_VAL(0xff); /* non-transparent alpha */
632
633 /* the same configuration for both layers */
634 mixer_reg_write(res, MXR_GRAPHIC_CFG(0), val);
635
636 val |= MXR_GRP_CFG_BLEND_PRE_MUL;
637 val |= MXR_GRP_CFG_PIXEL_BLEND_EN;
638 mixer_reg_write(res, MXR_GRAPHIC_CFG(1), val);
639
640 /* configuration of Video Processor Registers */
641 vp_win_reset(ctx);
642 vp_default_filter(res);
643
644 /* disable all layers */
645 mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_GRP0_ENABLE);
646 mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_GRP1_ENABLE);
647 mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_VP_ENABLE);
648
649 mixer_vsync_set_update(ctx, true);
650 spin_unlock_irqrestore(&res->reg_slock, flags);
651 }
652
653 static void mixer_poweron(struct mixer_context *ctx)
654 {
655 struct mixer_resources *res = &ctx->mixer_res;
656
657 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
658
659 mutex_lock(&ctx->mixer_mutex);
660 if (ctx->powered) {
661 mutex_unlock(&ctx->mixer_mutex);
662 return;
663 }
664 ctx->powered = true;
665 mutex_unlock(&ctx->mixer_mutex);
666
667 pm_runtime_get_sync(ctx->dev);
668
669 clk_enable(res->mixer);
670 clk_enable(res->vp);
671 clk_enable(res->sclk_mixer);
672
673 mixer_reg_write(res, MXR_INT_EN, ctx->int_en);
674 mixer_win_reset(ctx);
675 }
676
677 static void mixer_poweroff(struct mixer_context *ctx)
678 {
679 struct mixer_resources *res = &ctx->mixer_res;
680
681 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
682
683 mutex_lock(&ctx->mixer_mutex);
684 if (!ctx->powered)
685 goto out;
686 mutex_unlock(&ctx->mixer_mutex);
687
688 ctx->int_en = mixer_reg_read(res, MXR_INT_EN);
689
690 clk_disable(res->mixer);
691 clk_disable(res->vp);
692 clk_disable(res->sclk_mixer);
693
694 pm_runtime_put_sync(ctx->dev);
695
696 mutex_lock(&ctx->mixer_mutex);
697 ctx->powered = false;
698
699 out:
700 mutex_unlock(&ctx->mixer_mutex);
701 }
702
703 static int mixer_enable_vblank(void *ctx, int pipe)
704 {
705 struct mixer_context *mixer_ctx = ctx;
706 struct mixer_resources *res = &mixer_ctx->mixer_res;
707
708 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
709
710 mixer_ctx->pipe = pipe;
711
712 /* enable vsync interrupt */
713 mixer_reg_writemask(res, MXR_INT_EN, MXR_INT_EN_VSYNC,
714 MXR_INT_EN_VSYNC);
715
716 return 0;
717 }
718
719 static void mixer_disable_vblank(void *ctx)
720 {
721 struct mixer_context *mixer_ctx = ctx;
722 struct mixer_resources *res = &mixer_ctx->mixer_res;
723
724 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
725
726 /* disable vsync interrupt */
727 mixer_reg_writemask(res, MXR_INT_EN, 0, MXR_INT_EN_VSYNC);
728 }
729
730 static void mixer_dpms(void *ctx, int mode)
731 {
732 struct mixer_context *mixer_ctx = ctx;
733
734 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
735
736 switch (mode) {
737 case DRM_MODE_DPMS_ON:
738 mixer_poweron(mixer_ctx);
739 break;
740 case DRM_MODE_DPMS_STANDBY:
741 case DRM_MODE_DPMS_SUSPEND:
742 case DRM_MODE_DPMS_OFF:
743 mixer_poweroff(mixer_ctx);
744 break;
745 default:
746 DRM_DEBUG_KMS("unknown dpms mode: %d\n", mode);
747 break;
748 }
749 }
750
751 static void mixer_win_mode_set(void *ctx,
752 struct exynos_drm_overlay *overlay)
753 {
754 struct mixer_context *mixer_ctx = ctx;
755 struct hdmi_win_data *win_data;
756 int win;
757
758 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
759
760 if (!overlay) {
761 DRM_ERROR("overlay is NULL\n");
762 return;
763 }
764
765 DRM_DEBUG_KMS("set [%d]x[%d] at (%d,%d) to [%d]x[%d] at (%d,%d)\n",
766 overlay->fb_width, overlay->fb_height,
767 overlay->fb_x, overlay->fb_y,
768 overlay->crtc_width, overlay->crtc_height,
769 overlay->crtc_x, overlay->crtc_y);
770
771 win = overlay->zpos;
772 if (win == DEFAULT_ZPOS)
773 win = MIXER_DEFAULT_WIN;
774
775 if (win < 0 || win > MIXER_WIN_NR) {
776 DRM_ERROR("mixer window[%d] is wrong\n", win);
777 return;
778 }
779
780 win_data = &mixer_ctx->win_data[win];
781
782 win_data->dma_addr = overlay->dma_addr[0];
783 win_data->vaddr = overlay->vaddr[0];
784 win_data->chroma_dma_addr = overlay->dma_addr[1];
785 win_data->chroma_vaddr = overlay->vaddr[1];
786 win_data->pixel_format = overlay->pixel_format;
787 win_data->bpp = overlay->bpp;
788
789 win_data->crtc_x = overlay->crtc_x;
790 win_data->crtc_y = overlay->crtc_y;
791 win_data->crtc_width = overlay->crtc_width;
792 win_data->crtc_height = overlay->crtc_height;
793
794 win_data->fb_x = overlay->fb_x;
795 win_data->fb_y = overlay->fb_y;
796 win_data->fb_width = overlay->fb_width;
797 win_data->fb_height = overlay->fb_height;
798
799 win_data->mode_width = overlay->mode_width;
800 win_data->mode_height = overlay->mode_height;
801
802 win_data->scan_flags = overlay->scan_flag;
803 }
804
805 static void mixer_win_commit(void *ctx, int win)
806 {
807 struct mixer_context *mixer_ctx = ctx;
808
809 DRM_DEBUG_KMS("[%d] %s, win: %d\n", __LINE__, __func__, win);
810
811 if (win > 1)
812 vp_video_buffer(mixer_ctx, win);
813 else
814 mixer_graph_buffer(mixer_ctx, win);
815 }
816
817 static void mixer_win_disable(void *ctx, int win)
818 {
819 struct mixer_context *mixer_ctx = ctx;
820 struct mixer_resources *res = &mixer_ctx->mixer_res;
821 unsigned long flags;
822
823 DRM_DEBUG_KMS("[%d] %s, win: %d\n", __LINE__, __func__, win);
824
825 spin_lock_irqsave(&res->reg_slock, flags);
826 mixer_vsync_set_update(mixer_ctx, false);
827
828 mixer_cfg_layer(mixer_ctx, win, false);
829
830 mixer_vsync_set_update(mixer_ctx, true);
831 spin_unlock_irqrestore(&res->reg_slock, flags);
832 }
833
834 static struct exynos_mixer_ops mixer_ops = {
835 /* manager */
836 .enable_vblank = mixer_enable_vblank,
837 .disable_vblank = mixer_disable_vblank,
838 .dpms = mixer_dpms,
839
840 /* overlay */
841 .win_mode_set = mixer_win_mode_set,
842 .win_commit = mixer_win_commit,
843 .win_disable = mixer_win_disable,
844 };
845
846 /* for pageflip event */
847 static void mixer_finish_pageflip(struct drm_device *drm_dev, int crtc)
848 {
849 struct exynos_drm_private *dev_priv = drm_dev->dev_private;
850 struct drm_pending_vblank_event *e, *t;
851 struct timeval now;
852 unsigned long flags;
853 bool is_checked = false;
854
855 spin_lock_irqsave(&drm_dev->event_lock, flags);
856
857 list_for_each_entry_safe(e, t, &dev_priv->pageflip_event_list,
858 base.link) {
859 /* if event's pipe isn't same as crtc then ignore it. */
860 if (crtc != e->pipe)
861 continue;
862
863 is_checked = true;
864 do_gettimeofday(&now);
865 e->event.sequence = 0;
866 e->event.tv_sec = now.tv_sec;
867 e->event.tv_usec = now.tv_usec;
868
869 list_move_tail(&e->base.link, &e->base.file_priv->event_list);
870 wake_up_interruptible(&e->base.file_priv->event_wait);
871 }
872
873 if (is_checked)
874 /*
875 * call drm_vblank_put only in case that drm_vblank_get was
876 * called.
877 */
878 if (atomic_read(&drm_dev->vblank_refcount[crtc]) > 0)
879 drm_vblank_put(drm_dev, crtc);
880
881 spin_unlock_irqrestore(&drm_dev->event_lock, flags);
882 }
883
884 static irqreturn_t mixer_irq_handler(int irq, void *arg)
885 {
886 struct exynos_drm_hdmi_context *drm_hdmi_ctx = arg;
887 struct mixer_context *ctx = drm_hdmi_ctx->ctx;
888 struct mixer_resources *res = &ctx->mixer_res;
889 u32 val, base, shadow;
890
891 spin_lock(&res->reg_slock);
892
893 /* read interrupt status for handling and clearing flags for VSYNC */
894 val = mixer_reg_read(res, MXR_INT_STATUS);
895
896 /* handling VSYNC */
897 if (val & MXR_INT_STATUS_VSYNC) {
898 /* interlace scan need to check shadow register */
899 if (ctx->interlace) {
900 base = mixer_reg_read(res, MXR_GRAPHIC_BASE(0));
901 shadow = mixer_reg_read(res, MXR_GRAPHIC_BASE_S(0));
902 if (base != shadow)
903 goto out;
904
905 base = mixer_reg_read(res, MXR_GRAPHIC_BASE(1));
906 shadow = mixer_reg_read(res, MXR_GRAPHIC_BASE_S(1));
907 if (base != shadow)
908 goto out;
909 }
910
911 drm_handle_vblank(drm_hdmi_ctx->drm_dev, ctx->pipe);
912 mixer_finish_pageflip(drm_hdmi_ctx->drm_dev, ctx->pipe);
913 }
914
915 out:
916 /* clear interrupts */
917 if (~val & MXR_INT_EN_VSYNC) {
918 /* vsync interrupt use different bit for read and clear */
919 val &= ~MXR_INT_EN_VSYNC;
920 val |= MXR_INT_CLEAR_VSYNC;
921 }
922 mixer_reg_write(res, MXR_INT_STATUS, val);
923
924 spin_unlock(&res->reg_slock);
925
926 return IRQ_HANDLED;
927 }
928
929 static int __devinit mixer_resources_init(struct exynos_drm_hdmi_context *ctx,
930 struct platform_device *pdev)
931 {
932 struct mixer_context *mixer_ctx = ctx->ctx;
933 struct device *dev = &pdev->dev;
934 struct mixer_resources *mixer_res = &mixer_ctx->mixer_res;
935 struct resource *res;
936 int ret;
937
938 spin_lock_init(&mixer_res->reg_slock);
939
940 mixer_res->mixer = clk_get(dev, "mixer");
941 if (IS_ERR_OR_NULL(mixer_res->mixer)) {
942 dev_err(dev, "failed to get clock 'mixer'\n");
943 ret = -ENODEV;
944 goto fail;
945 }
946 mixer_res->vp = clk_get(dev, "vp");
947 if (IS_ERR_OR_NULL(mixer_res->vp)) {
948 dev_err(dev, "failed to get clock 'vp'\n");
949 ret = -ENODEV;
950 goto fail;
951 }
952 mixer_res->sclk_mixer = clk_get(dev, "sclk_mixer");
953 if (IS_ERR_OR_NULL(mixer_res->sclk_mixer)) {
954 dev_err(dev, "failed to get clock 'sclk_mixer'\n");
955 ret = -ENODEV;
956 goto fail;
957 }
958 mixer_res->sclk_hdmi = clk_get(dev, "sclk_hdmi");
959 if (IS_ERR_OR_NULL(mixer_res->sclk_hdmi)) {
960 dev_err(dev, "failed to get clock 'sclk_hdmi'\n");
961 ret = -ENODEV;
962 goto fail;
963 }
964 mixer_res->sclk_dac = clk_get(dev, "sclk_dac");
965 if (IS_ERR_OR_NULL(mixer_res->sclk_dac)) {
966 dev_err(dev, "failed to get clock 'sclk_dac'\n");
967 ret = -ENODEV;
968 goto fail;
969 }
970 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mxr");
971 if (res == NULL) {
972 dev_err(dev, "get memory resource failed.\n");
973 ret = -ENXIO;
974 goto fail;
975 }
976
977 clk_set_parent(mixer_res->sclk_mixer, mixer_res->sclk_hdmi);
978
979 mixer_res->mixer_regs = ioremap(res->start, resource_size(res));
980 if (mixer_res->mixer_regs == NULL) {
981 dev_err(dev, "register mapping failed.\n");
982 ret = -ENXIO;
983 goto fail;
984 }
985
986 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "vp");
987 if (res == NULL) {
988 dev_err(dev, "get memory resource failed.\n");
989 ret = -ENXIO;
990 goto fail_mixer_regs;
991 }
992
993 mixer_res->vp_regs = ioremap(res->start, resource_size(res));
994 if (mixer_res->vp_regs == NULL) {
995 dev_err(dev, "register mapping failed.\n");
996 ret = -ENXIO;
997 goto fail_mixer_regs;
998 }
999
1000 res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "irq");
1001 if (res == NULL) {
1002 dev_err(dev, "get interrupt resource failed.\n");
1003 ret = -ENXIO;
1004 goto fail_vp_regs;
1005 }
1006
1007 ret = request_irq(res->start, mixer_irq_handler, 0, "drm_mixer", ctx);
1008 if (ret) {
1009 dev_err(dev, "request interrupt failed.\n");
1010 goto fail_vp_regs;
1011 }
1012 mixer_res->irq = res->start;
1013
1014 return 0;
1015
1016 fail_vp_regs:
1017 iounmap(mixer_res->vp_regs);
1018
1019 fail_mixer_regs:
1020 iounmap(mixer_res->mixer_regs);
1021
1022 fail:
1023 if (!IS_ERR_OR_NULL(mixer_res->sclk_dac))
1024 clk_put(mixer_res->sclk_dac);
1025 if (!IS_ERR_OR_NULL(mixer_res->sclk_hdmi))
1026 clk_put(mixer_res->sclk_hdmi);
1027 if (!IS_ERR_OR_NULL(mixer_res->sclk_mixer))
1028 clk_put(mixer_res->sclk_mixer);
1029 if (!IS_ERR_OR_NULL(mixer_res->vp))
1030 clk_put(mixer_res->vp);
1031 if (!IS_ERR_OR_NULL(mixer_res->mixer))
1032 clk_put(mixer_res->mixer);
1033 return ret;
1034 }
1035
1036 static void mixer_resources_cleanup(struct mixer_context *ctx)
1037 {
1038 struct mixer_resources *res = &ctx->mixer_res;
1039
1040 free_irq(res->irq, ctx);
1041
1042 iounmap(res->vp_regs);
1043 iounmap(res->mixer_regs);
1044 }
1045
1046 static int __devinit mixer_probe(struct platform_device *pdev)
1047 {
1048 struct device *dev = &pdev->dev;
1049 struct exynos_drm_hdmi_context *drm_hdmi_ctx;
1050 struct mixer_context *ctx;
1051 int ret;
1052
1053 dev_info(dev, "probe start\n");
1054
1055 drm_hdmi_ctx = kzalloc(sizeof(*drm_hdmi_ctx), GFP_KERNEL);
1056 if (!drm_hdmi_ctx) {
1057 DRM_ERROR("failed to allocate common hdmi context.\n");
1058 return -ENOMEM;
1059 }
1060
1061 ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
1062 if (!ctx) {
1063 DRM_ERROR("failed to alloc mixer context.\n");
1064 kfree(drm_hdmi_ctx);
1065 return -ENOMEM;
1066 }
1067
1068 mutex_init(&ctx->mixer_mutex);
1069
1070 ctx->dev = &pdev->dev;
1071 drm_hdmi_ctx->ctx = (void *)ctx;
1072
1073 platform_set_drvdata(pdev, drm_hdmi_ctx);
1074
1075 /* acquire resources: regs, irqs, clocks */
1076 ret = mixer_resources_init(drm_hdmi_ctx, pdev);
1077 if (ret)
1078 goto fail;
1079
1080 /* register specific callback point to common hdmi. */
1081 exynos_mixer_ops_register(&mixer_ops);
1082
1083 pm_runtime_enable(dev);
1084
1085 return 0;
1086
1087
1088 fail:
1089 dev_info(dev, "probe failed\n");
1090 return ret;
1091 }
1092
1093 static int mixer_remove(struct platform_device *pdev)
1094 {
1095 struct device *dev = &pdev->dev;
1096 struct exynos_drm_hdmi_context *drm_hdmi_ctx =
1097 platform_get_drvdata(pdev);
1098 struct mixer_context *ctx = drm_hdmi_ctx->ctx;
1099
1100 dev_info(dev, "remove successful\n");
1101
1102 pm_runtime_disable(&pdev->dev);
1103
1104 mixer_resources_cleanup(ctx);
1105
1106 return 0;
1107 }
1108
1109 #ifdef CONFIG_PM_SLEEP
1110 static int mixer_suspend(struct device *dev)
1111 {
1112 struct exynos_drm_hdmi_context *drm_hdmi_ctx = get_mixer_context(dev);
1113 struct mixer_context *ctx = drm_hdmi_ctx->ctx;
1114
1115 mixer_poweroff(ctx);
1116
1117 return 0;
1118 }
1119 #endif
1120
1121 static SIMPLE_DEV_PM_OPS(mixer_pm_ops, mixer_suspend, NULL);
1122
1123 struct platform_driver mixer_driver = {
1124 .driver = {
1125 .name = "s5p-mixer",
1126 .owner = THIS_MODULE,
1127 .pm = &mixer_pm_ops,
1128 },
1129 .probe = mixer_probe,
1130 .remove = __devexit_p(mixer_remove),
1131 };