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