Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
exynos_mixer.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2011 Samsung Electronics Co.Ltd
3  * Authors:
4  * Seung-Woo Kim <[email protected]>
5  * Inki Dae <[email protected]>
6  * Joonyoung Shim <[email protected]>
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/module.h>
27 #include <linux/platform_device.h>
28 #include <linux/interrupt.h>
29 #include <linux/irq.h>
30 #include <linux/delay.h>
31 #include <linux/pm_runtime.h>
32 #include <linux/clk.h>
34 
35 #include <drm/exynos_drm.h>
36 
37 #include "exynos_drm_drv.h"
38 #include "exynos_drm_hdmi.h"
39 
40 #define get_mixer_context(dev) platform_get_drvdata(to_platform_device(dev))
41 
42 struct hdmi_win_data {
44  void __iomem *vaddr;
48  unsigned int bpp;
49  unsigned int crtc_x;
50  unsigned int crtc_y;
51  unsigned int crtc_width;
52  unsigned int crtc_height;
53  unsigned int fb_x;
54  unsigned int fb_y;
55  unsigned int fb_width;
56  unsigned int fb_height;
57  unsigned int src_width;
58  unsigned int src_height;
59  unsigned int mode_width;
60  unsigned int mode_height;
61  unsigned int scan_flags;
62 };
63 
65  int irq;
69  struct clk *mixer;
70  struct clk *vp;
71  struct clk *sclk_mixer;
72  struct clk *sclk_hdmi;
73  struct clk *sclk_dac;
74 };
75 
79 };
80 
81 struct mixer_context {
82  struct device *dev;
83  int pipe;
84  bool interlace;
85  bool powered;
86  bool vp_enabled;
88 
93 };
94 
98 };
99 
100 static const u8 filter_y_horiz_tap8[] = {
101  0, -1, -1, -1, -1, -1, -1, -1,
102  -1, -1, -1, -1, -1, 0, 0, 0,
103  0, 2, 4, 5, 6, 6, 6, 6,
104  6, 5, 5, 4, 3, 2, 1, 1,
105  0, -6, -12, -16, -18, -20, -21, -20,
106  -20, -18, -16, -13, -10, -8, -5, -2,
107  127, 126, 125, 121, 114, 107, 99, 89,
108  79, 68, 57, 46, 35, 25, 16, 8,
109 };
110 
111 static const u8 filter_y_vert_tap4[] = {
112  0, -3, -6, -8, -8, -8, -8, -7,
113  -6, -5, -4, -3, -2, -1, -1, 0,
114  127, 126, 124, 118, 111, 102, 92, 81,
115  70, 59, 48, 37, 27, 19, 11, 5,
116  0, 5, 11, 19, 27, 37, 48, 59,
117  70, 81, 92, 102, 111, 118, 124, 126,
118  0, 0, -1, -1, -2, -3, -4, -5,
119  -6, -7, -8, -8, -8, -8, -6, -3,
120 };
121 
122 static const u8 filter_cr_horiz_tap4[] = {
123  0, -3, -6, -8, -8, -8, -8, -7,
124  -6, -5, -4, -3, -2, -1, -1, 0,
125  127, 126, 124, 118, 111, 102, 92, 81,
126  70, 59, 48, 37, 27, 19, 11, 5,
127 };
128 
129 static inline u32 vp_reg_read(struct mixer_resources *res, u32 reg_id)
130 {
131  return readl(res->vp_regs + reg_id);
132 }
133 
134 static inline void vp_reg_write(struct mixer_resources *res, u32 reg_id,
135  u32 val)
136 {
137  writel(val, res->vp_regs + reg_id);
138 }
139 
140 static inline void vp_reg_writemask(struct mixer_resources *res, u32 reg_id,
141  u32 val, u32 mask)
142 {
143  u32 old = vp_reg_read(res, reg_id);
144 
145  val = (val & mask) | (old & ~mask);
146  writel(val, res->vp_regs + reg_id);
147 }
148 
149 static inline u32 mixer_reg_read(struct mixer_resources *res, u32 reg_id)
150 {
151  return readl(res->mixer_regs + reg_id);
152 }
153 
154 static inline void mixer_reg_write(struct mixer_resources *res, u32 reg_id,
155  u32 val)
156 {
157  writel(val, res->mixer_regs + reg_id);
158 }
159 
160 static inline void mixer_reg_writemask(struct mixer_resources *res,
161  u32 reg_id, u32 val, u32 mask)
162 {
163  u32 old = mixer_reg_read(res, reg_id);
164 
165  val = (val & mask) | (old & ~mask);
166  writel(val, res->mixer_regs + reg_id);
167 }
168 
169 static void mixer_regs_dump(struct mixer_context *ctx)
170 {
171 #define DUMPREG(reg_id) \
172 do { \
173  DRM_DEBUG_KMS(#reg_id " = %08x\n", \
174  (u32)readl(ctx->mixer_res.mixer_regs + reg_id)); \
175 } while (0)
176 
178  DUMPREG(MXR_CFG);
181 
184 
191 
198 #undef DUMPREG
199 }
200 
201 static void vp_regs_dump(struct mixer_context *ctx)
202 {
203 #define DUMPREG(reg_id) \
204 do { \
205  DRM_DEBUG_KMS(#reg_id " = %08x\n", \
206  (u32) readl(ctx->mixer_res.vp_regs + reg_id)); \
207 } while (0)
208 
213  DUMPREG(VP_MODE);
232 
233 #undef DUMPREG
234 }
235 
236 static inline void vp_filter_set(struct mixer_resources *res,
237  int reg_id, const u8 *data, unsigned int size)
238 {
239  /* assure 4-byte align */
240  BUG_ON(size & 3);
241  for (; size; size -= 4, reg_id += 4, data += 4) {
242  u32 val = (data[0] << 24) | (data[1] << 16) |
243  (data[2] << 8) | data[3];
244  vp_reg_write(res, reg_id, val);
245  }
246 }
247 
248 static void vp_default_filter(struct mixer_resources *res)
249 {
250  vp_filter_set(res, VP_POLY8_Y0_LL,
251  filter_y_horiz_tap8, sizeof(filter_y_horiz_tap8));
252  vp_filter_set(res, VP_POLY4_Y0_LL,
253  filter_y_vert_tap4, sizeof(filter_y_vert_tap4));
254  vp_filter_set(res, VP_POLY4_C0_LL,
255  filter_cr_horiz_tap4, sizeof(filter_cr_horiz_tap4));
256 }
257 
258 static void mixer_vsync_set_update(struct mixer_context *ctx, bool enable)
259 {
260  struct mixer_resources *res = &ctx->mixer_res;
261 
262  /* block update on vsync */
263  mixer_reg_writemask(res, MXR_STATUS, enable ?
264  MXR_STATUS_SYNC_ENABLE : 0, MXR_STATUS_SYNC_ENABLE);
265 
266  if (ctx->vp_enabled)
267  vp_reg_write(res, VP_SHADOW_UPDATE, enable ?
269 }
270 
271 static void mixer_cfg_scan(struct mixer_context *ctx, unsigned int height)
272 {
273  struct mixer_resources *res = &ctx->mixer_res;
274  u32 val;
275 
276  /* choosing between interlace and progressive mode */
277  val = (ctx->interlace ? MXR_CFG_SCAN_INTERLACE :
279 
280  /* choosing between porper HD and SD mode */
281  if (height == 480)
283  else if (height == 576)
285  else if (height == 720)
287  else if (height == 1080)
289  else
291 
292  mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_SCAN_MASK);
293 }
294 
295 static void mixer_cfg_rgb_fmt(struct mixer_context *ctx, unsigned int height)
296 {
297  struct mixer_resources *res = &ctx->mixer_res;
298  u32 val;
299 
300  if (height == 480) {
301  val = MXR_CFG_RGB601_0_255;
302  } else if (height == 576) {
303  val = MXR_CFG_RGB601_0_255;
304  } else if (height == 720) {
305  val = MXR_CFG_RGB709_16_235;
306  mixer_reg_write(res, MXR_CM_COEFF_Y,
307  (1 << 30) | (94 << 20) | (314 << 10) |
308  (32 << 0));
309  mixer_reg_write(res, MXR_CM_COEFF_CB,
310  (972 << 20) | (851 << 10) | (225 << 0));
311  mixer_reg_write(res, MXR_CM_COEFF_CR,
312  (225 << 20) | (820 << 10) | (1004 << 0));
313  } else if (height == 1080) {
314  val = MXR_CFG_RGB709_16_235;
315  mixer_reg_write(res, MXR_CM_COEFF_Y,
316  (1 << 30) | (94 << 20) | (314 << 10) |
317  (32 << 0));
318  mixer_reg_write(res, MXR_CM_COEFF_CB,
319  (972 << 20) | (851 << 10) | (225 << 0));
320  mixer_reg_write(res, MXR_CM_COEFF_CR,
321  (225 << 20) | (820 << 10) | (1004 << 0));
322  } else {
323  val = MXR_CFG_RGB709_16_235;
324  mixer_reg_write(res, MXR_CM_COEFF_Y,
325  (1 << 30) | (94 << 20) | (314 << 10) |
326  (32 << 0));
327  mixer_reg_write(res, MXR_CM_COEFF_CB,
328  (972 << 20) | (851 << 10) | (225 << 0));
329  mixer_reg_write(res, MXR_CM_COEFF_CR,
330  (225 << 20) | (820 << 10) | (1004 << 0));
331  }
332 
333  mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_RGB_FMT_MASK);
334 }
335 
336 static void mixer_cfg_layer(struct mixer_context *ctx, int win, bool enable)
337 {
338  struct mixer_resources *res = &ctx->mixer_res;
339  u32 val = enable ? ~0 : 0;
340 
341  switch (win) {
342  case 0:
343  mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP0_ENABLE);
344  break;
345  case 1:
346  mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP1_ENABLE);
347  break;
348  case 2:
349  if (ctx->vp_enabled) {
350  vp_reg_writemask(res, VP_ENABLE, val, VP_ENABLE_ON);
351  mixer_reg_writemask(res, MXR_CFG, val,
353  }
354  break;
355  }
356 }
357 
358 static void mixer_run(struct mixer_context *ctx)
359 {
360  struct mixer_resources *res = &ctx->mixer_res;
361 
362  mixer_reg_writemask(res, MXR_STATUS, ~0, MXR_STATUS_REG_RUN);
363 
364  mixer_regs_dump(ctx);
365 }
366 
367 static void vp_video_buffer(struct mixer_context *ctx, int win)
368 {
369  struct mixer_resources *res = &ctx->mixer_res;
370  unsigned long flags;
371  struct hdmi_win_data *win_data;
372  unsigned int x_ratio, y_ratio;
373  unsigned int buf_num;
374  dma_addr_t luma_addr[2], chroma_addr[2];
375  bool tiled_mode = false;
376  bool crcb_mode = false;
377  u32 val;
378 
379  win_data = &ctx->win_data[win];
380 
381  switch (win_data->pixel_format) {
382  case DRM_FORMAT_NV12MT:
383  tiled_mode = true;
384  case DRM_FORMAT_NV12:
385  crcb_mode = false;
386  buf_num = 2;
387  break;
388  /* TODO: single buffer format NV12, NV21 */
389  default:
390  /* ignore pixel format at disable time */
391  if (!win_data->dma_addr)
392  break;
393 
394  DRM_ERROR("pixel format for vp is wrong [%d].\n",
395  win_data->pixel_format);
396  return;
397  }
398 
399  /* scaling feature: (src << 16) / dst */
400  x_ratio = (win_data->src_width << 16) / win_data->crtc_width;
401  y_ratio = (win_data->src_height << 16) / win_data->crtc_height;
402 
403  if (buf_num == 2) {
404  luma_addr[0] = win_data->dma_addr;
405  chroma_addr[0] = win_data->chroma_dma_addr;
406  } else {
407  luma_addr[0] = win_data->dma_addr;
408  chroma_addr[0] = win_data->dma_addr
409  + (win_data->fb_width * win_data->fb_height);
410  }
411 
412  if (win_data->scan_flags & DRM_MODE_FLAG_INTERLACE) {
413  ctx->interlace = true;
414  if (tiled_mode) {
415  luma_addr[1] = luma_addr[0] + 0x40;
416  chroma_addr[1] = chroma_addr[0] + 0x40;
417  } else {
418  luma_addr[1] = luma_addr[0] + win_data->fb_width;
419  chroma_addr[1] = chroma_addr[0] + win_data->fb_width;
420  }
421  } else {
422  ctx->interlace = false;
423  luma_addr[1] = 0;
424  chroma_addr[1] = 0;
425  }
426 
427  spin_lock_irqsave(&res->reg_slock, flags);
428  mixer_vsync_set_update(ctx, false);
429 
430  /* interlace or progressive scan mode */
431  val = (ctx->interlace ? ~0 : 0);
432  vp_reg_writemask(res, VP_MODE, val, VP_MODE_LINE_SKIP);
433 
434  /* setup format */
435  val = (crcb_mode ? VP_MODE_NV21 : VP_MODE_NV12);
436  val |= (tiled_mode ? VP_MODE_MEM_TILED : VP_MODE_MEM_LINEAR);
437  vp_reg_writemask(res, VP_MODE, val, VP_MODE_FMT_MASK);
438 
439  /* setting size of input image */
440  vp_reg_write(res, VP_IMG_SIZE_Y, VP_IMG_HSIZE(win_data->fb_width) |
441  VP_IMG_VSIZE(win_data->fb_height));
442  /* chroma height has to reduced by 2 to avoid chroma distorions */
443  vp_reg_write(res, VP_IMG_SIZE_C, VP_IMG_HSIZE(win_data->fb_width) |
444  VP_IMG_VSIZE(win_data->fb_height / 2));
445 
446  vp_reg_write(res, VP_SRC_WIDTH, win_data->src_width);
447  vp_reg_write(res, VP_SRC_HEIGHT, win_data->src_height);
448  vp_reg_write(res, VP_SRC_H_POSITION,
449  VP_SRC_H_POSITION_VAL(win_data->fb_x));
450  vp_reg_write(res, VP_SRC_V_POSITION, win_data->fb_y);
451 
452  vp_reg_write(res, VP_DST_WIDTH, win_data->crtc_width);
453  vp_reg_write(res, VP_DST_H_POSITION, win_data->crtc_x);
454  if (ctx->interlace) {
455  vp_reg_write(res, VP_DST_HEIGHT, win_data->crtc_height / 2);
456  vp_reg_write(res, VP_DST_V_POSITION, win_data->crtc_y / 2);
457  } else {
458  vp_reg_write(res, VP_DST_HEIGHT, win_data->crtc_height);
459  vp_reg_write(res, VP_DST_V_POSITION, win_data->crtc_y);
460  }
461 
462  vp_reg_write(res, VP_H_RATIO, x_ratio);
463  vp_reg_write(res, VP_V_RATIO, y_ratio);
464 
465  vp_reg_write(res, VP_ENDIAN_MODE, VP_ENDIAN_MODE_LITTLE);
466 
467  /* set buffer address to vp */
468  vp_reg_write(res, VP_TOP_Y_PTR, luma_addr[0]);
469  vp_reg_write(res, VP_BOT_Y_PTR, luma_addr[1]);
470  vp_reg_write(res, VP_TOP_C_PTR, chroma_addr[0]);
471  vp_reg_write(res, VP_BOT_C_PTR, chroma_addr[1]);
472 
473  mixer_cfg_scan(ctx, win_data->mode_height);
474  mixer_cfg_rgb_fmt(ctx, win_data->mode_height);
475  mixer_cfg_layer(ctx, win, true);
476  mixer_run(ctx);
477 
478  mixer_vsync_set_update(ctx, true);
479  spin_unlock_irqrestore(&res->reg_slock, flags);
480 
481  vp_regs_dump(ctx);
482 }
483 
484 static void mixer_layer_update(struct mixer_context *ctx)
485 {
486  struct mixer_resources *res = &ctx->mixer_res;
487  u32 val;
488 
489  val = mixer_reg_read(res, MXR_CFG);
490 
491  /* allow one update per vsync only */
492  if (!(val & MXR_CFG_LAYER_UPDATE_COUNT_MASK))
493  mixer_reg_writemask(res, MXR_CFG, ~0, MXR_CFG_LAYER_UPDATE);
494 }
495 
496 static void mixer_graph_buffer(struct mixer_context *ctx, int win)
497 {
498  struct mixer_resources *res = &ctx->mixer_res;
499  unsigned long flags;
500  struct hdmi_win_data *win_data;
501  unsigned int x_ratio, y_ratio;
502  unsigned int src_x_offset, src_y_offset, dst_x_offset, dst_y_offset;
504  unsigned int fmt;
505  u32 val;
506 
507  win_data = &ctx->win_data[win];
508 
509  #define RGB565 4
510  #define ARGB1555 5
511  #define ARGB4444 6
512  #define ARGB8888 7
513 
514  switch (win_data->bpp) {
515  case 16:
516  fmt = ARGB4444;
517  break;
518  case 32:
519  fmt = ARGB8888;
520  break;
521  default:
522  fmt = ARGB8888;
523  }
524 
525  /* 2x scaling feature */
526  x_ratio = 0;
527  y_ratio = 0;
528 
529  dst_x_offset = win_data->crtc_x;
530  dst_y_offset = win_data->crtc_y;
531 
532  /* converting dma address base and source offset */
533  dma_addr = win_data->dma_addr
534  + (win_data->fb_x * win_data->bpp >> 3)
535  + (win_data->fb_y * win_data->fb_width * win_data->bpp >> 3);
536  src_x_offset = 0;
537  src_y_offset = 0;
538 
539  if (win_data->scan_flags & DRM_MODE_FLAG_INTERLACE)
540  ctx->interlace = true;
541  else
542  ctx->interlace = false;
543 
544  spin_lock_irqsave(&res->reg_slock, flags);
545  mixer_vsync_set_update(ctx, false);
546 
547  /* setup format */
548  mixer_reg_writemask(res, MXR_GRAPHIC_CFG(win),
550 
551  /* setup geometry */
552  mixer_reg_write(res, MXR_GRAPHIC_SPAN(win), win_data->fb_width);
553 
554  val = MXR_GRP_WH_WIDTH(win_data->crtc_width);
555  val |= MXR_GRP_WH_HEIGHT(win_data->crtc_height);
556  val |= MXR_GRP_WH_H_SCALE(x_ratio);
557  val |= MXR_GRP_WH_V_SCALE(y_ratio);
558  mixer_reg_write(res, MXR_GRAPHIC_WH(win), val);
559 
560  /* setup offsets in source image */
561  val = MXR_GRP_SXY_SX(src_x_offset);
562  val |= MXR_GRP_SXY_SY(src_y_offset);
563  mixer_reg_write(res, MXR_GRAPHIC_SXY(win), val);
564 
565  /* setup offsets in display image */
566  val = MXR_GRP_DXY_DX(dst_x_offset);
567  val |= MXR_GRP_DXY_DY(dst_y_offset);
568  mixer_reg_write(res, MXR_GRAPHIC_DXY(win), val);
569 
570  /* set buffer address to mixer */
571  mixer_reg_write(res, MXR_GRAPHIC_BASE(win), dma_addr);
572 
573  mixer_cfg_scan(ctx, win_data->mode_height);
574  mixer_cfg_rgb_fmt(ctx, win_data->mode_height);
575  mixer_cfg_layer(ctx, win, true);
576 
577  /* layer update mandatory for mixer 16.0.33.0 */
578  if (ctx->mxr_ver == MXR_VER_16_0_33_0)
579  mixer_layer_update(ctx);
580 
581  mixer_run(ctx);
582 
583  mixer_vsync_set_update(ctx, true);
584  spin_unlock_irqrestore(&res->reg_slock, flags);
585 }
586 
587 static void vp_win_reset(struct mixer_context *ctx)
588 {
589  struct mixer_resources *res = &ctx->mixer_res;
590  int tries = 100;
591 
592  vp_reg_write(res, VP_SRESET, VP_SRESET_PROCESSING);
593  for (tries = 100; tries; --tries) {
594  /* waiting until VP_SRESET_PROCESSING is 0 */
595  if (~vp_reg_read(res, VP_SRESET) & VP_SRESET_PROCESSING)
596  break;
597  mdelay(10);
598  }
599  WARN(tries == 0, "failed to reset Video Processor\n");
600 }
601 
602 static void mixer_win_reset(struct mixer_context *ctx)
603 {
604  struct mixer_resources *res = &ctx->mixer_res;
605  unsigned long flags;
606  u32 val; /* value stored to register */
607 
608  spin_lock_irqsave(&res->reg_slock, flags);
609  mixer_vsync_set_update(ctx, false);
610 
611  mixer_reg_writemask(res, MXR_CFG, MXR_CFG_DST_HDMI, MXR_CFG_DST_MASK);
612 
613  /* set output in RGB888 mode */
614  mixer_reg_writemask(res, MXR_CFG, MXR_CFG_OUT_RGB888, MXR_CFG_OUT_MASK);
615 
616  /* 16 beat burst in DMA */
617  mixer_reg_writemask(res, MXR_STATUS, MXR_STATUS_16_BURST,
619 
620  /* setting default layer priority: layer1 > layer0 > video
621  * because typical usage scenario would be
622  * layer1 - OSD
623  * layer0 - framebuffer
624  * video - video overlay
625  */
626  val = MXR_LAYER_CFG_GRP1_VAL(3);
627  val |= MXR_LAYER_CFG_GRP0_VAL(2);
628  if (ctx->vp_enabled)
629  val |= MXR_LAYER_CFG_VP_VAL(1);
630  mixer_reg_write(res, MXR_LAYER_CFG, val);
631 
632  /* setting background color */
633  mixer_reg_write(res, MXR_BG_COLOR0, 0x008080);
634  mixer_reg_write(res, MXR_BG_COLOR1, 0x008080);
635  mixer_reg_write(res, MXR_BG_COLOR2, 0x008080);
636 
637  /* setting graphical layers */
638  val = MXR_GRP_CFG_COLOR_KEY_DISABLE; /* no blank key */
642  val |= MXR_GRP_CFG_ALPHA_VAL(0xff); /* non-transparent alpha */
643 
644  /* the same configuration for both layers */
645  mixer_reg_write(res, MXR_GRAPHIC_CFG(0), val);
646  mixer_reg_write(res, MXR_GRAPHIC_CFG(1), val);
647 
648  /* setting video layers */
649  val = MXR_GRP_CFG_ALPHA_VAL(0);
650  mixer_reg_write(res, MXR_VIDEO_CFG, val);
651 
652  if (ctx->vp_enabled) {
653  /* configuration of Video Processor Registers */
654  vp_win_reset(ctx);
655  vp_default_filter(res);
656  }
657 
658  /* disable all layers */
659  mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_GRP0_ENABLE);
660  mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_GRP1_ENABLE);
661  if (ctx->vp_enabled)
662  mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_VP_ENABLE);
663 
664  mixer_vsync_set_update(ctx, true);
665  spin_unlock_irqrestore(&res->reg_slock, flags);
666 }
667 
668 static void mixer_poweron(struct mixer_context *ctx)
669 {
670  struct mixer_resources *res = &ctx->mixer_res;
671 
672  DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
673 
674  mutex_lock(&ctx->mixer_mutex);
675  if (ctx->powered) {
676  mutex_unlock(&ctx->mixer_mutex);
677  return;
678  }
679  ctx->powered = true;
680  mutex_unlock(&ctx->mixer_mutex);
681 
682  pm_runtime_get_sync(ctx->dev);
683 
684  clk_enable(res->mixer);
685  if (ctx->vp_enabled) {
686  clk_enable(res->vp);
687  clk_enable(res->sclk_mixer);
688  }
689 
690  mixer_reg_write(res, MXR_INT_EN, ctx->int_en);
691  mixer_win_reset(ctx);
692 }
693 
694 static void mixer_poweroff(struct mixer_context *ctx)
695 {
696  struct mixer_resources *res = &ctx->mixer_res;
697 
698  DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
699 
700  mutex_lock(&ctx->mixer_mutex);
701  if (!ctx->powered)
702  goto out;
703  mutex_unlock(&ctx->mixer_mutex);
704 
705  ctx->int_en = mixer_reg_read(res, MXR_INT_EN);
706 
707  clk_disable(res->mixer);
708  if (ctx->vp_enabled) {
709  clk_disable(res->vp);
710  clk_disable(res->sclk_mixer);
711  }
712 
713  pm_runtime_put_sync(ctx->dev);
714 
715  mutex_lock(&ctx->mixer_mutex);
716  ctx->powered = false;
717 
718 out:
719  mutex_unlock(&ctx->mixer_mutex);
720 }
721 
722 static int mixer_enable_vblank(void *ctx, int pipe)
723 {
724  struct mixer_context *mixer_ctx = ctx;
725  struct mixer_resources *res = &mixer_ctx->mixer_res;
726 
727  DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
728 
729  mixer_ctx->pipe = pipe;
730 
731  /* enable vsync interrupt */
732  mixer_reg_writemask(res, MXR_INT_EN, MXR_INT_EN_VSYNC,
734 
735  return 0;
736 }
737 
738 static void mixer_disable_vblank(void *ctx)
739 {
740  struct mixer_context *mixer_ctx = ctx;
741  struct mixer_resources *res = &mixer_ctx->mixer_res;
742 
743  DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
744 
745  /* disable vsync interrupt */
746  mixer_reg_writemask(res, MXR_INT_EN, 0, MXR_INT_EN_VSYNC);
747 }
748 
749 static void mixer_dpms(void *ctx, int mode)
750 {
751  struct mixer_context *mixer_ctx = ctx;
752 
753  DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
754 
755  switch (mode) {
756  case DRM_MODE_DPMS_ON:
757  mixer_poweron(mixer_ctx);
758  break;
761  case DRM_MODE_DPMS_OFF:
762  mixer_poweroff(mixer_ctx);
763  break;
764  default:
765  DRM_DEBUG_KMS("unknown dpms mode: %d\n", mode);
766  break;
767  }
768 }
769 
770 static void mixer_wait_for_vblank(void *ctx)
771 {
772  struct mixer_context *mixer_ctx = ctx;
773  struct mixer_resources *res = &mixer_ctx->mixer_res;
774  int ret;
775 
776  ret = wait_for((mixer_reg_read(res, MXR_INT_STATUS) &
777  MXR_INT_STATUS_VSYNC), 50);
778  if (ret < 0)
779  DRM_DEBUG_KMS("vblank wait timed out.\n");
780 }
781 
782 static void mixer_win_mode_set(void *ctx,
783  struct exynos_drm_overlay *overlay)
784 {
785  struct mixer_context *mixer_ctx = ctx;
786  struct hdmi_win_data *win_data;
787  int win;
788 
789  DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
790 
791  if (!overlay) {
792  DRM_ERROR("overlay is NULL\n");
793  return;
794  }
795 
796  DRM_DEBUG_KMS("set [%d]x[%d] at (%d,%d) to [%d]x[%d] at (%d,%d)\n",
797  overlay->fb_width, overlay->fb_height,
798  overlay->fb_x, overlay->fb_y,
799  overlay->crtc_width, overlay->crtc_height,
800  overlay->crtc_x, overlay->crtc_y);
801 
802  win = overlay->zpos;
803  if (win == DEFAULT_ZPOS)
804  win = MIXER_DEFAULT_WIN;
805 
806  if (win < 0 || win > MIXER_WIN_NR) {
807  DRM_ERROR("mixer window[%d] is wrong\n", win);
808  return;
809  }
810 
811  win_data = &mixer_ctx->win_data[win];
812 
813  win_data->dma_addr = overlay->dma_addr[0];
814  win_data->vaddr = overlay->vaddr[0];
815  win_data->chroma_dma_addr = overlay->dma_addr[1];
816  win_data->chroma_vaddr = overlay->vaddr[1];
817  win_data->pixel_format = overlay->pixel_format;
818  win_data->bpp = overlay->bpp;
819 
820  win_data->crtc_x = overlay->crtc_x;
821  win_data->crtc_y = overlay->crtc_y;
822  win_data->crtc_width = overlay->crtc_width;
823  win_data->crtc_height = overlay->crtc_height;
824 
825  win_data->fb_x = overlay->fb_x;
826  win_data->fb_y = overlay->fb_y;
827  win_data->fb_width = overlay->fb_width;
828  win_data->fb_height = overlay->fb_height;
829  win_data->src_width = overlay->src_width;
830  win_data->src_height = overlay->src_height;
831 
832  win_data->mode_width = overlay->mode_width;
833  win_data->mode_height = overlay->mode_height;
834 
835  win_data->scan_flags = overlay->scan_flag;
836 }
837 
838 static void mixer_win_commit(void *ctx, int win)
839 {
840  struct mixer_context *mixer_ctx = ctx;
841 
842  DRM_DEBUG_KMS("[%d] %s, win: %d\n", __LINE__, __func__, win);
843 
844  if (win > 1 && mixer_ctx->vp_enabled)
845  vp_video_buffer(mixer_ctx, win);
846  else
847  mixer_graph_buffer(mixer_ctx, win);
848 }
849 
850 static void mixer_win_disable(void *ctx, int win)
851 {
852  struct mixer_context *mixer_ctx = ctx;
853  struct mixer_resources *res = &mixer_ctx->mixer_res;
854  unsigned long flags;
855 
856  DRM_DEBUG_KMS("[%d] %s, win: %d\n", __LINE__, __func__, win);
857 
858  spin_lock_irqsave(&res->reg_slock, flags);
859  mixer_vsync_set_update(mixer_ctx, false);
860 
861  mixer_cfg_layer(mixer_ctx, win, false);
862 
863  mixer_vsync_set_update(mixer_ctx, true);
864  spin_unlock_irqrestore(&res->reg_slock, flags);
865 }
866 
867 static struct exynos_mixer_ops mixer_ops = {
868  /* manager */
869  .enable_vblank = mixer_enable_vblank,
870  .disable_vblank = mixer_disable_vblank,
871  .dpms = mixer_dpms,
872 
873  /* overlay */
874  .wait_for_vblank = mixer_wait_for_vblank,
875  .win_mode_set = mixer_win_mode_set,
876  .win_commit = mixer_win_commit,
877  .win_disable = mixer_win_disable,
878 };
879 
880 /* for pageflip event */
881 static void mixer_finish_pageflip(struct drm_device *drm_dev, int crtc)
882 {
883  struct exynos_drm_private *dev_priv = drm_dev->dev_private;
884  struct drm_pending_vblank_event *e, *t;
885  struct timeval now;
886  unsigned long flags;
887  bool is_checked = false;
888 
889  spin_lock_irqsave(&drm_dev->event_lock, flags);
890 
892  base.link) {
893  /* if event's pipe isn't same as crtc then ignore it. */
894  if (crtc != e->pipe)
895  continue;
896 
897  is_checked = true;
898  do_gettimeofday(&now);
899  e->event.sequence = 0;
900  e->event.tv_sec = now.tv_sec;
901  e->event.tv_usec = now.tv_usec;
902 
903  list_move_tail(&e->base.link, &e->base.file_priv->event_list);
904  wake_up_interruptible(&e->base.file_priv->event_wait);
905  }
906 
907  if (is_checked)
908  /*
909  * call drm_vblank_put only in case that drm_vblank_get was
910  * called.
911  */
912  if (atomic_read(&drm_dev->vblank_refcount[crtc]) > 0)
913  drm_vblank_put(drm_dev, crtc);
914 
915  spin_unlock_irqrestore(&drm_dev->event_lock, flags);
916 }
917 
918 static irqreturn_t mixer_irq_handler(int irq, void *arg)
919 {
920  struct exynos_drm_hdmi_context *drm_hdmi_ctx = arg;
921  struct mixer_context *ctx = drm_hdmi_ctx->ctx;
922  struct mixer_resources *res = &ctx->mixer_res;
923  u32 val, base, shadow;
924 
925  spin_lock(&res->reg_slock);
926 
927  /* read interrupt status for handling and clearing flags for VSYNC */
928  val = mixer_reg_read(res, MXR_INT_STATUS);
929 
930  /* handling VSYNC */
931  if (val & MXR_INT_STATUS_VSYNC) {
932  /* interlace scan need to check shadow register */
933  if (ctx->interlace) {
934  base = mixer_reg_read(res, MXR_GRAPHIC_BASE(0));
935  shadow = mixer_reg_read(res, MXR_GRAPHIC_BASE_S(0));
936  if (base != shadow)
937  goto out;
938 
939  base = mixer_reg_read(res, MXR_GRAPHIC_BASE(1));
940  shadow = mixer_reg_read(res, MXR_GRAPHIC_BASE_S(1));
941  if (base != shadow)
942  goto out;
943  }
944 
945  drm_handle_vblank(drm_hdmi_ctx->drm_dev, ctx->pipe);
946  mixer_finish_pageflip(drm_hdmi_ctx->drm_dev, ctx->pipe);
947  }
948 
949 out:
950  /* clear interrupts */
951  if (~val & MXR_INT_EN_VSYNC) {
952  /* vsync interrupt use different bit for read and clear */
953  val &= ~MXR_INT_EN_VSYNC;
954  val |= MXR_INT_CLEAR_VSYNC;
955  }
956  mixer_reg_write(res, MXR_INT_STATUS, val);
957 
958  spin_unlock(&res->reg_slock);
959 
960  return IRQ_HANDLED;
961 }
962 
963 static int __devinit mixer_resources_init(struct exynos_drm_hdmi_context *ctx,
964  struct platform_device *pdev)
965 {
966  struct mixer_context *mixer_ctx = ctx->ctx;
967  struct device *dev = &pdev->dev;
968  struct mixer_resources *mixer_res = &mixer_ctx->mixer_res;
969  struct resource *res;
970  int ret;
971 
972  spin_lock_init(&mixer_res->reg_slock);
973 
974  mixer_res->mixer = clk_get(dev, "mixer");
975  if (IS_ERR_OR_NULL(mixer_res->mixer)) {
976  dev_err(dev, "failed to get clock 'mixer'\n");
977  ret = -ENODEV;
978  goto fail;
979  }
980 
981  mixer_res->sclk_hdmi = clk_get(dev, "sclk_hdmi");
982  if (IS_ERR_OR_NULL(mixer_res->sclk_hdmi)) {
983  dev_err(dev, "failed to get clock 'sclk_hdmi'\n");
984  ret = -ENODEV;
985  goto fail;
986  }
987  res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
988  if (res == NULL) {
989  dev_err(dev, "get memory resource failed.\n");
990  ret = -ENXIO;
991  goto fail;
992  }
993 
994  mixer_res->mixer_regs = devm_ioremap(&pdev->dev, res->start,
995  resource_size(res));
996  if (mixer_res->mixer_regs == NULL) {
997  dev_err(dev, "register mapping failed.\n");
998  ret = -ENXIO;
999  goto fail;
1000  }
1001 
1002  res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
1003  if (res == NULL) {
1004  dev_err(dev, "get interrupt resource failed.\n");
1005  ret = -ENXIO;
1006  goto fail;
1007  }
1008 
1009  ret = devm_request_irq(&pdev->dev, res->start, mixer_irq_handler,
1010  0, "drm_mixer", ctx);
1011  if (ret) {
1012  dev_err(dev, "request interrupt failed.\n");
1013  goto fail;
1014  }
1015  mixer_res->irq = res->start;
1016 
1017  return 0;
1018 
1019 fail:
1020  if (!IS_ERR_OR_NULL(mixer_res->sclk_hdmi))
1021  clk_put(mixer_res->sclk_hdmi);
1022  if (!IS_ERR_OR_NULL(mixer_res->mixer))
1023  clk_put(mixer_res->mixer);
1024  return ret;
1025 }
1026 
1027 static int __devinit vp_resources_init(struct exynos_drm_hdmi_context *ctx,
1028  struct platform_device *pdev)
1029 {
1030  struct mixer_context *mixer_ctx = ctx->ctx;
1031  struct device *dev = &pdev->dev;
1032  struct mixer_resources *mixer_res = &mixer_ctx->mixer_res;
1033  struct resource *res;
1034  int ret;
1035 
1036  mixer_res->vp = clk_get(dev, "vp");
1037  if (IS_ERR_OR_NULL(mixer_res->vp)) {
1038  dev_err(dev, "failed to get clock 'vp'\n");
1039  ret = -ENODEV;
1040  goto fail;
1041  }
1042  mixer_res->sclk_mixer = clk_get(dev, "sclk_mixer");
1043  if (IS_ERR_OR_NULL(mixer_res->sclk_mixer)) {
1044  dev_err(dev, "failed to get clock 'sclk_mixer'\n");
1045  ret = -ENODEV;
1046  goto fail;
1047  }
1048  mixer_res->sclk_dac = clk_get(dev, "sclk_dac");
1049  if (IS_ERR_OR_NULL(mixer_res->sclk_dac)) {
1050  dev_err(dev, "failed to get clock 'sclk_dac'\n");
1051  ret = -ENODEV;
1052  goto fail;
1053  }
1054 
1055  if (mixer_res->sclk_hdmi)
1056  clk_set_parent(mixer_res->sclk_mixer, mixer_res->sclk_hdmi);
1057 
1058  res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
1059  if (res == NULL) {
1060  dev_err(dev, "get memory resource failed.\n");
1061  ret = -ENXIO;
1062  goto fail;
1063  }
1064 
1065  mixer_res->vp_regs = devm_ioremap(&pdev->dev, res->start,
1066  resource_size(res));
1067  if (mixer_res->vp_regs == NULL) {
1068  dev_err(dev, "register mapping failed.\n");
1069  ret = -ENXIO;
1070  goto fail;
1071  }
1072 
1073  return 0;
1074 
1075 fail:
1076  if (!IS_ERR_OR_NULL(mixer_res->sclk_dac))
1077  clk_put(mixer_res->sclk_dac);
1078  if (!IS_ERR_OR_NULL(mixer_res->sclk_mixer))
1079  clk_put(mixer_res->sclk_mixer);
1080  if (!IS_ERR_OR_NULL(mixer_res->vp))
1081  clk_put(mixer_res->vp);
1082  return ret;
1083 }
1084 
1085 static struct mixer_drv_data exynos5_mxr_drv_data = {
1086  .version = MXR_VER_16_0_33_0,
1087  .is_vp_enabled = 0,
1088 };
1089 
1090 static struct mixer_drv_data exynos4_mxr_drv_data = {
1091  .version = MXR_VER_0_0_0_16,
1092  .is_vp_enabled = 1,
1093 };
1094 
1095 static struct platform_device_id mixer_driver_types[] = {
1096  {
1097  .name = "s5p-mixer",
1098  .driver_data = (unsigned long)&exynos4_mxr_drv_data,
1099  }, {
1100  .name = "exynos5-mixer",
1101  .driver_data = (unsigned long)&exynos5_mxr_drv_data,
1102  }, {
1103  /* end node */
1104  }
1105 };
1106 
1107 static struct of_device_id mixer_match_types[] = {
1108  {
1109  .compatible = "samsung,exynos5-mixer",
1110  .data = &exynos5_mxr_drv_data,
1111  }, {
1112  /* end node */
1113  }
1114 };
1115 
1116 static int __devinit mixer_probe(struct platform_device *pdev)
1117 {
1118  struct device *dev = &pdev->dev;
1119  struct exynos_drm_hdmi_context *drm_hdmi_ctx;
1120  struct mixer_context *ctx;
1121  struct mixer_drv_data *drv;
1122  int ret;
1123 
1124  dev_info(dev, "probe start\n");
1125 
1126  drm_hdmi_ctx = devm_kzalloc(&pdev->dev, sizeof(*drm_hdmi_ctx),
1127  GFP_KERNEL);
1128  if (!drm_hdmi_ctx) {
1129  DRM_ERROR("failed to allocate common hdmi context.\n");
1130  return -ENOMEM;
1131  }
1132 
1133  ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
1134  if (!ctx) {
1135  DRM_ERROR("failed to alloc mixer context.\n");
1136  return -ENOMEM;
1137  }
1138 
1139  mutex_init(&ctx->mixer_mutex);
1140 
1141  if (dev->of_node) {
1142  const struct of_device_id *match;
1143  match = of_match_node(of_match_ptr(mixer_match_types),
1144  pdev->dev.of_node);
1145  drv = (struct mixer_drv_data *)match->data;
1146  } else {
1147  drv = (struct mixer_drv_data *)
1148  platform_get_device_id(pdev)->driver_data;
1149  }
1150 
1151  ctx->dev = &pdev->dev;
1152  drm_hdmi_ctx->ctx = (void *)ctx;
1153  ctx->vp_enabled = drv->is_vp_enabled;
1154  ctx->mxr_ver = drv->version;
1155 
1156  platform_set_drvdata(pdev, drm_hdmi_ctx);
1157 
1158  /* acquire resources: regs, irqs, clocks */
1159  ret = mixer_resources_init(drm_hdmi_ctx, pdev);
1160  if (ret) {
1161  DRM_ERROR("mixer_resources_init failed\n");
1162  goto fail;
1163  }
1164 
1165  if (ctx->vp_enabled) {
1166  /* acquire vp resources: regs, irqs, clocks */
1167  ret = vp_resources_init(drm_hdmi_ctx, pdev);
1168  if (ret) {
1169  DRM_ERROR("vp_resources_init failed\n");
1170  goto fail;
1171  }
1172  }
1173 
1174  /* attach mixer driver to common hdmi. */
1175  exynos_mixer_drv_attach(drm_hdmi_ctx);
1176 
1177  /* register specific callback point to common hdmi. */
1178  exynos_mixer_ops_register(&mixer_ops);
1179 
1180  pm_runtime_enable(dev);
1181 
1182  return 0;
1183 
1184 
1185 fail:
1186  dev_info(dev, "probe failed\n");
1187  return ret;
1188 }
1189 
1190 static int mixer_remove(struct platform_device *pdev)
1191 {
1192  dev_info(&pdev->dev, "remove successful\n");
1193 
1194  pm_runtime_disable(&pdev->dev);
1195 
1196  return 0;
1197 }
1198 
1199 #ifdef CONFIG_PM_SLEEP
1200 static int mixer_suspend(struct device *dev)
1201 {
1202  struct exynos_drm_hdmi_context *drm_hdmi_ctx = get_mixer_context(dev);
1203  struct mixer_context *ctx = drm_hdmi_ctx->ctx;
1204 
1205  mixer_poweroff(ctx);
1206 
1207  return 0;
1208 }
1209 #endif
1210 
1211 static SIMPLE_DEV_PM_OPS(mixer_pm_ops, mixer_suspend, NULL);
1212 
1214  .driver = {
1215  .name = "exynos-mixer",
1216  .owner = THIS_MODULE,
1217  .pm = &mixer_pm_ops,
1218  .of_match_table = mixer_match_types,
1219  },
1220  .probe = mixer_probe,
1221  .remove = __devexit_p(mixer_remove),
1222  .id_table = mixer_driver_types,
1223 };