drm/exynos: remove unused codes in hdmi and mixer
[~shefty/rdma-dev.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 HDMI_OVERLAY_NUMBER     3
41
42 #define get_mixer_context(dev)  platform_get_drvdata(to_platform_device(dev))
43
44 struct hdmi_win_data {
45         dma_addr_t              dma_addr;
46         void __iomem            *vaddr;
47         dma_addr_t              chroma_dma_addr;
48         void __iomem            *chroma_vaddr;
49         uint32_t                pixel_format;
50         unsigned int            bpp;
51         unsigned int            crtc_x;
52         unsigned int            crtc_y;
53         unsigned int            crtc_width;
54         unsigned int            crtc_height;
55         unsigned int            fb_x;
56         unsigned int            fb_y;
57         unsigned int            fb_width;
58         unsigned int            fb_height;
59         unsigned int            mode_width;
60         unsigned int            mode_height;
61         unsigned int            scan_flags;
62 };
63
64 struct mixer_resources {
65         struct device           *dev;
66         int                     irq;
67         void __iomem            *mixer_regs;
68         void __iomem            *vp_regs;
69         spinlock_t              reg_slock;
70         struct clk              *mixer;
71         struct clk              *vp;
72         struct clk              *sclk_mixer;
73         struct clk              *sclk_hdmi;
74         struct clk              *sclk_dac;
75 };
76
77 struct mixer_context {
78         unsigned int            default_win;
79         unsigned int            irq;
80         int                     pipe;
81         bool                    interlace;
82
83         struct mixer_resources  mixer_res;
84         struct hdmi_win_data    win_data[HDMI_OVERLAY_NUMBER];
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_ctx->default_win;
644
645         if (win < 0 || win > HDMI_OVERLAY_NUMBER) {
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_ctx->default_win;
684
685         if (win < 0 || win > HDMI_OVERLAY_NUMBER) {
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_ctx->default_win;
707
708         if (win < 0 || win > HDMI_OVERLAY_NUMBER) {
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_hdmi_overlay_ops overlay_ops = {
723         .enable_vblank          = mixer_enable_vblank,
724         .disable_vblank         = mixer_disable_vblank,
725         .win_mode_set           = mixer_win_mode_set,
726         .win_commit             = mixer_win_commit,
727         .win_disable            = mixer_win_disable,
728 };
729
730 /* for pageflip event */
731 static void mixer_finish_pageflip(struct drm_device *drm_dev, int crtc)
732 {
733         struct exynos_drm_private *dev_priv = drm_dev->dev_private;
734         struct drm_pending_vblank_event *e, *t;
735         struct timeval now;
736         unsigned long flags;
737         bool is_checked = false;
738
739         spin_lock_irqsave(&drm_dev->event_lock, flags);
740
741         list_for_each_entry_safe(e, t, &dev_priv->pageflip_event_list,
742                         base.link) {
743                 /* if event's pipe isn't same as crtc then ignore it. */
744                 if (crtc != e->pipe)
745                         continue;
746
747                 is_checked = true;
748                 do_gettimeofday(&now);
749                 e->event.sequence = 0;
750                 e->event.tv_sec = now.tv_sec;
751                 e->event.tv_usec = now.tv_usec;
752
753                 list_move_tail(&e->base.link, &e->base.file_priv->event_list);
754                 wake_up_interruptible(&e->base.file_priv->event_wait);
755         }
756
757         if (is_checked)
758                 /*
759                  * call drm_vblank_put only in case that drm_vblank_get was
760                  * called.
761                  */
762                 if (atomic_read(&drm_dev->vblank_refcount[crtc]) > 0)
763                         drm_vblank_put(drm_dev, crtc);
764
765         spin_unlock_irqrestore(&drm_dev->event_lock, flags);
766 }
767
768 static irqreturn_t mixer_irq_handler(int irq, void *arg)
769 {
770         struct exynos_drm_hdmi_context *drm_hdmi_ctx = arg;
771         struct mixer_context *ctx = drm_hdmi_ctx->ctx;
772         struct mixer_resources *res = &ctx->mixer_res;
773         u32 val, val_base;
774
775         spin_lock(&res->reg_slock);
776
777         /* read interrupt status for handling and clearing flags for VSYNC */
778         val = mixer_reg_read(res, MXR_INT_STATUS);
779
780         /* handling VSYNC */
781         if (val & MXR_INT_STATUS_VSYNC) {
782                 /* interlace scan need to check shadow register */
783                 if (ctx->interlace) {
784                         val_base = mixer_reg_read(res, MXR_GRAPHIC_BASE_S(0));
785                         if (ctx->win_data[0].dma_addr != val_base)
786                                 goto out;
787
788                         val_base = mixer_reg_read(res, MXR_GRAPHIC_BASE_S(1));
789                         if (ctx->win_data[1].dma_addr != val_base)
790                                 goto out;
791                 }
792
793                 drm_handle_vblank(drm_hdmi_ctx->drm_dev, ctx->pipe);
794                 mixer_finish_pageflip(drm_hdmi_ctx->drm_dev, ctx->pipe);
795         }
796
797 out:
798         /* clear interrupts */
799         if (~val & MXR_INT_EN_VSYNC) {
800                 /* vsync interrupt use different bit for read and clear */
801                 val &= ~MXR_INT_EN_VSYNC;
802                 val |= MXR_INT_CLEAR_VSYNC;
803         }
804         mixer_reg_write(res, MXR_INT_STATUS, val);
805
806         spin_unlock(&res->reg_slock);
807
808         return IRQ_HANDLED;
809 }
810
811 static void mixer_win_reset(struct mixer_context *ctx)
812 {
813         struct mixer_resources *res = &ctx->mixer_res;
814         unsigned long flags;
815         u32 val; /* value stored to register */
816
817         spin_lock_irqsave(&res->reg_slock, flags);
818         mixer_vsync_set_update(ctx, false);
819
820         mixer_reg_writemask(res, MXR_CFG, MXR_CFG_DST_HDMI, MXR_CFG_DST_MASK);
821
822         /* set output in RGB888 mode */
823         mixer_reg_writemask(res, MXR_CFG, MXR_CFG_OUT_RGB888, MXR_CFG_OUT_MASK);
824
825         /* 16 beat burst in DMA */
826         mixer_reg_writemask(res, MXR_STATUS, MXR_STATUS_16_BURST,
827                 MXR_STATUS_BURST_MASK);
828
829         /* setting default layer priority: layer1 > layer0 > video
830          * because typical usage scenario would be
831          * layer1 - OSD
832          * layer0 - framebuffer
833          * video - video overlay
834          */
835         val = MXR_LAYER_CFG_GRP1_VAL(3);
836         val |= MXR_LAYER_CFG_GRP0_VAL(2);
837         val |= MXR_LAYER_CFG_VP_VAL(1);
838         mixer_reg_write(res, MXR_LAYER_CFG, val);
839
840         /* setting background color */
841         mixer_reg_write(res, MXR_BG_COLOR0, 0x008080);
842         mixer_reg_write(res, MXR_BG_COLOR1, 0x008080);
843         mixer_reg_write(res, MXR_BG_COLOR2, 0x008080);
844
845         /* setting graphical layers */
846
847         val  = MXR_GRP_CFG_COLOR_KEY_DISABLE; /* no blank key */
848         val |= MXR_GRP_CFG_WIN_BLEND_EN;
849         val |= MXR_GRP_CFG_ALPHA_VAL(0xff); /* non-transparent alpha */
850
851         /* the same configuration for both layers */
852         mixer_reg_write(res, MXR_GRAPHIC_CFG(0), val);
853
854         val |= MXR_GRP_CFG_BLEND_PRE_MUL;
855         val |= MXR_GRP_CFG_PIXEL_BLEND_EN;
856         mixer_reg_write(res, MXR_GRAPHIC_CFG(1), val);
857
858         /* configuration of Video Processor Registers */
859         vp_win_reset(ctx);
860         vp_default_filter(res);
861
862         /* disable all layers */
863         mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_GRP0_ENABLE);
864         mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_GRP1_ENABLE);
865         mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_VP_ENABLE);
866
867         mixer_vsync_set_update(ctx, true);
868         spin_unlock_irqrestore(&res->reg_slock, flags);
869 }
870
871 static void mixer_resource_poweron(struct mixer_context *ctx)
872 {
873         struct mixer_resources *res = &ctx->mixer_res;
874
875         DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
876
877         clk_enable(res->mixer);
878         clk_enable(res->vp);
879         clk_enable(res->sclk_mixer);
880
881         mixer_win_reset(ctx);
882 }
883
884 static void mixer_resource_poweroff(struct mixer_context *ctx)
885 {
886         struct mixer_resources *res = &ctx->mixer_res;
887
888         DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
889
890         clk_disable(res->mixer);
891         clk_disable(res->vp);
892         clk_disable(res->sclk_mixer);
893 }
894
895 static int mixer_runtime_resume(struct device *dev)
896 {
897         struct exynos_drm_hdmi_context *ctx = get_mixer_context(dev);
898
899         DRM_DEBUG_KMS("resume - start\n");
900
901         mixer_resource_poweron(ctx->ctx);
902
903         return 0;
904 }
905
906 static int mixer_runtime_suspend(struct device *dev)
907 {
908         struct exynos_drm_hdmi_context *ctx = get_mixer_context(dev);
909
910         DRM_DEBUG_KMS("suspend - start\n");
911
912         mixer_resource_poweroff(ctx->ctx);
913
914         return 0;
915 }
916
917 static const struct dev_pm_ops mixer_pm_ops = {
918         .runtime_suspend = mixer_runtime_suspend,
919         .runtime_resume  = mixer_runtime_resume,
920 };
921
922 static int __devinit mixer_resources_init(struct exynos_drm_hdmi_context *ctx,
923                                  struct platform_device *pdev)
924 {
925         struct mixer_context *mixer_ctx = ctx->ctx;
926         struct device *dev = &pdev->dev;
927         struct mixer_resources *mixer_res = &mixer_ctx->mixer_res;
928         struct resource *res;
929         int ret;
930
931         mixer_res->dev = dev;
932         spin_lock_init(&mixer_res->reg_slock);
933
934         mixer_res->mixer = clk_get(dev, "mixer");
935         if (IS_ERR_OR_NULL(mixer_res->mixer)) {
936                 dev_err(dev, "failed to get clock 'mixer'\n");
937                 ret = -ENODEV;
938                 goto fail;
939         }
940         mixer_res->vp = clk_get(dev, "vp");
941         if (IS_ERR_OR_NULL(mixer_res->vp)) {
942                 dev_err(dev, "failed to get clock 'vp'\n");
943                 ret = -ENODEV;
944                 goto fail;
945         }
946         mixer_res->sclk_mixer = clk_get(dev, "sclk_mixer");
947         if (IS_ERR_OR_NULL(mixer_res->sclk_mixer)) {
948                 dev_err(dev, "failed to get clock 'sclk_mixer'\n");
949                 ret = -ENODEV;
950                 goto fail;
951         }
952         mixer_res->sclk_hdmi = clk_get(dev, "sclk_hdmi");
953         if (IS_ERR_OR_NULL(mixer_res->sclk_hdmi)) {
954                 dev_err(dev, "failed to get clock 'sclk_hdmi'\n");
955                 ret = -ENODEV;
956                 goto fail;
957         }
958         mixer_res->sclk_dac = clk_get(dev, "sclk_dac");
959         if (IS_ERR_OR_NULL(mixer_res->sclk_dac)) {
960                 dev_err(dev, "failed to get clock 'sclk_dac'\n");
961                 ret = -ENODEV;
962                 goto fail;
963         }
964         res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mxr");
965         if (res == NULL) {
966                 dev_err(dev, "get memory resource failed.\n");
967                 ret = -ENXIO;
968                 goto fail;
969         }
970
971         clk_set_parent(mixer_res->sclk_mixer, mixer_res->sclk_hdmi);
972
973         mixer_res->mixer_regs = ioremap(res->start, resource_size(res));
974         if (mixer_res->mixer_regs == NULL) {
975                 dev_err(dev, "register mapping failed.\n");
976                 ret = -ENXIO;
977                 goto fail;
978         }
979
980         res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "vp");
981         if (res == NULL) {
982                 dev_err(dev, "get memory resource failed.\n");
983                 ret = -ENXIO;
984                 goto fail_mixer_regs;
985         }
986
987         mixer_res->vp_regs = ioremap(res->start, resource_size(res));
988         if (mixer_res->vp_regs == NULL) {
989                 dev_err(dev, "register mapping failed.\n");
990                 ret = -ENXIO;
991                 goto fail_mixer_regs;
992         }
993
994         res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "irq");
995         if (res == NULL) {
996                 dev_err(dev, "get interrupt resource failed.\n");
997                 ret = -ENXIO;
998                 goto fail_vp_regs;
999         }
1000
1001         ret = request_irq(res->start, mixer_irq_handler, 0, "drm_mixer", ctx);
1002         if (ret) {
1003                 dev_err(dev, "request interrupt failed.\n");
1004                 goto fail_vp_regs;
1005         }
1006         mixer_res->irq = res->start;
1007
1008         return 0;
1009
1010 fail_vp_regs:
1011         iounmap(mixer_res->vp_regs);
1012
1013 fail_mixer_regs:
1014         iounmap(mixer_res->mixer_regs);
1015
1016 fail:
1017         if (!IS_ERR_OR_NULL(mixer_res->sclk_dac))
1018                 clk_put(mixer_res->sclk_dac);
1019         if (!IS_ERR_OR_NULL(mixer_res->sclk_hdmi))
1020                 clk_put(mixer_res->sclk_hdmi);
1021         if (!IS_ERR_OR_NULL(mixer_res->sclk_mixer))
1022                 clk_put(mixer_res->sclk_mixer);
1023         if (!IS_ERR_OR_NULL(mixer_res->vp))
1024                 clk_put(mixer_res->vp);
1025         if (!IS_ERR_OR_NULL(mixer_res->mixer))
1026                 clk_put(mixer_res->mixer);
1027         mixer_res->dev = NULL;
1028         return ret;
1029 }
1030
1031 static void mixer_resources_cleanup(struct mixer_context *ctx)
1032 {
1033         struct mixer_resources *res = &ctx->mixer_res;
1034
1035         disable_irq(res->irq);
1036         free_irq(res->irq, ctx);
1037
1038         iounmap(res->vp_regs);
1039         iounmap(res->mixer_regs);
1040 }
1041
1042 static int __devinit mixer_probe(struct platform_device *pdev)
1043 {
1044         struct device *dev = &pdev->dev;
1045         struct exynos_drm_hdmi_context *drm_hdmi_ctx;
1046         struct mixer_context *ctx;
1047         int ret;
1048
1049         dev_info(dev, "probe start\n");
1050
1051         drm_hdmi_ctx = kzalloc(sizeof(*drm_hdmi_ctx), GFP_KERNEL);
1052         if (!drm_hdmi_ctx) {
1053                 DRM_ERROR("failed to allocate common hdmi context.\n");
1054                 return -ENOMEM;
1055         }
1056
1057         ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
1058         if (!ctx) {
1059                 DRM_ERROR("failed to alloc mixer context.\n");
1060                 kfree(drm_hdmi_ctx);
1061                 return -ENOMEM;
1062         }
1063
1064         drm_hdmi_ctx->ctx = (void *)ctx;
1065
1066         platform_set_drvdata(pdev, drm_hdmi_ctx);
1067
1068         /* acquire resources: regs, irqs, clocks */
1069         ret = mixer_resources_init(drm_hdmi_ctx, pdev);
1070         if (ret)
1071                 goto fail;
1072
1073         /* register specific callback point to common hdmi. */
1074         exynos_drm_overlay_ops_register(&overlay_ops);
1075
1076         mixer_resource_poweron(ctx);
1077
1078         return 0;
1079
1080
1081 fail:
1082         dev_info(dev, "probe failed\n");
1083         return ret;
1084 }
1085
1086 static int mixer_remove(struct platform_device *pdev)
1087 {
1088         struct device *dev = &pdev->dev;
1089         struct exynos_drm_hdmi_context *drm_hdmi_ctx =
1090                                         platform_get_drvdata(pdev);
1091         struct mixer_context *ctx = drm_hdmi_ctx->ctx;
1092
1093         dev_info(dev, "remove successful\n");
1094
1095         mixer_resource_poweroff(ctx);
1096         mixer_resources_cleanup(ctx);
1097
1098         return 0;
1099 }
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 };