netfilter: remove unnecessary goto statement for error recovery
[cascardo/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 "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_NV12:
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         val  = MXR_GRP_CFG_COLOR_KEY_DISABLE; /* no blank key */
605         val |= MXR_GRP_CFG_WIN_BLEND_EN;
606         val |= MXR_GRP_CFG_BLEND_PRE_MUL;
607         val |= MXR_GRP_CFG_PIXEL_BLEND_EN;
608         val |= MXR_GRP_CFG_ALPHA_VAL(0xff); /* non-transparent alpha */
609
610         /* the same configuration for both layers */
611         mixer_reg_write(res, MXR_GRAPHIC_CFG(0), val);
612         mixer_reg_write(res, MXR_GRAPHIC_CFG(1), val);
613
614         /* setting video layers */
615         val = MXR_GRP_CFG_ALPHA_VAL(0);
616         mixer_reg_write(res, MXR_VIDEO_CFG, val);
617
618         /* configuration of Video Processor Registers */
619         vp_win_reset(ctx);
620         vp_default_filter(res);
621
622         /* disable all layers */
623         mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_GRP0_ENABLE);
624         mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_GRP1_ENABLE);
625         mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_VP_ENABLE);
626
627         mixer_vsync_set_update(ctx, true);
628         spin_unlock_irqrestore(&res->reg_slock, flags);
629 }
630
631 static void mixer_poweron(struct mixer_context *ctx)
632 {
633         struct mixer_resources *res = &ctx->mixer_res;
634
635         DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
636
637         mutex_lock(&ctx->mixer_mutex);
638         if (ctx->powered) {
639                 mutex_unlock(&ctx->mixer_mutex);
640                 return;
641         }
642         ctx->powered = true;
643         mutex_unlock(&ctx->mixer_mutex);
644
645         pm_runtime_get_sync(ctx->dev);
646
647         clk_enable(res->mixer);
648         clk_enable(res->vp);
649         clk_enable(res->sclk_mixer);
650
651         mixer_reg_write(res, MXR_INT_EN, ctx->int_en);
652         mixer_win_reset(ctx);
653 }
654
655 static void mixer_poweroff(struct mixer_context *ctx)
656 {
657         struct mixer_resources *res = &ctx->mixer_res;
658
659         DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
660
661         mutex_lock(&ctx->mixer_mutex);
662         if (!ctx->powered)
663                 goto out;
664         mutex_unlock(&ctx->mixer_mutex);
665
666         ctx->int_en = mixer_reg_read(res, MXR_INT_EN);
667
668         clk_disable(res->mixer);
669         clk_disable(res->vp);
670         clk_disable(res->sclk_mixer);
671
672         pm_runtime_put_sync(ctx->dev);
673
674         mutex_lock(&ctx->mixer_mutex);
675         ctx->powered = false;
676
677 out:
678         mutex_unlock(&ctx->mixer_mutex);
679 }
680
681 static int mixer_enable_vblank(void *ctx, int pipe)
682 {
683         struct mixer_context *mixer_ctx = ctx;
684         struct mixer_resources *res = &mixer_ctx->mixer_res;
685
686         DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
687
688         mixer_ctx->pipe = pipe;
689
690         /* enable vsync interrupt */
691         mixer_reg_writemask(res, MXR_INT_EN, MXR_INT_EN_VSYNC,
692                         MXR_INT_EN_VSYNC);
693
694         return 0;
695 }
696
697 static void mixer_disable_vblank(void *ctx)
698 {
699         struct mixer_context *mixer_ctx = ctx;
700         struct mixer_resources *res = &mixer_ctx->mixer_res;
701
702         DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
703
704         /* disable vsync interrupt */
705         mixer_reg_writemask(res, MXR_INT_EN, 0, MXR_INT_EN_VSYNC);
706 }
707
708 static void mixer_dpms(void *ctx, int mode)
709 {
710         struct mixer_context *mixer_ctx = ctx;
711
712         DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
713
714         switch (mode) {
715         case DRM_MODE_DPMS_ON:
716                 mixer_poweron(mixer_ctx);
717                 break;
718         case DRM_MODE_DPMS_STANDBY:
719         case DRM_MODE_DPMS_SUSPEND:
720         case DRM_MODE_DPMS_OFF:
721                 mixer_poweroff(mixer_ctx);
722                 break;
723         default:
724                 DRM_DEBUG_KMS("unknown dpms mode: %d\n", mode);
725                 break;
726         }
727 }
728
729 static void mixer_win_mode_set(void *ctx,
730                               struct exynos_drm_overlay *overlay)
731 {
732         struct mixer_context *mixer_ctx = ctx;
733         struct hdmi_win_data *win_data;
734         int win;
735
736         DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
737
738         if (!overlay) {
739                 DRM_ERROR("overlay is NULL\n");
740                 return;
741         }
742
743         DRM_DEBUG_KMS("set [%d]x[%d] at (%d,%d) to [%d]x[%d] at (%d,%d)\n",
744                                  overlay->fb_width, overlay->fb_height,
745                                  overlay->fb_x, overlay->fb_y,
746                                  overlay->crtc_width, overlay->crtc_height,
747                                  overlay->crtc_x, overlay->crtc_y);
748
749         win = overlay->zpos;
750         if (win == DEFAULT_ZPOS)
751                 win = MIXER_DEFAULT_WIN;
752
753         if (win < 0 || win > MIXER_WIN_NR) {
754                 DRM_ERROR("mixer window[%d] is wrong\n", win);
755                 return;
756         }
757
758         win_data = &mixer_ctx->win_data[win];
759
760         win_data->dma_addr = overlay->dma_addr[0];
761         win_data->vaddr = overlay->vaddr[0];
762         win_data->chroma_dma_addr = overlay->dma_addr[1];
763         win_data->chroma_vaddr = overlay->vaddr[1];
764         win_data->pixel_format = overlay->pixel_format;
765         win_data->bpp = overlay->bpp;
766
767         win_data->crtc_x = overlay->crtc_x;
768         win_data->crtc_y = overlay->crtc_y;
769         win_data->crtc_width = overlay->crtc_width;
770         win_data->crtc_height = overlay->crtc_height;
771
772         win_data->fb_x = overlay->fb_x;
773         win_data->fb_y = overlay->fb_y;
774         win_data->fb_width = overlay->fb_width;
775         win_data->fb_height = overlay->fb_height;
776         win_data->src_width = overlay->src_width;
777         win_data->src_height = overlay->src_height;
778
779         win_data->mode_width = overlay->mode_width;
780         win_data->mode_height = overlay->mode_height;
781
782         win_data->scan_flags = overlay->scan_flag;
783 }
784
785 static void mixer_win_commit(void *ctx, int win)
786 {
787         struct mixer_context *mixer_ctx = ctx;
788
789         DRM_DEBUG_KMS("[%d] %s, win: %d\n", __LINE__, __func__, win);
790
791         if (win > 1)
792                 vp_video_buffer(mixer_ctx, win);
793         else
794                 mixer_graph_buffer(mixer_ctx, win);
795 }
796
797 static void mixer_win_disable(void *ctx, int win)
798 {
799         struct mixer_context *mixer_ctx = ctx;
800         struct mixer_resources *res = &mixer_ctx->mixer_res;
801         unsigned long flags;
802
803         DRM_DEBUG_KMS("[%d] %s, win: %d\n", __LINE__, __func__, win);
804
805         spin_lock_irqsave(&res->reg_slock, flags);
806         mixer_vsync_set_update(mixer_ctx, false);
807
808         mixer_cfg_layer(mixer_ctx, win, false);
809
810         mixer_vsync_set_update(mixer_ctx, true);
811         spin_unlock_irqrestore(&res->reg_slock, flags);
812 }
813
814 static struct exynos_mixer_ops mixer_ops = {
815         /* manager */
816         .enable_vblank          = mixer_enable_vblank,
817         .disable_vblank         = mixer_disable_vblank,
818         .dpms                   = mixer_dpms,
819
820         /* overlay */
821         .win_mode_set           = mixer_win_mode_set,
822         .win_commit             = mixer_win_commit,
823         .win_disable            = mixer_win_disable,
824 };
825
826 /* for pageflip event */
827 static void mixer_finish_pageflip(struct drm_device *drm_dev, int crtc)
828 {
829         struct exynos_drm_private *dev_priv = drm_dev->dev_private;
830         struct drm_pending_vblank_event *e, *t;
831         struct timeval now;
832         unsigned long flags;
833         bool is_checked = false;
834
835         spin_lock_irqsave(&drm_dev->event_lock, flags);
836
837         list_for_each_entry_safe(e, t, &dev_priv->pageflip_event_list,
838                         base.link) {
839                 /* if event's pipe isn't same as crtc then ignore it. */
840                 if (crtc != e->pipe)
841                         continue;
842
843                 is_checked = true;
844                 do_gettimeofday(&now);
845                 e->event.sequence = 0;
846                 e->event.tv_sec = now.tv_sec;
847                 e->event.tv_usec = now.tv_usec;
848
849                 list_move_tail(&e->base.link, &e->base.file_priv->event_list);
850                 wake_up_interruptible(&e->base.file_priv->event_wait);
851         }
852
853         if (is_checked)
854                 /*
855                  * call drm_vblank_put only in case that drm_vblank_get was
856                  * called.
857                  */
858                 if (atomic_read(&drm_dev->vblank_refcount[crtc]) > 0)
859                         drm_vblank_put(drm_dev, crtc);
860
861         spin_unlock_irqrestore(&drm_dev->event_lock, flags);
862 }
863
864 static irqreturn_t mixer_irq_handler(int irq, void *arg)
865 {
866         struct exynos_drm_hdmi_context *drm_hdmi_ctx = arg;
867         struct mixer_context *ctx = drm_hdmi_ctx->ctx;
868         struct mixer_resources *res = &ctx->mixer_res;
869         u32 val, base, shadow;
870
871         spin_lock(&res->reg_slock);
872
873         /* read interrupt status for handling and clearing flags for VSYNC */
874         val = mixer_reg_read(res, MXR_INT_STATUS);
875
876         /* handling VSYNC */
877         if (val & MXR_INT_STATUS_VSYNC) {
878                 /* interlace scan need to check shadow register */
879                 if (ctx->interlace) {
880                         base = mixer_reg_read(res, MXR_GRAPHIC_BASE(0));
881                         shadow = mixer_reg_read(res, MXR_GRAPHIC_BASE_S(0));
882                         if (base != shadow)
883                                 goto out;
884
885                         base = mixer_reg_read(res, MXR_GRAPHIC_BASE(1));
886                         shadow = mixer_reg_read(res, MXR_GRAPHIC_BASE_S(1));
887                         if (base != shadow)
888                                 goto out;
889                 }
890
891                 drm_handle_vblank(drm_hdmi_ctx->drm_dev, ctx->pipe);
892                 mixer_finish_pageflip(drm_hdmi_ctx->drm_dev, ctx->pipe);
893         }
894
895 out:
896         /* clear interrupts */
897         if (~val & MXR_INT_EN_VSYNC) {
898                 /* vsync interrupt use different bit for read and clear */
899                 val &= ~MXR_INT_EN_VSYNC;
900                 val |= MXR_INT_CLEAR_VSYNC;
901         }
902         mixer_reg_write(res, MXR_INT_STATUS, val);
903
904         spin_unlock(&res->reg_slock);
905
906         return IRQ_HANDLED;
907 }
908
909 static int __devinit mixer_resources_init(struct exynos_drm_hdmi_context *ctx,
910                                  struct platform_device *pdev)
911 {
912         struct mixer_context *mixer_ctx = ctx->ctx;
913         struct device *dev = &pdev->dev;
914         struct mixer_resources *mixer_res = &mixer_ctx->mixer_res;
915         struct resource *res;
916         int ret;
917
918         spin_lock_init(&mixer_res->reg_slock);
919
920         mixer_res->mixer = clk_get(dev, "mixer");
921         if (IS_ERR_OR_NULL(mixer_res->mixer)) {
922                 dev_err(dev, "failed to get clock 'mixer'\n");
923                 ret = -ENODEV;
924                 goto fail;
925         }
926         mixer_res->vp = clk_get(dev, "vp");
927         if (IS_ERR_OR_NULL(mixer_res->vp)) {
928                 dev_err(dev, "failed to get clock 'vp'\n");
929                 ret = -ENODEV;
930                 goto fail;
931         }
932         mixer_res->sclk_mixer = clk_get(dev, "sclk_mixer");
933         if (IS_ERR_OR_NULL(mixer_res->sclk_mixer)) {
934                 dev_err(dev, "failed to get clock 'sclk_mixer'\n");
935                 ret = -ENODEV;
936                 goto fail;
937         }
938         mixer_res->sclk_hdmi = clk_get(dev, "sclk_hdmi");
939         if (IS_ERR_OR_NULL(mixer_res->sclk_hdmi)) {
940                 dev_err(dev, "failed to get clock 'sclk_hdmi'\n");
941                 ret = -ENODEV;
942                 goto fail;
943         }
944         mixer_res->sclk_dac = clk_get(dev, "sclk_dac");
945         if (IS_ERR_OR_NULL(mixer_res->sclk_dac)) {
946                 dev_err(dev, "failed to get clock 'sclk_dac'\n");
947                 ret = -ENODEV;
948                 goto fail;
949         }
950         res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mxr");
951         if (res == NULL) {
952                 dev_err(dev, "get memory resource failed.\n");
953                 ret = -ENXIO;
954                 goto fail;
955         }
956
957         clk_set_parent(mixer_res->sclk_mixer, mixer_res->sclk_hdmi);
958
959         mixer_res->mixer_regs = ioremap(res->start, resource_size(res));
960         if (mixer_res->mixer_regs == NULL) {
961                 dev_err(dev, "register mapping failed.\n");
962                 ret = -ENXIO;
963                 goto fail;
964         }
965
966         res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "vp");
967         if (res == NULL) {
968                 dev_err(dev, "get memory resource failed.\n");
969                 ret = -ENXIO;
970                 goto fail_mixer_regs;
971         }
972
973         mixer_res->vp_regs = ioremap(res->start, resource_size(res));
974         if (mixer_res->vp_regs == NULL) {
975                 dev_err(dev, "register mapping failed.\n");
976                 ret = -ENXIO;
977                 goto fail_mixer_regs;
978         }
979
980         res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "irq");
981         if (res == NULL) {
982                 dev_err(dev, "get interrupt resource failed.\n");
983                 ret = -ENXIO;
984                 goto fail_vp_regs;
985         }
986
987         ret = request_irq(res->start, mixer_irq_handler, 0, "drm_mixer", ctx);
988         if (ret) {
989                 dev_err(dev, "request interrupt failed.\n");
990                 goto fail_vp_regs;
991         }
992         mixer_res->irq = res->start;
993
994         return 0;
995
996 fail_vp_regs:
997         iounmap(mixer_res->vp_regs);
998
999 fail_mixer_regs:
1000         iounmap(mixer_res->mixer_regs);
1001
1002 fail:
1003         if (!IS_ERR_OR_NULL(mixer_res->sclk_dac))
1004                 clk_put(mixer_res->sclk_dac);
1005         if (!IS_ERR_OR_NULL(mixer_res->sclk_hdmi))
1006                 clk_put(mixer_res->sclk_hdmi);
1007         if (!IS_ERR_OR_NULL(mixer_res->sclk_mixer))
1008                 clk_put(mixer_res->sclk_mixer);
1009         if (!IS_ERR_OR_NULL(mixer_res->vp))
1010                 clk_put(mixer_res->vp);
1011         if (!IS_ERR_OR_NULL(mixer_res->mixer))
1012                 clk_put(mixer_res->mixer);
1013         return ret;
1014 }
1015
1016 static void mixer_resources_cleanup(struct mixer_context *ctx)
1017 {
1018         struct mixer_resources *res = &ctx->mixer_res;
1019
1020         free_irq(res->irq, ctx);
1021
1022         iounmap(res->vp_regs);
1023         iounmap(res->mixer_regs);
1024 }
1025
1026 static int __devinit mixer_probe(struct platform_device *pdev)
1027 {
1028         struct device *dev = &pdev->dev;
1029         struct exynos_drm_hdmi_context *drm_hdmi_ctx;
1030         struct mixer_context *ctx;
1031         int ret;
1032
1033         dev_info(dev, "probe start\n");
1034
1035         drm_hdmi_ctx = kzalloc(sizeof(*drm_hdmi_ctx), GFP_KERNEL);
1036         if (!drm_hdmi_ctx) {
1037                 DRM_ERROR("failed to allocate common hdmi context.\n");
1038                 return -ENOMEM;
1039         }
1040
1041         ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
1042         if (!ctx) {
1043                 DRM_ERROR("failed to alloc mixer context.\n");
1044                 kfree(drm_hdmi_ctx);
1045                 return -ENOMEM;
1046         }
1047
1048         mutex_init(&ctx->mixer_mutex);
1049
1050         ctx->dev = &pdev->dev;
1051         drm_hdmi_ctx->ctx = (void *)ctx;
1052
1053         platform_set_drvdata(pdev, drm_hdmi_ctx);
1054
1055         /* acquire resources: regs, irqs, clocks */
1056         ret = mixer_resources_init(drm_hdmi_ctx, pdev);
1057         if (ret)
1058                 goto fail;
1059
1060         /* register specific callback point to common hdmi. */
1061         exynos_mixer_ops_register(&mixer_ops);
1062
1063         pm_runtime_enable(dev);
1064
1065         return 0;
1066
1067
1068 fail:
1069         dev_info(dev, "probe failed\n");
1070         return ret;
1071 }
1072
1073 static int mixer_remove(struct platform_device *pdev)
1074 {
1075         struct device *dev = &pdev->dev;
1076         struct exynos_drm_hdmi_context *drm_hdmi_ctx =
1077                                         platform_get_drvdata(pdev);
1078         struct mixer_context *ctx = drm_hdmi_ctx->ctx;
1079
1080         dev_info(dev, "remove successful\n");
1081
1082         pm_runtime_disable(&pdev->dev);
1083
1084         mixer_resources_cleanup(ctx);
1085
1086         return 0;
1087 }
1088
1089 #ifdef CONFIG_PM_SLEEP
1090 static int mixer_suspend(struct device *dev)
1091 {
1092         struct exynos_drm_hdmi_context *drm_hdmi_ctx = get_mixer_context(dev);
1093         struct mixer_context *ctx = drm_hdmi_ctx->ctx;
1094
1095         mixer_poweroff(ctx);
1096
1097         return 0;
1098 }
1099 #endif
1100
1101 static SIMPLE_DEV_PM_OPS(mixer_pm_ops, mixer_suspend, NULL);
1102
1103 struct platform_driver mixer_driver = {
1104         .driver = {
1105                 .name = "s5p-mixer",
1106                 .owner = THIS_MODULE,
1107                 .pm = &mixer_pm_ops,
1108         },
1109         .probe = mixer_probe,
1110         .remove = __devexit_p(mixer_remove),
1111 };