Version:  2.0.40 2.2.26 2.4.37 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 3.15 3.16

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