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