17f881f1749d85ea1bdabf136f43cf71a0069637
[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 vp_video_buffer(struct mixer_context *ctx, int win)
355 {
356         struct mixer_resources *res = &ctx->mixer_res;
357         unsigned long flags;
358         struct hdmi_win_data *win_data;
359         unsigned int x_ratio, y_ratio;
360         unsigned int buf_num;
361         dma_addr_t luma_addr[2], chroma_addr[2];
362         bool tiled_mode = false;
363         bool crcb_mode = false;
364         u32 val;
365
366         win_data = &ctx->win_data[win];
367
368         switch (win_data->pixel_format) {
369         case DRM_FORMAT_NV12MT:
370                 tiled_mode = true;
371         case DRM_FORMAT_NV12M:
372                 crcb_mode = false;
373                 buf_num = 2;
374                 break;
375         /* TODO: single buffer format NV12, NV21 */
376         default:
377                 /* ignore pixel format at disable time */
378                 if (!win_data->dma_addr)
379                         break;
380
381                 DRM_ERROR("pixel format for vp is wrong [%d].\n",
382                                 win_data->pixel_format);
383                 return;
384         }
385
386         /* scaling feature: (src << 16) / dst */
387         x_ratio = (win_data->src_width << 16) / win_data->crtc_width;
388         y_ratio = (win_data->src_height << 16) / win_data->crtc_height;
389
390         if (buf_num == 2) {
391                 luma_addr[0] = win_data->dma_addr;
392                 chroma_addr[0] = win_data->chroma_dma_addr;
393         } else {
394                 luma_addr[0] = win_data->dma_addr;
395                 chroma_addr[0] = win_data->dma_addr
396                         + (win_data->fb_width * win_data->fb_height);
397         }
398
399         if (win_data->scan_flags & DRM_MODE_FLAG_INTERLACE) {
400                 ctx->interlace = true;
401                 if (tiled_mode) {
402                         luma_addr[1] = luma_addr[0] + 0x40;
403                         chroma_addr[1] = chroma_addr[0] + 0x40;
404                 } else {
405                         luma_addr[1] = luma_addr[0] + win_data->fb_width;
406                         chroma_addr[1] = chroma_addr[0] + win_data->fb_width;
407                 }
408         } else {
409                 ctx->interlace = false;
410                 luma_addr[1] = 0;
411                 chroma_addr[1] = 0;
412         }
413
414         spin_lock_irqsave(&res->reg_slock, flags);
415         mixer_vsync_set_update(ctx, false);
416
417         /* interlace or progressive scan mode */
418         val = (ctx->interlace ? ~0 : 0);
419         vp_reg_writemask(res, VP_MODE, val, VP_MODE_LINE_SKIP);
420
421         /* setup format */
422         val = (crcb_mode ? VP_MODE_NV21 : VP_MODE_NV12);
423         val |= (tiled_mode ? VP_MODE_MEM_TILED : VP_MODE_MEM_LINEAR);
424         vp_reg_writemask(res, VP_MODE, val, VP_MODE_FMT_MASK);
425
426         /* setting size of input image */
427         vp_reg_write(res, VP_IMG_SIZE_Y, VP_IMG_HSIZE(win_data->fb_width) |
428                 VP_IMG_VSIZE(win_data->fb_height));
429         /* chroma height has to reduced by 2 to avoid chroma distorions */
430         vp_reg_write(res, VP_IMG_SIZE_C, VP_IMG_HSIZE(win_data->fb_width) |
431                 VP_IMG_VSIZE(win_data->fb_height / 2));
432
433         vp_reg_write(res, VP_SRC_WIDTH, win_data->src_width);
434         vp_reg_write(res, VP_SRC_HEIGHT, win_data->src_height);
435         vp_reg_write(res, VP_SRC_H_POSITION,
436                         VP_SRC_H_POSITION_VAL(win_data->fb_x));
437         vp_reg_write(res, VP_SRC_V_POSITION, win_data->fb_y);
438
439         vp_reg_write(res, VP_DST_WIDTH, win_data->crtc_width);
440         vp_reg_write(res, VP_DST_H_POSITION, win_data->crtc_x);
441         if (ctx->interlace) {
442                 vp_reg_write(res, VP_DST_HEIGHT, win_data->crtc_height / 2);
443                 vp_reg_write(res, VP_DST_V_POSITION, win_data->crtc_y / 2);
444         } else {
445                 vp_reg_write(res, VP_DST_HEIGHT, win_data->crtc_height);
446                 vp_reg_write(res, VP_DST_V_POSITION, win_data->crtc_y);
447         }
448
449         vp_reg_write(res, VP_H_RATIO, x_ratio);
450         vp_reg_write(res, VP_V_RATIO, y_ratio);
451
452         vp_reg_write(res, VP_ENDIAN_MODE, VP_ENDIAN_MODE_LITTLE);
453
454         /* set buffer address to vp */
455         vp_reg_write(res, VP_TOP_Y_PTR, luma_addr[0]);
456         vp_reg_write(res, VP_BOT_Y_PTR, luma_addr[1]);
457         vp_reg_write(res, VP_TOP_C_PTR, chroma_addr[0]);
458         vp_reg_write(res, VP_BOT_C_PTR, chroma_addr[1]);
459
460         mixer_cfg_scan(ctx, win_data->mode_height);
461         mixer_cfg_rgb_fmt(ctx, win_data->mode_height);
462         mixer_cfg_layer(ctx, win, true);
463         mixer_run(ctx);
464
465         mixer_vsync_set_update(ctx, true);
466         spin_unlock_irqrestore(&res->reg_slock, flags);
467
468         vp_regs_dump(ctx);
469 }
470
471 static void mixer_graph_buffer(struct mixer_context *ctx, int win)
472 {
473         struct mixer_resources *res = &ctx->mixer_res;
474         unsigned long flags;
475         struct hdmi_win_data *win_data;
476         unsigned int x_ratio, y_ratio;
477         unsigned int src_x_offset, src_y_offset, dst_x_offset, dst_y_offset;
478         dma_addr_t dma_addr;
479         unsigned int fmt;
480         u32 val;
481
482         win_data = &ctx->win_data[win];
483
484         #define RGB565 4
485         #define ARGB1555 5
486         #define ARGB4444 6
487         #define ARGB8888 7
488
489         switch (win_data->bpp) {
490         case 16:
491                 fmt = ARGB4444;
492                 break;
493         case 32:
494                 fmt = ARGB8888;
495                 break;
496         default:
497                 fmt = ARGB8888;
498         }
499
500         /* 2x scaling feature */
501         x_ratio = 0;
502         y_ratio = 0;
503
504         dst_x_offset = win_data->crtc_x;
505         dst_y_offset = win_data->crtc_y;
506
507         /* converting dma address base and source offset */
508         dma_addr = win_data->dma_addr
509                 + (win_data->fb_x * win_data->bpp >> 3)
510                 + (win_data->fb_y * win_data->fb_width * win_data->bpp >> 3);
511         src_x_offset = 0;
512         src_y_offset = 0;
513
514         if (win_data->scan_flags & DRM_MODE_FLAG_INTERLACE)
515                 ctx->interlace = true;
516         else
517                 ctx->interlace = false;
518
519         spin_lock_irqsave(&res->reg_slock, flags);
520         mixer_vsync_set_update(ctx, false);
521
522         /* setup format */
523         mixer_reg_writemask(res, MXR_GRAPHIC_CFG(win),
524                 MXR_GRP_CFG_FORMAT_VAL(fmt), MXR_GRP_CFG_FORMAT_MASK);
525
526         /* setup geometry */
527         mixer_reg_write(res, MXR_GRAPHIC_SPAN(win), win_data->fb_width);
528
529         val  = MXR_GRP_WH_WIDTH(win_data->crtc_width);
530         val |= MXR_GRP_WH_HEIGHT(win_data->crtc_height);
531         val |= MXR_GRP_WH_H_SCALE(x_ratio);
532         val |= MXR_GRP_WH_V_SCALE(y_ratio);
533         mixer_reg_write(res, MXR_GRAPHIC_WH(win), val);
534
535         /* setup offsets in source image */
536         val  = MXR_GRP_SXY_SX(src_x_offset);
537         val |= MXR_GRP_SXY_SY(src_y_offset);
538         mixer_reg_write(res, MXR_GRAPHIC_SXY(win), val);
539
540         /* setup offsets in display image */
541         val  = MXR_GRP_DXY_DX(dst_x_offset);
542         val |= MXR_GRP_DXY_DY(dst_y_offset);
543         mixer_reg_write(res, MXR_GRAPHIC_DXY(win), val);
544
545         /* set buffer address to mixer */
546         mixer_reg_write(res, MXR_GRAPHIC_BASE(win), dma_addr);
547
548         mixer_cfg_scan(ctx, win_data->mode_height);
549         mixer_cfg_rgb_fmt(ctx, win_data->mode_height);
550         mixer_cfg_layer(ctx, win, true);
551         mixer_run(ctx);
552
553         mixer_vsync_set_update(ctx, true);
554         spin_unlock_irqrestore(&res->reg_slock, flags);
555 }
556
557 static void vp_win_reset(struct mixer_context *ctx)
558 {
559         struct mixer_resources *res = &ctx->mixer_res;
560         int tries = 100;
561
562         vp_reg_write(res, VP_SRESET, VP_SRESET_PROCESSING);
563         for (tries = 100; tries; --tries) {
564                 /* waiting until VP_SRESET_PROCESSING is 0 */
565                 if (~vp_reg_read(res, VP_SRESET) & VP_SRESET_PROCESSING)
566                         break;
567                 mdelay(10);
568         }
569         WARN(tries == 0, "failed to reset Video Processor\n");
570 }
571
572 static void mixer_win_reset(struct mixer_context *ctx)
573 {
574         struct mixer_resources *res = &ctx->mixer_res;
575         unsigned long flags;
576         u32 val; /* value stored to register */
577
578         spin_lock_irqsave(&res->reg_slock, flags);
579         mixer_vsync_set_update(ctx, false);
580
581         mixer_reg_writemask(res, MXR_CFG, MXR_CFG_DST_HDMI, MXR_CFG_DST_MASK);
582
583         /* set output in RGB888 mode */
584         mixer_reg_writemask(res, MXR_CFG, MXR_CFG_OUT_RGB888, MXR_CFG_OUT_MASK);
585
586         /* 16 beat burst in DMA */
587         mixer_reg_writemask(res, MXR_STATUS, MXR_STATUS_16_BURST,
588                 MXR_STATUS_BURST_MASK);
589
590         /* setting default layer priority: layer1 > layer0 > video
591          * because typical usage scenario would be
592          * layer1 - OSD
593          * layer0 - framebuffer
594          * video - video overlay
595          */
596         val = MXR_LAYER_CFG_GRP1_VAL(3);
597         val |= MXR_LAYER_CFG_GRP0_VAL(2);
598         val |= MXR_LAYER_CFG_VP_VAL(1);
599         mixer_reg_write(res, MXR_LAYER_CFG, val);
600
601         /* setting background color */
602         mixer_reg_write(res, MXR_BG_COLOR0, 0x008080);
603         mixer_reg_write(res, MXR_BG_COLOR1, 0x008080);
604         mixer_reg_write(res, MXR_BG_COLOR2, 0x008080);
605
606         /* setting graphical layers */
607         val  = MXR_GRP_CFG_COLOR_KEY_DISABLE; /* no blank key */
608         val |= MXR_GRP_CFG_WIN_BLEND_EN;
609         val |= MXR_GRP_CFG_BLEND_PRE_MUL;
610         val |= MXR_GRP_CFG_PIXEL_BLEND_EN;
611         val |= MXR_GRP_CFG_ALPHA_VAL(0xff); /* non-transparent alpha */
612
613         /* the same configuration for both layers */
614         mixer_reg_write(res, MXR_GRAPHIC_CFG(0), val);
615         mixer_reg_write(res, MXR_GRAPHIC_CFG(1), val);
616
617         /* setting video layers */
618         val = MXR_GRP_CFG_ALPHA_VAL(0);
619         mixer_reg_write(res, MXR_VIDEO_CFG, val);
620
621         /* configuration of Video Processor Registers */
622         vp_win_reset(ctx);
623         vp_default_filter(res);
624
625         /* disable all layers */
626         mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_GRP0_ENABLE);
627         mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_GRP1_ENABLE);
628         mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_VP_ENABLE);
629
630         mixer_vsync_set_update(ctx, true);
631         spin_unlock_irqrestore(&res->reg_slock, flags);
632 }
633
634 static void mixer_poweron(struct mixer_context *ctx)
635 {
636         struct mixer_resources *res = &ctx->mixer_res;
637
638         DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
639
640         mutex_lock(&ctx->mixer_mutex);
641         if (ctx->powered) {
642                 mutex_unlock(&ctx->mixer_mutex);
643                 return;
644         }
645         ctx->powered = true;
646         mutex_unlock(&ctx->mixer_mutex);
647
648         res->mixer_regs = res->saved_mixer_regs;
649         res->vp_regs = res->saved_vp_regs;
650
651         pm_runtime_get_sync(ctx->dev);
652
653         clk_enable(res->mixer);
654         clk_enable(res->vp);
655         clk_enable(res->sclk_mixer);
656
657         mixer_reg_write(res, MXR_INT_EN, ctx->int_en);
658         mixer_win_reset(ctx);
659 }
660
661 static void vp_cleanup(struct mixer_context *ctx)
662 {
663         struct mixer_resources *res = &ctx->mixer_res;
664         int val, retries = 200;
665
666         DRM_DEBUG_KMS("%s\n", __func__);
667
668         vp_reg_writemask(res, VP_ENABLE, 0, VP_ENABLE_ON);
669
670         do {
671                 val = vp_reg_read(res, VP_ENABLE);
672         } while (!(val & VP_ENABLE_OPERATING) && retries--);
673
674         if (!retries)
675                 DRM_ERROR("vp disable failed.\n");
676
677         /* clean buffer address to vp */
678         vp_reg_write(res, VP_TOP_Y_PTR, 0);
679         vp_reg_write(res, VP_BOT_Y_PTR, 0);
680         vp_reg_write(res, VP_TOP_C_PTR, 0);
681         vp_reg_write(res, VP_BOT_C_PTR, 0);
682 }
683
684 static void mixer_cleanup(struct mixer_context *ctx)
685 {
686         struct mixer_resources *res = &ctx->mixer_res;
687         int val, retries = 200;
688
689         DRM_DEBUG_KMS("%s\n", __func__);
690
691         /* disable vsync */
692         mixer_reg_writemask(res, MXR_INT_EN, 0, MXR_INT_EN_VSYNC);
693
694         /* stop MIXER */
695         mixer_reg_writemask(res, MXR_STATUS, 0, MXR_STATUS_REG_RUN);
696
697         do {
698                 val = mixer_reg_read(res, MXR_STATUS);
699         } while (!(val & MXR_STATUS_IDLE_MODE) && retries--);
700
701         if (!retries)
702                 DRM_ERROR("mixer disable failed.\n");
703 }
704
705 static void mixer_poweroff(struct mixer_context *ctx)
706 {
707         struct mixer_resources *res = &ctx->mixer_res;
708         unsigned long flags;
709
710         DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
711
712         mutex_lock(&ctx->mixer_mutex);
713         if (!ctx->powered)
714                 goto out;
715         mutex_unlock(&ctx->mixer_mutex);
716
717         spin_lock_irqsave(&res->reg_slock, flags);
718
719         ctx->int_en = mixer_reg_read(res, MXR_INT_EN);
720         mixer_vsync_set_update(ctx, false);
721
722         vp_cleanup(ctx);
723         mixer_cleanup(ctx);
724
725         spin_unlock_irqrestore(&res->reg_slock, flags);
726
727         /* HDMI changed sclk_hdmi parent clock from pixel to hdmiphy */
728         clk_set_parent(res->sclk_hdmi, res->sclk_pixel);
729
730         clk_disable(res->mixer);
731         clk_disable(res->vp);
732         clk_disable(res->sclk_mixer);
733
734         res->mixer_regs = NULL;
735         res->vp_regs = NULL;
736
737         pm_runtime_put_sync(ctx->dev);
738
739         mutex_lock(&ctx->mixer_mutex);
740         ctx->powered = false;
741
742 out:
743         mutex_unlock(&ctx->mixer_mutex);
744 }
745
746 static int mixer_enable_vblank(void *ctx, int pipe)
747 {
748         struct mixer_context *mixer_ctx = ctx;
749         struct mixer_resources *res = &mixer_ctx->mixer_res;
750
751         DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
752
753         mixer_ctx->pipe = pipe;
754
755         /* enable vsync interrupt */
756         mixer_reg_writemask(res, MXR_INT_EN, MXR_INT_EN_VSYNC,
757                         MXR_INT_EN_VSYNC);
758
759         return 0;
760 }
761
762 static void mixer_disable_vblank(void *ctx)
763 {
764         struct mixer_context *mixer_ctx = ctx;
765         struct mixer_resources *res = &mixer_ctx->mixer_res;
766
767         DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
768
769         /* disable vsync interrupt */
770         mixer_reg_writemask(res, MXR_INT_EN, 0, MXR_INT_EN_VSYNC);
771 }
772
773 static void mixer_dpms(void *ctx, int mode)
774 {
775         struct mixer_context *mixer_ctx = ctx;
776
777         DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
778
779         switch (mode) {
780         case DRM_MODE_DPMS_ON:
781                 mixer_poweron(mixer_ctx);
782                 break;
783         case DRM_MODE_DPMS_STANDBY:
784         case DRM_MODE_DPMS_SUSPEND:
785         case DRM_MODE_DPMS_OFF:
786                 mixer_poweroff(mixer_ctx);
787                 break;
788         default:
789                 DRM_DEBUG_KMS("unknown dpms mode: %d\n", mode);
790                 break;
791         }
792 }
793
794 static void mixer_wait_for_vblank(void *ctx)
795 {
796         struct mixer_context *mixer_ctx = ctx;
797         struct mixer_resources *res = &mixer_ctx->mixer_res;
798         int ret;
799
800         ret = wait_for((mixer_reg_read(res, MXR_INT_STATUS) &
801                                 MXR_INT_STATUS_VSYNC), 50);
802         if (ret < 0)
803                 DRM_DEBUG_KMS("vblank wait timed out.\n");
804 }
805
806 static void mixer_win_mode_set(void *ctx,
807                               struct exynos_drm_overlay *overlay)
808 {
809         struct mixer_context *mixer_ctx = ctx;
810         struct hdmi_win_data *win_data;
811         int win;
812
813         DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
814
815         if (!overlay) {
816                 DRM_ERROR("overlay is NULL\n");
817                 return;
818         }
819
820         DRM_DEBUG_KMS("set [%d]x[%d] at (%d,%d) to [%d]x[%d] at (%d,%d)\n",
821                                  overlay->fb_width, overlay->fb_height,
822                                  overlay->fb_x, overlay->fb_y,
823                                  overlay->crtc_width, overlay->crtc_height,
824                                  overlay->crtc_x, overlay->crtc_y);
825
826         win = overlay->zpos;
827         if (win == DEFAULT_ZPOS)
828                 win = MIXER_DEFAULT_WIN;
829
830         if (win < 0 || win > MIXER_WIN_NR) {
831                 DRM_ERROR("mixer window[%d] is wrong\n", win);
832                 return;
833         }
834
835         win_data = &mixer_ctx->win_data[win];
836
837         win_data->dma_addr = overlay->dma_addr[0];
838         win_data->vaddr = overlay->vaddr[0];
839         win_data->chroma_dma_addr = overlay->dma_addr[1];
840         win_data->chroma_vaddr = overlay->vaddr[1];
841         win_data->pixel_format = overlay->pixel_format;
842         win_data->bpp = overlay->bpp;
843
844         win_data->crtc_x = overlay->crtc_x;
845         win_data->crtc_y = overlay->crtc_y;
846         win_data->crtc_width = overlay->crtc_width;
847         win_data->crtc_height = overlay->crtc_height;
848
849         win_data->fb_x = overlay->fb_x;
850         win_data->fb_y = overlay->fb_y;
851         win_data->fb_width = overlay->fb_width;
852         win_data->fb_height = overlay->fb_height;
853         win_data->src_width = overlay->src_width;
854         win_data->src_height = overlay->src_height;
855
856         win_data->mode_width = overlay->mode_width;
857         win_data->mode_height = overlay->mode_height;
858
859         win_data->scan_flags = overlay->scan_flag;
860 }
861
862 static void mixer_win_commit(void *ctx, int win)
863 {
864         struct mixer_context *mixer_ctx = ctx;
865
866         DRM_DEBUG_KMS("[%d] %s, win: %d\n", __LINE__, __func__, win);
867
868         if (win > 1)
869                 vp_video_buffer(mixer_ctx, win);
870         else
871                 mixer_graph_buffer(mixer_ctx, win);
872 }
873
874 static void mixer_win_disable(void *ctx, int win)
875 {
876         struct mixer_context *mixer_ctx = ctx;
877         struct mixer_resources *res = &mixer_ctx->mixer_res;
878         unsigned long flags;
879
880         DRM_DEBUG_KMS("[%d] %s, win: %d\n", __LINE__, __func__, win);
881
882         spin_lock_irqsave(&res->reg_slock, flags);
883         mixer_vsync_set_update(mixer_ctx, false);
884
885         mixer_cfg_layer(mixer_ctx, win, false);
886
887         mixer_vsync_set_update(mixer_ctx, true);
888         spin_unlock_irqrestore(&res->reg_slock, flags);
889 }
890
891 static struct exynos_mixer_ops mixer_ops = {
892         /* manager */
893         .enable_vblank          = mixer_enable_vblank,
894         .disable_vblank         = mixer_disable_vblank,
895         .dpms                   = mixer_dpms,
896
897         /* overlay */
898         .wait_for_vblank        = mixer_wait_for_vblank,
899         .win_mode_set           = mixer_win_mode_set,
900         .win_commit             = mixer_win_commit,
901         .win_disable            = mixer_win_disable,
902 };
903
904 /* for pageflip event */
905 static void mixer_finish_pageflip(struct drm_device *drm_dev, int crtc)
906 {
907         struct exynos_drm_private *dev_priv = drm_dev->dev_private;
908         struct drm_pending_vblank_event *e, *t;
909         struct timeval now;
910         unsigned long flags;
911         bool is_checked = false;
912
913         spin_lock_irqsave(&drm_dev->event_lock, flags);
914
915         list_for_each_entry_safe(e, t, &dev_priv->pageflip_event_list,
916                         base.link) {
917                 /* if event's pipe isn't same as crtc then ignore it. */
918                 if (crtc != e->pipe)
919                         continue;
920
921                 is_checked = true;
922                 do_gettimeofday(&now);
923                 e->event.sequence = 0;
924                 e->event.tv_sec = now.tv_sec;
925                 e->event.tv_usec = now.tv_usec;
926
927                 list_move_tail(&e->base.link, &e->base.file_priv->event_list);
928                 wake_up_interruptible(&e->base.file_priv->event_wait);
929         }
930
931         if (is_checked)
932                 /*
933                  * call drm_vblank_put only in case that drm_vblank_get was
934                  * called.
935                  */
936                 if (atomic_read(&drm_dev->vblank_refcount[crtc]) > 0)
937                         drm_vblank_put(drm_dev, crtc);
938
939         spin_unlock_irqrestore(&drm_dev->event_lock, flags);
940 }
941
942 static irqreturn_t mixer_irq_handler(int irq, void *arg)
943 {
944         struct exynos_drm_hdmi_context *drm_hdmi_ctx = arg;
945         struct mixer_context *ctx = drm_hdmi_ctx->ctx;
946         struct mixer_resources *res = &ctx->mixer_res;
947         u32 val, base, shadow;
948
949         spin_lock(&res->reg_slock);
950
951         if (!ctx->powered) {
952                 spin_unlock(&res->reg_slock);
953                 return IRQ_HANDLED;
954         }
955
956         /* read interrupt status for handling and clearing flags for VSYNC */
957         val = mixer_reg_read(res, MXR_INT_STATUS);
958
959         /* handling VSYNC */
960         if (val & MXR_INT_STATUS_VSYNC) {
961                 /* interlace scan need to check shadow register */
962                 if (ctx->interlace) {
963                         base = mixer_reg_read(res, MXR_GRAPHIC_BASE(0));
964                         shadow = mixer_reg_read(res, MXR_GRAPHIC_BASE_S(0));
965                         if (base != shadow)
966                                 goto out;
967
968                         base = mixer_reg_read(res, MXR_GRAPHIC_BASE(1));
969                         shadow = mixer_reg_read(res, MXR_GRAPHIC_BASE_S(1));
970                         if (base != shadow)
971                                 goto out;
972                 }
973
974                 drm_handle_vblank(drm_hdmi_ctx->drm_dev, ctx->pipe);
975                 mixer_finish_pageflip(drm_hdmi_ctx->drm_dev, ctx->pipe);
976         }
977
978 out:
979         /* clear interrupts */
980         if (~val & MXR_INT_EN_VSYNC) {
981                 /* vsync interrupt use different bit for read and clear */
982                 val &= ~MXR_INT_EN_VSYNC;
983                 val |= MXR_INT_CLEAR_VSYNC;
984         }
985         mixer_reg_write(res, MXR_INT_STATUS, val);
986
987         spin_unlock(&res->reg_slock);
988
989         return IRQ_HANDLED;
990 }
991
992 static int __devinit mixer_resources_init(struct exynos_drm_hdmi_context *ctx,
993                                  struct platform_device *pdev)
994 {
995         struct mixer_context *mixer_ctx = ctx->ctx;
996         struct device *dev = &pdev->dev;
997         struct mixer_resources *mixer_res = &mixer_ctx->mixer_res;
998         struct resource *res;
999         int ret;
1000
1001         spin_lock_init(&mixer_res->reg_slock);
1002
1003         mixer_res->mixer = clk_get(dev, "mixer");
1004         if (IS_ERR_OR_NULL(mixer_res->mixer)) {
1005                 dev_err(dev, "failed to get clock 'mixer'\n");
1006                 ret = -ENODEV;
1007                 goto fail;
1008         }
1009         mixer_res->vp = clk_get(dev, "vp");
1010         if (IS_ERR_OR_NULL(mixer_res->vp)) {
1011                 dev_err(dev, "failed to get clock 'vp'\n");
1012                 ret = -ENODEV;
1013                 goto fail;
1014         }
1015         mixer_res->sclk_mixer = clk_get(dev, "sclk_mixer");
1016         if (IS_ERR_OR_NULL(mixer_res->sclk_mixer)) {
1017                 dev_err(dev, "failed to get clock 'sclk_mixer'\n");
1018                 ret = -ENODEV;
1019                 goto fail;
1020         }
1021         mixer_res->sclk_hdmi = clk_get(dev, "sclk_hdmi");
1022         if (IS_ERR_OR_NULL(mixer_res->sclk_hdmi)) {
1023                 dev_err(dev, "failed to get clock 'sclk_hdmi'\n");
1024                 ret = -ENODEV;
1025                 goto fail;
1026         }
1027         mixer_res->sclk_pixel = clk_get(dev, "sclk_pixel");
1028         if (IS_ERR_OR_NULL(mixer_res->sclk_pixel)) {
1029                 DRM_ERROR("failed to get clock 'sclk_pixel'\n");
1030                 goto fail;
1031         }
1032         mixer_res->sclk_dac = clk_get(dev, "sclk_dac");
1033         if (IS_ERR_OR_NULL(mixer_res->sclk_dac)) {
1034                 dev_err(dev, "failed to get clock 'sclk_dac'\n");
1035                 ret = -ENODEV;
1036                 goto fail;
1037         }
1038         res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mxr");
1039         if (res == NULL) {
1040                 dev_err(dev, "get memory resource failed.\n");
1041                 ret = -ENXIO;
1042                 goto fail;
1043         }
1044
1045         clk_set_parent(mixer_res->sclk_mixer, mixer_res->sclk_hdmi);
1046
1047         mixer_res->mixer_regs = ioremap(res->start, resource_size(res));
1048         if (mixer_res->mixer_regs == NULL) {
1049                 dev_err(dev, "register mapping failed.\n");
1050                 ret = -ENXIO;
1051                 goto fail;
1052         }
1053         mixer_res->saved_mixer_regs = mixer_res->mixer_regs;
1054
1055         res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "vp");
1056         if (res == NULL) {
1057                 dev_err(dev, "get memory resource failed.\n");
1058                 ret = -ENXIO;
1059                 goto fail_mixer_regs;
1060         }
1061
1062         mixer_res->vp_regs = ioremap(res->start, resource_size(res));
1063         if (mixer_res->vp_regs == NULL) {
1064                 dev_err(dev, "register mapping failed.\n");
1065                 ret = -ENXIO;
1066                 goto fail_mixer_regs;
1067         }
1068         mixer_res->saved_vp_regs = mixer_res->vp_regs;
1069
1070         res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "irq");
1071         if (res == NULL) {
1072                 dev_err(dev, "get interrupt resource failed.\n");
1073                 ret = -ENXIO;
1074                 goto fail_vp_regs;
1075         }
1076
1077         ret = request_irq(res->start, mixer_irq_handler, 0, "drm_mixer", ctx);
1078         if (ret) {
1079                 dev_err(dev, "request interrupt failed.\n");
1080                 goto fail_vp_regs;
1081         }
1082         mixer_res->irq = res->start;
1083
1084         return 0;
1085
1086 fail_vp_regs:
1087         iounmap(mixer_res->vp_regs);
1088
1089 fail_mixer_regs:
1090         iounmap(mixer_res->mixer_regs);
1091
1092 fail:
1093         if (!IS_ERR_OR_NULL(mixer_res->sclk_dac))
1094                 clk_put(mixer_res->sclk_dac);
1095         if (!IS_ERR_OR_NULL(mixer_res->sclk_hdmi))
1096                 clk_put(mixer_res->sclk_hdmi);
1097         if (!IS_ERR_OR_NULL(mixer_res->sclk_pixel))
1098                 clk_put(mixer_res->sclk_pixel);
1099         if (!IS_ERR_OR_NULL(mixer_res->sclk_mixer))
1100                 clk_put(mixer_res->sclk_mixer);
1101         if (!IS_ERR_OR_NULL(mixer_res->vp))
1102                 clk_put(mixer_res->vp);
1103         if (!IS_ERR_OR_NULL(mixer_res->mixer))
1104                 clk_put(mixer_res->mixer);
1105         return ret;
1106 }
1107
1108 static void mixer_resources_cleanup(struct mixer_context *ctx)
1109 {
1110         struct mixer_resources *res = &ctx->mixer_res;
1111
1112         free_irq(res->irq, ctx);
1113
1114         if (!IS_ERR_OR_NULL(res->sclk_dac))
1115                 clk_put(res->sclk_dac);
1116         if (!IS_ERR_OR_NULL(res->sclk_hdmi))
1117                 clk_put(res->sclk_hdmi);
1118         if (!IS_ERR_OR_NULL(res->sclk_pixel))
1119                 clk_put(res->sclk_pixel);
1120         if (!IS_ERR_OR_NULL(res->sclk_mixer))
1121                 clk_put(res->sclk_mixer);
1122         if (!IS_ERR_OR_NULL(res->vp))
1123                 clk_put(res->vp);
1124         if (!IS_ERR_OR_NULL(res->mixer))
1125                 clk_put(res->mixer);
1126
1127         iounmap(res->vp_regs);
1128         iounmap(res->mixer_regs);
1129 }
1130
1131 static int __devinit mixer_probe(struct platform_device *pdev)
1132 {
1133         struct device *dev = &pdev->dev;
1134         struct exynos_drm_hdmi_context *drm_hdmi_ctx;
1135         struct mixer_context *ctx;
1136         int ret;
1137
1138         dev_info(dev, "probe start\n");
1139
1140         drm_hdmi_ctx = kzalloc(sizeof(*drm_hdmi_ctx), GFP_KERNEL);
1141         if (!drm_hdmi_ctx) {
1142                 DRM_ERROR("failed to allocate common hdmi context.\n");
1143                 return -ENOMEM;
1144         }
1145
1146         ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
1147         if (!ctx) {
1148                 DRM_ERROR("failed to alloc mixer context.\n");
1149                 kfree(drm_hdmi_ctx);
1150                 return -ENOMEM;
1151         }
1152
1153         mutex_init(&ctx->mixer_mutex);
1154
1155         ctx->dev = &pdev->dev;
1156         drm_hdmi_ctx->ctx = (void *)ctx;
1157
1158         platform_set_drvdata(pdev, drm_hdmi_ctx);
1159
1160         /* acquire resources: regs, irqs, clocks */
1161         ret = mixer_resources_init(drm_hdmi_ctx, pdev);
1162         if (ret)
1163                 goto fail;
1164
1165         /* register specific callback point to common hdmi. */
1166         exynos_mixer_ops_register(&mixer_ops);
1167
1168         pm_runtime_enable(dev);
1169
1170         return 0;
1171
1172
1173 fail:
1174         dev_info(dev, "probe failed\n");
1175         return ret;
1176 }
1177
1178 static int mixer_remove(struct platform_device *pdev)
1179 {
1180         struct device *dev = &pdev->dev;
1181         struct exynos_drm_hdmi_context *drm_hdmi_ctx =
1182                                         platform_get_drvdata(pdev);
1183         struct mixer_context *ctx = drm_hdmi_ctx->ctx;
1184
1185         dev_info(dev, "remove successful\n");
1186
1187         pm_runtime_disable(&pdev->dev);
1188
1189         mixer_resources_cleanup(ctx);
1190
1191         return 0;
1192 }
1193
1194 #ifdef CONFIG_PM_SLEEP
1195 static int mixer_suspend(struct device *dev)
1196 {
1197         struct exynos_drm_hdmi_context *drm_hdmi_ctx = get_mixer_context(dev);
1198         struct mixer_context *ctx = drm_hdmi_ctx->ctx;
1199
1200         mixer_poweroff(ctx);
1201
1202         return 0;
1203 }
1204 #endif
1205
1206 static SIMPLE_DEV_PM_OPS(mixer_pm_ops, mixer_suspend, NULL);
1207
1208 struct platform_driver mixer_driver = {
1209         .driver = {
1210                 .name = "s5p-mixer",
1211                 .owner = THIS_MODULE,
1212                 .pm = &mixer_pm_ops,
1213         },
1214         .probe = mixer_probe,
1215         .remove = __devexit_p(mixer_remove),
1216 };