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