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

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

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