Version:  2.6.34 2.6.35 2.6.36 2.6.37 2.6.38 2.6.39 3.0 3.1 3.2 3.3 3.4 3.5 3.6 3.7 3.8 3.9 3.10 3.11 3.12 3.13 3.14

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

This page was automatically generated by LXR 0.3.1 (source).  •  Linux is a registered trademark of Linus Torvalds  •  Contact us