2 * Copyright (C) 2013 Red Hat
3 * Author: Rob Clark <robdclark@gmail.com>
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 as published by
7 * the Free Software Foundation.
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * You should have received a copy of the GNU General Public License along with
15 * this program. If not, see <http://www.gnu.org/licenses/>.
20 #include <drm/drm_mode.h>
22 #include "drm_crtc_helper.h"
23 #include "drm_flip_work.h"
28 struct drm_plane
*plane
;
29 struct drm_plane
*planes
[8];
35 /* which mixer/encoder we route output to: */
41 uint32_t width
, height
;
44 /* next cursor to scan-out: */
46 struct drm_gem_object
*next_bo
;
48 /* current cursor being scanned out: */
49 struct drm_gem_object
*scanout_bo
;
53 /* if there is a pending flip, these will be non-null: */
54 struct drm_pending_vblank_event
*event
;
55 struct msm_fence_cb pageflip_cb
;
57 #define PENDING_CURSOR 0x1
58 #define PENDING_FLIP 0x2
61 /* the fb that we logically (from PoV of KMS API) hold a ref
62 * to. Which we may not yet be scanning out (we may still
63 * be scanning out previous in case of page_flip while waiting
64 * for gpu rendering to complete:
66 struct drm_framebuffer
*fb
;
68 /* the fb that we currently hold a scanout ref to: */
69 struct drm_framebuffer
*scanout_fb
;
71 /* for unref'ing framebuffers after scanout completes: */
72 struct drm_flip_work unref_fb_work
;
74 /* for unref'ing cursor bo's after scanout completes: */
75 struct drm_flip_work unref_cursor_work
;
77 struct mdp_irq vblank
;
80 #define to_mdp4_crtc(x) container_of(x, struct mdp4_crtc, base)
82 static struct mdp4_kms
*get_kms(struct drm_crtc
*crtc
)
84 struct msm_drm_private
*priv
= crtc
->dev
->dev_private
;
85 return to_mdp4_kms(to_mdp_kms(priv
->kms
));
88 static void request_pending(struct drm_crtc
*crtc
, uint32_t pending
)
90 struct mdp4_crtc
*mdp4_crtc
= to_mdp4_crtc(crtc
);
92 atomic_or(pending
, &mdp4_crtc
->pending
);
93 mdp_irq_register(&get_kms(crtc
)->base
, &mdp4_crtc
->vblank
);
96 static void crtc_flush(struct drm_crtc
*crtc
)
98 struct mdp4_crtc
*mdp4_crtc
= to_mdp4_crtc(crtc
);
99 struct mdp4_kms
*mdp4_kms
= get_kms(crtc
);
100 uint32_t i
, flush
= 0;
102 for (i
= 0; i
< ARRAY_SIZE(mdp4_crtc
->planes
); i
++) {
103 struct drm_plane
*plane
= mdp4_crtc
->planes
[i
];
105 enum mdp4_pipe pipe_id
= mdp4_plane_pipe(plane
);
106 flush
|= pipe2flush(pipe_id
);
109 flush
|= ovlp2flush(mdp4_crtc
->ovlp
);
111 DBG("%s: flush=%08x", mdp4_crtc
->name
, flush
);
113 mdp4_write(mdp4_kms
, REG_MDP4_OVERLAY_FLUSH
, flush
);
116 static void update_fb(struct drm_crtc
*crtc
, struct drm_framebuffer
*new_fb
)
118 struct mdp4_crtc
*mdp4_crtc
= to_mdp4_crtc(crtc
);
119 struct drm_framebuffer
*old_fb
= mdp4_crtc
->fb
;
121 /* grab reference to incoming scanout fb: */
122 drm_framebuffer_reference(new_fb
);
123 mdp4_crtc
->base
.fb
= new_fb
;
124 mdp4_crtc
->fb
= new_fb
;
127 drm_flip_work_queue(&mdp4_crtc
->unref_fb_work
, old_fb
);
130 /* unlike update_fb(), take a ref to the new scanout fb *before* updating
131 * plane, then call this. Needed to ensure we don't unref the buffer that
132 * is actually still being scanned out.
134 * Note that this whole thing goes away with atomic.. since we can defer
135 * calling into driver until rendering is done.
137 static void update_scanout(struct drm_crtc
*crtc
, struct drm_framebuffer
*fb
)
139 struct mdp4_crtc
*mdp4_crtc
= to_mdp4_crtc(crtc
);
141 /* flush updates, to make sure hw is updated to new scanout fb,
142 * so that we can safely queue unref to current fb (ie. next
143 * vblank we know hw is done w/ previous scanout_fb).
147 if (mdp4_crtc
->scanout_fb
)
148 drm_flip_work_queue(&mdp4_crtc
->unref_fb_work
,
149 mdp4_crtc
->scanout_fb
);
151 mdp4_crtc
->scanout_fb
= fb
;
153 /* enable vblank to complete flip: */
154 request_pending(crtc
, PENDING_FLIP
);
157 /* if file!=NULL, this is preclose potential cancel-flip path */
158 static void complete_flip(struct drm_crtc
*crtc
, struct drm_file
*file
)
160 struct mdp4_crtc
*mdp4_crtc
= to_mdp4_crtc(crtc
);
161 struct drm_device
*dev
= crtc
->dev
;
162 struct drm_pending_vblank_event
*event
;
165 spin_lock_irqsave(&dev
->event_lock
, flags
);
166 event
= mdp4_crtc
->event
;
168 /* if regular vblank case (!file) or if cancel-flip from
169 * preclose on file that requested flip, then send the
172 if (!file
|| (event
->base
.file_priv
== file
)) {
173 mdp4_crtc
->event
= NULL
;
174 drm_send_vblank_event(dev
, mdp4_crtc
->id
, event
);
177 spin_unlock_irqrestore(&dev
->event_lock
, flags
);
180 static void pageflip_cb(struct msm_fence_cb
*cb
)
182 struct mdp4_crtc
*mdp4_crtc
=
183 container_of(cb
, struct mdp4_crtc
, pageflip_cb
);
184 struct drm_crtc
*crtc
= &mdp4_crtc
->base
;
185 struct drm_framebuffer
*fb
= crtc
->fb
;
190 drm_framebuffer_reference(fb
);
191 mdp4_plane_set_scanout(mdp4_crtc
->plane
, fb
);
192 update_scanout(crtc
, fb
);
195 static void unref_fb_worker(struct drm_flip_work
*work
, void *val
)
197 struct mdp4_crtc
*mdp4_crtc
=
198 container_of(work
, struct mdp4_crtc
, unref_fb_work
);
199 struct drm_device
*dev
= mdp4_crtc
->base
.dev
;
201 mutex_lock(&dev
->mode_config
.mutex
);
202 drm_framebuffer_unreference(val
);
203 mutex_unlock(&dev
->mode_config
.mutex
);
206 static void unref_cursor_worker(struct drm_flip_work
*work
, void *val
)
208 struct mdp4_crtc
*mdp4_crtc
=
209 container_of(work
, struct mdp4_crtc
, unref_cursor_work
);
210 struct mdp4_kms
*mdp4_kms
= get_kms(&mdp4_crtc
->base
);
212 msm_gem_put_iova(val
, mdp4_kms
->id
);
213 drm_gem_object_unreference_unlocked(val
);
216 static void mdp4_crtc_destroy(struct drm_crtc
*crtc
)
218 struct mdp4_crtc
*mdp4_crtc
= to_mdp4_crtc(crtc
);
220 mdp4_crtc
->plane
->funcs
->destroy(mdp4_crtc
->plane
);
222 drm_crtc_cleanup(crtc
);
223 drm_flip_work_cleanup(&mdp4_crtc
->unref_fb_work
);
224 drm_flip_work_cleanup(&mdp4_crtc
->unref_cursor_work
);
229 static void mdp4_crtc_dpms(struct drm_crtc
*crtc
, int mode
)
231 struct mdp4_crtc
*mdp4_crtc
= to_mdp4_crtc(crtc
);
232 struct mdp4_kms
*mdp4_kms
= get_kms(crtc
);
233 bool enabled
= (mode
== DRM_MODE_DPMS_ON
);
235 DBG("%s: mode=%d", mdp4_crtc
->name
, mode
);
237 if (enabled
!= mdp4_crtc
->enabled
) {
239 mdp4_enable(mdp4_kms
);
240 mdp_irq_register(&mdp4_kms
->base
, &mdp4_crtc
->err
);
242 mdp_irq_unregister(&mdp4_kms
->base
, &mdp4_crtc
->err
);
243 mdp4_disable(mdp4_kms
);
245 mdp4_crtc
->enabled
= enabled
;
249 static bool mdp4_crtc_mode_fixup(struct drm_crtc
*crtc
,
250 const struct drm_display_mode
*mode
,
251 struct drm_display_mode
*adjusted_mode
)
256 static void blend_setup(struct drm_crtc
*crtc
)
258 struct mdp4_crtc
*mdp4_crtc
= to_mdp4_crtc(crtc
);
259 struct mdp4_kms
*mdp4_kms
= get_kms(crtc
);
260 int i
, ovlp
= mdp4_crtc
->ovlp
;
261 uint32_t mixer_cfg
= 0;
262 static const enum mdp_mixer_stage_id stages
[] = {
263 STAGE_BASE
, STAGE0
, STAGE1
, STAGE2
, STAGE3
,
265 /* statically (for now) map planes to mixer stage (z-order): */
266 static const int idxs
[] = {
276 bool alpha
[4]= { false, false, false, false };
278 mdp4_write(mdp4_kms
, REG_MDP4_OVLP_TRANSP_LOW0(ovlp
), 0);
279 mdp4_write(mdp4_kms
, REG_MDP4_OVLP_TRANSP_LOW1(ovlp
), 0);
280 mdp4_write(mdp4_kms
, REG_MDP4_OVLP_TRANSP_HIGH0(ovlp
), 0);
281 mdp4_write(mdp4_kms
, REG_MDP4_OVLP_TRANSP_HIGH1(ovlp
), 0);
283 /* TODO single register for all CRTCs, so this won't work properly
284 * when multiple CRTCs are active..
286 for (i
= 0; i
< ARRAY_SIZE(mdp4_crtc
->planes
); i
++) {
287 struct drm_plane
*plane
= mdp4_crtc
->planes
[i
];
289 enum mdp4_pipe pipe_id
= mdp4_plane_pipe(plane
);
290 int idx
= idxs
[pipe_id
];
292 const struct mdp_format
*format
=
293 to_mdp_format(msm_framebuffer_format(plane
->fb
));
294 alpha
[idx
-1] = format
->alpha_enable
;
296 mixer_cfg
|= mixercfg(mdp4_crtc
->mixer
, pipe_id
, stages
[idx
]);
300 /* this shouldn't happen.. and seems to cause underflow: */
303 for (i
= 0; i
< 4; i
++) {
307 op
= MDP4_OVLP_STAGE_OP_FG_ALPHA(FG_PIXEL
) |
308 MDP4_OVLP_STAGE_OP_BG_ALPHA(FG_PIXEL
) |
309 MDP4_OVLP_STAGE_OP_BG_INV_ALPHA
;
311 op
= MDP4_OVLP_STAGE_OP_FG_ALPHA(FG_CONST
) |
312 MDP4_OVLP_STAGE_OP_BG_ALPHA(BG_CONST
);
315 mdp4_write(mdp4_kms
, REG_MDP4_OVLP_STAGE_FG_ALPHA(ovlp
, i
), 0xff);
316 mdp4_write(mdp4_kms
, REG_MDP4_OVLP_STAGE_BG_ALPHA(ovlp
, i
), 0x00);
317 mdp4_write(mdp4_kms
, REG_MDP4_OVLP_STAGE_OP(ovlp
, i
), op
);
318 mdp4_write(mdp4_kms
, REG_MDP4_OVLP_STAGE_CO3(ovlp
, i
), 1);
319 mdp4_write(mdp4_kms
, REG_MDP4_OVLP_STAGE_TRANSP_LOW0(ovlp
, i
), 0);
320 mdp4_write(mdp4_kms
, REG_MDP4_OVLP_STAGE_TRANSP_LOW1(ovlp
, i
), 0);
321 mdp4_write(mdp4_kms
, REG_MDP4_OVLP_STAGE_TRANSP_HIGH0(ovlp
, i
), 0);
322 mdp4_write(mdp4_kms
, REG_MDP4_OVLP_STAGE_TRANSP_HIGH1(ovlp
, i
), 0);
325 mdp4_write(mdp4_kms
, REG_MDP4_LAYERMIXER_IN_CFG
, mixer_cfg
);
328 static int mdp4_crtc_mode_set(struct drm_crtc
*crtc
,
329 struct drm_display_mode
*mode
,
330 struct drm_display_mode
*adjusted_mode
,
332 struct drm_framebuffer
*old_fb
)
334 struct mdp4_crtc
*mdp4_crtc
= to_mdp4_crtc(crtc
);
335 struct mdp4_kms
*mdp4_kms
= get_kms(crtc
);
336 enum mdp4_dma dma
= mdp4_crtc
->dma
;
337 int ret
, ovlp
= mdp4_crtc
->ovlp
;
339 mode
= adjusted_mode
;
341 DBG("%s: set mode: %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x",
342 mdp4_crtc
->name
, mode
->base
.id
, mode
->name
,
343 mode
->vrefresh
, mode
->clock
,
344 mode
->hdisplay
, mode
->hsync_start
,
345 mode
->hsync_end
, mode
->htotal
,
346 mode
->vdisplay
, mode
->vsync_start
,
347 mode
->vsync_end
, mode
->vtotal
,
348 mode
->type
, mode
->flags
);
350 /* grab extra ref for update_scanout() */
351 drm_framebuffer_reference(crtc
->fb
);
353 ret
= mdp4_plane_mode_set(mdp4_crtc
->plane
, crtc
, crtc
->fb
,
354 0, 0, mode
->hdisplay
, mode
->vdisplay
,
356 mode
->hdisplay
<< 16, mode
->vdisplay
<< 16);
358 drm_framebuffer_unreference(crtc
->fb
);
359 dev_err(crtc
->dev
->dev
, "%s: failed to set mode on plane: %d\n",
360 mdp4_crtc
->name
, ret
);
364 mdp4_write(mdp4_kms
, REG_MDP4_DMA_SRC_SIZE(dma
),
365 MDP4_DMA_SRC_SIZE_WIDTH(mode
->hdisplay
) |
366 MDP4_DMA_SRC_SIZE_HEIGHT(mode
->vdisplay
));
368 /* take data from pipe: */
369 mdp4_write(mdp4_kms
, REG_MDP4_DMA_SRC_BASE(dma
), 0);
370 mdp4_write(mdp4_kms
, REG_MDP4_DMA_SRC_STRIDE(dma
),
371 crtc
->fb
->pitches
[0]);
372 mdp4_write(mdp4_kms
, REG_MDP4_DMA_DST_SIZE(dma
),
373 MDP4_DMA_DST_SIZE_WIDTH(0) |
374 MDP4_DMA_DST_SIZE_HEIGHT(0));
376 mdp4_write(mdp4_kms
, REG_MDP4_OVLP_BASE(ovlp
), 0);
377 mdp4_write(mdp4_kms
, REG_MDP4_OVLP_SIZE(ovlp
),
378 MDP4_OVLP_SIZE_WIDTH(mode
->hdisplay
) |
379 MDP4_OVLP_SIZE_HEIGHT(mode
->vdisplay
));
380 mdp4_write(mdp4_kms
, REG_MDP4_OVLP_STRIDE(ovlp
),
381 crtc
->fb
->pitches
[0]);
383 mdp4_write(mdp4_kms
, REG_MDP4_OVLP_CFG(ovlp
), 1);
386 mdp4_write(mdp4_kms
, REG_MDP4_DMA_E_QUANT(0), 0x00ff0000);
387 mdp4_write(mdp4_kms
, REG_MDP4_DMA_E_QUANT(1), 0x00ff0000);
388 mdp4_write(mdp4_kms
, REG_MDP4_DMA_E_QUANT(2), 0x00ff0000);
391 update_fb(crtc
, crtc
->fb
);
392 update_scanout(crtc
, crtc
->fb
);
397 static void mdp4_crtc_prepare(struct drm_crtc
*crtc
)
399 struct mdp4_crtc
*mdp4_crtc
= to_mdp4_crtc(crtc
);
400 DBG("%s", mdp4_crtc
->name
);
401 /* make sure we hold a ref to mdp clks while setting up mode: */
402 mdp4_enable(get_kms(crtc
));
403 mdp4_crtc_dpms(crtc
, DRM_MODE_DPMS_OFF
);
406 static void mdp4_crtc_commit(struct drm_crtc
*crtc
)
408 mdp4_crtc_dpms(crtc
, DRM_MODE_DPMS_ON
);
410 /* drop the ref to mdp clk's that we got in prepare: */
411 mdp4_disable(get_kms(crtc
));
414 static int mdp4_crtc_mode_set_base(struct drm_crtc
*crtc
, int x
, int y
,
415 struct drm_framebuffer
*old_fb
)
417 struct mdp4_crtc
*mdp4_crtc
= to_mdp4_crtc(crtc
);
418 struct drm_plane
*plane
= mdp4_crtc
->plane
;
419 struct drm_display_mode
*mode
= &crtc
->mode
;
422 /* grab extra ref for update_scanout() */
423 drm_framebuffer_reference(crtc
->fb
);
425 ret
= mdp4_plane_mode_set(plane
, crtc
, crtc
->fb
,
426 0, 0, mode
->hdisplay
, mode
->vdisplay
,
428 mode
->hdisplay
<< 16, mode
->vdisplay
<< 16);
430 drm_framebuffer_unreference(crtc
->fb
);
434 update_fb(crtc
, crtc
->fb
);
435 update_scanout(crtc
, crtc
->fb
);
440 static void mdp4_crtc_load_lut(struct drm_crtc
*crtc
)
444 static int mdp4_crtc_page_flip(struct drm_crtc
*crtc
,
445 struct drm_framebuffer
*new_fb
,
446 struct drm_pending_vblank_event
*event
,
447 uint32_t page_flip_flags
)
449 struct mdp4_crtc
*mdp4_crtc
= to_mdp4_crtc(crtc
);
450 struct drm_device
*dev
= crtc
->dev
;
451 struct drm_gem_object
*obj
;
454 if (mdp4_crtc
->event
) {
455 dev_err(dev
->dev
, "already pending flip!\n");
459 obj
= msm_framebuffer_bo(new_fb
, 0);
461 spin_lock_irqsave(&dev
->event_lock
, flags
);
462 mdp4_crtc
->event
= event
;
463 spin_unlock_irqrestore(&dev
->event_lock
, flags
);
465 update_fb(crtc
, new_fb
);
467 return msm_gem_queue_inactive_cb(obj
, &mdp4_crtc
->pageflip_cb
);
470 static int mdp4_crtc_set_property(struct drm_crtc
*crtc
,
471 struct drm_property
*property
, uint64_t val
)
477 #define CURSOR_WIDTH 64
478 #define CURSOR_HEIGHT 64
480 /* called from IRQ to update cursor related registers (if needed). The
481 * cursor registers, other than x/y position, appear not to be double
482 * buffered, and changing them other than from vblank seems to trigger
485 static void update_cursor(struct drm_crtc
*crtc
)
487 struct mdp4_crtc
*mdp4_crtc
= to_mdp4_crtc(crtc
);
488 struct mdp4_kms
*mdp4_kms
= get_kms(crtc
);
489 enum mdp4_dma dma
= mdp4_crtc
->dma
;
492 spin_lock_irqsave(&mdp4_crtc
->cursor
.lock
, flags
);
493 if (mdp4_crtc
->cursor
.stale
) {
494 struct drm_gem_object
*next_bo
= mdp4_crtc
->cursor
.next_bo
;
495 struct drm_gem_object
*prev_bo
= mdp4_crtc
->cursor
.scanout_bo
;
496 uint32_t iova
= mdp4_crtc
->cursor
.next_iova
;
499 /* take a obj ref + iova ref when we start scanning out: */
500 drm_gem_object_reference(next_bo
);
501 msm_gem_get_iova_locked(next_bo
, mdp4_kms
->id
, &iova
);
504 mdp4_write(mdp4_kms
, REG_MDP4_DMA_CURSOR_SIZE(dma
),
505 MDP4_DMA_CURSOR_SIZE_WIDTH(mdp4_crtc
->cursor
.width
) |
506 MDP4_DMA_CURSOR_SIZE_HEIGHT(mdp4_crtc
->cursor
.height
));
507 mdp4_write(mdp4_kms
, REG_MDP4_DMA_CURSOR_BASE(dma
), iova
);
508 mdp4_write(mdp4_kms
, REG_MDP4_DMA_CURSOR_BLEND_CONFIG(dma
),
509 MDP4_DMA_CURSOR_BLEND_CONFIG_FORMAT(CURSOR_ARGB
) |
510 MDP4_DMA_CURSOR_BLEND_CONFIG_CURSOR_EN
);
512 /* disable cursor: */
513 mdp4_write(mdp4_kms
, REG_MDP4_DMA_CURSOR_BASE(dma
), 0);
514 mdp4_write(mdp4_kms
, REG_MDP4_DMA_CURSOR_BLEND_CONFIG(dma
),
515 MDP4_DMA_CURSOR_BLEND_CONFIG_FORMAT(CURSOR_ARGB
));
518 /* and drop the iova ref + obj rev when done scanning out: */
520 drm_flip_work_queue(&mdp4_crtc
->unref_cursor_work
, prev_bo
);
522 mdp4_crtc
->cursor
.scanout_bo
= next_bo
;
523 mdp4_crtc
->cursor
.stale
= false;
526 mdp4_write(mdp4_kms
, REG_MDP4_DMA_CURSOR_POS(dma
),
527 MDP4_DMA_CURSOR_POS_X(mdp4_crtc
->cursor
.x
) |
528 MDP4_DMA_CURSOR_POS_Y(mdp4_crtc
->cursor
.y
));
530 spin_unlock_irqrestore(&mdp4_crtc
->cursor
.lock
, flags
);
533 static int mdp4_crtc_cursor_set(struct drm_crtc
*crtc
,
534 struct drm_file
*file_priv
, uint32_t handle
,
535 uint32_t width
, uint32_t height
)
537 struct mdp4_crtc
*mdp4_crtc
= to_mdp4_crtc(crtc
);
538 struct mdp4_kms
*mdp4_kms
= get_kms(crtc
);
539 struct drm_device
*dev
= crtc
->dev
;
540 struct drm_gem_object
*cursor_bo
, *old_bo
;
545 if ((width
> CURSOR_WIDTH
) || (height
> CURSOR_HEIGHT
)) {
546 dev_err(dev
->dev
, "bad cursor size: %dx%d\n", width
, height
);
551 cursor_bo
= drm_gem_object_lookup(dev
, file_priv
, handle
);
559 ret
= msm_gem_get_iova(cursor_bo
, mdp4_kms
->id
, &iova
);
566 spin_lock_irqsave(&mdp4_crtc
->cursor
.lock
, flags
);
567 old_bo
= mdp4_crtc
->cursor
.next_bo
;
568 mdp4_crtc
->cursor
.next_bo
= cursor_bo
;
569 mdp4_crtc
->cursor
.next_iova
= iova
;
570 mdp4_crtc
->cursor
.width
= width
;
571 mdp4_crtc
->cursor
.height
= height
;
572 mdp4_crtc
->cursor
.stale
= true;
573 spin_unlock_irqrestore(&mdp4_crtc
->cursor
.lock
, flags
);
576 /* drop our previous reference: */
577 msm_gem_put_iova(old_bo
, mdp4_kms
->id
);
578 drm_gem_object_unreference_unlocked(old_bo
);
582 request_pending(crtc
, PENDING_CURSOR
);
587 drm_gem_object_unreference_unlocked(cursor_bo
);
591 static int mdp4_crtc_cursor_move(struct drm_crtc
*crtc
, int x
, int y
)
593 struct mdp4_crtc
*mdp4_crtc
= to_mdp4_crtc(crtc
);
596 spin_lock_irqsave(&mdp4_crtc
->cursor
.lock
, flags
);
597 mdp4_crtc
->cursor
.x
= x
;
598 mdp4_crtc
->cursor
.y
= y
;
599 spin_unlock_irqrestore(&mdp4_crtc
->cursor
.lock
, flags
);
602 request_pending(crtc
, PENDING_CURSOR
);
607 static const struct drm_crtc_funcs mdp4_crtc_funcs
= {
608 .set_config
= drm_crtc_helper_set_config
,
609 .destroy
= mdp4_crtc_destroy
,
610 .page_flip
= mdp4_crtc_page_flip
,
611 .set_property
= mdp4_crtc_set_property
,
612 .cursor_set
= mdp4_crtc_cursor_set
,
613 .cursor_move
= mdp4_crtc_cursor_move
,
616 static const struct drm_crtc_helper_funcs mdp4_crtc_helper_funcs
= {
617 .dpms
= mdp4_crtc_dpms
,
618 .mode_fixup
= mdp4_crtc_mode_fixup
,
619 .mode_set
= mdp4_crtc_mode_set
,
620 .prepare
= mdp4_crtc_prepare
,
621 .commit
= mdp4_crtc_commit
,
622 .mode_set_base
= mdp4_crtc_mode_set_base
,
623 .load_lut
= mdp4_crtc_load_lut
,
626 static void mdp4_crtc_vblank_irq(struct mdp_irq
*irq
, uint32_t irqstatus
)
628 struct mdp4_crtc
*mdp4_crtc
= container_of(irq
, struct mdp4_crtc
, vblank
);
629 struct drm_crtc
*crtc
= &mdp4_crtc
->base
;
630 struct msm_drm_private
*priv
= crtc
->dev
->dev_private
;
633 mdp_irq_unregister(&get_kms(crtc
)->base
, &mdp4_crtc
->vblank
);
635 pending
= atomic_xchg(&mdp4_crtc
->pending
, 0);
637 if (pending
& PENDING_FLIP
) {
638 complete_flip(crtc
, NULL
);
639 drm_flip_work_commit(&mdp4_crtc
->unref_fb_work
, priv
->wq
);
642 if (pending
& PENDING_CURSOR
) {
644 drm_flip_work_commit(&mdp4_crtc
->unref_cursor_work
, priv
->wq
);
648 static void mdp4_crtc_err_irq(struct mdp_irq
*irq
, uint32_t irqstatus
)
650 struct mdp4_crtc
*mdp4_crtc
= container_of(irq
, struct mdp4_crtc
, err
);
651 struct drm_crtc
*crtc
= &mdp4_crtc
->base
;
652 DBG("%s: error: %08x", mdp4_crtc
->name
, irqstatus
);
656 uint32_t mdp4_crtc_vblank(struct drm_crtc
*crtc
)
658 struct mdp4_crtc
*mdp4_crtc
= to_mdp4_crtc(crtc
);
659 return mdp4_crtc
->vblank
.irqmask
;
662 void mdp4_crtc_cancel_pending_flip(struct drm_crtc
*crtc
, struct drm_file
*file
)
664 DBG("cancel: %p", file
);
665 complete_flip(crtc
, file
);
668 /* set dma config, ie. the format the encoder wants. */
669 void mdp4_crtc_set_config(struct drm_crtc
*crtc
, uint32_t config
)
671 struct mdp4_crtc
*mdp4_crtc
= to_mdp4_crtc(crtc
);
672 struct mdp4_kms
*mdp4_kms
= get_kms(crtc
);
674 mdp4_write(mdp4_kms
, REG_MDP4_DMA_CONFIG(mdp4_crtc
->dma
), config
);
677 /* set interface for routing crtc->encoder: */
678 void mdp4_crtc_set_intf(struct drm_crtc
*crtc
, enum mdp4_intf intf
)
680 struct mdp4_crtc
*mdp4_crtc
= to_mdp4_crtc(crtc
);
681 struct mdp4_kms
*mdp4_kms
= get_kms(crtc
);
684 intf_sel
= mdp4_read(mdp4_kms
, REG_MDP4_DISP_INTF_SEL
);
686 switch (mdp4_crtc
->dma
) {
688 intf_sel
&= ~MDP4_DISP_INTF_SEL_PRIM__MASK
;
689 intf_sel
|= MDP4_DISP_INTF_SEL_PRIM(intf
);
692 intf_sel
&= ~MDP4_DISP_INTF_SEL_SEC__MASK
;
693 intf_sel
|= MDP4_DISP_INTF_SEL_SEC(intf
);
696 intf_sel
&= ~MDP4_DISP_INTF_SEL_EXT__MASK
;
697 intf_sel
|= MDP4_DISP_INTF_SEL_EXT(intf
);
701 if (intf
== INTF_DSI_VIDEO
) {
702 intf_sel
&= ~MDP4_DISP_INTF_SEL_DSI_CMD
;
703 intf_sel
|= MDP4_DISP_INTF_SEL_DSI_VIDEO
;
704 mdp4_crtc
->mixer
= 0;
705 } else if (intf
== INTF_DSI_CMD
) {
706 intf_sel
&= ~MDP4_DISP_INTF_SEL_DSI_VIDEO
;
707 intf_sel
|= MDP4_DISP_INTF_SEL_DSI_CMD
;
708 mdp4_crtc
->mixer
= 0;
709 } else if (intf
== INTF_LCDC_DTV
){
710 mdp4_crtc
->mixer
= 1;
715 DBG("%s: intf_sel=%08x", mdp4_crtc
->name
, intf_sel
);
717 mdp4_write(mdp4_kms
, REG_MDP4_DISP_INTF_SEL
, intf_sel
);
720 static void set_attach(struct drm_crtc
*crtc
, enum mdp4_pipe pipe_id
,
721 struct drm_plane
*plane
)
723 struct mdp4_crtc
*mdp4_crtc
= to_mdp4_crtc(crtc
);
725 BUG_ON(pipe_id
>= ARRAY_SIZE(mdp4_crtc
->planes
));
727 if (mdp4_crtc
->planes
[pipe_id
] == plane
)
730 mdp4_crtc
->planes
[pipe_id
] = plane
;
732 if (mdp4_crtc
->enabled
&& (plane
!= mdp4_crtc
->plane
))
736 void mdp4_crtc_attach(struct drm_crtc
*crtc
, struct drm_plane
*plane
)
738 set_attach(crtc
, mdp4_plane_pipe(plane
), plane
);
741 void mdp4_crtc_detach(struct drm_crtc
*crtc
, struct drm_plane
*plane
)
743 set_attach(crtc
, mdp4_plane_pipe(plane
), NULL
);
746 static const char *dma_names
[] = {
747 "DMA_P", "DMA_S", "DMA_E",
750 /* initialize crtc */
751 struct drm_crtc
*mdp4_crtc_init(struct drm_device
*dev
,
752 struct drm_plane
*plane
, int id
, int ovlp_id
,
753 enum mdp4_dma dma_id
)
755 struct drm_crtc
*crtc
= NULL
;
756 struct mdp4_crtc
*mdp4_crtc
;
759 mdp4_crtc
= kzalloc(sizeof(*mdp4_crtc
), GFP_KERNEL
);
765 crtc
= &mdp4_crtc
->base
;
767 mdp4_crtc
->plane
= plane
;
770 mdp4_crtc
->ovlp
= ovlp_id
;
771 mdp4_crtc
->dma
= dma_id
;
773 mdp4_crtc
->vblank
.irqmask
= dma2irq(mdp4_crtc
->dma
);
774 mdp4_crtc
->vblank
.irq
= mdp4_crtc_vblank_irq
;
776 mdp4_crtc
->err
.irqmask
= dma2err(mdp4_crtc
->dma
);
777 mdp4_crtc
->err
.irq
= mdp4_crtc_err_irq
;
779 snprintf(mdp4_crtc
->name
, sizeof(mdp4_crtc
->name
), "%s:%d",
780 dma_names
[dma_id
], ovlp_id
);
782 spin_lock_init(&mdp4_crtc
->cursor
.lock
);
784 ret
= drm_flip_work_init(&mdp4_crtc
->unref_fb_work
, 16,
785 "unref fb", unref_fb_worker
);
789 ret
= drm_flip_work_init(&mdp4_crtc
->unref_cursor_work
, 64,
790 "unref cursor", unref_cursor_worker
);
792 INIT_FENCE_CB(&mdp4_crtc
->pageflip_cb
, pageflip_cb
);
794 drm_crtc_init(dev
, crtc
, &mdp4_crtc_funcs
);
795 drm_crtc_helper_add(crtc
, &mdp4_crtc_helper_funcs
);
797 mdp4_plane_install_properties(mdp4_crtc
->plane
, &crtc
->base
);
803 mdp4_crtc_destroy(crtc
);