Version:  2.0.40 2.2.26 2.4.37 3.3 3.4 3.5 3.6 3.7 3.8 3.9 3.10 3.11 3.12 3.13 3.14 3.15 3.16 3.17 3.18 3.19

Linux/drivers/gpu/drm/exynos/exynos_mixer.c

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

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