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