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