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

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

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