Version:  2.0.40 2.2.26 2.4.37 3.6 3.7 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

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

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