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

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 int priority = state->base.normalized_zpos + 1;
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, priority, 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 int priority = state->base.normalized_zpos + 1;
591         unsigned long flags;
592         unsigned int win = plane->index;
593         unsigned int x_ratio = 0, y_ratio = 0;
594         unsigned int src_x_offset, src_y_offset, dst_x_offset, dst_y_offset;
595         dma_addr_t dma_addr;
596         unsigned int fmt;
597         u32 val;
598 
599         switch (fb->pixel_format) {
600         case DRM_FORMAT_XRGB4444:
601         case DRM_FORMAT_ARGB4444:
602                 fmt = MXR_FORMAT_ARGB4444;
603                 break;
604 
605         case DRM_FORMAT_XRGB1555:
606         case DRM_FORMAT_ARGB1555:
607                 fmt = MXR_FORMAT_ARGB1555;
608                 break;
609 
610         case DRM_FORMAT_RGB565:
611                 fmt = MXR_FORMAT_RGB565;
612                 break;
613 
614         case DRM_FORMAT_XRGB8888:
615         case DRM_FORMAT_ARGB8888:
616                 fmt = MXR_FORMAT_ARGB8888;
617                 break;
618 
619         default:
620                 DRM_DEBUG_KMS("pixelformat unsupported by mixer\n");
621                 return;
622         }
623 
624         /* ratio is already checked by common plane code */
625         x_ratio = state->h_ratio == (1 << 15);
626         y_ratio = state->v_ratio == (1 << 15);
627 
628         dst_x_offset = state->crtc.x;
629         dst_y_offset = state->crtc.y;
630 
631         /* converting dma address base and source offset */
632         dma_addr = exynos_drm_fb_dma_addr(fb, 0)
633                 + (state->src.x * fb->bits_per_pixel >> 3)
634                 + (state->src.y * fb->pitches[0]);
635         src_x_offset = 0;
636         src_y_offset = 0;
637 
638         if (mode->flags & DRM_MODE_FLAG_INTERLACE)
639                 ctx->interlace = true;
640         else
641                 ctx->interlace = false;
642 
643         spin_lock_irqsave(&res->reg_slock, flags);
644 
645         /* setup format */
646         mixer_reg_writemask(res, MXR_GRAPHIC_CFG(win),
647                 MXR_GRP_CFG_FORMAT_VAL(fmt), MXR_GRP_CFG_FORMAT_MASK);
648 
649         /* setup geometry */
650         mixer_reg_write(res, MXR_GRAPHIC_SPAN(win),
651                         fb->pitches[0] / (fb->bits_per_pixel >> 3));
652 
653         /* setup display size */
654         if (ctx->mxr_ver == MXR_VER_128_0_0_184 &&
655                 win == DEFAULT_WIN) {
656                 val  = MXR_MXR_RES_HEIGHT(mode->vdisplay);
657                 val |= MXR_MXR_RES_WIDTH(mode->hdisplay);
658                 mixer_reg_write(res, MXR_RESOLUTION, val);
659         }
660 
661         val  = MXR_GRP_WH_WIDTH(state->src.w);
662         val |= MXR_GRP_WH_HEIGHT(state->src.h);
663         val |= MXR_GRP_WH_H_SCALE(x_ratio);
664         val |= MXR_GRP_WH_V_SCALE(y_ratio);
665         mixer_reg_write(res, MXR_GRAPHIC_WH(win), val);
666 
667         /* setup offsets in source image */
668         val  = MXR_GRP_SXY_SX(src_x_offset);
669         val |= MXR_GRP_SXY_SY(src_y_offset);
670         mixer_reg_write(res, MXR_GRAPHIC_SXY(win), val);
671 
672         /* setup offsets in display image */
673         val  = MXR_GRP_DXY_DX(dst_x_offset);
674         val |= MXR_GRP_DXY_DY(dst_y_offset);
675         mixer_reg_write(res, MXR_GRAPHIC_DXY(win), val);
676 
677         /* set buffer address to mixer */
678         mixer_reg_write(res, MXR_GRAPHIC_BASE(win), dma_addr);
679 
680         mixer_cfg_scan(ctx, mode->vdisplay);
681         mixer_cfg_rgb_fmt(ctx, mode->vdisplay);
682         mixer_cfg_layer(ctx, win, priority, true);
683         mixer_cfg_gfx_blend(ctx, win, is_alpha_format(fb->pixel_format));
684 
685         /* layer update mandatory for mixer 16.0.33.0 */
686         if (ctx->mxr_ver == MXR_VER_16_0_33_0 ||
687                 ctx->mxr_ver == MXR_VER_128_0_0_184)
688                 mixer_layer_update(ctx);
689 
690         mixer_run(ctx);
691 
692         spin_unlock_irqrestore(&res->reg_slock, flags);
693 
694         mixer_regs_dump(ctx);
695 }
696 
697 static void vp_win_reset(struct mixer_context *ctx)
698 {
699         struct mixer_resources *res = &ctx->mixer_res;
700         int tries = 100;
701 
702         vp_reg_write(res, VP_SRESET, VP_SRESET_PROCESSING);
703         for (tries = 100; tries; --tries) {
704                 /* waiting until VP_SRESET_PROCESSING is 0 */
705                 if (~vp_reg_read(res, VP_SRESET) & VP_SRESET_PROCESSING)
706                         break;
707                 mdelay(10);
708         }
709         WARN(tries == 0, "failed to reset Video Processor\n");
710 }
711 
712 static void mixer_win_reset(struct mixer_context *ctx)
713 {
714         struct mixer_resources *res = &ctx->mixer_res;
715         unsigned long flags;
716 
717         spin_lock_irqsave(&res->reg_slock, flags);
718 
719         mixer_reg_writemask(res, MXR_CFG, MXR_CFG_DST_HDMI, MXR_CFG_DST_MASK);
720 
721         /* set output in RGB888 mode */
722         mixer_reg_writemask(res, MXR_CFG, MXR_CFG_OUT_RGB888, MXR_CFG_OUT_MASK);
723 
724         /* 16 beat burst in DMA */
725         mixer_reg_writemask(res, MXR_STATUS, MXR_STATUS_16_BURST,
726                 MXR_STATUS_BURST_MASK);
727 
728         /* reset default layer priority */
729         mixer_reg_write(res, MXR_LAYER_CFG, 0);
730 
731         /* setting background color */
732         mixer_reg_write(res, MXR_BG_COLOR0, 0x008080);
733         mixer_reg_write(res, MXR_BG_COLOR1, 0x008080);
734         mixer_reg_write(res, MXR_BG_COLOR2, 0x008080);
735 
736         if (ctx->vp_enabled) {
737                 /* configuration of Video Processor Registers */
738                 vp_win_reset(ctx);
739                 vp_default_filter(res);
740         }
741 
742         /* disable all layers */
743         mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_GRP0_ENABLE);
744         mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_GRP1_ENABLE);
745         if (ctx->vp_enabled)
746                 mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_VP_ENABLE);
747 
748         spin_unlock_irqrestore(&res->reg_slock, flags);
749 }
750 
751 static irqreturn_t mixer_irq_handler(int irq, void *arg)
752 {
753         struct mixer_context *ctx = arg;
754         struct mixer_resources *res = &ctx->mixer_res;
755         u32 val, base, shadow;
756         int win;
757 
758         spin_lock(&res->reg_slock);
759 
760         /* read interrupt status for handling and clearing flags for VSYNC */
761         val = mixer_reg_read(res, MXR_INT_STATUS);
762 
763         /* handling VSYNC */
764         if (val & MXR_INT_STATUS_VSYNC) {
765                 /* vsync interrupt use different bit for read and clear */
766                 val |= MXR_INT_CLEAR_VSYNC;
767                 val &= ~MXR_INT_STATUS_VSYNC;
768 
769                 /* interlace scan need to check shadow register */
770                 if (ctx->interlace) {
771                         base = mixer_reg_read(res, MXR_GRAPHIC_BASE(0));
772                         shadow = mixer_reg_read(res, MXR_GRAPHIC_BASE_S(0));
773                         if (base != shadow)
774                                 goto out;
775 
776                         base = mixer_reg_read(res, MXR_GRAPHIC_BASE(1));
777                         shadow = mixer_reg_read(res, MXR_GRAPHIC_BASE_S(1));
778                         if (base != shadow)
779                                 goto out;
780                 }
781 
782                 drm_crtc_handle_vblank(&ctx->crtc->base);
783                 for (win = 0 ; win < MIXER_WIN_NR ; win++) {
784                         struct exynos_drm_plane *plane = &ctx->planes[win];
785 
786                         if (!plane->pending_fb)
787                                 continue;
788 
789                         exynos_drm_crtc_finish_update(ctx->crtc, plane);
790                 }
791         }
792 
793 out:
794         /* clear interrupts */
795         mixer_reg_write(res, MXR_INT_STATUS, val);
796 
797         spin_unlock(&res->reg_slock);
798 
799         return IRQ_HANDLED;
800 }
801 
802 static int mixer_resources_init(struct mixer_context *mixer_ctx)
803 {
804         struct device *dev = &mixer_ctx->pdev->dev;
805         struct mixer_resources *mixer_res = &mixer_ctx->mixer_res;
806         struct resource *res;
807         int ret;
808 
809         spin_lock_init(&mixer_res->reg_slock);
810 
811         mixer_res->mixer = devm_clk_get(dev, "mixer");
812         if (IS_ERR(mixer_res->mixer)) {
813                 dev_err(dev, "failed to get clock 'mixer'\n");
814                 return -ENODEV;
815         }
816 
817         mixer_res->hdmi = devm_clk_get(dev, "hdmi");
818         if (IS_ERR(mixer_res->hdmi)) {
819                 dev_err(dev, "failed to get clock 'hdmi'\n");
820                 return PTR_ERR(mixer_res->hdmi);
821         }
822 
823         mixer_res->sclk_hdmi = devm_clk_get(dev, "sclk_hdmi");
824         if (IS_ERR(mixer_res->sclk_hdmi)) {
825                 dev_err(dev, "failed to get clock 'sclk_hdmi'\n");
826                 return -ENODEV;
827         }
828         res = platform_get_resource(mixer_ctx->pdev, IORESOURCE_MEM, 0);
829         if (res == NULL) {
830                 dev_err(dev, "get memory resource failed.\n");
831                 return -ENXIO;
832         }
833 
834         mixer_res->mixer_regs = devm_ioremap(dev, res->start,
835                                                         resource_size(res));
836         if (mixer_res->mixer_regs == NULL) {
837                 dev_err(dev, "register mapping failed.\n");
838                 return -ENXIO;
839         }
840 
841         res = platform_get_resource(mixer_ctx->pdev, IORESOURCE_IRQ, 0);
842         if (res == NULL) {
843                 dev_err(dev, "get interrupt resource failed.\n");
844                 return -ENXIO;
845         }
846 
847         ret = devm_request_irq(dev, res->start, mixer_irq_handler,
848                                                 0, "drm_mixer", mixer_ctx);
849         if (ret) {
850                 dev_err(dev, "request interrupt failed.\n");
851                 return ret;
852         }
853         mixer_res->irq = res->start;
854 
855         return 0;
856 }
857 
858 static int vp_resources_init(struct mixer_context *mixer_ctx)
859 {
860         struct device *dev = &mixer_ctx->pdev->dev;
861         struct mixer_resources *mixer_res = &mixer_ctx->mixer_res;
862         struct resource *res;
863 
864         mixer_res->vp = devm_clk_get(dev, "vp");
865         if (IS_ERR(mixer_res->vp)) {
866                 dev_err(dev, "failed to get clock 'vp'\n");
867                 return -ENODEV;
868         }
869 
870         if (mixer_ctx->has_sclk) {
871                 mixer_res->sclk_mixer = devm_clk_get(dev, "sclk_mixer");
872                 if (IS_ERR(mixer_res->sclk_mixer)) {
873                         dev_err(dev, "failed to get clock 'sclk_mixer'\n");
874                         return -ENODEV;
875                 }
876                 mixer_res->mout_mixer = devm_clk_get(dev, "mout_mixer");
877                 if (IS_ERR(mixer_res->mout_mixer)) {
878                         dev_err(dev, "failed to get clock 'mout_mixer'\n");
879                         return -ENODEV;
880                 }
881 
882                 if (mixer_res->sclk_hdmi && mixer_res->mout_mixer)
883                         clk_set_parent(mixer_res->mout_mixer,
884                                        mixer_res->sclk_hdmi);
885         }
886 
887         res = platform_get_resource(mixer_ctx->pdev, IORESOURCE_MEM, 1);
888         if (res == NULL) {
889                 dev_err(dev, "get memory resource failed.\n");
890                 return -ENXIO;
891         }
892 
893         mixer_res->vp_regs = devm_ioremap(dev, res->start,
894                                                         resource_size(res));
895         if (mixer_res->vp_regs == NULL) {
896                 dev_err(dev, "register mapping failed.\n");
897                 return -ENXIO;
898         }
899 
900         return 0;
901 }
902 
903 static int mixer_initialize(struct mixer_context *mixer_ctx,
904                         struct drm_device *drm_dev)
905 {
906         int ret;
907         struct exynos_drm_private *priv;
908         priv = drm_dev->dev_private;
909 
910         mixer_ctx->drm_dev = drm_dev;
911         mixer_ctx->pipe = priv->pipe++;
912 
913         /* acquire resources: regs, irqs, clocks */
914         ret = mixer_resources_init(mixer_ctx);
915         if (ret) {
916                 DRM_ERROR("mixer_resources_init failed ret=%d\n", ret);
917                 return ret;
918         }
919 
920         if (mixer_ctx->vp_enabled) {
921                 /* acquire vp resources: regs, irqs, clocks */
922                 ret = vp_resources_init(mixer_ctx);
923                 if (ret) {
924                         DRM_ERROR("vp_resources_init failed ret=%d\n", ret);
925                         return ret;
926                 }
927         }
928 
929         ret = drm_iommu_attach_device(drm_dev, mixer_ctx->dev);
930         if (ret)
931                 priv->pipe--;
932 
933         return ret;
934 }
935 
936 static void mixer_ctx_remove(struct mixer_context *mixer_ctx)
937 {
938         drm_iommu_detach_device(mixer_ctx->drm_dev, mixer_ctx->dev);
939 }
940 
941 static int mixer_enable_vblank(struct exynos_drm_crtc *crtc)
942 {
943         struct mixer_context *mixer_ctx = crtc->ctx;
944         struct mixer_resources *res = &mixer_ctx->mixer_res;
945 
946         __set_bit(MXR_BIT_VSYNC, &mixer_ctx->flags);
947         if (!test_bit(MXR_BIT_POWERED, &mixer_ctx->flags))
948                 return 0;
949 
950         /* enable vsync interrupt */
951         mixer_reg_writemask(res, MXR_INT_STATUS, ~0, MXR_INT_CLEAR_VSYNC);
952         mixer_reg_writemask(res, MXR_INT_EN, ~0, MXR_INT_EN_VSYNC);
953 
954         return 0;
955 }
956 
957 static void mixer_disable_vblank(struct exynos_drm_crtc *crtc)
958 {
959         struct mixer_context *mixer_ctx = crtc->ctx;
960         struct mixer_resources *res = &mixer_ctx->mixer_res;
961 
962         __clear_bit(MXR_BIT_VSYNC, &mixer_ctx->flags);
963 
964         if (!test_bit(MXR_BIT_POWERED, &mixer_ctx->flags))
965                 return;
966 
967         /* disable vsync interrupt */
968         mixer_reg_writemask(res, MXR_INT_STATUS, ~0, MXR_INT_CLEAR_VSYNC);
969         mixer_reg_writemask(res, MXR_INT_EN, 0, MXR_INT_EN_VSYNC);
970 }
971 
972 static void mixer_atomic_begin(struct exynos_drm_crtc *crtc)
973 {
974         struct mixer_context *mixer_ctx = crtc->ctx;
975 
976         if (!test_bit(MXR_BIT_POWERED, &mixer_ctx->flags))
977                 return;
978 
979         mixer_vsync_set_update(mixer_ctx, false);
980 }
981 
982 static void mixer_update_plane(struct exynos_drm_crtc *crtc,
983                                struct exynos_drm_plane *plane)
984 {
985         struct mixer_context *mixer_ctx = crtc->ctx;
986 
987         DRM_DEBUG_KMS("win: %d\n", plane->index);
988 
989         if (!test_bit(MXR_BIT_POWERED, &mixer_ctx->flags))
990                 return;
991 
992         if (plane->index == VP_DEFAULT_WIN)
993                 vp_video_buffer(mixer_ctx, plane);
994         else
995                 mixer_graph_buffer(mixer_ctx, plane);
996 }
997 
998 static void mixer_disable_plane(struct exynos_drm_crtc *crtc,
999                                 struct exynos_drm_plane *plane)
1000 {
1001         struct mixer_context *mixer_ctx = crtc->ctx;
1002         struct mixer_resources *res = &mixer_ctx->mixer_res;
1003         unsigned long flags;
1004 
1005         DRM_DEBUG_KMS("win: %d\n", plane->index);
1006 
1007         if (!test_bit(MXR_BIT_POWERED, &mixer_ctx->flags))
1008                 return;
1009 
1010         spin_lock_irqsave(&res->reg_slock, flags);
1011         mixer_cfg_layer(mixer_ctx, plane->index, 0, false);
1012         spin_unlock_irqrestore(&res->reg_slock, flags);
1013 }
1014 
1015 static void mixer_atomic_flush(struct exynos_drm_crtc *crtc)
1016 {
1017         struct mixer_context *mixer_ctx = crtc->ctx;
1018 
1019         if (!test_bit(MXR_BIT_POWERED, &mixer_ctx->flags))
1020                 return;
1021 
1022         mixer_vsync_set_update(mixer_ctx, true);
1023 }
1024 
1025 static void mixer_enable(struct exynos_drm_crtc *crtc)
1026 {
1027         struct mixer_context *ctx = crtc->ctx;
1028         struct mixer_resources *res = &ctx->mixer_res;
1029 
1030         if (test_bit(MXR_BIT_POWERED, &ctx->flags))
1031                 return;
1032 
1033         pm_runtime_get_sync(ctx->dev);
1034 
1035         exynos_drm_pipe_clk_enable(crtc, true);
1036 
1037         mixer_vsync_set_update(ctx, false);
1038 
1039         mixer_reg_writemask(res, MXR_STATUS, ~0, MXR_STATUS_SOFT_RESET);
1040 
1041         if (test_bit(MXR_BIT_VSYNC, &ctx->flags)) {
1042                 mixer_reg_writemask(res, MXR_INT_STATUS, ~0, MXR_INT_CLEAR_VSYNC);
1043                 mixer_reg_writemask(res, MXR_INT_EN, ~0, MXR_INT_EN_VSYNC);
1044         }
1045         mixer_win_reset(ctx);
1046 
1047         mixer_vsync_set_update(ctx, true);
1048 
1049         set_bit(MXR_BIT_POWERED, &ctx->flags);
1050 }
1051 
1052 static void mixer_disable(struct exynos_drm_crtc *crtc)
1053 {
1054         struct mixer_context *ctx = crtc->ctx;
1055         int i;
1056 
1057         if (!test_bit(MXR_BIT_POWERED, &ctx->flags))
1058                 return;
1059 
1060         mixer_stop(ctx);
1061         mixer_regs_dump(ctx);
1062 
1063         for (i = 0; i < MIXER_WIN_NR; i++)
1064                 mixer_disable_plane(crtc, &ctx->planes[i]);
1065 
1066         exynos_drm_pipe_clk_enable(crtc, false);
1067 
1068         pm_runtime_put(ctx->dev);
1069 
1070         clear_bit(MXR_BIT_POWERED, &ctx->flags);
1071 }
1072 
1073 /* Only valid for Mixer version 16.0.33.0 */
1074 static int mixer_atomic_check(struct exynos_drm_crtc *crtc,
1075                        struct drm_crtc_state *state)
1076 {
1077         struct drm_display_mode *mode = &state->adjusted_mode;
1078         u32 w, h;
1079 
1080         w = mode->hdisplay;
1081         h = mode->vdisplay;
1082 
1083         DRM_DEBUG_KMS("xres=%d, yres=%d, refresh=%d, intl=%d\n",
1084                 mode->hdisplay, mode->vdisplay, mode->vrefresh,
1085                 (mode->flags & DRM_MODE_FLAG_INTERLACE) ? 1 : 0);
1086 
1087         if ((w >= 464 && w <= 720 && h >= 261 && h <= 576) ||
1088                 (w >= 1024 && w <= 1280 && h >= 576 && h <= 720) ||
1089                 (w >= 1664 && w <= 1920 && h >= 936 && h <= 1080))
1090                 return 0;
1091 
1092         return -EINVAL;
1093 }
1094 
1095 static const struct exynos_drm_crtc_ops mixer_crtc_ops = {
1096         .enable                 = mixer_enable,
1097         .disable                = mixer_disable,
1098         .enable_vblank          = mixer_enable_vblank,
1099         .disable_vblank         = mixer_disable_vblank,
1100         .atomic_begin           = mixer_atomic_begin,
1101         .update_plane           = mixer_update_plane,
1102         .disable_plane          = mixer_disable_plane,
1103         .atomic_flush           = mixer_atomic_flush,
1104         .atomic_check           = mixer_atomic_check,
1105 };
1106 
1107 static struct mixer_drv_data exynos5420_mxr_drv_data = {
1108         .version = MXR_VER_128_0_0_184,
1109         .is_vp_enabled = 0,
1110 };
1111 
1112 static struct mixer_drv_data exynos5250_mxr_drv_data = {
1113         .version = MXR_VER_16_0_33_0,
1114         .is_vp_enabled = 0,
1115 };
1116 
1117 static struct mixer_drv_data exynos4212_mxr_drv_data = {
1118         .version = MXR_VER_0_0_0_16,
1119         .is_vp_enabled = 1,
1120 };
1121 
1122 static struct mixer_drv_data exynos4210_mxr_drv_data = {
1123         .version = MXR_VER_0_0_0_16,
1124         .is_vp_enabled = 1,
1125         .has_sclk = 1,
1126 };
1127 
1128 static struct of_device_id mixer_match_types[] = {
1129         {
1130                 .compatible = "samsung,exynos4210-mixer",
1131                 .data   = &exynos4210_mxr_drv_data,
1132         }, {
1133                 .compatible = "samsung,exynos4212-mixer",
1134                 .data   = &exynos4212_mxr_drv_data,
1135         }, {
1136                 .compatible = "samsung,exynos5-mixer",
1137                 .data   = &exynos5250_mxr_drv_data,
1138         }, {
1139                 .compatible = "samsung,exynos5250-mixer",
1140                 .data   = &exynos5250_mxr_drv_data,
1141         }, {
1142                 .compatible = "samsung,exynos5420-mixer",
1143                 .data   = &exynos5420_mxr_drv_data,
1144         }, {
1145                 /* end node */
1146         }
1147 };
1148 MODULE_DEVICE_TABLE(of, mixer_match_types);
1149 
1150 static int mixer_bind(struct device *dev, struct device *manager, void *data)
1151 {
1152         struct mixer_context *ctx = dev_get_drvdata(dev);
1153         struct drm_device *drm_dev = data;
1154         struct exynos_drm_plane *exynos_plane;
1155         unsigned int i;
1156         int ret;
1157 
1158         ret = mixer_initialize(ctx, drm_dev);
1159         if (ret)
1160                 return ret;
1161 
1162         for (i = 0; i < MIXER_WIN_NR; i++) {
1163                 if (i == VP_DEFAULT_WIN && !ctx->vp_enabled)
1164                         continue;
1165 
1166                 ret = exynos_plane_init(drm_dev, &ctx->planes[i], i,
1167                                         1 << ctx->pipe, &plane_configs[i]);
1168                 if (ret)
1169                         return ret;
1170         }
1171 
1172         exynos_plane = &ctx->planes[DEFAULT_WIN];
1173         ctx->crtc = exynos_drm_crtc_create(drm_dev, &exynos_plane->base,
1174                                            ctx->pipe, EXYNOS_DISPLAY_TYPE_HDMI,
1175                                            &mixer_crtc_ops, ctx);
1176         if (IS_ERR(ctx->crtc)) {
1177                 mixer_ctx_remove(ctx);
1178                 ret = PTR_ERR(ctx->crtc);
1179                 goto free_ctx;
1180         }
1181 
1182         return 0;
1183 
1184 free_ctx:
1185         devm_kfree(dev, ctx);
1186         return ret;
1187 }
1188 
1189 static void mixer_unbind(struct device *dev, struct device *master, void *data)
1190 {
1191         struct mixer_context *ctx = dev_get_drvdata(dev);
1192 
1193         mixer_ctx_remove(ctx);
1194 }
1195 
1196 static const struct component_ops mixer_component_ops = {
1197         .bind   = mixer_bind,
1198         .unbind = mixer_unbind,
1199 };
1200 
1201 static int mixer_probe(struct platform_device *pdev)
1202 {
1203         struct device *dev = &pdev->dev;
1204         const struct mixer_drv_data *drv;
1205         struct mixer_context *ctx;
1206         int ret;
1207 
1208         ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
1209         if (!ctx) {
1210                 DRM_ERROR("failed to alloc mixer context.\n");
1211                 return -ENOMEM;
1212         }
1213 
1214         drv = of_device_get_match_data(dev);
1215 
1216         ctx->pdev = pdev;
1217         ctx->dev = dev;
1218         ctx->vp_enabled = drv->is_vp_enabled;
1219         ctx->has_sclk = drv->has_sclk;
1220         ctx->mxr_ver = drv->version;
1221 
1222         platform_set_drvdata(pdev, ctx);
1223 
1224         ret = component_add(&pdev->dev, &mixer_component_ops);
1225         if (!ret)
1226                 pm_runtime_enable(dev);
1227 
1228         return ret;
1229 }
1230 
1231 static int mixer_remove(struct platform_device *pdev)
1232 {
1233         pm_runtime_disable(&pdev->dev);
1234 
1235         component_del(&pdev->dev, &mixer_component_ops);
1236 
1237         return 0;
1238 }
1239 
1240 static int __maybe_unused exynos_mixer_suspend(struct device *dev)
1241 {
1242         struct mixer_context *ctx = dev_get_drvdata(dev);
1243         struct mixer_resources *res = &ctx->mixer_res;
1244 
1245         clk_disable_unprepare(res->hdmi);
1246         clk_disable_unprepare(res->mixer);
1247         if (ctx->vp_enabled) {
1248                 clk_disable_unprepare(res->vp);
1249                 if (ctx->has_sclk)
1250                         clk_disable_unprepare(res->sclk_mixer);
1251         }
1252 
1253         return 0;
1254 }
1255 
1256 static int __maybe_unused exynos_mixer_resume(struct device *dev)
1257 {
1258         struct mixer_context *ctx = dev_get_drvdata(dev);
1259         struct mixer_resources *res = &ctx->mixer_res;
1260         int ret;
1261 
1262         ret = clk_prepare_enable(res->mixer);
1263         if (ret < 0) {
1264                 DRM_ERROR("Failed to prepare_enable the mixer clk [%d]\n", ret);
1265                 return ret;
1266         }
1267         ret = clk_prepare_enable(res->hdmi);
1268         if (ret < 0) {
1269                 DRM_ERROR("Failed to prepare_enable the hdmi clk [%d]\n", ret);
1270                 return ret;
1271         }
1272         if (ctx->vp_enabled) {
1273                 ret = clk_prepare_enable(res->vp);
1274                 if (ret < 0) {
1275                         DRM_ERROR("Failed to prepare_enable the vp clk [%d]\n",
1276                                   ret);
1277                         return ret;
1278                 }
1279                 if (ctx->has_sclk) {
1280                         ret = clk_prepare_enable(res->sclk_mixer);
1281                         if (ret < 0) {
1282                                 DRM_ERROR("Failed to prepare_enable the " \
1283                                            "sclk_mixer clk [%d]\n",
1284                                           ret);
1285                                 return ret;
1286                         }
1287                 }
1288         }
1289 
1290         return 0;
1291 }
1292 
1293 static const struct dev_pm_ops exynos_mixer_pm_ops = {
1294         SET_RUNTIME_PM_OPS(exynos_mixer_suspend, exynos_mixer_resume, NULL)
1295 };
1296 
1297 struct platform_driver mixer_driver = {
1298         .driver = {
1299                 .name = "exynos-mixer",
1300                 .owner = THIS_MODULE,
1301                 .pm = &exynos_mixer_pm_ops,
1302                 .of_match_table = mixer_match_types,
1303         },
1304         .probe = mixer_probe,
1305         .remove = mixer_remove,
1306 };
1307 

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