Version:  2.0.40 2.2.26 2.4.37 3.8 3.9 3.10 3.11 3.12 3.13 3.14 3.15 3.16 3.17 3.18 3.19 4.0 4.1 4.2 4.3 4.4

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

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