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