]>
Commit | Line | Data |
---|---|---|
1ccea77e | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
bbbe775e NA |
2 | /* |
3 | * Copyright (C) 2016 BayLibre, SAS | |
4 | * Author: Neil Armstrong <narmstrong@baylibre.com> | |
5 | * Copyright (C) 2015 Amlogic, Inc. All rights reserved. | |
6 | * Copyright (C) 2014 Endless Mobile | |
7 | * | |
bbbe775e NA |
8 | * Written by: |
9 | * Jasper St. Pierre <jstpierre@mecheye.net> | |
10 | */ | |
11 | ||
12 | #include <linux/kernel.h> | |
13 | #include <linux/module.h> | |
14 | #include <linux/mutex.h> | |
15 | #include <linux/platform_device.h> | |
f9a23481 | 16 | #include <linux/bitfield.h> |
bbbe775e NA |
17 | #include <drm/drmP.h> |
18 | #include <drm/drm_atomic.h> | |
19 | #include <drm/drm_atomic_helper.h> | |
20 | #include <drm/drm_flip_work.h> | |
fcd70cd3 | 21 | #include <drm/drm_probe_helper.h> |
bbbe775e NA |
22 | |
23 | #include "meson_crtc.h" | |
24 | #include "meson_plane.h" | |
65686873 | 25 | #include "meson_venc.h" |
bbbe775e NA |
26 | #include "meson_vpp.h" |
27 | #include "meson_viu.h" | |
28 | #include "meson_registers.h" | |
29 | ||
68679d41 NA |
30 | #define MESON_G12A_VIU_OFFSET 0x5ec0 |
31 | ||
bbbe775e NA |
32 | /* CRTC definition */ |
33 | ||
34 | struct meson_crtc { | |
35 | struct drm_crtc base; | |
36 | struct drm_pending_vblank_event *event; | |
37 | struct meson_drm *priv; | |
68679d41 NA |
38 | void (*enable_osd1)(struct meson_drm *priv); |
39 | void (*enable_vd1)(struct meson_drm *priv); | |
40 | unsigned int viu_offset; | |
bbbe775e NA |
41 | }; |
42 | #define to_meson_crtc(x) container_of(x, struct meson_crtc, base) | |
43 | ||
44 | /* CRTC */ | |
45 | ||
65686873 SG |
46 | static int meson_crtc_enable_vblank(struct drm_crtc *crtc) |
47 | { | |
48 | struct meson_crtc *meson_crtc = to_meson_crtc(crtc); | |
49 | struct meson_drm *priv = meson_crtc->priv; | |
50 | ||
51 | meson_venc_enable_vsync(priv); | |
52 | ||
53 | return 0; | |
54 | } | |
55 | ||
56 | static void meson_crtc_disable_vblank(struct drm_crtc *crtc) | |
57 | { | |
58 | struct meson_crtc *meson_crtc = to_meson_crtc(crtc); | |
59 | struct meson_drm *priv = meson_crtc->priv; | |
60 | ||
61 | meson_venc_disable_vsync(priv); | |
62 | } | |
63 | ||
bbbe775e NA |
64 | static const struct drm_crtc_funcs meson_crtc_funcs = { |
65 | .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, | |
66 | .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state, | |
67 | .destroy = drm_crtc_cleanup, | |
68 | .page_flip = drm_atomic_helper_page_flip, | |
69 | .reset = drm_atomic_helper_crtc_reset, | |
70 | .set_config = drm_atomic_helper_set_config, | |
65686873 SG |
71 | .enable_vblank = meson_crtc_enable_vblank, |
72 | .disable_vblank = meson_crtc_disable_vblank, | |
73 | ||
bbbe775e NA |
74 | }; |
75 | ||
68679d41 NA |
76 | static void meson_g12a_crtc_atomic_enable(struct drm_crtc *crtc, |
77 | struct drm_crtc_state *old_state) | |
78 | { | |
79 | struct meson_crtc *meson_crtc = to_meson_crtc(crtc); | |
80 | struct drm_crtc_state *crtc_state = crtc->state; | |
81 | struct meson_drm *priv = meson_crtc->priv; | |
82 | ||
83 | DRM_DEBUG_DRIVER("\n"); | |
84 | ||
85 | if (!crtc_state) { | |
86 | DRM_ERROR("Invalid crtc_state\n"); | |
87 | return; | |
88 | } | |
89 | ||
90 | /* VD1 Preblend vertical start/end */ | |
91 | writel(FIELD_PREP(GENMASK(11, 0), 2303), | |
92 | priv->io_base + _REG(VPP_PREBLEND_VD1_V_START_END)); | |
93 | ||
94 | /* Setup Blender */ | |
95 | writel(crtc_state->mode.hdisplay | | |
96 | crtc_state->mode.vdisplay << 16, | |
97 | priv->io_base + _REG(VPP_POSTBLEND_H_SIZE)); | |
98 | ||
99 | writel_relaxed(0 << 16 | | |
100 | (crtc_state->mode.hdisplay - 1), | |
101 | priv->io_base + _REG(VPP_OSD1_BLD_H_SCOPE)); | |
102 | writel_relaxed(0 << 16 | | |
103 | (crtc_state->mode.vdisplay - 1), | |
104 | priv->io_base + _REG(VPP_OSD1_BLD_V_SCOPE)); | |
105 | writel_relaxed(crtc_state->mode.hdisplay << 16 | | |
106 | crtc_state->mode.vdisplay, | |
107 | priv->io_base + _REG(VPP_OUT_H_V_SIZE)); | |
108 | ||
109 | drm_crtc_vblank_on(crtc); | |
110 | ||
111 | priv->viu.osd1_enabled = true; | |
112 | } | |
113 | ||
ce0210c1 NA |
114 | static void meson_crtc_atomic_enable(struct drm_crtc *crtc, |
115 | struct drm_crtc_state *old_state) | |
bbbe775e NA |
116 | { |
117 | struct meson_crtc *meson_crtc = to_meson_crtc(crtc); | |
cc0c43a0 | 118 | struct drm_crtc_state *crtc_state = crtc->state; |
bbbe775e NA |
119 | struct meson_drm *priv = meson_crtc->priv; |
120 | ||
cc0c43a0 NA |
121 | DRM_DEBUG_DRIVER("\n"); |
122 | ||
123 | if (!crtc_state) { | |
124 | DRM_ERROR("Invalid crtc_state\n"); | |
125 | return; | |
126 | } | |
127 | ||
bbbe775e | 128 | /* Enable VPP Postblend */ |
cc0c43a0 | 129 | writel(crtc_state->mode.hdisplay, |
bbbe775e NA |
130 | priv->io_base + _REG(VPP_POSTBLEND_H_SIZE)); |
131 | ||
f9a23481 NA |
132 | /* VD1 Preblend vertical start/end */ |
133 | writel(FIELD_PREP(GENMASK(11, 0), 2303), | |
134 | priv->io_base + _REG(VPP_PREBLEND_VD1_V_START_END)); | |
135 | ||
bbbe775e NA |
136 | writel_bits_relaxed(VPP_POSTBLEND_ENABLE, VPP_POSTBLEND_ENABLE, |
137 | priv->io_base + _REG(VPP_MISC)); | |
138 | ||
2bcd3eca NA |
139 | drm_crtc_vblank_on(crtc); |
140 | ||
bbbe775e NA |
141 | priv->viu.osd1_enabled = true; |
142 | } | |
143 | ||
68679d41 NA |
144 | static void meson_g12a_crtc_atomic_disable(struct drm_crtc *crtc, |
145 | struct drm_crtc_state *old_state) | |
146 | { | |
147 | struct meson_crtc *meson_crtc = to_meson_crtc(crtc); | |
148 | struct meson_drm *priv = meson_crtc->priv; | |
149 | ||
150 | DRM_DEBUG_DRIVER("\n"); | |
151 | ||
152 | drm_crtc_vblank_off(crtc); | |
153 | ||
154 | priv->viu.osd1_enabled = false; | |
155 | priv->viu.osd1_commit = false; | |
156 | ||
157 | priv->viu.vd1_enabled = false; | |
158 | priv->viu.vd1_commit = false; | |
159 | ||
160 | if (crtc->state->event && !crtc->state->active) { | |
161 | spin_lock_irq(&crtc->dev->event_lock); | |
162 | drm_crtc_send_vblank_event(crtc, crtc->state->event); | |
163 | spin_unlock_irq(&crtc->dev->event_lock); | |
164 | ||
165 | crtc->state->event = NULL; | |
166 | } | |
167 | } | |
168 | ||
64581714 LP |
169 | static void meson_crtc_atomic_disable(struct drm_crtc *crtc, |
170 | struct drm_crtc_state *old_state) | |
bbbe775e NA |
171 | { |
172 | struct meson_crtc *meson_crtc = to_meson_crtc(crtc); | |
173 | struct meson_drm *priv = meson_crtc->priv; | |
174 | ||
f9a23481 NA |
175 | DRM_DEBUG_DRIVER("\n"); |
176 | ||
2bcd3eca NA |
177 | drm_crtc_vblank_off(crtc); |
178 | ||
bbbe775e | 179 | priv->viu.osd1_enabled = false; |
cc0c43a0 | 180 | priv->viu.osd1_commit = false; |
bbbe775e | 181 | |
f9a23481 NA |
182 | priv->viu.vd1_enabled = false; |
183 | priv->viu.vd1_commit = false; | |
184 | ||
bbbe775e | 185 | /* Disable VPP Postblend */ |
f9a23481 NA |
186 | writel_bits_relaxed(VPP_OSD1_POSTBLEND | VPP_VD1_POSTBLEND | |
187 | VPP_VD1_PREBLEND | VPP_POSTBLEND_ENABLE, 0, | |
bbbe775e NA |
188 | priv->io_base + _REG(VPP_MISC)); |
189 | ||
190 | if (crtc->state->event && !crtc->state->active) { | |
191 | spin_lock_irq(&crtc->dev->event_lock); | |
192 | drm_crtc_send_vblank_event(crtc, crtc->state->event); | |
193 | spin_unlock_irq(&crtc->dev->event_lock); | |
194 | ||
195 | crtc->state->event = NULL; | |
196 | } | |
197 | } | |
198 | ||
199 | static void meson_crtc_atomic_begin(struct drm_crtc *crtc, | |
200 | struct drm_crtc_state *state) | |
201 | { | |
202 | struct meson_crtc *meson_crtc = to_meson_crtc(crtc); | |
203 | unsigned long flags; | |
204 | ||
205 | if (crtc->state->event) { | |
206 | WARN_ON(drm_crtc_vblank_get(crtc) != 0); | |
207 | ||
208 | spin_lock_irqsave(&crtc->dev->event_lock, flags); | |
209 | meson_crtc->event = crtc->state->event; | |
210 | spin_unlock_irqrestore(&crtc->dev->event_lock, flags); | |
211 | crtc->state->event = NULL; | |
212 | } | |
213 | } | |
214 | ||
215 | static void meson_crtc_atomic_flush(struct drm_crtc *crtc, | |
216 | struct drm_crtc_state *old_crtc_state) | |
217 | { | |
218 | struct meson_crtc *meson_crtc = to_meson_crtc(crtc); | |
219 | struct meson_drm *priv = meson_crtc->priv; | |
220 | ||
cc0c43a0 | 221 | priv->viu.osd1_commit = true; |
f9a23481 | 222 | priv->viu.vd1_commit = true; |
bbbe775e NA |
223 | } |
224 | ||
225 | static const struct drm_crtc_helper_funcs meson_crtc_helper_funcs = { | |
bbbe775e NA |
226 | .atomic_begin = meson_crtc_atomic_begin, |
227 | .atomic_flush = meson_crtc_atomic_flush, | |
0b20a0f8 | 228 | .atomic_enable = meson_crtc_atomic_enable, |
64581714 | 229 | .atomic_disable = meson_crtc_atomic_disable, |
bbbe775e NA |
230 | }; |
231 | ||
68679d41 NA |
232 | static const struct drm_crtc_helper_funcs meson_g12a_crtc_helper_funcs = { |
233 | .atomic_begin = meson_crtc_atomic_begin, | |
234 | .atomic_flush = meson_crtc_atomic_flush, | |
235 | .atomic_enable = meson_g12a_crtc_atomic_enable, | |
236 | .atomic_disable = meson_g12a_crtc_atomic_disable, | |
237 | }; | |
238 | ||
239 | static void meson_crtc_enable_osd1(struct meson_drm *priv) | |
240 | { | |
241 | writel_bits_relaxed(VPP_OSD1_POSTBLEND, VPP_OSD1_POSTBLEND, | |
242 | priv->io_base + _REG(VPP_MISC)); | |
243 | } | |
244 | ||
245 | static void meson_g12a_crtc_enable_osd1(struct meson_drm *priv) | |
246 | { | |
247 | writel_relaxed(priv->viu.osd_blend_din0_scope_h, | |
248 | priv->io_base + | |
249 | _REG(VIU_OSD_BLEND_DIN0_SCOPE_H)); | |
250 | writel_relaxed(priv->viu.osd_blend_din0_scope_v, | |
251 | priv->io_base + | |
252 | _REG(VIU_OSD_BLEND_DIN0_SCOPE_V)); | |
253 | writel_relaxed(priv->viu.osb_blend0_size, | |
254 | priv->io_base + | |
255 | _REG(VIU_OSD_BLEND_BLEND0_SIZE)); | |
256 | writel_relaxed(priv->viu.osb_blend1_size, | |
257 | priv->io_base + | |
258 | _REG(VIU_OSD_BLEND_BLEND1_SIZE)); | |
259 | } | |
260 | ||
261 | static void meson_crtc_enable_vd1(struct meson_drm *priv) | |
262 | { | |
263 | writel_bits_relaxed(VPP_VD1_PREBLEND | VPP_VD1_POSTBLEND | | |
264 | VPP_COLOR_MNG_ENABLE, | |
265 | VPP_VD1_PREBLEND | VPP_VD1_POSTBLEND | | |
266 | VPP_COLOR_MNG_ENABLE, | |
267 | priv->io_base + _REG(VPP_MISC)); | |
268 | } | |
269 | ||
270 | static void meson_g12a_crtc_enable_vd1(struct meson_drm *priv) | |
271 | { | |
272 | writel_relaxed(((1 << 16) | /* post bld premult*/ | |
273 | (1 << 8) | /* post src */ | |
274 | (1 << 4) | /* pre bld premult*/ | |
275 | (1 << 0)), | |
276 | priv->io_base + _REG(VD1_BLEND_SRC_CTRL)); | |
277 | } | |
278 | ||
bbbe775e NA |
279 | void meson_crtc_irq(struct meson_drm *priv) |
280 | { | |
281 | struct meson_crtc *meson_crtc = to_meson_crtc(priv->crtc); | |
282 | unsigned long flags; | |
283 | ||
284 | /* Update the OSD registers */ | |
285 | if (priv->viu.osd1_enabled && priv->viu.osd1_commit) { | |
286 | writel_relaxed(priv->viu.osd1_ctrl_stat, | |
287 | priv->io_base + _REG(VIU_OSD1_CTRL_STAT)); | |
288 | writel_relaxed(priv->viu.osd1_blk0_cfg[0], | |
289 | priv->io_base + _REG(VIU_OSD1_BLK0_CFG_W0)); | |
290 | writel_relaxed(priv->viu.osd1_blk0_cfg[1], | |
291 | priv->io_base + _REG(VIU_OSD1_BLK0_CFG_W1)); | |
292 | writel_relaxed(priv->viu.osd1_blk0_cfg[2], | |
293 | priv->io_base + _REG(VIU_OSD1_BLK0_CFG_W2)); | |
294 | writel_relaxed(priv->viu.osd1_blk0_cfg[3], | |
295 | priv->io_base + _REG(VIU_OSD1_BLK0_CFG_W3)); | |
296 | writel_relaxed(priv->viu.osd1_blk0_cfg[4], | |
297 | priv->io_base + _REG(VIU_OSD1_BLK0_CFG_W4)); | |
20d7fe03 NA |
298 | writel_relaxed(priv->viu.osd_sc_ctrl0, |
299 | priv->io_base + _REG(VPP_OSD_SC_CTRL0)); | |
300 | writel_relaxed(priv->viu.osd_sc_i_wh_m1, | |
301 | priv->io_base + _REG(VPP_OSD_SCI_WH_M1)); | |
302 | writel_relaxed(priv->viu.osd_sc_o_h_start_end, | |
303 | priv->io_base + _REG(VPP_OSD_SCO_H_START_END)); | |
304 | writel_relaxed(priv->viu.osd_sc_o_v_start_end, | |
305 | priv->io_base + _REG(VPP_OSD_SCO_V_START_END)); | |
306 | writel_relaxed(priv->viu.osd_sc_v_ini_phase, | |
307 | priv->io_base + _REG(VPP_OSD_VSC_INI_PHASE)); | |
308 | writel_relaxed(priv->viu.osd_sc_v_phase_step, | |
309 | priv->io_base + _REG(VPP_OSD_VSC_PHASE_STEP)); | |
310 | writel_relaxed(priv->viu.osd_sc_h_ini_phase, | |
311 | priv->io_base + _REG(VPP_OSD_HSC_INI_PHASE)); | |
312 | writel_relaxed(priv->viu.osd_sc_h_phase_step, | |
313 | priv->io_base + _REG(VPP_OSD_HSC_PHASE_STEP)); | |
314 | writel_relaxed(priv->viu.osd_sc_h_ctrl0, | |
315 | priv->io_base + _REG(VPP_OSD_HSC_CTRL0)); | |
316 | writel_relaxed(priv->viu.osd_sc_v_ctrl0, | |
317 | priv->io_base + _REG(VPP_OSD_VSC_CTRL0)); | |
bbbe775e | 318 | |
2bf6b5b0 | 319 | meson_canvas_config(priv->canvas, priv->canvas_id_osd1, |
66cae477 MJ |
320 | priv->viu.osd1_addr, priv->viu.osd1_stride, |
321 | priv->viu.osd1_height, MESON_CANVAS_WRAP_NONE, | |
f9a23481 | 322 | MESON_CANVAS_BLKMODE_LINEAR, 0); |
e88230a3 | 323 | |
bbbe775e | 324 | /* Enable OSD1 */ |
68679d41 NA |
325 | if (meson_crtc->enable_osd1) |
326 | meson_crtc->enable_osd1(priv); | |
bbbe775e NA |
327 | |
328 | priv->viu.osd1_commit = false; | |
329 | } | |
330 | ||
f9a23481 NA |
331 | /* Update the VD1 registers */ |
332 | if (priv->viu.vd1_enabled && priv->viu.vd1_commit) { | |
333 | ||
334 | switch (priv->viu.vd1_planes) { | |
335 | case 3: | |
2bf6b5b0 MJ |
336 | meson_canvas_config(priv->canvas, |
337 | priv->canvas_id_vd1_2, | |
338 | priv->viu.vd1_addr2, | |
339 | priv->viu.vd1_stride2, | |
340 | priv->viu.vd1_height2, | |
341 | MESON_CANVAS_WRAP_NONE, | |
342 | MESON_CANVAS_BLKMODE_LINEAR, | |
343 | MESON_CANVAS_ENDIAN_SWAP64); | |
f9a23481 NA |
344 | /* fallthrough */ |
345 | case 2: | |
2bf6b5b0 MJ |
346 | meson_canvas_config(priv->canvas, |
347 | priv->canvas_id_vd1_1, | |
348 | priv->viu.vd1_addr1, | |
349 | priv->viu.vd1_stride1, | |
350 | priv->viu.vd1_height1, | |
351 | MESON_CANVAS_WRAP_NONE, | |
352 | MESON_CANVAS_BLKMODE_LINEAR, | |
353 | MESON_CANVAS_ENDIAN_SWAP64); | |
f9a23481 NA |
354 | /* fallthrough */ |
355 | case 1: | |
2bf6b5b0 MJ |
356 | meson_canvas_config(priv->canvas, |
357 | priv->canvas_id_vd1_0, | |
358 | priv->viu.vd1_addr0, | |
359 | priv->viu.vd1_stride0, | |
360 | priv->viu.vd1_height0, | |
361 | MESON_CANVAS_WRAP_NONE, | |
362 | MESON_CANVAS_BLKMODE_LINEAR, | |
363 | MESON_CANVAS_ENDIAN_SWAP64); | |
f9a23481 NA |
364 | }; |
365 | ||
366 | writel_relaxed(priv->viu.vd1_if0_gen_reg, | |
68679d41 NA |
367 | priv->io_base + meson_crtc->viu_offset + |
368 | _REG(VD1_IF0_GEN_REG)); | |
f9a23481 | 369 | writel_relaxed(priv->viu.vd1_if0_gen_reg, |
68679d41 NA |
370 | priv->io_base + meson_crtc->viu_offset + |
371 | _REG(VD2_IF0_GEN_REG)); | |
f9a23481 | 372 | writel_relaxed(priv->viu.vd1_if0_gen_reg2, |
68679d41 NA |
373 | priv->io_base + meson_crtc->viu_offset + |
374 | _REG(VD1_IF0_GEN_REG2)); | |
f9a23481 | 375 | writel_relaxed(priv->viu.viu_vd1_fmt_ctrl, |
68679d41 NA |
376 | priv->io_base + meson_crtc->viu_offset + |
377 | _REG(VIU_VD1_FMT_CTRL)); | |
f9a23481 | 378 | writel_relaxed(priv->viu.viu_vd1_fmt_ctrl, |
68679d41 NA |
379 | priv->io_base + meson_crtc->viu_offset + |
380 | _REG(VIU_VD2_FMT_CTRL)); | |
f9a23481 | 381 | writel_relaxed(priv->viu.viu_vd1_fmt_w, |
68679d41 NA |
382 | priv->io_base + meson_crtc->viu_offset + |
383 | _REG(VIU_VD1_FMT_W)); | |
f9a23481 | 384 | writel_relaxed(priv->viu.viu_vd1_fmt_w, |
68679d41 NA |
385 | priv->io_base + meson_crtc->viu_offset + |
386 | _REG(VIU_VD2_FMT_W)); | |
f9a23481 | 387 | writel_relaxed(priv->viu.vd1_if0_canvas0, |
68679d41 NA |
388 | priv->io_base + meson_crtc->viu_offset + |
389 | _REG(VD1_IF0_CANVAS0)); | |
f9a23481 | 390 | writel_relaxed(priv->viu.vd1_if0_canvas0, |
68679d41 NA |
391 | priv->io_base + meson_crtc->viu_offset + |
392 | _REG(VD1_IF0_CANVAS1)); | |
f9a23481 | 393 | writel_relaxed(priv->viu.vd1_if0_canvas0, |
68679d41 NA |
394 | priv->io_base + meson_crtc->viu_offset + |
395 | _REG(VD2_IF0_CANVAS0)); | |
f9a23481 | 396 | writel_relaxed(priv->viu.vd1_if0_canvas0, |
68679d41 NA |
397 | priv->io_base + meson_crtc->viu_offset + |
398 | _REG(VD2_IF0_CANVAS1)); | |
f9a23481 | 399 | writel_relaxed(priv->viu.vd1_if0_luma_x0, |
68679d41 NA |
400 | priv->io_base + meson_crtc->viu_offset + |
401 | _REG(VD1_IF0_LUMA_X0)); | |
f9a23481 | 402 | writel_relaxed(priv->viu.vd1_if0_luma_x0, |
68679d41 NA |
403 | priv->io_base + meson_crtc->viu_offset + |
404 | _REG(VD1_IF0_LUMA_X1)); | |
f9a23481 | 405 | writel_relaxed(priv->viu.vd1_if0_luma_x0, |
68679d41 NA |
406 | priv->io_base + meson_crtc->viu_offset + |
407 | _REG(VD2_IF0_LUMA_X0)); | |
f9a23481 | 408 | writel_relaxed(priv->viu.vd1_if0_luma_x0, |
68679d41 NA |
409 | priv->io_base + meson_crtc->viu_offset + |
410 | _REG(VD2_IF0_LUMA_X1)); | |
f9a23481 | 411 | writel_relaxed(priv->viu.vd1_if0_luma_y0, |
68679d41 NA |
412 | priv->io_base + meson_crtc->viu_offset + |
413 | _REG(VD1_IF0_LUMA_Y0)); | |
f9a23481 | 414 | writel_relaxed(priv->viu.vd1_if0_luma_y0, |
68679d41 NA |
415 | priv->io_base + meson_crtc->viu_offset + |
416 | _REG(VD1_IF0_LUMA_Y1)); | |
f9a23481 | 417 | writel_relaxed(priv->viu.vd1_if0_luma_y0, |
68679d41 NA |
418 | priv->io_base + meson_crtc->viu_offset + |
419 | _REG(VD2_IF0_LUMA_Y0)); | |
f9a23481 | 420 | writel_relaxed(priv->viu.vd1_if0_luma_y0, |
68679d41 NA |
421 | priv->io_base + meson_crtc->viu_offset + |
422 | _REG(VD2_IF0_LUMA_Y1)); | |
f9a23481 | 423 | writel_relaxed(priv->viu.vd1_if0_chroma_x0, |
68679d41 NA |
424 | priv->io_base + meson_crtc->viu_offset + |
425 | _REG(VD1_IF0_CHROMA_X0)); | |
f9a23481 | 426 | writel_relaxed(priv->viu.vd1_if0_chroma_x0, |
68679d41 NA |
427 | priv->io_base + meson_crtc->viu_offset + |
428 | _REG(VD1_IF0_CHROMA_X1)); | |
f9a23481 | 429 | writel_relaxed(priv->viu.vd1_if0_chroma_x0, |
68679d41 NA |
430 | priv->io_base + meson_crtc->viu_offset + |
431 | _REG(VD2_IF0_CHROMA_X0)); | |
f9a23481 | 432 | writel_relaxed(priv->viu.vd1_if0_chroma_x0, |
68679d41 NA |
433 | priv->io_base + meson_crtc->viu_offset + |
434 | _REG(VD2_IF0_CHROMA_X1)); | |
f9a23481 | 435 | writel_relaxed(priv->viu.vd1_if0_chroma_y0, |
68679d41 NA |
436 | priv->io_base + meson_crtc->viu_offset + |
437 | _REG(VD1_IF0_CHROMA_Y0)); | |
f9a23481 | 438 | writel_relaxed(priv->viu.vd1_if0_chroma_y0, |
68679d41 NA |
439 | priv->io_base + meson_crtc->viu_offset + |
440 | _REG(VD1_IF0_CHROMA_Y1)); | |
f9a23481 | 441 | writel_relaxed(priv->viu.vd1_if0_chroma_y0, |
68679d41 NA |
442 | priv->io_base + meson_crtc->viu_offset + |
443 | _REG(VD2_IF0_CHROMA_Y0)); | |
f9a23481 | 444 | writel_relaxed(priv->viu.vd1_if0_chroma_y0, |
68679d41 NA |
445 | priv->io_base + meson_crtc->viu_offset + |
446 | _REG(VD2_IF0_CHROMA_Y1)); | |
f9a23481 | 447 | writel_relaxed(priv->viu.vd1_if0_repeat_loop, |
68679d41 NA |
448 | priv->io_base + meson_crtc->viu_offset + |
449 | _REG(VD1_IF0_RPT_LOOP)); | |
f9a23481 | 450 | writel_relaxed(priv->viu.vd1_if0_repeat_loop, |
68679d41 NA |
451 | priv->io_base + meson_crtc->viu_offset + |
452 | _REG(VD2_IF0_RPT_LOOP)); | |
f9a23481 | 453 | writel_relaxed(priv->viu.vd1_if0_luma0_rpt_pat, |
68679d41 NA |
454 | priv->io_base + meson_crtc->viu_offset + |
455 | _REG(VD1_IF0_LUMA0_RPT_PAT)); | |
f9a23481 | 456 | writel_relaxed(priv->viu.vd1_if0_luma0_rpt_pat, |
68679d41 NA |
457 | priv->io_base + meson_crtc->viu_offset + |
458 | _REG(VD2_IF0_LUMA0_RPT_PAT)); | |
f9a23481 | 459 | writel_relaxed(priv->viu.vd1_if0_luma0_rpt_pat, |
68679d41 NA |
460 | priv->io_base + meson_crtc->viu_offset + |
461 | _REG(VD1_IF0_LUMA1_RPT_PAT)); | |
f9a23481 | 462 | writel_relaxed(priv->viu.vd1_if0_luma0_rpt_pat, |
68679d41 NA |
463 | priv->io_base + meson_crtc->viu_offset + |
464 | _REG(VD2_IF0_LUMA1_RPT_PAT)); | |
f9a23481 | 465 | writel_relaxed(priv->viu.vd1_if0_chroma0_rpt_pat, |
68679d41 NA |
466 | priv->io_base + meson_crtc->viu_offset + |
467 | _REG(VD1_IF0_CHROMA0_RPT_PAT)); | |
f9a23481 | 468 | writel_relaxed(priv->viu.vd1_if0_chroma0_rpt_pat, |
68679d41 NA |
469 | priv->io_base + meson_crtc->viu_offset + |
470 | _REG(VD2_IF0_CHROMA0_RPT_PAT)); | |
f9a23481 | 471 | writel_relaxed(priv->viu.vd1_if0_chroma0_rpt_pat, |
68679d41 NA |
472 | priv->io_base + meson_crtc->viu_offset + |
473 | _REG(VD1_IF0_CHROMA1_RPT_PAT)); | |
f9a23481 | 474 | writel_relaxed(priv->viu.vd1_if0_chroma0_rpt_pat, |
68679d41 NA |
475 | priv->io_base + meson_crtc->viu_offset + |
476 | _REG(VD2_IF0_CHROMA1_RPT_PAT)); | |
477 | writel_relaxed(0, priv->io_base + meson_crtc->viu_offset + | |
478 | _REG(VD1_IF0_LUMA_PSEL)); | |
479 | writel_relaxed(0, priv->io_base + meson_crtc->viu_offset + | |
480 | _REG(VD1_IF0_CHROMA_PSEL)); | |
481 | writel_relaxed(0, priv->io_base + meson_crtc->viu_offset + | |
482 | _REG(VD2_IF0_LUMA_PSEL)); | |
483 | writel_relaxed(0, priv->io_base + meson_crtc->viu_offset + | |
484 | _REG(VD2_IF0_CHROMA_PSEL)); | |
f9a23481 | 485 | writel_relaxed(priv->viu.vd1_range_map_y, |
68679d41 NA |
486 | priv->io_base + meson_crtc->viu_offset + |
487 | _REG(VD1_IF0_RANGE_MAP_Y)); | |
f9a23481 | 488 | writel_relaxed(priv->viu.vd1_range_map_cb, |
68679d41 NA |
489 | priv->io_base + meson_crtc->viu_offset + |
490 | _REG(VD1_IF0_RANGE_MAP_CB)); | |
f9a23481 | 491 | writel_relaxed(priv->viu.vd1_range_map_cr, |
68679d41 NA |
492 | priv->io_base + meson_crtc->viu_offset + |
493 | _REG(VD1_IF0_RANGE_MAP_CR)); | |
f9a23481 NA |
494 | writel_relaxed(0x78404, |
495 | priv->io_base + _REG(VPP_SC_MISC)); | |
496 | writel_relaxed(priv->viu.vpp_pic_in_height, | |
497 | priv->io_base + _REG(VPP_PIC_IN_HEIGHT)); | |
498 | writel_relaxed(priv->viu.vpp_postblend_vd1_h_start_end, | |
499 | priv->io_base + _REG(VPP_POSTBLEND_VD1_H_START_END)); | |
500 | writel_relaxed(priv->viu.vpp_blend_vd2_h_start_end, | |
501 | priv->io_base + _REG(VPP_BLEND_VD2_H_START_END)); | |
502 | writel_relaxed(priv->viu.vpp_postblend_vd1_v_start_end, | |
503 | priv->io_base + _REG(VPP_POSTBLEND_VD1_V_START_END)); | |
504 | writel_relaxed(priv->viu.vpp_blend_vd2_v_start_end, | |
505 | priv->io_base + _REG(VPP_BLEND_VD2_V_START_END)); | |
506 | writel_relaxed(priv->viu.vpp_hsc_region12_startp, | |
507 | priv->io_base + _REG(VPP_HSC_REGION12_STARTP)); | |
508 | writel_relaxed(priv->viu.vpp_hsc_region34_startp, | |
509 | priv->io_base + _REG(VPP_HSC_REGION34_STARTP)); | |
510 | writel_relaxed(priv->viu.vpp_hsc_region4_endp, | |
511 | priv->io_base + _REG(VPP_HSC_REGION4_ENDP)); | |
512 | writel_relaxed(priv->viu.vpp_hsc_start_phase_step, | |
513 | priv->io_base + _REG(VPP_HSC_START_PHASE_STEP)); | |
514 | writel_relaxed(priv->viu.vpp_hsc_region1_phase_slope, | |
515 | priv->io_base + _REG(VPP_HSC_REGION1_PHASE_SLOPE)); | |
516 | writel_relaxed(priv->viu.vpp_hsc_region3_phase_slope, | |
517 | priv->io_base + _REG(VPP_HSC_REGION3_PHASE_SLOPE)); | |
518 | writel_relaxed(priv->viu.vpp_line_in_length, | |
519 | priv->io_base + _REG(VPP_LINE_IN_LENGTH)); | |
520 | writel_relaxed(priv->viu.vpp_preblend_h_size, | |
521 | priv->io_base + _REG(VPP_PREBLEND_H_SIZE)); | |
522 | writel_relaxed(priv->viu.vpp_vsc_region12_startp, | |
523 | priv->io_base + _REG(VPP_VSC_REGION12_STARTP)); | |
524 | writel_relaxed(priv->viu.vpp_vsc_region34_startp, | |
525 | priv->io_base + _REG(VPP_VSC_REGION34_STARTP)); | |
526 | writel_relaxed(priv->viu.vpp_vsc_region4_endp, | |
527 | priv->io_base + _REG(VPP_VSC_REGION4_ENDP)); | |
528 | writel_relaxed(priv->viu.vpp_vsc_start_phase_step, | |
529 | priv->io_base + _REG(VPP_VSC_START_PHASE_STEP)); | |
530 | writel_relaxed(priv->viu.vpp_vsc_ini_phase, | |
531 | priv->io_base + _REG(VPP_VSC_INI_PHASE)); | |
532 | writel_relaxed(priv->viu.vpp_vsc_phase_ctrl, | |
533 | priv->io_base + _REG(VPP_VSC_PHASE_CTRL)); | |
534 | writel_relaxed(priv->viu.vpp_hsc_phase_ctrl, | |
535 | priv->io_base + _REG(VPP_HSC_PHASE_CTRL)); | |
536 | writel_relaxed(0x42, priv->io_base + _REG(VPP_SCALE_COEF_IDX)); | |
537 | ||
538 | /* Enable VD1 */ | |
68679d41 NA |
539 | if (meson_crtc->enable_vd1) |
540 | meson_crtc->enable_vd1(priv); | |
f9a23481 NA |
541 | |
542 | priv->viu.vd1_commit = false; | |
543 | } | |
544 | ||
bbbe775e NA |
545 | drm_crtc_handle_vblank(priv->crtc); |
546 | ||
547 | spin_lock_irqsave(&priv->drm->event_lock, flags); | |
548 | if (meson_crtc->event) { | |
549 | drm_crtc_send_vblank_event(priv->crtc, meson_crtc->event); | |
550 | drm_crtc_vblank_put(priv->crtc); | |
551 | meson_crtc->event = NULL; | |
552 | } | |
553 | spin_unlock_irqrestore(&priv->drm->event_lock, flags); | |
554 | } | |
555 | ||
556 | int meson_crtc_create(struct meson_drm *priv) | |
557 | { | |
558 | struct meson_crtc *meson_crtc; | |
559 | struct drm_crtc *crtc; | |
560 | int ret; | |
561 | ||
562 | meson_crtc = devm_kzalloc(priv->drm->dev, sizeof(*meson_crtc), | |
563 | GFP_KERNEL); | |
564 | if (!meson_crtc) | |
565 | return -ENOMEM; | |
566 | ||
567 | meson_crtc->priv = priv; | |
568 | crtc = &meson_crtc->base; | |
569 | ret = drm_crtc_init_with_planes(priv->drm, crtc, | |
570 | priv->primary_plane, NULL, | |
571 | &meson_crtc_funcs, "meson_crtc"); | |
572 | if (ret) { | |
573 | dev_err(priv->drm->dev, "Failed to init CRTC\n"); | |
574 | return ret; | |
575 | } | |
576 | ||
68679d41 NA |
577 | if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu")) { |
578 | meson_crtc->enable_osd1 = meson_g12a_crtc_enable_osd1; | |
579 | meson_crtc->enable_vd1 = meson_g12a_crtc_enable_vd1; | |
580 | meson_crtc->viu_offset = MESON_G12A_VIU_OFFSET; | |
581 | drm_crtc_helper_add(crtc, &meson_g12a_crtc_helper_funcs); | |
582 | } else { | |
583 | meson_crtc->enable_osd1 = meson_crtc_enable_osd1; | |
584 | meson_crtc->enable_vd1 = meson_crtc_enable_vd1; | |
585 | drm_crtc_helper_add(crtc, &meson_crtc_helper_funcs); | |
586 | } | |
bbbe775e NA |
587 | |
588 | priv->crtc = crtc; | |
589 | ||
590 | return 0; | |
591 | } |