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