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

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

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