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