2 * Copyright (C) 2016 BayLibre, SAS
3 * Author: Neil Armstrong <narmstrong@baylibre.com>
4 * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
5 * Copyright (C) 2014 Endless Mobile
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 2 of the
10 * License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, see <http://www.gnu.org/licenses/>.
21 * Jasper St. Pierre <jstpierre@mecheye.net>
24 #include <linux/kernel.h>
25 #include <linux/module.h>
26 #include <linux/mutex.h>
27 #include <linux/platform_device.h>
28 #include <linux/bitfield.h>
30 #include <drm/drm_atomic.h>
31 #include <drm/drm_atomic_helper.h>
32 #include <drm/drm_flip_work.h>
33 #include <drm/drm_probe_helper.h>
35 #include "meson_crtc.h"
36 #include "meson_plane.h"
37 #include "meson_venc.h"
38 #include "meson_vpp.h"
39 #include "meson_viu.h"
40 #include "meson_canvas.h"
41 #include "meson_registers.h"
47 struct drm_pending_vblank_event
*event
;
48 struct meson_drm
*priv
;
50 #define to_meson_crtc(x) container_of(x, struct meson_crtc, base)
54 static int meson_crtc_enable_vblank(struct drm_crtc
*crtc
)
56 struct meson_crtc
*meson_crtc
= to_meson_crtc(crtc
);
57 struct meson_drm
*priv
= meson_crtc
->priv
;
59 meson_venc_enable_vsync(priv
);
64 static void meson_crtc_disable_vblank(struct drm_crtc
*crtc
)
66 struct meson_crtc
*meson_crtc
= to_meson_crtc(crtc
);
67 struct meson_drm
*priv
= meson_crtc
->priv
;
69 meson_venc_disable_vsync(priv
);
72 static const struct drm_crtc_funcs meson_crtc_funcs
= {
73 .atomic_destroy_state
= drm_atomic_helper_crtc_destroy_state
,
74 .atomic_duplicate_state
= drm_atomic_helper_crtc_duplicate_state
,
75 .destroy
= drm_crtc_cleanup
,
76 .page_flip
= drm_atomic_helper_page_flip
,
77 .reset
= drm_atomic_helper_crtc_reset
,
78 .set_config
= drm_atomic_helper_set_config
,
79 .enable_vblank
= meson_crtc_enable_vblank
,
80 .disable_vblank
= meson_crtc_disable_vblank
,
84 static void meson_crtc_atomic_enable(struct drm_crtc
*crtc
,
85 struct drm_crtc_state
*old_state
)
87 struct meson_crtc
*meson_crtc
= to_meson_crtc(crtc
);
88 struct drm_crtc_state
*crtc_state
= crtc
->state
;
89 struct meson_drm
*priv
= meson_crtc
->priv
;
91 DRM_DEBUG_DRIVER("\n");
94 DRM_ERROR("Invalid crtc_state\n");
98 /* Enable VPP Postblend */
99 writel(crtc_state
->mode
.hdisplay
,
100 priv
->io_base
+ _REG(VPP_POSTBLEND_H_SIZE
));
102 /* VD1 Preblend vertical start/end */
103 writel(FIELD_PREP(GENMASK(11, 0), 2303),
104 priv
->io_base
+ _REG(VPP_PREBLEND_VD1_V_START_END
));
106 writel_bits_relaxed(VPP_POSTBLEND_ENABLE
, VPP_POSTBLEND_ENABLE
,
107 priv
->io_base
+ _REG(VPP_MISC
));
109 drm_crtc_vblank_on(crtc
);
111 priv
->viu
.osd1_enabled
= true;
114 static void meson_crtc_atomic_disable(struct drm_crtc
*crtc
,
115 struct drm_crtc_state
*old_state
)
117 struct meson_crtc
*meson_crtc
= to_meson_crtc(crtc
);
118 struct meson_drm
*priv
= meson_crtc
->priv
;
120 DRM_DEBUG_DRIVER("\n");
122 drm_crtc_vblank_off(crtc
);
124 priv
->viu
.osd1_enabled
= false;
125 priv
->viu
.osd1_commit
= false;
127 priv
->viu
.vd1_enabled
= false;
128 priv
->viu
.vd1_commit
= false;
130 /* Disable VPP Postblend */
131 writel_bits_relaxed(VPP_OSD1_POSTBLEND
| VPP_VD1_POSTBLEND
|
132 VPP_VD1_PREBLEND
| VPP_POSTBLEND_ENABLE
, 0,
133 priv
->io_base
+ _REG(VPP_MISC
));
135 if (crtc
->state
->event
&& !crtc
->state
->active
) {
136 spin_lock_irq(&crtc
->dev
->event_lock
);
137 drm_crtc_send_vblank_event(crtc
, crtc
->state
->event
);
138 spin_unlock_irq(&crtc
->dev
->event_lock
);
140 crtc
->state
->event
= NULL
;
144 static void meson_crtc_atomic_begin(struct drm_crtc
*crtc
,
145 struct drm_crtc_state
*state
)
147 struct meson_crtc
*meson_crtc
= to_meson_crtc(crtc
);
150 if (crtc
->state
->event
) {
151 WARN_ON(drm_crtc_vblank_get(crtc
) != 0);
153 spin_lock_irqsave(&crtc
->dev
->event_lock
, flags
);
154 meson_crtc
->event
= crtc
->state
->event
;
155 spin_unlock_irqrestore(&crtc
->dev
->event_lock
, flags
);
156 crtc
->state
->event
= NULL
;
160 static void meson_crtc_atomic_flush(struct drm_crtc
*crtc
,
161 struct drm_crtc_state
*old_crtc_state
)
163 struct meson_crtc
*meson_crtc
= to_meson_crtc(crtc
);
164 struct meson_drm
*priv
= meson_crtc
->priv
;
166 priv
->viu
.osd1_commit
= true;
167 priv
->viu
.vd1_commit
= true;
170 static const struct drm_crtc_helper_funcs meson_crtc_helper_funcs
= {
171 .atomic_begin
= meson_crtc_atomic_begin
,
172 .atomic_flush
= meson_crtc_atomic_flush
,
173 .atomic_enable
= meson_crtc_atomic_enable
,
174 .atomic_disable
= meson_crtc_atomic_disable
,
177 void meson_crtc_irq(struct meson_drm
*priv
)
179 struct meson_crtc
*meson_crtc
= to_meson_crtc(priv
->crtc
);
182 /* Update the OSD registers */
183 if (priv
->viu
.osd1_enabled
&& priv
->viu
.osd1_commit
) {
184 writel_relaxed(priv
->viu
.osd1_ctrl_stat
,
185 priv
->io_base
+ _REG(VIU_OSD1_CTRL_STAT
));
186 writel_relaxed(priv
->viu
.osd1_blk0_cfg
[0],
187 priv
->io_base
+ _REG(VIU_OSD1_BLK0_CFG_W0
));
188 writel_relaxed(priv
->viu
.osd1_blk0_cfg
[1],
189 priv
->io_base
+ _REG(VIU_OSD1_BLK0_CFG_W1
));
190 writel_relaxed(priv
->viu
.osd1_blk0_cfg
[2],
191 priv
->io_base
+ _REG(VIU_OSD1_BLK0_CFG_W2
));
192 writel_relaxed(priv
->viu
.osd1_blk0_cfg
[3],
193 priv
->io_base
+ _REG(VIU_OSD1_BLK0_CFG_W3
));
194 writel_relaxed(priv
->viu
.osd1_blk0_cfg
[4],
195 priv
->io_base
+ _REG(VIU_OSD1_BLK0_CFG_W4
));
196 writel_relaxed(priv
->viu
.osd_sc_ctrl0
,
197 priv
->io_base
+ _REG(VPP_OSD_SC_CTRL0
));
198 writel_relaxed(priv
->viu
.osd_sc_i_wh_m1
,
199 priv
->io_base
+ _REG(VPP_OSD_SCI_WH_M1
));
200 writel_relaxed(priv
->viu
.osd_sc_o_h_start_end
,
201 priv
->io_base
+ _REG(VPP_OSD_SCO_H_START_END
));
202 writel_relaxed(priv
->viu
.osd_sc_o_v_start_end
,
203 priv
->io_base
+ _REG(VPP_OSD_SCO_V_START_END
));
204 writel_relaxed(priv
->viu
.osd_sc_v_ini_phase
,
205 priv
->io_base
+ _REG(VPP_OSD_VSC_INI_PHASE
));
206 writel_relaxed(priv
->viu
.osd_sc_v_phase_step
,
207 priv
->io_base
+ _REG(VPP_OSD_VSC_PHASE_STEP
));
208 writel_relaxed(priv
->viu
.osd_sc_h_ini_phase
,
209 priv
->io_base
+ _REG(VPP_OSD_HSC_INI_PHASE
));
210 writel_relaxed(priv
->viu
.osd_sc_h_phase_step
,
211 priv
->io_base
+ _REG(VPP_OSD_HSC_PHASE_STEP
));
212 writel_relaxed(priv
->viu
.osd_sc_h_ctrl0
,
213 priv
->io_base
+ _REG(VPP_OSD_HSC_CTRL0
));
214 writel_relaxed(priv
->viu
.osd_sc_v_ctrl0
,
215 priv
->io_base
+ _REG(VPP_OSD_VSC_CTRL0
));
218 meson_canvas_config(priv
->canvas
, priv
->canvas_id_osd1
,
219 priv
->viu
.osd1_addr
, priv
->viu
.osd1_stride
,
220 priv
->viu
.osd1_height
, MESON_CANVAS_WRAP_NONE
,
221 MESON_CANVAS_BLKMODE_LINEAR
, 0);
223 meson_canvas_setup(priv
, MESON_CANVAS_ID_OSD1
,
224 priv
->viu
.osd1_addr
, priv
->viu
.osd1_stride
,
225 priv
->viu
.osd1_height
, MESON_CANVAS_WRAP_NONE
,
226 MESON_CANVAS_BLKMODE_LINEAR
, 0);
229 writel_bits_relaxed(VPP_OSD1_POSTBLEND
, VPP_OSD1_POSTBLEND
,
230 priv
->io_base
+ _REG(VPP_MISC
));
232 priv
->viu
.osd1_commit
= false;
235 /* Update the VD1 registers */
236 if (priv
->viu
.vd1_enabled
&& priv
->viu
.vd1_commit
) {
238 switch (priv
->viu
.vd1_planes
) {
241 meson_canvas_config(priv
->canvas
,
242 priv
->canvas_id_vd1_2
,
244 priv
->viu
.vd1_stride2
,
245 priv
->viu
.vd1_height2
,
246 MESON_CANVAS_WRAP_NONE
,
247 MESON_CANVAS_BLKMODE_LINEAR
,
248 MESON_CANVAS_ENDIAN_SWAP64
);
250 meson_canvas_setup(priv
, MESON_CANVAS_ID_VD1_2
,
252 priv
->viu
.vd1_stride2
,
253 priv
->viu
.vd1_height2
,
254 MESON_CANVAS_WRAP_NONE
,
255 MESON_CANVAS_BLKMODE_LINEAR
,
256 MESON_CANVAS_ENDIAN_SWAP64
);
260 meson_canvas_config(priv
->canvas
,
261 priv
->canvas_id_vd1_1
,
263 priv
->viu
.vd1_stride1
,
264 priv
->viu
.vd1_height1
,
265 MESON_CANVAS_WRAP_NONE
,
266 MESON_CANVAS_BLKMODE_LINEAR
,
267 MESON_CANVAS_ENDIAN_SWAP64
);
269 meson_canvas_setup(priv
, MESON_CANVAS_ID_VD1_1
,
271 priv
->viu
.vd1_stride2
,
272 priv
->viu
.vd1_height2
,
273 MESON_CANVAS_WRAP_NONE
,
274 MESON_CANVAS_BLKMODE_LINEAR
,
275 MESON_CANVAS_ENDIAN_SWAP64
);
279 meson_canvas_config(priv
->canvas
,
280 priv
->canvas_id_vd1_0
,
282 priv
->viu
.vd1_stride0
,
283 priv
->viu
.vd1_height0
,
284 MESON_CANVAS_WRAP_NONE
,
285 MESON_CANVAS_BLKMODE_LINEAR
,
286 MESON_CANVAS_ENDIAN_SWAP64
);
288 meson_canvas_setup(priv
, MESON_CANVAS_ID_VD1_0
,
290 priv
->viu
.vd1_stride2
,
291 priv
->viu
.vd1_height2
,
292 MESON_CANVAS_WRAP_NONE
,
293 MESON_CANVAS_BLKMODE_LINEAR
,
294 MESON_CANVAS_ENDIAN_SWAP64
);
297 writel_relaxed(priv
->viu
.vd1_if0_gen_reg
,
298 priv
->io_base
+ _REG(VD1_IF0_GEN_REG
));
299 writel_relaxed(priv
->viu
.vd1_if0_gen_reg
,
300 priv
->io_base
+ _REG(VD2_IF0_GEN_REG
));
301 writel_relaxed(priv
->viu
.vd1_if0_gen_reg2
,
302 priv
->io_base
+ _REG(VD1_IF0_GEN_REG2
));
303 writel_relaxed(priv
->viu
.viu_vd1_fmt_ctrl
,
304 priv
->io_base
+ _REG(VIU_VD1_FMT_CTRL
));
305 writel_relaxed(priv
->viu
.viu_vd1_fmt_ctrl
,
306 priv
->io_base
+ _REG(VIU_VD2_FMT_CTRL
));
307 writel_relaxed(priv
->viu
.viu_vd1_fmt_w
,
308 priv
->io_base
+ _REG(VIU_VD1_FMT_W
));
309 writel_relaxed(priv
->viu
.viu_vd1_fmt_w
,
310 priv
->io_base
+ _REG(VIU_VD2_FMT_W
));
311 writel_relaxed(priv
->viu
.vd1_if0_canvas0
,
312 priv
->io_base
+ _REG(VD1_IF0_CANVAS0
));
313 writel_relaxed(priv
->viu
.vd1_if0_canvas0
,
314 priv
->io_base
+ _REG(VD1_IF0_CANVAS1
));
315 writel_relaxed(priv
->viu
.vd1_if0_canvas0
,
316 priv
->io_base
+ _REG(VD2_IF0_CANVAS0
));
317 writel_relaxed(priv
->viu
.vd1_if0_canvas0
,
318 priv
->io_base
+ _REG(VD2_IF0_CANVAS1
));
319 writel_relaxed(priv
->viu
.vd1_if0_luma_x0
,
320 priv
->io_base
+ _REG(VD1_IF0_LUMA_X0
));
321 writel_relaxed(priv
->viu
.vd1_if0_luma_x0
,
322 priv
->io_base
+ _REG(VD1_IF0_LUMA_X1
));
323 writel_relaxed(priv
->viu
.vd1_if0_luma_x0
,
324 priv
->io_base
+ _REG(VD2_IF0_LUMA_X0
));
325 writel_relaxed(priv
->viu
.vd1_if0_luma_x0
,
326 priv
->io_base
+ _REG(VD2_IF0_LUMA_X1
));
327 writel_relaxed(priv
->viu
.vd1_if0_luma_y0
,
328 priv
->io_base
+ _REG(VD1_IF0_LUMA_Y0
));
329 writel_relaxed(priv
->viu
.vd1_if0_luma_y0
,
330 priv
->io_base
+ _REG(VD1_IF0_LUMA_Y1
));
331 writel_relaxed(priv
->viu
.vd1_if0_luma_y0
,
332 priv
->io_base
+ _REG(VD2_IF0_LUMA_Y0
));
333 writel_relaxed(priv
->viu
.vd1_if0_luma_y0
,
334 priv
->io_base
+ _REG(VD2_IF0_LUMA_Y1
));
335 writel_relaxed(priv
->viu
.vd1_if0_chroma_x0
,
336 priv
->io_base
+ _REG(VD1_IF0_CHROMA_X0
));
337 writel_relaxed(priv
->viu
.vd1_if0_chroma_x0
,
338 priv
->io_base
+ _REG(VD1_IF0_CHROMA_X1
));
339 writel_relaxed(priv
->viu
.vd1_if0_chroma_x0
,
340 priv
->io_base
+ _REG(VD2_IF0_CHROMA_X0
));
341 writel_relaxed(priv
->viu
.vd1_if0_chroma_x0
,
342 priv
->io_base
+ _REG(VD2_IF0_CHROMA_X1
));
343 writel_relaxed(priv
->viu
.vd1_if0_chroma_y0
,
344 priv
->io_base
+ _REG(VD1_IF0_CHROMA_Y0
));
345 writel_relaxed(priv
->viu
.vd1_if0_chroma_y0
,
346 priv
->io_base
+ _REG(VD1_IF0_CHROMA_Y1
));
347 writel_relaxed(priv
->viu
.vd1_if0_chroma_y0
,
348 priv
->io_base
+ _REG(VD2_IF0_CHROMA_Y0
));
349 writel_relaxed(priv
->viu
.vd1_if0_chroma_y0
,
350 priv
->io_base
+ _REG(VD2_IF0_CHROMA_Y1
));
351 writel_relaxed(priv
->viu
.vd1_if0_repeat_loop
,
352 priv
->io_base
+ _REG(VD1_IF0_RPT_LOOP
));
353 writel_relaxed(priv
->viu
.vd1_if0_repeat_loop
,
354 priv
->io_base
+ _REG(VD2_IF0_RPT_LOOP
));
355 writel_relaxed(priv
->viu
.vd1_if0_luma0_rpt_pat
,
356 priv
->io_base
+ _REG(VD1_IF0_LUMA0_RPT_PAT
));
357 writel_relaxed(priv
->viu
.vd1_if0_luma0_rpt_pat
,
358 priv
->io_base
+ _REG(VD2_IF0_LUMA0_RPT_PAT
));
359 writel_relaxed(priv
->viu
.vd1_if0_luma0_rpt_pat
,
360 priv
->io_base
+ _REG(VD1_IF0_LUMA1_RPT_PAT
));
361 writel_relaxed(priv
->viu
.vd1_if0_luma0_rpt_pat
,
362 priv
->io_base
+ _REG(VD2_IF0_LUMA1_RPT_PAT
));
363 writel_relaxed(priv
->viu
.vd1_if0_chroma0_rpt_pat
,
364 priv
->io_base
+ _REG(VD1_IF0_CHROMA0_RPT_PAT
));
365 writel_relaxed(priv
->viu
.vd1_if0_chroma0_rpt_pat
,
366 priv
->io_base
+ _REG(VD2_IF0_CHROMA0_RPT_PAT
));
367 writel_relaxed(priv
->viu
.vd1_if0_chroma0_rpt_pat
,
368 priv
->io_base
+ _REG(VD1_IF0_CHROMA1_RPT_PAT
));
369 writel_relaxed(priv
->viu
.vd1_if0_chroma0_rpt_pat
,
370 priv
->io_base
+ _REG(VD2_IF0_CHROMA1_RPT_PAT
));
371 writel_relaxed(0, priv
->io_base
+ _REG(VD1_IF0_LUMA_PSEL
));
372 writel_relaxed(0, priv
->io_base
+ _REG(VD1_IF0_CHROMA_PSEL
));
373 writel_relaxed(0, priv
->io_base
+ _REG(VD2_IF0_LUMA_PSEL
));
374 writel_relaxed(0, priv
->io_base
+ _REG(VD2_IF0_CHROMA_PSEL
));
375 writel_relaxed(priv
->viu
.vd1_range_map_y
,
376 priv
->io_base
+ _REG(VD1_IF0_RANGE_MAP_Y
));
377 writel_relaxed(priv
->viu
.vd1_range_map_cb
,
378 priv
->io_base
+ _REG(VD1_IF0_RANGE_MAP_CB
));
379 writel_relaxed(priv
->viu
.vd1_range_map_cr
,
380 priv
->io_base
+ _REG(VD1_IF0_RANGE_MAP_CR
));
381 writel_relaxed(0x78404,
382 priv
->io_base
+ _REG(VPP_SC_MISC
));
383 writel_relaxed(priv
->viu
.vpp_pic_in_height
,
384 priv
->io_base
+ _REG(VPP_PIC_IN_HEIGHT
));
385 writel_relaxed(priv
->viu
.vpp_postblend_vd1_h_start_end
,
386 priv
->io_base
+ _REG(VPP_POSTBLEND_VD1_H_START_END
));
387 writel_relaxed(priv
->viu
.vpp_blend_vd2_h_start_end
,
388 priv
->io_base
+ _REG(VPP_BLEND_VD2_H_START_END
));
389 writel_relaxed(priv
->viu
.vpp_postblend_vd1_v_start_end
,
390 priv
->io_base
+ _REG(VPP_POSTBLEND_VD1_V_START_END
));
391 writel_relaxed(priv
->viu
.vpp_blend_vd2_v_start_end
,
392 priv
->io_base
+ _REG(VPP_BLEND_VD2_V_START_END
));
393 writel_relaxed(priv
->viu
.vpp_hsc_region12_startp
,
394 priv
->io_base
+ _REG(VPP_HSC_REGION12_STARTP
));
395 writel_relaxed(priv
->viu
.vpp_hsc_region34_startp
,
396 priv
->io_base
+ _REG(VPP_HSC_REGION34_STARTP
));
397 writel_relaxed(priv
->viu
.vpp_hsc_region4_endp
,
398 priv
->io_base
+ _REG(VPP_HSC_REGION4_ENDP
));
399 writel_relaxed(priv
->viu
.vpp_hsc_start_phase_step
,
400 priv
->io_base
+ _REG(VPP_HSC_START_PHASE_STEP
));
401 writel_relaxed(priv
->viu
.vpp_hsc_region1_phase_slope
,
402 priv
->io_base
+ _REG(VPP_HSC_REGION1_PHASE_SLOPE
));
403 writel_relaxed(priv
->viu
.vpp_hsc_region3_phase_slope
,
404 priv
->io_base
+ _REG(VPP_HSC_REGION3_PHASE_SLOPE
));
405 writel_relaxed(priv
->viu
.vpp_line_in_length
,
406 priv
->io_base
+ _REG(VPP_LINE_IN_LENGTH
));
407 writel_relaxed(priv
->viu
.vpp_preblend_h_size
,
408 priv
->io_base
+ _REG(VPP_PREBLEND_H_SIZE
));
409 writel_relaxed(priv
->viu
.vpp_vsc_region12_startp
,
410 priv
->io_base
+ _REG(VPP_VSC_REGION12_STARTP
));
411 writel_relaxed(priv
->viu
.vpp_vsc_region34_startp
,
412 priv
->io_base
+ _REG(VPP_VSC_REGION34_STARTP
));
413 writel_relaxed(priv
->viu
.vpp_vsc_region4_endp
,
414 priv
->io_base
+ _REG(VPP_VSC_REGION4_ENDP
));
415 writel_relaxed(priv
->viu
.vpp_vsc_start_phase_step
,
416 priv
->io_base
+ _REG(VPP_VSC_START_PHASE_STEP
));
417 writel_relaxed(priv
->viu
.vpp_vsc_ini_phase
,
418 priv
->io_base
+ _REG(VPP_VSC_INI_PHASE
));
419 writel_relaxed(priv
->viu
.vpp_vsc_phase_ctrl
,
420 priv
->io_base
+ _REG(VPP_VSC_PHASE_CTRL
));
421 writel_relaxed(priv
->viu
.vpp_hsc_phase_ctrl
,
422 priv
->io_base
+ _REG(VPP_HSC_PHASE_CTRL
));
423 writel_relaxed(0x42, priv
->io_base
+ _REG(VPP_SCALE_COEF_IDX
));
426 writel_bits_relaxed(VPP_VD1_PREBLEND
| VPP_VD1_POSTBLEND
|
427 VPP_COLOR_MNG_ENABLE
,
428 VPP_VD1_PREBLEND
| VPP_VD1_POSTBLEND
|
429 VPP_COLOR_MNG_ENABLE
,
430 priv
->io_base
+ _REG(VPP_MISC
));
432 priv
->viu
.vd1_commit
= false;
435 drm_crtc_handle_vblank(priv
->crtc
);
437 spin_lock_irqsave(&priv
->drm
->event_lock
, flags
);
438 if (meson_crtc
->event
) {
439 drm_crtc_send_vblank_event(priv
->crtc
, meson_crtc
->event
);
440 drm_crtc_vblank_put(priv
->crtc
);
441 meson_crtc
->event
= NULL
;
443 spin_unlock_irqrestore(&priv
->drm
->event_lock
, flags
);
446 int meson_crtc_create(struct meson_drm
*priv
)
448 struct meson_crtc
*meson_crtc
;
449 struct drm_crtc
*crtc
;
452 meson_crtc
= devm_kzalloc(priv
->drm
->dev
, sizeof(*meson_crtc
),
457 meson_crtc
->priv
= priv
;
458 crtc
= &meson_crtc
->base
;
459 ret
= drm_crtc_init_with_planes(priv
->drm
, crtc
,
460 priv
->primary_plane
, NULL
,
461 &meson_crtc_funcs
, "meson_crtc");
463 dev_err(priv
->drm
->dev
, "Failed to init CRTC\n");
467 drm_crtc_helper_add(crtc
, &meson_crtc_helper_funcs
);