Version:  2.0.40 2.2.26 2.4.37 2.6.39 3.0 3.1 3.2 3.3 3.4 3.5 3.6 3.7 3.8 3.9 3.10 3.11 3.12 3.13 3.14 3.15

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

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