blob: db0b698ea8ea50e4fe4c562a2c85914d34b1cf47 [file] [log] [blame]
Thomas Gleixner2874c5f2019-05-27 08:55:01 +02001// SPDX-License-Identifier: GPL-2.0-or-later
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002/*
3 * Copyright (C) 2011 Samsung Electronics Co.Ltd
4 * Authors:
5 * Seung-Woo Kim <sw0312.kim@samsung.com>
6 * Inki Dae <inki.dae@samsung.com>
7 * Joonyoung Shim <jy0922.shim@samsung.com>
8 *
9 * Based on drivers/media/video/s5p-tv/mixer_reg.c
Seung-Woo Kimd8408322011-12-21 17:39:39 +090010 */
11
David Howells760285e2012-10-02 18:01:07 +010012#include <drm/drmP.h>
Seung-Woo Kimd8408322011-12-21 17:39:39 +090013
14#include "regs-mixer.h"
15#include "regs-vp.h"
16
17#include <linux/kernel.h>
Andrzej Hajda6a3b45a2019-03-19 14:05:11 +010018#include <linux/ktime.h>
Seung-Woo Kimd8408322011-12-21 17:39:39 +090019#include <linux/spinlock.h>
20#include <linux/wait.h>
21#include <linux/i2c.h>
Seung-Woo Kimd8408322011-12-21 17:39:39 +090022#include <linux/platform_device.h>
23#include <linux/interrupt.h>
24#include <linux/irq.h>
25#include <linux/delay.h>
26#include <linux/pm_runtime.h>
27#include <linux/clk.h>
28#include <linux/regulator/consumer.h>
Sachin Kamat3f1c7812013-08-14 16:38:01 +053029#include <linux/of.h>
Marek Szyprowski48f61552016-04-01 15:17:46 +020030#include <linux/of_device.h>
Inki Daef37cd5e2014-05-09 14:25:20 +090031#include <linux/component.h>
Seung-Woo Kimd8408322011-12-21 17:39:39 +090032
33#include <drm/exynos_drm.h>
34
35#include "exynos_drm_drv.h"
Rahul Sharma663d8762013-01-03 05:44:04 -050036#include "exynos_drm_crtc.h"
Marek Szyprowski0488f502015-11-30 14:53:21 +010037#include "exynos_drm_fb.h"
Gustavo Padovan7ee14cd2015-04-03 21:03:40 +090038#include "exynos_drm_plane.h"
Joonyoung Shim22b21ae2012-03-15 17:19:04 +090039
Sean Paulf041b252014-01-30 16:19:15 -050040#define MIXER_WIN_NR 3
Marek Szyprowskifbbb1e12015-08-31 00:53:57 +090041#define VP_DEFAULT_WIN 2
Seung-Woo Kimd8408322011-12-21 17:39:39 +090042
Tobias Jakobi2a6e4cd2017-03-10 15:21:54 +010043/*
44 * Mixer color space conversion coefficient triplet.
45 * Used for CSC from RGB to YCbCr.
46 * Each coefficient is a 10-bit fixed point number with
47 * sign and no integer part, i.e.
48 * [0:8] = fractional part (representing a value y = x / 2^9)
49 * [9] = sign
50 * Negative values are encoded with two's complement.
51 */
52#define MXR_CSC_C(x) ((int)((x) * 512.0) & 0x3ff)
53#define MXR_CSC_CT(a0, a1, a2) \
54 ((MXR_CSC_C(a0) << 20) | (MXR_CSC_C(a1) << 10) | (MXR_CSC_C(a2) << 0))
55
56/* YCbCr value, used for mixer background color configuration. */
57#define MXR_YCBCR_VAL(y, cb, cr) (((y) << 16) | ((cb) << 8) | ((cr) << 0))
58
Tobias Jakobi7a57ca72015-04-27 23:11:59 +020059/* The pixelformats that are natively supported by the mixer. */
60#define MXR_FORMAT_RGB565 4
61#define MXR_FORMAT_ARGB1555 5
62#define MXR_FORMAT_ARGB4444 6
63#define MXR_FORMAT_ARGB8888 7
64
Rahul Sharma1e123442012-10-04 20:48:51 +053065enum mixer_version_id {
66 MXR_VER_0_0_0_16,
67 MXR_VER_16_0_33_0,
Rahul Sharmadef5e092013-06-19 18:21:08 +053068 MXR_VER_128_0_0_184,
Rahul Sharma1e123442012-10-04 20:48:51 +053069};
70
Andrzej Hajdaa44652e2015-07-09 08:25:42 +020071enum mixer_flag_bits {
72 MXR_BIT_POWERED,
Andrzej Hajda0df5e4a2015-07-09 08:25:43 +020073 MXR_BIT_VSYNC,
Tobias Jakobiadeb6f442016-09-22 11:36:13 +090074 MXR_BIT_INTERLACE,
75 MXR_BIT_VP_ENABLED,
76 MXR_BIT_HAS_SCLK,
Andrzej Hajdaa44652e2015-07-09 08:25:42 +020077};
78
Marek Szyprowskifbbb1e12015-08-31 00:53:57 +090079static const uint32_t mixer_formats[] = {
80 DRM_FORMAT_XRGB4444,
Tobias Jakobi26a7af32015-12-16 13:21:47 +010081 DRM_FORMAT_ARGB4444,
Marek Szyprowskifbbb1e12015-08-31 00:53:57 +090082 DRM_FORMAT_XRGB1555,
Tobias Jakobi26a7af32015-12-16 13:21:47 +010083 DRM_FORMAT_ARGB1555,
Marek Szyprowskifbbb1e12015-08-31 00:53:57 +090084 DRM_FORMAT_RGB565,
85 DRM_FORMAT_XRGB8888,
86 DRM_FORMAT_ARGB8888,
87};
88
89static const uint32_t vp_formats[] = {
90 DRM_FORMAT_NV12,
91 DRM_FORMAT_NV21,
92};
93
Joonyoung Shim22b21ae2012-03-15 17:19:04 +090094struct mixer_context {
Sean Paul45517892014-01-30 16:19:05 -050095 struct platform_device *pdev;
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +090096 struct device *dev;
Inki Dae1055b392012-10-19 17:37:35 +090097 struct drm_device *drm_dev;
Gustavo Padovan93bca242015-01-18 18:16:23 +090098 struct exynos_drm_crtc *crtc;
Gustavo Padovan7ee14cd2015-04-03 21:03:40 +090099 struct exynos_drm_plane planes[MIXER_WIN_NR];
Andrzej Hajdaa44652e2015-07-09 08:25:42 +0200100 unsigned long flags;
Joonyoung Shim22b21ae2012-03-15 17:19:04 +0900101
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200102 int irq;
103 void __iomem *mixer_regs;
104 void __iomem *vp_regs;
105 spinlock_t reg_slock;
106 struct clk *mixer;
107 struct clk *vp;
108 struct clk *hdmi;
109 struct clk *sclk_mixer;
110 struct clk *sclk_hdmi;
111 struct clk *mout_mixer;
Rahul Sharma1e123442012-10-04 20:48:51 +0530112 enum mixer_version_id mxr_ver;
Andrzej Hajdaacc8bf02017-09-29 12:05:39 +0200113 int scan_value;
Rahul Sharma1e123442012-10-04 20:48:51 +0530114};
115
116struct mixer_drv_data {
117 enum mixer_version_id version;
Rahul Sharma1b8e5742012-10-04 20:48:52 +0530118 bool is_vp_enabled;
Marek Szyprowskiff830c92014-07-01 10:10:07 +0200119 bool has_sclk;
Joonyoung Shim22b21ae2012-03-15 17:19:04 +0900120};
121
Marek Szyprowskifd2d2fc2015-11-30 14:53:25 +0100122static const struct exynos_drm_plane_config plane_configs[MIXER_WIN_NR] = {
123 {
124 .zpos = 0,
125 .type = DRM_PLANE_TYPE_PRIMARY,
126 .pixel_formats = mixer_formats,
127 .num_pixel_formats = ARRAY_SIZE(mixer_formats),
Marek Szyprowskia2cb9112015-12-16 13:21:44 +0100128 .capabilities = EXYNOS_DRM_PLANE_CAP_DOUBLE |
Christoph Manszewski482582c2018-09-21 14:24:37 +0200129 EXYNOS_DRM_PLANE_CAP_ZPOS |
Christoph Manszewski6ac99a32018-09-21 14:24:38 +0200130 EXYNOS_DRM_PLANE_CAP_PIX_BLEND |
131 EXYNOS_DRM_PLANE_CAP_WIN_BLEND,
Marek Szyprowskifd2d2fc2015-11-30 14:53:25 +0100132 }, {
133 .zpos = 1,
134 .type = DRM_PLANE_TYPE_CURSOR,
135 .pixel_formats = mixer_formats,
136 .num_pixel_formats = ARRAY_SIZE(mixer_formats),
Marek Szyprowskia2cb9112015-12-16 13:21:44 +0100137 .capabilities = EXYNOS_DRM_PLANE_CAP_DOUBLE |
Christoph Manszewski482582c2018-09-21 14:24:37 +0200138 EXYNOS_DRM_PLANE_CAP_ZPOS |
Christoph Manszewski6ac99a32018-09-21 14:24:38 +0200139 EXYNOS_DRM_PLANE_CAP_PIX_BLEND |
140 EXYNOS_DRM_PLANE_CAP_WIN_BLEND,
Marek Szyprowskifd2d2fc2015-11-30 14:53:25 +0100141 }, {
142 .zpos = 2,
143 .type = DRM_PLANE_TYPE_OVERLAY,
144 .pixel_formats = vp_formats,
145 .num_pixel_formats = ARRAY_SIZE(vp_formats),
Marek Szyprowskia2cb9112015-12-16 13:21:44 +0100146 .capabilities = EXYNOS_DRM_PLANE_CAP_SCALE |
Tobias Jakobif40031c2017-08-22 16:19:37 +0200147 EXYNOS_DRM_PLANE_CAP_ZPOS |
Christoph Manszewski6ac99a32018-09-21 14:24:38 +0200148 EXYNOS_DRM_PLANE_CAP_TILE |
149 EXYNOS_DRM_PLANE_CAP_WIN_BLEND,
Marek Szyprowskifd2d2fc2015-11-30 14:53:25 +0100150 },
151};
152
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900153static const u8 filter_y_horiz_tap8[] = {
154 0, -1, -1, -1, -1, -1, -1, -1,
155 -1, -1, -1, -1, -1, 0, 0, 0,
156 0, 2, 4, 5, 6, 6, 6, 6,
157 6, 5, 5, 4, 3, 2, 1, 1,
158 0, -6, -12, -16, -18, -20, -21, -20,
159 -20, -18, -16, -13, -10, -8, -5, -2,
160 127, 126, 125, 121, 114, 107, 99, 89,
161 79, 68, 57, 46, 35, 25, 16, 8,
162};
163
164static const u8 filter_y_vert_tap4[] = {
165 0, -3, -6, -8, -8, -8, -8, -7,
166 -6, -5, -4, -3, -2, -1, -1, 0,
167 127, 126, 124, 118, 111, 102, 92, 81,
168 70, 59, 48, 37, 27, 19, 11, 5,
169 0, 5, 11, 19, 27, 37, 48, 59,
170 70, 81, 92, 102, 111, 118, 124, 126,
171 0, 0, -1, -1, -2, -3, -4, -5,
172 -6, -7, -8, -8, -8, -8, -6, -3,
173};
174
175static const u8 filter_cr_horiz_tap4[] = {
176 0, -3, -6, -8, -8, -8, -8, -7,
177 -6, -5, -4, -3, -2, -1, -1, 0,
178 127, 126, 124, 118, 111, 102, 92, 81,
179 70, 59, 48, 37, 27, 19, 11, 5,
180};
181
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200182static inline u32 vp_reg_read(struct mixer_context *ctx, u32 reg_id)
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900183{
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200184 return readl(ctx->vp_regs + reg_id);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900185}
186
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200187static inline void vp_reg_write(struct mixer_context *ctx, u32 reg_id,
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900188 u32 val)
189{
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200190 writel(val, ctx->vp_regs + reg_id);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900191}
192
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200193static inline void vp_reg_writemask(struct mixer_context *ctx, u32 reg_id,
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900194 u32 val, u32 mask)
195{
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200196 u32 old = vp_reg_read(ctx, reg_id);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900197
198 val = (val & mask) | (old & ~mask);
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200199 writel(val, ctx->vp_regs + reg_id);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900200}
201
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200202static inline u32 mixer_reg_read(struct mixer_context *ctx, u32 reg_id)
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900203{
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200204 return readl(ctx->mixer_regs + reg_id);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900205}
206
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200207static inline void mixer_reg_write(struct mixer_context *ctx, u32 reg_id,
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900208 u32 val)
209{
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200210 writel(val, ctx->mixer_regs + reg_id);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900211}
212
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200213static inline void mixer_reg_writemask(struct mixer_context *ctx,
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900214 u32 reg_id, u32 val, u32 mask)
215{
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200216 u32 old = mixer_reg_read(ctx, reg_id);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900217
218 val = (val & mask) | (old & ~mask);
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200219 writel(val, ctx->mixer_regs + reg_id);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900220}
221
222static void mixer_regs_dump(struct mixer_context *ctx)
223{
224#define DUMPREG(reg_id) \
225do { \
Inki Dae6be90052019-04-15 16:25:12 +0900226 DRM_DEV_DEBUG_KMS(ctx->dev, #reg_id " = %08x\n", \
227 (u32)readl(ctx->mixer_regs + reg_id)); \
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900228} while (0)
229
230 DUMPREG(MXR_STATUS);
231 DUMPREG(MXR_CFG);
232 DUMPREG(MXR_INT_EN);
233 DUMPREG(MXR_INT_STATUS);
234
235 DUMPREG(MXR_LAYER_CFG);
236 DUMPREG(MXR_VIDEO_CFG);
237
238 DUMPREG(MXR_GRAPHIC0_CFG);
239 DUMPREG(MXR_GRAPHIC0_BASE);
240 DUMPREG(MXR_GRAPHIC0_SPAN);
241 DUMPREG(MXR_GRAPHIC0_WH);
242 DUMPREG(MXR_GRAPHIC0_SXY);
243 DUMPREG(MXR_GRAPHIC0_DXY);
244
245 DUMPREG(MXR_GRAPHIC1_CFG);
246 DUMPREG(MXR_GRAPHIC1_BASE);
247 DUMPREG(MXR_GRAPHIC1_SPAN);
248 DUMPREG(MXR_GRAPHIC1_WH);
249 DUMPREG(MXR_GRAPHIC1_SXY);
250 DUMPREG(MXR_GRAPHIC1_DXY);
251#undef DUMPREG
252}
253
254static void vp_regs_dump(struct mixer_context *ctx)
255{
256#define DUMPREG(reg_id) \
257do { \
Inki Dae6be90052019-04-15 16:25:12 +0900258 DRM_DEV_DEBUG_KMS(ctx->dev, #reg_id " = %08x\n", \
259 (u32) readl(ctx->vp_regs + reg_id)); \
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900260} while (0)
261
262 DUMPREG(VP_ENABLE);
263 DUMPREG(VP_SRESET);
264 DUMPREG(VP_SHADOW_UPDATE);
265 DUMPREG(VP_FIELD_ID);
266 DUMPREG(VP_MODE);
267 DUMPREG(VP_IMG_SIZE_Y);
268 DUMPREG(VP_IMG_SIZE_C);
269 DUMPREG(VP_PER_RATE_CTRL);
270 DUMPREG(VP_TOP_Y_PTR);
271 DUMPREG(VP_BOT_Y_PTR);
272 DUMPREG(VP_TOP_C_PTR);
273 DUMPREG(VP_BOT_C_PTR);
274 DUMPREG(VP_ENDIAN_MODE);
275 DUMPREG(VP_SRC_H_POSITION);
276 DUMPREG(VP_SRC_V_POSITION);
277 DUMPREG(VP_SRC_WIDTH);
278 DUMPREG(VP_SRC_HEIGHT);
279 DUMPREG(VP_DST_H_POSITION);
280 DUMPREG(VP_DST_V_POSITION);
281 DUMPREG(VP_DST_WIDTH);
282 DUMPREG(VP_DST_HEIGHT);
283 DUMPREG(VP_H_RATIO);
284 DUMPREG(VP_V_RATIO);
285
286#undef DUMPREG
287}
288
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200289static inline void vp_filter_set(struct mixer_context *ctx,
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900290 int reg_id, const u8 *data, unsigned int size)
291{
292 /* assure 4-byte align */
293 BUG_ON(size & 3);
294 for (; size; size -= 4, reg_id += 4, data += 4) {
295 u32 val = (data[0] << 24) | (data[1] << 16) |
296 (data[2] << 8) | data[3];
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200297 vp_reg_write(ctx, reg_id, val);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900298 }
299}
300
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200301static void vp_default_filter(struct mixer_context *ctx)
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900302{
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200303 vp_filter_set(ctx, VP_POLY8_Y0_LL,
Sachin Kamate25e1b62012-08-31 15:50:48 +0530304 filter_y_horiz_tap8, sizeof(filter_y_horiz_tap8));
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200305 vp_filter_set(ctx, VP_POLY4_Y0_LL,
Sachin Kamate25e1b62012-08-31 15:50:48 +0530306 filter_y_vert_tap4, sizeof(filter_y_vert_tap4));
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200307 vp_filter_set(ctx, VP_POLY4_C0_LL,
Sachin Kamate25e1b62012-08-31 15:50:48 +0530308 filter_cr_horiz_tap4, sizeof(filter_cr_horiz_tap4));
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900309}
310
Marek Szyprowskif657a992015-12-16 13:21:46 +0100311static void mixer_cfg_gfx_blend(struct mixer_context *ctx, unsigned int win,
Christoph Manszewski6ac99a32018-09-21 14:24:38 +0200312 unsigned int pixel_alpha, unsigned int alpha)
Marek Szyprowskif657a992015-12-16 13:21:46 +0100313{
Christoph Manszewski6ac99a32018-09-21 14:24:38 +0200314 u32 win_alpha = alpha >> 8;
Marek Szyprowskif657a992015-12-16 13:21:46 +0100315 u32 val;
316
317 val = MXR_GRP_CFG_COLOR_KEY_DISABLE; /* no blank key */
Christoph Manszewski482582c2018-09-21 14:24:37 +0200318 switch (pixel_alpha) {
319 case DRM_MODE_BLEND_PIXEL_NONE:
320 break;
321 case DRM_MODE_BLEND_COVERAGE:
322 val |= MXR_GRP_CFG_PIXEL_BLEND_EN;
323 break;
324 case DRM_MODE_BLEND_PREMULTI:
325 default:
Marek Szyprowskif657a992015-12-16 13:21:46 +0100326 val |= MXR_GRP_CFG_BLEND_PRE_MUL;
327 val |= MXR_GRP_CFG_PIXEL_BLEND_EN;
Christoph Manszewski482582c2018-09-21 14:24:37 +0200328 break;
Marek Szyprowskif657a992015-12-16 13:21:46 +0100329 }
Christoph Manszewski6ac99a32018-09-21 14:24:38 +0200330
331 if (alpha != DRM_BLEND_ALPHA_OPAQUE) {
332 val |= MXR_GRP_CFG_WIN_BLEND_EN;
333 val |= win_alpha;
334 }
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200335 mixer_reg_writemask(ctx, MXR_GRAPHIC_CFG(win),
Marek Szyprowskif657a992015-12-16 13:21:46 +0100336 val, MXR_GRP_CFG_MISC_MASK);
337}
338
Christoph Manszewski6ac99a32018-09-21 14:24:38 +0200339static void mixer_cfg_vp_blend(struct mixer_context *ctx, unsigned int alpha)
Marek Szyprowskif657a992015-12-16 13:21:46 +0100340{
Christoph Manszewski6ac99a32018-09-21 14:24:38 +0200341 u32 win_alpha = alpha >> 8;
342 u32 val = 0;
Marek Szyprowskif657a992015-12-16 13:21:46 +0100343
Christoph Manszewski6ac99a32018-09-21 14:24:38 +0200344 if (alpha != DRM_BLEND_ALPHA_OPAQUE) {
345 val |= MXR_VID_CFG_BLEND_EN;
346 val |= win_alpha;
347 }
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200348 mixer_reg_write(ctx, MXR_VIDEO_CFG, val);
Marek Szyprowskif657a992015-12-16 13:21:46 +0100349}
350
Andrzej Hajda6a3b45a2019-03-19 14:05:11 +0100351static bool mixer_is_synced(struct mixer_context *ctx)
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900352{
Andrzej Hajda6a3b45a2019-03-19 14:05:11 +0100353 u32 base, shadow;
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900354
Andrzej Hajda6a3b45a2019-03-19 14:05:11 +0100355 if (ctx->mxr_ver == MXR_VER_16_0_33_0 ||
356 ctx->mxr_ver == MXR_VER_128_0_0_184)
357 return !(mixer_reg_read(ctx, MXR_CFG) &
358 MXR_CFG_LAYER_UPDATE_COUNT_MASK);
359
360 if (test_bit(MXR_BIT_VP_ENABLED, &ctx->flags) &&
361 vp_reg_read(ctx, VP_SHADOW_UPDATE))
362 return false;
363
364 base = mixer_reg_read(ctx, MXR_CFG);
365 shadow = mixer_reg_read(ctx, MXR_CFG_S);
366 if (base != shadow)
367 return false;
368
369 base = mixer_reg_read(ctx, MXR_GRAPHIC_BASE(0));
370 shadow = mixer_reg_read(ctx, MXR_GRAPHIC_BASE_S(0));
371 if (base != shadow)
372 return false;
373
374 base = mixer_reg_read(ctx, MXR_GRAPHIC_BASE(1));
375 shadow = mixer_reg_read(ctx, MXR_GRAPHIC_BASE_S(1));
376 if (base != shadow)
377 return false;
378
379 return true;
380}
381
382static int mixer_wait_for_sync(struct mixer_context *ctx)
383{
384 ktime_t timeout = ktime_add_us(ktime_get(), 100000);
385
386 while (!mixer_is_synced(ctx)) {
387 usleep_range(1000, 2000);
388 if (ktime_compare(ktime_get(), timeout) > 0)
389 return -ETIMEDOUT;
390 }
391 return 0;
392}
393
394static void mixer_disable_sync(struct mixer_context *ctx)
395{
396 mixer_reg_writemask(ctx, MXR_STATUS, 0, MXR_STATUS_SYNC_ENABLE);
397}
398
399static void mixer_enable_sync(struct mixer_context *ctx)
400{
401 if (ctx->mxr_ver == MXR_VER_16_0_33_0 ||
402 ctx->mxr_ver == MXR_VER_128_0_0_184)
403 mixer_reg_writemask(ctx, MXR_CFG, ~0, MXR_CFG_LAYER_UPDATE);
404 mixer_reg_writemask(ctx, MXR_STATUS, ~0, MXR_STATUS_SYNC_ENABLE);
Tobias Jakobiadeb6f442016-09-22 11:36:13 +0900405 if (test_bit(MXR_BIT_VP_ENABLED, &ctx->flags))
Andrzej Hajda6a3b45a2019-03-19 14:05:11 +0100406 vp_reg_write(ctx, VP_SHADOW_UPDATE, VP_SHADOW_UPDATE_ENABLE);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900407}
408
Andrzej Hajda3fc40ca2017-09-29 12:05:34 +0200409static void mixer_cfg_scan(struct mixer_context *ctx, int width, int height)
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900410{
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900411 u32 val;
412
413 /* choosing between interlace and progressive mode */
Tobias Jakobiadeb6f442016-09-22 11:36:13 +0900414 val = test_bit(MXR_BIT_INTERLACE, &ctx->flags) ?
415 MXR_CFG_SCAN_INTERLACE : MXR_CFG_SCAN_PROGRESSIVE;
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900416
Andrzej Hajdaacc8bf02017-09-29 12:05:39 +0200417 if (ctx->mxr_ver == MXR_VER_128_0_0_184)
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200418 mixer_reg_write(ctx, MXR_RESOLUTION,
Andrzej Hajda3fc40ca2017-09-29 12:05:34 +0200419 MXR_MXR_RES_HEIGHT(height) | MXR_MXR_RES_WIDTH(width));
Andrzej Hajdaacc8bf02017-09-29 12:05:39 +0200420 else
421 val |= ctx->scan_value;
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900422
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200423 mixer_reg_writemask(ctx, MXR_CFG, val, MXR_CFG_SCAN_MASK);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900424}
425
Christoph Manszewski13e810f2018-11-28 16:32:12 +0100426static void mixer_cfg_rgb_fmt(struct mixer_context *ctx, struct drm_display_mode *mode)
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900427{
Christoph Manszewski13e810f2018-11-28 16:32:12 +0100428 enum hdmi_quantization_range range = drm_default_rgb_quant_range(mode);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900429 u32 val;
430
Christoph Manszewski13e810f2018-11-28 16:32:12 +0100431 if (mode->vdisplay < 720) {
432 val = MXR_CFG_RGB601;
Christoph Manszewskie9e5ba92018-11-28 16:32:11 +0100433 } else {
Christoph Manszewski13e810f2018-11-28 16:32:12 +0100434 val = MXR_CFG_RGB709;
435
Tobias Jakobi2a6e4cd2017-03-10 15:21:54 +0100436 /* Configure the BT.709 CSC matrix for full range RGB. */
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200437 mixer_reg_write(ctx, MXR_CM_COEFF_Y,
Tobias Jakobi2a6e4cd2017-03-10 15:21:54 +0100438 MXR_CSC_CT( 0.184, 0.614, 0.063) |
439 MXR_CM_COEFF_RGB_FULL);
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200440 mixer_reg_write(ctx, MXR_CM_COEFF_CB,
Tobias Jakobi2a6e4cd2017-03-10 15:21:54 +0100441 MXR_CSC_CT(-0.102, -0.338, 0.440));
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200442 mixer_reg_write(ctx, MXR_CM_COEFF_CR,
Tobias Jakobi2a6e4cd2017-03-10 15:21:54 +0100443 MXR_CSC_CT( 0.440, -0.399, -0.040));
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900444 }
445
Christoph Manszewski13e810f2018-11-28 16:32:12 +0100446 if (range == HDMI_QUANTIZATION_RANGE_FULL)
447 val |= MXR_CFG_QUANT_RANGE_FULL;
448 else
449 val |= MXR_CFG_QUANT_RANGE_LIMITED;
450
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200451 mixer_reg_writemask(ctx, MXR_CFG, val, MXR_CFG_RGB_FMT_MASK);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900452}
453
Tobias Jakobi5b1d5bc2015-05-06 14:10:22 +0200454static void mixer_cfg_layer(struct mixer_context *ctx, unsigned int win,
Marek Szyprowskia2cb9112015-12-16 13:21:44 +0100455 unsigned int priority, bool enable)
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900456{
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900457 u32 val = enable ? ~0 : 0;
458
459 switch (win) {
460 case 0:
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200461 mixer_reg_writemask(ctx, MXR_CFG, val, MXR_CFG_GRP0_ENABLE);
462 mixer_reg_writemask(ctx, MXR_LAYER_CFG,
Marek Szyprowskia2cb9112015-12-16 13:21:44 +0100463 MXR_LAYER_CFG_GRP0_VAL(priority),
464 MXR_LAYER_CFG_GRP0_MASK);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900465 break;
466 case 1:
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200467 mixer_reg_writemask(ctx, MXR_CFG, val, MXR_CFG_GRP1_ENABLE);
468 mixer_reg_writemask(ctx, MXR_LAYER_CFG,
Marek Szyprowskia2cb9112015-12-16 13:21:44 +0100469 MXR_LAYER_CFG_GRP1_VAL(priority),
470 MXR_LAYER_CFG_GRP1_MASK);
Tobias Jakobiadeb6f442016-09-22 11:36:13 +0900471
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900472 break;
Marek Szyprowski5e68fef2015-12-16 13:21:48 +0100473 case VP_DEFAULT_WIN:
Tobias Jakobiadeb6f442016-09-22 11:36:13 +0900474 if (test_bit(MXR_BIT_VP_ENABLED, &ctx->flags)) {
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200475 vp_reg_writemask(ctx, VP_ENABLE, val, VP_ENABLE_ON);
476 mixer_reg_writemask(ctx, MXR_CFG, val,
Rahul Sharma1b8e5742012-10-04 20:48:52 +0530477 MXR_CFG_VP_ENABLE);
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200478 mixer_reg_writemask(ctx, MXR_LAYER_CFG,
Marek Szyprowskia2cb9112015-12-16 13:21:44 +0100479 MXR_LAYER_CFG_VP_VAL(priority),
480 MXR_LAYER_CFG_VP_MASK);
Rahul Sharma1b8e5742012-10-04 20:48:52 +0530481 }
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900482 break;
483 }
484}
485
486static void mixer_run(struct mixer_context *ctx)
487{
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200488 mixer_reg_writemask(ctx, MXR_STATUS, ~0, MXR_STATUS_REG_RUN);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900489}
490
Rahul Sharma381be022014-06-23 11:02:22 +0530491static void mixer_stop(struct mixer_context *ctx)
492{
Rahul Sharma381be022014-06-23 11:02:22 +0530493 int timeout = 20;
494
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200495 mixer_reg_writemask(ctx, MXR_STATUS, 0, MXR_STATUS_REG_RUN);
Rahul Sharma381be022014-06-23 11:02:22 +0530496
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200497 while (!(mixer_reg_read(ctx, MXR_STATUS) & MXR_STATUS_REG_IDLE) &&
Rahul Sharma381be022014-06-23 11:02:22 +0530498 --timeout)
499 usleep_range(10000, 12000);
Rahul Sharma381be022014-06-23 11:02:22 +0530500}
501
Andrzej Hajda521d98a2017-09-29 12:05:32 +0200502static void mixer_commit(struct mixer_context *ctx)
503{
504 struct drm_display_mode *mode = &ctx->crtc->base.state->adjusted_mode;
505
Andrzej Hajda3fc40ca2017-09-29 12:05:34 +0200506 mixer_cfg_scan(ctx, mode->hdisplay, mode->vdisplay);
Christoph Manszewski13e810f2018-11-28 16:32:12 +0100507 mixer_cfg_rgb_fmt(ctx, mode);
Andrzej Hajda521d98a2017-09-29 12:05:32 +0200508 mixer_run(ctx);
509}
510
Gustavo Padovan2eeb2e52015-08-03 14:40:44 +0900511static void vp_video_buffer(struct mixer_context *ctx,
512 struct exynos_drm_plane *plane)
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900513{
Marek Szyprowski0114f402015-11-30 14:53:22 +0100514 struct exynos_drm_plane_state *state =
515 to_exynos_plane_state(plane->base.state);
Marek Szyprowski0114f402015-11-30 14:53:22 +0100516 struct drm_framebuffer *fb = state->base.fb;
Marek Szyprowskie47726a2016-05-11 17:16:06 +0200517 unsigned int priority = state->base.normalized_zpos + 1;
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900518 unsigned long flags;
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900519 dma_addr_t luma_addr[2], chroma_addr[2];
Tobias Jakobi0f752692017-08-22 16:19:38 +0200520 bool is_tiled, is_nv21;
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900521 u32 val;
522
Tobias Jakobi0f752692017-08-22 16:19:38 +0200523 is_nv21 = (fb->format->format == DRM_FORMAT_NV21);
524 is_tiled = (fb->modifier == DRM_FORMAT_MOD_SAMSUNG_64_32_TILE);
Tobias Jakobif40031c2017-08-22 16:19:37 +0200525
Marek Szyprowski0488f502015-11-30 14:53:21 +0100526 luma_addr[0] = exynos_drm_fb_dma_addr(fb, 0);
527 chroma_addr[0] = exynos_drm_fb_dma_addr(fb, 1);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900528
Andrzej Hajda71469942017-09-29 12:05:33 +0200529 if (test_bit(MXR_BIT_INTERLACE, &ctx->flags)) {
Tobias Jakobi0f752692017-08-22 16:19:38 +0200530 if (is_tiled) {
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900531 luma_addr[1] = luma_addr[0] + 0x40;
532 chroma_addr[1] = chroma_addr[0] + 0x40;
533 } else {
Gustavo Padovan2eeb2e52015-08-03 14:40:44 +0900534 luma_addr[1] = luma_addr[0] + fb->pitches[0];
Tobias Jakobi0ccc1c82018-02-02 16:11:23 +0100535 chroma_addr[1] = chroma_addr[0] + fb->pitches[1];
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900536 }
537 } else {
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900538 luma_addr[1] = 0;
539 chroma_addr[1] = 0;
540 }
541
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200542 spin_lock_irqsave(&ctx->reg_slock, flags);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900543
544 /* interlace or progressive scan mode */
Tobias Jakobiadeb6f442016-09-22 11:36:13 +0900545 val = (test_bit(MXR_BIT_INTERLACE, &ctx->flags) ? ~0 : 0);
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200546 vp_reg_writemask(ctx, VP_MODE, val, VP_MODE_LINE_SKIP);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900547
548 /* setup format */
Tobias Jakobi0f752692017-08-22 16:19:38 +0200549 val = (is_nv21 ? VP_MODE_NV21 : VP_MODE_NV12);
550 val |= (is_tiled ? VP_MODE_MEM_TILED : VP_MODE_MEM_LINEAR);
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200551 vp_reg_writemask(ctx, VP_MODE, val, VP_MODE_FMT_MASK);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900552
553 /* setting size of input image */
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200554 vp_reg_write(ctx, VP_IMG_SIZE_Y, VP_IMG_HSIZE(fb->pitches[0]) |
Gustavo Padovan2eeb2e52015-08-03 14:40:44 +0900555 VP_IMG_VSIZE(fb->height));
Tobias Jakobidc500cf2017-08-22 16:19:36 +0200556 /* chroma plane for NV12/NV21 is half the height of the luma plane */
Tobias Jakobi0ccc1c82018-02-02 16:11:23 +0100557 vp_reg_write(ctx, VP_IMG_SIZE_C, VP_IMG_HSIZE(fb->pitches[1]) |
Gustavo Padovan2eeb2e52015-08-03 14:40:44 +0900558 VP_IMG_VSIZE(fb->height / 2));
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900559
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200560 vp_reg_write(ctx, VP_SRC_WIDTH, state->src.w);
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200561 vp_reg_write(ctx, VP_SRC_H_POSITION,
Marek Szyprowski0114f402015-11-30 14:53:22 +0100562 VP_SRC_H_POSITION_VAL(state->src.x));
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200563 vp_reg_write(ctx, VP_DST_WIDTH, state->crtc.w);
564 vp_reg_write(ctx, VP_DST_H_POSITION, state->crtc.x);
Tobias Jakobi0ccc1c82018-02-02 16:11:23 +0100565
Tobias Jakobiadeb6f442016-09-22 11:36:13 +0900566 if (test_bit(MXR_BIT_INTERLACE, &ctx->flags)) {
Tobias Jakobi0ccc1c82018-02-02 16:11:23 +0100567 vp_reg_write(ctx, VP_SRC_HEIGHT, state->src.h / 2);
568 vp_reg_write(ctx, VP_SRC_V_POSITION, state->src.y / 2);
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200569 vp_reg_write(ctx, VP_DST_HEIGHT, state->crtc.h / 2);
570 vp_reg_write(ctx, VP_DST_V_POSITION, state->crtc.y / 2);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900571 } else {
Tobias Jakobi0ccc1c82018-02-02 16:11:23 +0100572 vp_reg_write(ctx, VP_SRC_HEIGHT, state->src.h);
573 vp_reg_write(ctx, VP_SRC_V_POSITION, state->src.y);
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200574 vp_reg_write(ctx, VP_DST_HEIGHT, state->crtc.h);
575 vp_reg_write(ctx, VP_DST_V_POSITION, state->crtc.y);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900576 }
577
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200578 vp_reg_write(ctx, VP_H_RATIO, state->h_ratio);
579 vp_reg_write(ctx, VP_V_RATIO, state->v_ratio);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900580
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200581 vp_reg_write(ctx, VP_ENDIAN_MODE, VP_ENDIAN_MODE_LITTLE);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900582
583 /* set buffer address to vp */
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200584 vp_reg_write(ctx, VP_TOP_Y_PTR, luma_addr[0]);
585 vp_reg_write(ctx, VP_BOT_Y_PTR, luma_addr[1]);
586 vp_reg_write(ctx, VP_TOP_C_PTR, chroma_addr[0]);
587 vp_reg_write(ctx, VP_BOT_C_PTR, chroma_addr[1]);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900588
Marek Szyprowskie47726a2016-05-11 17:16:06 +0200589 mixer_cfg_layer(ctx, plane->index, priority, true);
Christoph Manszewski6ac99a32018-09-21 14:24:38 +0200590 mixer_cfg_vp_blend(ctx, state->base.alpha);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900591
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200592 spin_unlock_irqrestore(&ctx->reg_slock, flags);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900593
Tobias Jakobic0734fb2015-05-06 14:10:21 +0200594 mixer_regs_dump(ctx);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900595 vp_regs_dump(ctx);
596}
597
Gustavo Padovan2eeb2e52015-08-03 14:40:44 +0900598static void mixer_graph_buffer(struct mixer_context *ctx,
599 struct exynos_drm_plane *plane)
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900600{
Marek Szyprowski0114f402015-11-30 14:53:22 +0100601 struct exynos_drm_plane_state *state =
602 to_exynos_plane_state(plane->base.state);
Marek Szyprowski0114f402015-11-30 14:53:22 +0100603 struct drm_framebuffer *fb = state->base.fb;
Marek Szyprowskie47726a2016-05-11 17:16:06 +0200604 unsigned int priority = state->base.normalized_zpos + 1;
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900605 unsigned long flags;
Marek Szyprowski40bdfb02015-12-16 13:21:42 +0100606 unsigned int win = plane->index;
Tobias Jakobi26110152015-04-07 01:14:52 +0200607 unsigned int x_ratio = 0, y_ratio = 0;
Tobias Jakobi5dff6902017-08-22 16:19:40 +0200608 unsigned int dst_x_offset, dst_y_offset;
Christoph Manszewski482582c2018-09-21 14:24:37 +0200609 unsigned int pixel_alpha;
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900610 dma_addr_t dma_addr;
611 unsigned int fmt;
612 u32 val;
613
Christoph Manszewski482582c2018-09-21 14:24:37 +0200614 if (fb->format->has_alpha)
615 pixel_alpha = state->base.pixel_blend_mode;
616 else
617 pixel_alpha = DRM_MODE_BLEND_PIXEL_NONE;
618
Ville Syrjälä438b74a2016-12-14 23:32:55 +0200619 switch (fb->format->format) {
Tobias Jakobi7a57ca72015-04-27 23:11:59 +0200620 case DRM_FORMAT_XRGB4444:
Tobias Jakobi26a7af32015-12-16 13:21:47 +0100621 case DRM_FORMAT_ARGB4444:
Tobias Jakobi7a57ca72015-04-27 23:11:59 +0200622 fmt = MXR_FORMAT_ARGB4444;
623 break;
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900624
Tobias Jakobi7a57ca72015-04-27 23:11:59 +0200625 case DRM_FORMAT_XRGB1555:
Tobias Jakobi26a7af32015-12-16 13:21:47 +0100626 case DRM_FORMAT_ARGB1555:
Tobias Jakobi7a57ca72015-04-27 23:11:59 +0200627 fmt = MXR_FORMAT_ARGB1555;
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900628 break;
Tobias Jakobi7a57ca72015-04-27 23:11:59 +0200629
630 case DRM_FORMAT_RGB565:
631 fmt = MXR_FORMAT_RGB565;
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900632 break;
Tobias Jakobi7a57ca72015-04-27 23:11:59 +0200633
634 case DRM_FORMAT_XRGB8888:
635 case DRM_FORMAT_ARGB8888:
Tobias Jakobi1e60d622017-08-22 16:19:39 +0200636 default:
Tobias Jakobi7a57ca72015-04-27 23:11:59 +0200637 fmt = MXR_FORMAT_ARGB8888;
638 break;
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900639 }
640
Marek Szyprowskie463b062015-11-30 14:53:27 +0100641 /* ratio is already checked by common plane code */
642 x_ratio = state->h_ratio == (1 << 15);
643 y_ratio = state->v_ratio == (1 << 15);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900644
Marek Szyprowski0114f402015-11-30 14:53:22 +0100645 dst_x_offset = state->crtc.x;
646 dst_y_offset = state->crtc.y;
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900647
Tobias Jakobi5dff6902017-08-22 16:19:40 +0200648 /* translate dma address base s.t. the source image offset is zero */
Marek Szyprowski0488f502015-11-30 14:53:21 +0100649 dma_addr = exynos_drm_fb_dma_addr(fb, 0)
Ville Syrjälä272725c2016-12-14 23:32:20 +0200650 + (state->src.x * fb->format->cpp[0])
Marek Szyprowski0114f402015-11-30 14:53:22 +0100651 + (state->src.y * fb->pitches[0]);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900652
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200653 spin_lock_irqsave(&ctx->reg_slock, flags);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900654
655 /* setup format */
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200656 mixer_reg_writemask(ctx, MXR_GRAPHIC_CFG(win),
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900657 MXR_GRP_CFG_FORMAT_VAL(fmt), MXR_GRP_CFG_FORMAT_MASK);
658
659 /* setup geometry */
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200660 mixer_reg_write(ctx, MXR_GRAPHIC_SPAN(win),
Ville Syrjälä272725c2016-12-14 23:32:20 +0200661 fb->pitches[0] / fb->format->cpp[0]);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900662
Marek Szyprowski0114f402015-11-30 14:53:22 +0100663 val = MXR_GRP_WH_WIDTH(state->src.w);
664 val |= MXR_GRP_WH_HEIGHT(state->src.h);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900665 val |= MXR_GRP_WH_H_SCALE(x_ratio);
666 val |= MXR_GRP_WH_V_SCALE(y_ratio);
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200667 mixer_reg_write(ctx, MXR_GRAPHIC_WH(win), val);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900668
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900669 /* setup offsets in display image */
670 val = MXR_GRP_DXY_DX(dst_x_offset);
671 val |= MXR_GRP_DXY_DY(dst_y_offset);
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200672 mixer_reg_write(ctx, MXR_GRAPHIC_DXY(win), val);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900673
674 /* set buffer address to mixer */
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200675 mixer_reg_write(ctx, MXR_GRAPHIC_BASE(win), dma_addr);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900676
Marek Szyprowskie47726a2016-05-11 17:16:06 +0200677 mixer_cfg_layer(ctx, win, priority, true);
Christoph Manszewski6ac99a32018-09-21 14:24:38 +0200678 mixer_cfg_gfx_blend(ctx, win, pixel_alpha, state->base.alpha);
Rahul Sharmaaaf8b492012-10-04 20:48:53 +0530679
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200680 spin_unlock_irqrestore(&ctx->reg_slock, flags);
Tobias Jakobic0734fb2015-05-06 14:10:21 +0200681
682 mixer_regs_dump(ctx);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900683}
684
685static void vp_win_reset(struct mixer_context *ctx)
686{
Tobias Jakobia6963942016-09-22 16:57:19 +0200687 unsigned int tries = 100;
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900688
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200689 vp_reg_write(ctx, VP_SRESET, VP_SRESET_PROCESSING);
Dan Carpenter8646dcb2017-01-20 17:54:32 +0100690 while (--tries) {
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900691 /* waiting until VP_SRESET_PROCESSING is 0 */
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200692 if (~vp_reg_read(ctx, VP_SRESET) & VP_SRESET_PROCESSING)
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900693 break;
Tomasz Stanislawski02b3de42015-09-25 14:48:29 +0200694 mdelay(10);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900695 }
696 WARN(tries == 0, "failed to reset Video Processor\n");
697}
698
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +0900699static void mixer_win_reset(struct mixer_context *ctx)
700{
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +0900701 unsigned long flags;
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +0900702
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200703 spin_lock_irqsave(&ctx->reg_slock, flags);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +0900704
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200705 mixer_reg_writemask(ctx, MXR_CFG, MXR_CFG_DST_HDMI, MXR_CFG_DST_MASK);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +0900706
707 /* set output in RGB888 mode */
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200708 mixer_reg_writemask(ctx, MXR_CFG, MXR_CFG_OUT_RGB888, MXR_CFG_OUT_MASK);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +0900709
710 /* 16 beat burst in DMA */
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200711 mixer_reg_writemask(ctx, MXR_STATUS, MXR_STATUS_16_BURST,
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +0900712 MXR_STATUS_BURST_MASK);
713
Marek Szyprowskia2cb9112015-12-16 13:21:44 +0100714 /* reset default layer priority */
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200715 mixer_reg_write(ctx, MXR_LAYER_CFG, 0);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +0900716
Tobias Jakobi2a6e4cd2017-03-10 15:21:54 +0100717 /* set all background colors to RGB (0,0,0) */
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200718 mixer_reg_write(ctx, MXR_BG_COLOR0, MXR_YCBCR_VAL(0, 128, 128));
719 mixer_reg_write(ctx, MXR_BG_COLOR1, MXR_YCBCR_VAL(0, 128, 128));
720 mixer_reg_write(ctx, MXR_BG_COLOR2, MXR_YCBCR_VAL(0, 128, 128));
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +0900721
Tobias Jakobiadeb6f442016-09-22 11:36:13 +0900722 if (test_bit(MXR_BIT_VP_ENABLED, &ctx->flags)) {
Rahul Sharma1b8e5742012-10-04 20:48:52 +0530723 /* configuration of Video Processor Registers */
724 vp_win_reset(ctx);
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200725 vp_default_filter(ctx);
Rahul Sharma1b8e5742012-10-04 20:48:52 +0530726 }
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +0900727
728 /* disable all layers */
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200729 mixer_reg_writemask(ctx, MXR_CFG, 0, MXR_CFG_GRP0_ENABLE);
730 mixer_reg_writemask(ctx, MXR_CFG, 0, MXR_CFG_GRP1_ENABLE);
Tobias Jakobiadeb6f442016-09-22 11:36:13 +0900731 if (test_bit(MXR_BIT_VP_ENABLED, &ctx->flags))
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200732 mixer_reg_writemask(ctx, MXR_CFG, 0, MXR_CFG_VP_ENABLE);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +0900733
Tobias Jakobi5dff6902017-08-22 16:19:40 +0200734 /* set all source image offsets to zero */
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200735 mixer_reg_write(ctx, MXR_GRAPHIC_SXY(0), 0);
736 mixer_reg_write(ctx, MXR_GRAPHIC_SXY(1), 0);
Tobias Jakobi5dff6902017-08-22 16:19:40 +0200737
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200738 spin_unlock_irqrestore(&ctx->reg_slock, flags);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +0900739}
740
Sean Paul45517892014-01-30 16:19:05 -0500741static irqreturn_t mixer_irq_handler(int irq, void *arg)
742{
743 struct mixer_context *ctx = arg;
Andrzej Hajda6a3b45a2019-03-19 14:05:11 +0100744 u32 val;
Sean Paul45517892014-01-30 16:19:05 -0500745
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200746 spin_lock(&ctx->reg_slock);
Sean Paul45517892014-01-30 16:19:05 -0500747
748 /* read interrupt status for handling and clearing flags for VSYNC */
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200749 val = mixer_reg_read(ctx, MXR_INT_STATUS);
Sean Paul45517892014-01-30 16:19:05 -0500750
751 /* handling VSYNC */
752 if (val & MXR_INT_STATUS_VSYNC) {
Andrzej Hajda81a464d2015-07-09 10:07:53 +0200753 /* vsync interrupt use different bit for read and clear */
754 val |= MXR_INT_CLEAR_VSYNC;
755 val &= ~MXR_INT_STATUS_VSYNC;
756
Sean Paul45517892014-01-30 16:19:05 -0500757 /* interlace scan need to check shadow register */
Andrzej Hajda6a3b45a2019-03-19 14:05:11 +0100758 if (test_bit(MXR_BIT_INTERLACE, &ctx->flags)
759 && !mixer_is_synced(ctx))
760 goto out;
Sean Paul45517892014-01-30 16:19:05 -0500761
Gustavo Padovaneafd5402015-07-16 12:23:32 -0300762 drm_crtc_handle_vblank(&ctx->crtc->base);
Sean Paul45517892014-01-30 16:19:05 -0500763 }
764
765out:
766 /* clear interrupts */
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200767 mixer_reg_write(ctx, MXR_INT_STATUS, val);
Sean Paul45517892014-01-30 16:19:05 -0500768
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200769 spin_unlock(&ctx->reg_slock);
Sean Paul45517892014-01-30 16:19:05 -0500770
771 return IRQ_HANDLED;
772}
773
774static int mixer_resources_init(struct mixer_context *mixer_ctx)
775{
776 struct device *dev = &mixer_ctx->pdev->dev;
Sean Paul45517892014-01-30 16:19:05 -0500777 struct resource *res;
778 int ret;
779
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200780 spin_lock_init(&mixer_ctx->reg_slock);
Sean Paul45517892014-01-30 16:19:05 -0500781
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200782 mixer_ctx->mixer = devm_clk_get(dev, "mixer");
783 if (IS_ERR(mixer_ctx->mixer)) {
Sean Paul45517892014-01-30 16:19:05 -0500784 dev_err(dev, "failed to get clock 'mixer'\n");
785 return -ENODEV;
786 }
787
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200788 mixer_ctx->hdmi = devm_clk_get(dev, "hdmi");
789 if (IS_ERR(mixer_ctx->hdmi)) {
Marek Szyprowski04427ec2015-02-02 14:20:28 +0100790 dev_err(dev, "failed to get clock 'hdmi'\n");
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200791 return PTR_ERR(mixer_ctx->hdmi);
Marek Szyprowski04427ec2015-02-02 14:20:28 +0100792 }
793
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200794 mixer_ctx->sclk_hdmi = devm_clk_get(dev, "sclk_hdmi");
795 if (IS_ERR(mixer_ctx->sclk_hdmi)) {
Sean Paul45517892014-01-30 16:19:05 -0500796 dev_err(dev, "failed to get clock 'sclk_hdmi'\n");
797 return -ENODEV;
798 }
799 res = platform_get_resource(mixer_ctx->pdev, IORESOURCE_MEM, 0);
800 if (res == NULL) {
801 dev_err(dev, "get memory resource failed.\n");
802 return -ENXIO;
803 }
804
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200805 mixer_ctx->mixer_regs = devm_ioremap(dev, res->start,
Sean Paul45517892014-01-30 16:19:05 -0500806 resource_size(res));
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200807 if (mixer_ctx->mixer_regs == NULL) {
Sean Paul45517892014-01-30 16:19:05 -0500808 dev_err(dev, "register mapping failed.\n");
809 return -ENXIO;
810 }
811
812 res = platform_get_resource(mixer_ctx->pdev, IORESOURCE_IRQ, 0);
813 if (res == NULL) {
814 dev_err(dev, "get interrupt resource failed.\n");
815 return -ENXIO;
816 }
817
818 ret = devm_request_irq(dev, res->start, mixer_irq_handler,
819 0, "drm_mixer", mixer_ctx);
820 if (ret) {
821 dev_err(dev, "request interrupt failed.\n");
822 return ret;
823 }
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200824 mixer_ctx->irq = res->start;
Sean Paul45517892014-01-30 16:19:05 -0500825
826 return 0;
827}
828
829static int vp_resources_init(struct mixer_context *mixer_ctx)
830{
831 struct device *dev = &mixer_ctx->pdev->dev;
Sean Paul45517892014-01-30 16:19:05 -0500832 struct resource *res;
833
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200834 mixer_ctx->vp = devm_clk_get(dev, "vp");
835 if (IS_ERR(mixer_ctx->vp)) {
Sean Paul45517892014-01-30 16:19:05 -0500836 dev_err(dev, "failed to get clock 'vp'\n");
837 return -ENODEV;
838 }
Sean Paul45517892014-01-30 16:19:05 -0500839
Tobias Jakobiadeb6f442016-09-22 11:36:13 +0900840 if (test_bit(MXR_BIT_HAS_SCLK, &mixer_ctx->flags)) {
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200841 mixer_ctx->sclk_mixer = devm_clk_get(dev, "sclk_mixer");
842 if (IS_ERR(mixer_ctx->sclk_mixer)) {
Marek Szyprowskiff830c92014-07-01 10:10:07 +0200843 dev_err(dev, "failed to get clock 'sclk_mixer'\n");
844 return -ENODEV;
845 }
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200846 mixer_ctx->mout_mixer = devm_clk_get(dev, "mout_mixer");
847 if (IS_ERR(mixer_ctx->mout_mixer)) {
Marek Szyprowskiff830c92014-07-01 10:10:07 +0200848 dev_err(dev, "failed to get clock 'mout_mixer'\n");
849 return -ENODEV;
850 }
851
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200852 if (mixer_ctx->sclk_hdmi && mixer_ctx->mout_mixer)
853 clk_set_parent(mixer_ctx->mout_mixer,
854 mixer_ctx->sclk_hdmi);
Marek Szyprowskiff830c92014-07-01 10:10:07 +0200855 }
Sean Paul45517892014-01-30 16:19:05 -0500856
857 res = platform_get_resource(mixer_ctx->pdev, IORESOURCE_MEM, 1);
858 if (res == NULL) {
859 dev_err(dev, "get memory resource failed.\n");
860 return -ENXIO;
861 }
862
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200863 mixer_ctx->vp_regs = devm_ioremap(dev, res->start,
Sean Paul45517892014-01-30 16:19:05 -0500864 resource_size(res));
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200865 if (mixer_ctx->vp_regs == NULL) {
Sean Paul45517892014-01-30 16:19:05 -0500866 dev_err(dev, "register mapping failed.\n");
867 return -ENXIO;
868 }
869
870 return 0;
871}
872
Gustavo Padovan93bca242015-01-18 18:16:23 +0900873static int mixer_initialize(struct mixer_context *mixer_ctx,
Inki Daef37cd5e2014-05-09 14:25:20 +0900874 struct drm_device *drm_dev)
Sean Paul45517892014-01-30 16:19:05 -0500875{
876 int ret;
Sean Paul45517892014-01-30 16:19:05 -0500877
Gustavo Padovaneb88e422014-11-26 16:43:27 -0200878 mixer_ctx->drm_dev = drm_dev;
Sean Paul45517892014-01-30 16:19:05 -0500879
880 /* acquire resources: regs, irqs, clocks */
881 ret = mixer_resources_init(mixer_ctx);
882 if (ret) {
Inki Dae6f83d202019-04-15 14:24:36 +0900883 DRM_DEV_ERROR(mixer_ctx->dev,
884 "mixer_resources_init failed ret=%d\n", ret);
Sean Paul45517892014-01-30 16:19:05 -0500885 return ret;
886 }
887
Tobias Jakobiadeb6f442016-09-22 11:36:13 +0900888 if (test_bit(MXR_BIT_VP_ENABLED, &mixer_ctx->flags)) {
Sean Paul45517892014-01-30 16:19:05 -0500889 /* acquire vp resources: regs, irqs, clocks */
890 ret = vp_resources_init(mixer_ctx);
891 if (ret) {
Inki Dae6f83d202019-04-15 14:24:36 +0900892 DRM_DEV_ERROR(mixer_ctx->dev,
893 "vp_resources_init failed ret=%d\n", ret);
Sean Paul45517892014-01-30 16:19:05 -0500894 return ret;
895 }
896 }
897
Andrzej Hajda29cbf242018-10-12 12:53:41 +0200898 return exynos_drm_register_dma(drm_dev, mixer_ctx->dev);
Sean Paul45517892014-01-30 16:19:05 -0500899}
900
Gustavo Padovan93bca242015-01-18 18:16:23 +0900901static void mixer_ctx_remove(struct mixer_context *mixer_ctx)
Inki Dae1055b392012-10-19 17:37:35 +0900902{
Andrzej Hajda23755692018-10-12 12:53:43 +0200903 exynos_drm_unregister_dma(mixer_ctx->drm_dev, mixer_ctx->dev);
Inki Dae1055b392012-10-19 17:37:35 +0900904}
905
Gustavo Padovan93bca242015-01-18 18:16:23 +0900906static int mixer_enable_vblank(struct exynos_drm_crtc *crtc)
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900907{
Gustavo Padovan93bca242015-01-18 18:16:23 +0900908 struct mixer_context *mixer_ctx = crtc->ctx;
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900909
Andrzej Hajda0df5e4a2015-07-09 08:25:43 +0200910 __set_bit(MXR_BIT_VSYNC, &mixer_ctx->flags);
911 if (!test_bit(MXR_BIT_POWERED, &mixer_ctx->flags))
Sean Paulf041b252014-01-30 16:19:15 -0500912 return 0;
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900913
914 /* enable vsync interrupt */
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200915 mixer_reg_writemask(mixer_ctx, MXR_INT_STATUS, ~0, MXR_INT_CLEAR_VSYNC);
916 mixer_reg_writemask(mixer_ctx, MXR_INT_EN, ~0, MXR_INT_EN_VSYNC);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900917
918 return 0;
919}
920
Gustavo Padovan93bca242015-01-18 18:16:23 +0900921static void mixer_disable_vblank(struct exynos_drm_crtc *crtc)
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900922{
Gustavo Padovan93bca242015-01-18 18:16:23 +0900923 struct mixer_context *mixer_ctx = crtc->ctx;
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900924
Andrzej Hajda0df5e4a2015-07-09 08:25:43 +0200925 __clear_bit(MXR_BIT_VSYNC, &mixer_ctx->flags);
926
927 if (!test_bit(MXR_BIT_POWERED, &mixer_ctx->flags))
Andrzej Hajda947710c2015-07-09 08:25:41 +0200928 return;
Andrzej Hajda947710c2015-07-09 08:25:41 +0200929
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900930 /* disable vsync interrupt */
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200931 mixer_reg_writemask(mixer_ctx, MXR_INT_STATUS, ~0, MXR_INT_CLEAR_VSYNC);
932 mixer_reg_writemask(mixer_ctx, MXR_INT_EN, 0, MXR_INT_EN_VSYNC);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900933}
934
Marek Szyprowski3dbaab12016-01-05 13:52:52 +0100935static void mixer_atomic_begin(struct exynos_drm_crtc *crtc)
936{
Andrzej Hajda6a3b45a2019-03-19 14:05:11 +0100937 struct mixer_context *ctx = crtc->ctx;
Marek Szyprowski3dbaab12016-01-05 13:52:52 +0100938
Andrzej Hajda6a3b45a2019-03-19 14:05:11 +0100939 if (!test_bit(MXR_BIT_POWERED, &ctx->flags))
Marek Szyprowski3dbaab12016-01-05 13:52:52 +0100940 return;
941
Andrzej Hajda6a3b45a2019-03-19 14:05:11 +0100942 if (mixer_wait_for_sync(ctx))
943 dev_err(ctx->dev, "timeout waiting for VSYNC\n");
944 mixer_disable_sync(ctx);
Marek Szyprowski3dbaab12016-01-05 13:52:52 +0100945}
946
Gustavo Padovan1e1d1392015-08-03 14:39:36 +0900947static void mixer_update_plane(struct exynos_drm_crtc *crtc,
948 struct exynos_drm_plane *plane)
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900949{
Gustavo Padovan93bca242015-01-18 18:16:23 +0900950 struct mixer_context *mixer_ctx = crtc->ctx;
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900951
Inki Dae6be90052019-04-15 16:25:12 +0900952 DRM_DEV_DEBUG_KMS(mixer_ctx->dev, "win: %d\n", plane->index);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900953
Andrzej Hajdaa44652e2015-07-09 08:25:42 +0200954 if (!test_bit(MXR_BIT_POWERED, &mixer_ctx->flags))
Shirish Sdda90122013-01-23 22:03:18 -0500955 return;
Shirish Sdda90122013-01-23 22:03:18 -0500956
Marek Szyprowski5e68fef2015-12-16 13:21:48 +0100957 if (plane->index == VP_DEFAULT_WIN)
Gustavo Padovan2eeb2e52015-08-03 14:40:44 +0900958 vp_video_buffer(mixer_ctx, plane);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900959 else
Gustavo Padovan2eeb2e52015-08-03 14:40:44 +0900960 mixer_graph_buffer(mixer_ctx, plane);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900961}
962
Gustavo Padovan1e1d1392015-08-03 14:39:36 +0900963static void mixer_disable_plane(struct exynos_drm_crtc *crtc,
964 struct exynos_drm_plane *plane)
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900965{
Gustavo Padovan93bca242015-01-18 18:16:23 +0900966 struct mixer_context *mixer_ctx = crtc->ctx;
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900967 unsigned long flags;
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900968
Inki Dae6be90052019-04-15 16:25:12 +0900969 DRM_DEV_DEBUG_KMS(mixer_ctx->dev, "win: %d\n", plane->index);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900970
Andrzej Hajdaa44652e2015-07-09 08:25:42 +0200971 if (!test_bit(MXR_BIT_POWERED, &mixer_ctx->flags))
Prathyush Kdb43fd12012-12-06 20:16:05 +0530972 return;
Prathyush Kdb43fd12012-12-06 20:16:05 +0530973
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200974 spin_lock_irqsave(&mixer_ctx->reg_slock, flags);
Marek Szyprowskia2cb9112015-12-16 13:21:44 +0100975 mixer_cfg_layer(mixer_ctx, plane->index, 0, false);
Andrzej Hajda524c59f2017-09-29 12:05:36 +0200976 spin_unlock_irqrestore(&mixer_ctx->reg_slock, flags);
Marek Szyprowski3dbaab12016-01-05 13:52:52 +0100977}
978
979static void mixer_atomic_flush(struct exynos_drm_crtc *crtc)
980{
981 struct mixer_context *mixer_ctx = crtc->ctx;
982
983 if (!test_bit(MXR_BIT_POWERED, &mixer_ctx->flags))
984 return;
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900985
Andrzej Hajda6a3b45a2019-03-19 14:05:11 +0100986 mixer_enable_sync(mixer_ctx);
Andrzej Hajdaa3922762017-03-14 09:27:56 +0100987 exynos_crtc_handle_event(crtc);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900988}
989
Gustavo Padovan3cecda02015-06-01 12:04:55 -0300990static void mixer_enable(struct exynos_drm_crtc *crtc)
Prathyush Kdb43fd12012-12-06 20:16:05 +0530991{
Gustavo Padovan3cecda02015-06-01 12:04:55 -0300992 struct mixer_context *ctx = crtc->ctx;
Prathyush Kdb43fd12012-12-06 20:16:05 +0530993
Andrzej Hajdaa44652e2015-07-09 08:25:42 +0200994 if (test_bit(MXR_BIT_POWERED, &ctx->flags))
Prathyush Kdb43fd12012-12-06 20:16:05 +0530995 return;
Prathyush Kdb43fd12012-12-06 20:16:05 +0530996
Sean Paulaf65c802014-01-30 16:19:27 -0500997 pm_runtime_get_sync(ctx->dev);
998
Andrzej Hajdaa121d172016-03-23 14:26:01 +0100999 exynos_drm_pipe_clk_enable(crtc, true);
1000
Andrzej Hajda6a3b45a2019-03-19 14:05:11 +01001001 mixer_disable_sync(ctx);
Marek Szyprowski3dbaab12016-01-05 13:52:52 +01001002
Andrzej Hajda524c59f2017-09-29 12:05:36 +02001003 mixer_reg_writemask(ctx, MXR_STATUS, ~0, MXR_STATUS_SOFT_RESET);
Rahul Sharmad74ed932014-06-23 11:02:24 +05301004
Andrzej Hajda0df5e4a2015-07-09 08:25:43 +02001005 if (test_bit(MXR_BIT_VSYNC, &ctx->flags)) {
Andrzej Hajda524c59f2017-09-29 12:05:36 +02001006 mixer_reg_writemask(ctx, MXR_INT_STATUS, ~0,
1007 MXR_INT_CLEAR_VSYNC);
1008 mixer_reg_writemask(ctx, MXR_INT_EN, ~0, MXR_INT_EN_VSYNC);
Andrzej Hajda0df5e4a2015-07-09 08:25:43 +02001009 }
Prathyush Kdb43fd12012-12-06 20:16:05 +05301010 mixer_win_reset(ctx);
Gustavo Padovanccf034a2015-09-04 17:15:46 -03001011
Andrzej Hajda71469942017-09-29 12:05:33 +02001012 mixer_commit(ctx);
1013
Andrzej Hajda6a3b45a2019-03-19 14:05:11 +01001014 mixer_enable_sync(ctx);
Marek Szyprowski3dbaab12016-01-05 13:52:52 +01001015
Gustavo Padovanccf034a2015-09-04 17:15:46 -03001016 set_bit(MXR_BIT_POWERED, &ctx->flags);
Prathyush Kdb43fd12012-12-06 20:16:05 +05301017}
1018
Gustavo Padovan3cecda02015-06-01 12:04:55 -03001019static void mixer_disable(struct exynos_drm_crtc *crtc)
Prathyush Kdb43fd12012-12-06 20:16:05 +05301020{
Gustavo Padovan3cecda02015-06-01 12:04:55 -03001021 struct mixer_context *ctx = crtc->ctx;
Joonyoung Shimc329f662015-06-12 20:34:28 +09001022 int i;
Prathyush Kdb43fd12012-12-06 20:16:05 +05301023
Andrzej Hajdaa44652e2015-07-09 08:25:42 +02001024 if (!test_bit(MXR_BIT_POWERED, &ctx->flags))
Rahul Sharmab4bfa3c2014-06-23 11:02:21 +05301025 return;
Prathyush Kdb43fd12012-12-06 20:16:05 +05301026
Rahul Sharma381be022014-06-23 11:02:22 +05301027 mixer_stop(ctx);
Tobias Jakobic0734fb2015-05-06 14:10:21 +02001028 mixer_regs_dump(ctx);
Joonyoung Shimc329f662015-06-12 20:34:28 +09001029
1030 for (i = 0; i < MIXER_WIN_NR; i++)
Gustavo Padovan1e1d1392015-08-03 14:39:36 +09001031 mixer_disable_plane(crtc, &ctx->planes[i]);
Prathyush Kdb43fd12012-12-06 20:16:05 +05301032
Andrzej Hajdaa121d172016-03-23 14:26:01 +01001033 exynos_drm_pipe_clk_enable(crtc, false);
1034
Gustavo Padovanccf034a2015-09-04 17:15:46 -03001035 pm_runtime_put(ctx->dev);
1036
Andrzej Hajdaa44652e2015-07-09 08:25:42 +02001037 clear_bit(MXR_BIT_POWERED, &ctx->flags);
Prathyush Kdb43fd12012-12-06 20:16:05 +05301038}
1039
Andrzej Hajda6ace38a2017-09-29 12:05:35 +02001040static int mixer_mode_valid(struct exynos_drm_crtc *crtc,
1041 const struct drm_display_mode *mode)
Sean Paulf041b252014-01-30 16:19:15 -05001042{
Andrzej Hajda6ace38a2017-09-29 12:05:35 +02001043 struct mixer_context *ctx = crtc->ctx;
1044 u32 w = mode->hdisplay, h = mode->vdisplay;
Sean Paulf041b252014-01-30 16:19:15 -05001045
Inki Dae6be90052019-04-15 16:25:12 +09001046 DRM_DEV_DEBUG_KMS(ctx->dev, "xres=%d, yres=%d, refresh=%d, intl=%d\n",
1047 w, h, mode->vrefresh,
1048 !!(mode->flags & DRM_MODE_FLAG_INTERLACE));
Sean Paulf041b252014-01-30 16:19:15 -05001049
Andrzej Hajda6ace38a2017-09-29 12:05:35 +02001050 if (ctx->mxr_ver == MXR_VER_128_0_0_184)
1051 return MODE_OK;
Sean Paulf041b252014-01-30 16:19:15 -05001052
1053 if ((w >= 464 && w <= 720 && h >= 261 && h <= 576) ||
Andrzej Hajda6ace38a2017-09-29 12:05:35 +02001054 (w >= 1024 && w <= 1280 && h >= 576 && h <= 720) ||
1055 (w >= 1664 && w <= 1920 && h >= 936 && h <= 1080))
1056 return MODE_OK;
Sean Paulf041b252014-01-30 16:19:15 -05001057
Daniel Drakeae58c032017-09-29 12:05:42 +02001058 if ((w == 1024 && h == 768) ||
1059 (w == 1366 && h == 768) ||
1060 (w == 1280 && h == 1024))
Andrzej Hajda09006732017-09-29 12:05:41 +02001061 return MODE_OK;
1062
Andrzej Hajda6ace38a2017-09-29 12:05:35 +02001063 return MODE_BAD;
Sean Paulf041b252014-01-30 16:19:15 -05001064}
1065
Andrzej Hajdaacc8bf02017-09-29 12:05:39 +02001066static bool mixer_mode_fixup(struct exynos_drm_crtc *crtc,
1067 const struct drm_display_mode *mode,
1068 struct drm_display_mode *adjusted_mode)
1069{
1070 struct mixer_context *ctx = crtc->ctx;
1071 int width = mode->hdisplay, height = mode->vdisplay, i;
1072
1073 struct {
1074 int hdisplay, vdisplay, htotal, vtotal, scan_val;
1075 } static const modes[] = {
1076 { 720, 480, 858, 525, MXR_CFG_SCAN_NTSC | MXR_CFG_SCAN_SD },
1077 { 720, 576, 864, 625, MXR_CFG_SCAN_PAL | MXR_CFG_SCAN_SD },
1078 { 1280, 720, 1650, 750, MXR_CFG_SCAN_HD_720 | MXR_CFG_SCAN_HD },
1079 { 1920, 1080, 2200, 1125, MXR_CFG_SCAN_HD_1080 |
1080 MXR_CFG_SCAN_HD }
1081 };
1082
1083 if (mode->flags & DRM_MODE_FLAG_INTERLACE)
1084 __set_bit(MXR_BIT_INTERLACE, &ctx->flags);
1085 else
1086 __clear_bit(MXR_BIT_INTERLACE, &ctx->flags);
1087
1088 if (ctx->mxr_ver == MXR_VER_128_0_0_184)
1089 return true;
1090
1091 for (i = 0; i < ARRAY_SIZE(modes); ++i)
1092 if (width <= modes[i].hdisplay && height <= modes[i].vdisplay) {
1093 ctx->scan_value = modes[i].scan_val;
1094 if (width < modes[i].hdisplay ||
1095 height < modes[i].vdisplay) {
1096 adjusted_mode->hdisplay = modes[i].hdisplay;
1097 adjusted_mode->hsync_start = modes[i].hdisplay;
1098 adjusted_mode->hsync_end = modes[i].htotal;
1099 adjusted_mode->htotal = modes[i].htotal;
1100 adjusted_mode->vdisplay = modes[i].vdisplay;
1101 adjusted_mode->vsync_start = modes[i].vdisplay;
1102 adjusted_mode->vsync_end = modes[i].vtotal;
1103 adjusted_mode->vtotal = modes[i].vtotal;
1104 }
1105
1106 return true;
1107 }
1108
1109 return false;
1110}
1111
Krzysztof Kozlowskif3aaf762015-05-07 09:04:45 +09001112static const struct exynos_drm_crtc_ops mixer_crtc_ops = {
Gustavo Padovan3cecda02015-06-01 12:04:55 -03001113 .enable = mixer_enable,
1114 .disable = mixer_disable,
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001115 .enable_vblank = mixer_enable_vblank,
1116 .disable_vblank = mixer_disable_vblank,
Marek Szyprowski3dbaab12016-01-05 13:52:52 +01001117 .atomic_begin = mixer_atomic_begin,
Gustavo Padovan9cc76102015-08-03 14:38:05 +09001118 .update_plane = mixer_update_plane,
1119 .disable_plane = mixer_disable_plane,
Marek Szyprowski3dbaab12016-01-05 13:52:52 +01001120 .atomic_flush = mixer_atomic_flush,
Andrzej Hajda6ace38a2017-09-29 12:05:35 +02001121 .mode_valid = mixer_mode_valid,
Andrzej Hajdaacc8bf02017-09-29 12:05:39 +02001122 .mode_fixup = mixer_mode_fixup,
Sean Paulf041b252014-01-30 16:19:15 -05001123};
Rahul Sharma0ea68222013-01-15 08:11:06 -05001124
Arvind Yadav5e6cc1c2017-06-19 15:42:42 +05301125static const struct mixer_drv_data exynos5420_mxr_drv_data = {
Rahul Sharmadef5e092013-06-19 18:21:08 +05301126 .version = MXR_VER_128_0_0_184,
1127 .is_vp_enabled = 0,
1128};
1129
Arvind Yadav5e6cc1c2017-06-19 15:42:42 +05301130static const struct mixer_drv_data exynos5250_mxr_drv_data = {
Rahul Sharmaaaf8b492012-10-04 20:48:53 +05301131 .version = MXR_VER_16_0_33_0,
1132 .is_vp_enabled = 0,
1133};
1134
Arvind Yadav5e6cc1c2017-06-19 15:42:42 +05301135static const struct mixer_drv_data exynos4212_mxr_drv_data = {
Marek Szyprowskiff830c92014-07-01 10:10:07 +02001136 .version = MXR_VER_0_0_0_16,
1137 .is_vp_enabled = 1,
1138};
1139
Arvind Yadav5e6cc1c2017-06-19 15:42:42 +05301140static const struct mixer_drv_data exynos4210_mxr_drv_data = {
Rahul Sharma1e123442012-10-04 20:48:51 +05301141 .version = MXR_VER_0_0_0_16,
Rahul Sharma1b8e5742012-10-04 20:48:52 +05301142 .is_vp_enabled = 1,
Marek Szyprowskiff830c92014-07-01 10:10:07 +02001143 .has_sclk = 1,
Rahul Sharma1e123442012-10-04 20:48:51 +05301144};
1145
Arvind Yadav5e6cc1c2017-06-19 15:42:42 +05301146static const struct of_device_id mixer_match_types[] = {
Rahul Sharmaaaf8b492012-10-04 20:48:53 +05301147 {
Marek Szyprowskiff830c92014-07-01 10:10:07 +02001148 .compatible = "samsung,exynos4210-mixer",
1149 .data = &exynos4210_mxr_drv_data,
1150 }, {
1151 .compatible = "samsung,exynos4212-mixer",
1152 .data = &exynos4212_mxr_drv_data,
1153 }, {
Rahul Sharmaaaf8b492012-10-04 20:48:53 +05301154 .compatible = "samsung,exynos5-mixer",
Rahul Sharmacc57caf2013-06-19 18:21:07 +05301155 .data = &exynos5250_mxr_drv_data,
1156 }, {
1157 .compatible = "samsung,exynos5250-mixer",
1158 .data = &exynos5250_mxr_drv_data,
Rahul Sharmaaaf8b492012-10-04 20:48:53 +05301159 }, {
Rahul Sharmadef5e092013-06-19 18:21:08 +05301160 .compatible = "samsung,exynos5420-mixer",
1161 .data = &exynos5420_mxr_drv_data,
1162 }, {
Rahul Sharma1e123442012-10-04 20:48:51 +05301163 /* end node */
1164 }
1165};
Sjoerd Simons39b58a32014-07-18 22:36:41 +02001166MODULE_DEVICE_TABLE(of, mixer_match_types);
Rahul Sharma1e123442012-10-04 20:48:51 +05301167
Inki Daef37cd5e2014-05-09 14:25:20 +09001168static int mixer_bind(struct device *dev, struct device *manager, void *data)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001169{
Andrzej Hajda8103ef12014-11-24 14:12:46 +09001170 struct mixer_context *ctx = dev_get_drvdata(dev);
Inki Daef37cd5e2014-05-09 14:25:20 +09001171 struct drm_device *drm_dev = data;
Gustavo Padovan7ee14cd2015-04-03 21:03:40 +09001172 struct exynos_drm_plane *exynos_plane;
Marek Szyprowskifd2d2fc2015-11-30 14:53:25 +01001173 unsigned int i;
Gustavo Padovan6e2a3b62015-04-03 21:05:52 +09001174 int ret;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001175
Alban Browaeyse2dc3f72015-01-29 22:18:40 +01001176 ret = mixer_initialize(ctx, drm_dev);
1177 if (ret)
1178 return ret;
1179
Marek Szyprowskifd2d2fc2015-11-30 14:53:25 +01001180 for (i = 0; i < MIXER_WIN_NR; i++) {
Tobias Jakobiadeb6f442016-09-22 11:36:13 +09001181 if (i == VP_DEFAULT_WIN && !test_bit(MXR_BIT_VP_ENABLED,
1182 &ctx->flags))
Marek Szyprowskiab144202015-11-30 14:53:24 +01001183 continue;
1184
Marek Szyprowski40bdfb02015-12-16 13:21:42 +01001185 ret = exynos_plane_init(drm_dev, &ctx->planes[i], i,
Andrzej Hajda2c826072017-03-15 15:41:05 +01001186 &plane_configs[i]);
Gustavo Padovan7ee14cd2015-04-03 21:03:40 +09001187 if (ret)
1188 return ret;
1189 }
1190
Gustavo Padovan5d3d0992015-10-12 22:07:48 +09001191 exynos_plane = &ctx->planes[DEFAULT_WIN];
Gustavo Padovan7ee14cd2015-04-03 21:03:40 +09001192 ctx->crtc = exynos_drm_crtc_create(drm_dev, &exynos_plane->base,
Andrzej Hajdad6449512017-05-29 10:05:25 +09001193 EXYNOS_DISPLAY_TYPE_HDMI, &mixer_crtc_ops, ctx);
Gustavo Padovan93bca242015-01-18 18:16:23 +09001194 if (IS_ERR(ctx->crtc)) {
Alban Browaeyse2dc3f72015-01-29 22:18:40 +01001195 mixer_ctx_remove(ctx);
Gustavo Padovan93bca242015-01-18 18:16:23 +09001196 ret = PTR_ERR(ctx->crtc);
1197 goto free_ctx;
Andrzej Hajda8103ef12014-11-24 14:12:46 +09001198 }
1199
Andrzej Hajda8103ef12014-11-24 14:12:46 +09001200 return 0;
Gustavo Padovan93bca242015-01-18 18:16:23 +09001201
1202free_ctx:
1203 devm_kfree(dev, ctx);
1204 return ret;
Andrzej Hajda8103ef12014-11-24 14:12:46 +09001205}
1206
1207static void mixer_unbind(struct device *dev, struct device *master, void *data)
1208{
1209 struct mixer_context *ctx = dev_get_drvdata(dev);
1210
Gustavo Padovan93bca242015-01-18 18:16:23 +09001211 mixer_ctx_remove(ctx);
Andrzej Hajda8103ef12014-11-24 14:12:46 +09001212}
1213
1214static const struct component_ops mixer_component_ops = {
1215 .bind = mixer_bind,
1216 .unbind = mixer_unbind,
1217};
1218
1219static int mixer_probe(struct platform_device *pdev)
1220{
1221 struct device *dev = &pdev->dev;
Marek Szyprowski48f61552016-04-01 15:17:46 +02001222 const struct mixer_drv_data *drv;
Andrzej Hajda8103ef12014-11-24 14:12:46 +09001223 struct mixer_context *ctx;
1224 int ret;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001225
Sean Paulf041b252014-01-30 16:19:15 -05001226 ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
1227 if (!ctx) {
Inki Dae6f83d202019-04-15 14:24:36 +09001228 DRM_DEV_ERROR(dev, "failed to alloc mixer context.\n");
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001229 return -ENOMEM;
Sean Paulf041b252014-01-30 16:19:15 -05001230 }
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001231
Marek Szyprowski48f61552016-04-01 15:17:46 +02001232 drv = of_device_get_match_data(dev);
Rahul Sharmaaaf8b492012-10-04 20:48:53 +05301233
Sean Paul45517892014-01-30 16:19:05 -05001234 ctx->pdev = pdev;
Seung-Woo Kimd873ab92013-05-22 21:14:14 +09001235 ctx->dev = dev;
Rahul Sharma1e123442012-10-04 20:48:51 +05301236 ctx->mxr_ver = drv->version;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001237
Tobias Jakobiadeb6f442016-09-22 11:36:13 +09001238 if (drv->is_vp_enabled)
1239 __set_bit(MXR_BIT_VP_ENABLED, &ctx->flags);
1240 if (drv->has_sclk)
1241 __set_bit(MXR_BIT_HAS_SCLK, &ctx->flags);
1242
Andrzej Hajda8103ef12014-11-24 14:12:46 +09001243 platform_set_drvdata(pdev, ctx);
Inki Daedf5225b2014-05-29 18:28:02 +09001244
Inki Daedf5225b2014-05-29 18:28:02 +09001245 ret = component_add(&pdev->dev, &mixer_component_ops);
Andrzej Hajda86650402015-06-11 23:23:37 +09001246 if (!ret)
1247 pm_runtime_enable(dev);
Inki Daedf5225b2014-05-29 18:28:02 +09001248
1249 return ret;
Inki Daef37cd5e2014-05-09 14:25:20 +09001250}
1251
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001252static int mixer_remove(struct platform_device *pdev)
1253{
Andrzej Hajda8103ef12014-11-24 14:12:46 +09001254 pm_runtime_disable(&pdev->dev);
1255
Inki Daedf5225b2014-05-29 18:28:02 +09001256 component_del(&pdev->dev, &mixer_component_ops);
Inki Daedf5225b2014-05-29 18:28:02 +09001257
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001258 return 0;
1259}
1260
Arnd Bergmanne0fea7e2015-11-17 16:08:36 +01001261static int __maybe_unused exynos_mixer_suspend(struct device *dev)
Gustavo Padovanccf034a2015-09-04 17:15:46 -03001262{
1263 struct mixer_context *ctx = dev_get_drvdata(dev);
Gustavo Padovanccf034a2015-09-04 17:15:46 -03001264
Andrzej Hajda524c59f2017-09-29 12:05:36 +02001265 clk_disable_unprepare(ctx->hdmi);
1266 clk_disable_unprepare(ctx->mixer);
Tobias Jakobiadeb6f442016-09-22 11:36:13 +09001267 if (test_bit(MXR_BIT_VP_ENABLED, &ctx->flags)) {
Andrzej Hajda524c59f2017-09-29 12:05:36 +02001268 clk_disable_unprepare(ctx->vp);
Tobias Jakobiadeb6f442016-09-22 11:36:13 +09001269 if (test_bit(MXR_BIT_HAS_SCLK, &ctx->flags))
Andrzej Hajda524c59f2017-09-29 12:05:36 +02001270 clk_disable_unprepare(ctx->sclk_mixer);
Gustavo Padovanccf034a2015-09-04 17:15:46 -03001271 }
1272
1273 return 0;
1274}
1275
Arnd Bergmanne0fea7e2015-11-17 16:08:36 +01001276static int __maybe_unused exynos_mixer_resume(struct device *dev)
Gustavo Padovanccf034a2015-09-04 17:15:46 -03001277{
1278 struct mixer_context *ctx = dev_get_drvdata(dev);
Gustavo Padovanccf034a2015-09-04 17:15:46 -03001279 int ret;
1280
Andrzej Hajda524c59f2017-09-29 12:05:36 +02001281 ret = clk_prepare_enable(ctx->mixer);
Gustavo Padovanccf034a2015-09-04 17:15:46 -03001282 if (ret < 0) {
Inki Dae6f83d202019-04-15 14:24:36 +09001283 DRM_DEV_ERROR(ctx->dev,
1284 "Failed to prepare_enable the mixer clk [%d]\n",
1285 ret);
Gustavo Padovanccf034a2015-09-04 17:15:46 -03001286 return ret;
1287 }
Andrzej Hajda524c59f2017-09-29 12:05:36 +02001288 ret = clk_prepare_enable(ctx->hdmi);
Gustavo Padovanccf034a2015-09-04 17:15:46 -03001289 if (ret < 0) {
Inki Dae6f83d202019-04-15 14:24:36 +09001290 DRM_DEV_ERROR(dev,
1291 "Failed to prepare_enable the hdmi clk [%d]\n",
1292 ret);
Gustavo Padovanccf034a2015-09-04 17:15:46 -03001293 return ret;
1294 }
Tobias Jakobiadeb6f442016-09-22 11:36:13 +09001295 if (test_bit(MXR_BIT_VP_ENABLED, &ctx->flags)) {
Andrzej Hajda524c59f2017-09-29 12:05:36 +02001296 ret = clk_prepare_enable(ctx->vp);
Gustavo Padovanccf034a2015-09-04 17:15:46 -03001297 if (ret < 0) {
Inki Dae6f83d202019-04-15 14:24:36 +09001298 DRM_DEV_ERROR(dev,
1299 "Failed to prepare_enable the vp clk [%d]\n",
1300 ret);
Gustavo Padovanccf034a2015-09-04 17:15:46 -03001301 return ret;
1302 }
Tobias Jakobiadeb6f442016-09-22 11:36:13 +09001303 if (test_bit(MXR_BIT_HAS_SCLK, &ctx->flags)) {
Andrzej Hajda524c59f2017-09-29 12:05:36 +02001304 ret = clk_prepare_enable(ctx->sclk_mixer);
Gustavo Padovanccf034a2015-09-04 17:15:46 -03001305 if (ret < 0) {
Inki Dae6f83d202019-04-15 14:24:36 +09001306 DRM_DEV_ERROR(dev,
1307 "Failed to prepare_enable the " \
Gustavo Padovanccf034a2015-09-04 17:15:46 -03001308 "sclk_mixer clk [%d]\n",
Inki Dae6f83d202019-04-15 14:24:36 +09001309 ret);
Gustavo Padovanccf034a2015-09-04 17:15:46 -03001310 return ret;
1311 }
1312 }
1313 }
1314
1315 return 0;
1316}
Gustavo Padovanccf034a2015-09-04 17:15:46 -03001317
1318static const struct dev_pm_ops exynos_mixer_pm_ops = {
1319 SET_RUNTIME_PM_OPS(exynos_mixer_suspend, exynos_mixer_resume, NULL)
Marek Szyprowski7e915742018-06-11 14:25:00 +02001320 SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
1321 pm_runtime_force_resume)
Gustavo Padovanccf034a2015-09-04 17:15:46 -03001322};
1323
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001324struct platform_driver mixer_driver = {
1325 .driver = {
Rahul Sharmaaaf8b492012-10-04 20:48:53 +05301326 .name = "exynos-mixer",
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001327 .owner = THIS_MODULE,
Gustavo Padovanccf034a2015-09-04 17:15:46 -03001328 .pm = &exynos_mixer_pm_ops,
Rahul Sharmaaaf8b492012-10-04 20:48:53 +05301329 .of_match_table = mixer_match_types,
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001330 },
1331 .probe = mixer_probe,
Greg Kroah-Hartman56550d92012-12-21 15:09:25 -08001332 .remove = mixer_remove,
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001333};