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
;
34 /* which mixer/encoder we route output to: */
40 uint32_t width
, height
;
42 /* next cursor to scan-out: */
44 struct drm_gem_object
*next_bo
;
46 /* current cursor being scanned out: */
47 struct drm_gem_object
*scanout_bo
;
51 /* if there is a pending flip, these will be non-null: */
52 struct drm_pending_vblank_event
*event
;
53 struct work_struct pageflip_work
;
55 /* the fb that we currently hold a scanout ref to: */
56 struct drm_framebuffer
*fb
;
58 /* for unref'ing framebuffers after scanout completes: */
59 struct drm_flip_work unref_fb_work
;
61 /* for unref'ing cursor bo's after scanout completes: */
62 struct drm_flip_work unref_cursor_work
;
64 struct mdp4_irq vblank
;
67 #define to_mdp4_crtc(x) container_of(x, struct mdp4_crtc, base)
69 static struct mdp4_kms
*get_kms(struct drm_crtc
*crtc
)
71 struct msm_drm_private
*priv
= crtc
->dev
->dev_private
;
72 return to_mdp4_kms(priv
->kms
);
75 static void update_fb(struct drm_crtc
*crtc
, bool async
,
76 struct drm_framebuffer
*new_fb
)
78 struct mdp4_crtc
*mdp4_crtc
= to_mdp4_crtc(crtc
);
79 struct drm_framebuffer
*old_fb
= mdp4_crtc
->fb
;
82 drm_flip_work_queue(&mdp4_crtc
->unref_fb_work
, old_fb
);
84 /* grab reference to incoming scanout fb: */
85 drm_framebuffer_reference(new_fb
);
86 mdp4_crtc
->base
.fb
= new_fb
;
87 mdp4_crtc
->fb
= new_fb
;
90 /* enable vblank to pick up the old_fb */
91 mdp4_irq_register(get_kms(crtc
), &mdp4_crtc
->vblank
);
95 static void complete_flip(struct drm_crtc
*crtc
, bool canceled
)
97 struct mdp4_crtc
*mdp4_crtc
= to_mdp4_crtc(crtc
);
98 struct drm_device
*dev
= crtc
->dev
;
99 struct drm_pending_vblank_event
*event
;
102 spin_lock_irqsave(&dev
->event_lock
, flags
);
103 event
= mdp4_crtc
->event
;
105 mdp4_crtc
->event
= NULL
;
107 event
->base
.destroy(&event
->base
);
109 drm_send_vblank_event(dev
, mdp4_crtc
->id
, event
);
111 spin_unlock_irqrestore(&dev
->event_lock
, flags
);
114 static void crtc_flush(struct drm_crtc
*crtc
)
116 struct mdp4_crtc
*mdp4_crtc
= to_mdp4_crtc(crtc
);
117 struct mdp4_kms
*mdp4_kms
= get_kms(crtc
);
120 flush
|= pipe2flush(mdp4_plane_pipe(mdp4_crtc
->plane
));
121 flush
|= ovlp2flush(mdp4_crtc
->ovlp
);
123 DBG("%s: flush=%08x", mdp4_crtc
->name
, flush
);
125 mdp4_write(mdp4_kms
, REG_MDP4_OVERLAY_FLUSH
, flush
);
128 static void pageflip_worker(struct work_struct
*work
)
130 struct mdp4_crtc
*mdp4_crtc
=
131 container_of(work
, struct mdp4_crtc
, pageflip_work
);
132 struct drm_crtc
*crtc
= &mdp4_crtc
->base
;
134 mdp4_plane_set_scanout(mdp4_crtc
->plane
, crtc
->fb
);
137 /* enable vblank to complete flip: */
138 mdp4_irq_register(get_kms(crtc
), &mdp4_crtc
->vblank
);
141 static void unref_fb_worker(struct drm_flip_work
*work
, void *val
)
143 struct mdp4_crtc
*mdp4_crtc
=
144 container_of(work
, struct mdp4_crtc
, unref_fb_work
);
145 struct drm_device
*dev
= mdp4_crtc
->base
.dev
;
147 mutex_lock(&dev
->mode_config
.mutex
);
148 drm_framebuffer_unreference(val
);
149 mutex_unlock(&dev
->mode_config
.mutex
);
152 static void unref_cursor_worker(struct drm_flip_work
*work
, void *val
)
154 struct mdp4_crtc
*mdp4_crtc
=
155 container_of(work
, struct mdp4_crtc
, unref_cursor_work
);
156 struct mdp4_kms
*mdp4_kms
= get_kms(&mdp4_crtc
->base
);
158 msm_gem_put_iova(val
, mdp4_kms
->id
);
159 drm_gem_object_unreference_unlocked(val
);
162 static void mdp4_crtc_destroy(struct drm_crtc
*crtc
)
164 struct mdp4_crtc
*mdp4_crtc
= to_mdp4_crtc(crtc
);
166 mdp4_crtc
->plane
->funcs
->destroy(mdp4_crtc
->plane
);
168 drm_crtc_cleanup(crtc
);
169 drm_flip_work_cleanup(&mdp4_crtc
->unref_fb_work
);
170 drm_flip_work_cleanup(&mdp4_crtc
->unref_cursor_work
);
175 static void mdp4_crtc_dpms(struct drm_crtc
*crtc
, int mode
)
177 struct mdp4_crtc
*mdp4_crtc
= to_mdp4_crtc(crtc
);
178 struct mdp4_kms
*mdp4_kms
= get_kms(crtc
);
179 bool enabled
= (mode
== DRM_MODE_DPMS_ON
);
181 DBG("%s: mode=%d", mdp4_crtc
->name
, mode
);
183 if (enabled
!= mdp4_crtc
->enabled
) {
185 mdp4_enable(mdp4_kms
);
186 mdp4_irq_register(mdp4_kms
, &mdp4_crtc
->err
);
188 mdp4_irq_unregister(mdp4_kms
, &mdp4_crtc
->err
);
189 mdp4_disable(mdp4_kms
);
191 mdp4_crtc
->enabled
= enabled
;
195 static bool mdp4_crtc_mode_fixup(struct drm_crtc
*crtc
,
196 const struct drm_display_mode
*mode
,
197 struct drm_display_mode
*adjusted_mode
)
202 static void blend_setup(struct drm_crtc
*crtc
)
204 struct mdp4_crtc
*mdp4_crtc
= to_mdp4_crtc(crtc
);
205 struct mdp4_kms
*mdp4_kms
= get_kms(crtc
);
206 int i
, ovlp
= mdp4_crtc
->ovlp
;
207 uint32_t mixer_cfg
= 0;
210 * This probably would also need to be triggered by any attached
211 * plane when it changes.. for now since we are only using a single
212 * private plane, the configuration is hard-coded:
215 mdp4_write(mdp4_kms
, REG_MDP4_OVLP_TRANSP_LOW0(ovlp
), 0);
216 mdp4_write(mdp4_kms
, REG_MDP4_OVLP_TRANSP_LOW1(ovlp
), 0);
217 mdp4_write(mdp4_kms
, REG_MDP4_OVLP_TRANSP_HIGH0(ovlp
), 0);
218 mdp4_write(mdp4_kms
, REG_MDP4_OVLP_TRANSP_HIGH1(ovlp
), 0);
220 for (i
= 0; i
< 4; i
++) {
221 mdp4_write(mdp4_kms
, REG_MDP4_OVLP_STAGE_FG_ALPHA(ovlp
, i
), 0);
222 mdp4_write(mdp4_kms
, REG_MDP4_OVLP_STAGE_BG_ALPHA(ovlp
, i
), 0);
223 mdp4_write(mdp4_kms
, REG_MDP4_OVLP_STAGE_OP(ovlp
, i
),
224 MDP4_OVLP_STAGE_OP_FG_ALPHA(FG_CONST
) |
225 MDP4_OVLP_STAGE_OP_BG_ALPHA(BG_CONST
));
226 mdp4_write(mdp4_kms
, REG_MDP4_OVLP_STAGE_CO3(ovlp
, i
), 0);
227 mdp4_write(mdp4_kms
, REG_MDP4_OVLP_STAGE_TRANSP_LOW0(ovlp
, i
), 0);
228 mdp4_write(mdp4_kms
, REG_MDP4_OVLP_STAGE_TRANSP_LOW1(ovlp
, i
), 0);
229 mdp4_write(mdp4_kms
, REG_MDP4_OVLP_STAGE_TRANSP_HIGH0(ovlp
, i
), 0);
230 mdp4_write(mdp4_kms
, REG_MDP4_OVLP_STAGE_TRANSP_HIGH1(ovlp
, i
), 0);
233 /* TODO single register for all CRTCs, so this won't work properly
234 * when multiple CRTCs are active..
236 switch (mdp4_plane_pipe(mdp4_crtc
->plane
)) {
238 mixer_cfg
= MDP4_LAYERMIXER_IN_CFG_PIPE0(STAGE_BASE
) |
239 COND(mdp4_crtc
->mixer
== 1, MDP4_LAYERMIXER_IN_CFG_PIPE0_MIXER1
);
242 mixer_cfg
= MDP4_LAYERMIXER_IN_CFG_PIPE1(STAGE_BASE
) |
243 COND(mdp4_crtc
->mixer
== 1, MDP4_LAYERMIXER_IN_CFG_PIPE1_MIXER1
);
246 mixer_cfg
= MDP4_LAYERMIXER_IN_CFG_PIPE2(STAGE_BASE
) |
247 COND(mdp4_crtc
->mixer
== 1, MDP4_LAYERMIXER_IN_CFG_PIPE2_MIXER1
);
250 mixer_cfg
= MDP4_LAYERMIXER_IN_CFG_PIPE3(STAGE_BASE
) |
251 COND(mdp4_crtc
->mixer
== 1, MDP4_LAYERMIXER_IN_CFG_PIPE3_MIXER1
);
254 mixer_cfg
= MDP4_LAYERMIXER_IN_CFG_PIPE4(STAGE_BASE
) |
255 COND(mdp4_crtc
->mixer
== 1, MDP4_LAYERMIXER_IN_CFG_PIPE4_MIXER1
);
258 mixer_cfg
= MDP4_LAYERMIXER_IN_CFG_PIPE5(STAGE_BASE
) |
259 COND(mdp4_crtc
->mixer
== 1, MDP4_LAYERMIXER_IN_CFG_PIPE5_MIXER1
);
262 mixer_cfg
= MDP4_LAYERMIXER_IN_CFG_PIPE6(STAGE_BASE
) |
263 COND(mdp4_crtc
->mixer
== 1, MDP4_LAYERMIXER_IN_CFG_PIPE6_MIXER1
);
266 WARN_ON("invalid pipe");
269 mdp4_write(mdp4_kms
, REG_MDP4_LAYERMIXER_IN_CFG
, mixer_cfg
);
272 static int mdp4_crtc_mode_set(struct drm_crtc
*crtc
,
273 struct drm_display_mode
*mode
,
274 struct drm_display_mode
*adjusted_mode
,
276 struct drm_framebuffer
*old_fb
)
278 struct mdp4_crtc
*mdp4_crtc
= to_mdp4_crtc(crtc
);
279 struct mdp4_kms
*mdp4_kms
= get_kms(crtc
);
280 enum mdp4_dma dma
= mdp4_crtc
->dma
;
281 int ret
, ovlp
= mdp4_crtc
->ovlp
;
283 mode
= adjusted_mode
;
285 DBG("%s: set mode: %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x",
286 mdp4_crtc
->name
, mode
->base
.id
, mode
->name
,
287 mode
->vrefresh
, mode
->clock
,
288 mode
->hdisplay
, mode
->hsync_start
,
289 mode
->hsync_end
, mode
->htotal
,
290 mode
->vdisplay
, mode
->vsync_start
,
291 mode
->vsync_end
, mode
->vtotal
,
292 mode
->type
, mode
->flags
);
294 mdp4_write(mdp4_kms
, REG_MDP4_DMA_SRC_SIZE(dma
),
295 MDP4_DMA_SRC_SIZE_WIDTH(mode
->hdisplay
) |
296 MDP4_DMA_SRC_SIZE_HEIGHT(mode
->vdisplay
));
298 /* take data from pipe: */
299 mdp4_write(mdp4_kms
, REG_MDP4_DMA_SRC_BASE(dma
), 0);
300 mdp4_write(mdp4_kms
, REG_MDP4_DMA_SRC_STRIDE(dma
),
301 crtc
->fb
->pitches
[0]);
302 mdp4_write(mdp4_kms
, REG_MDP4_DMA_DST_SIZE(dma
),
303 MDP4_DMA_DST_SIZE_WIDTH(0) |
304 MDP4_DMA_DST_SIZE_HEIGHT(0));
306 mdp4_write(mdp4_kms
, REG_MDP4_OVLP_BASE(ovlp
), 0);
307 mdp4_write(mdp4_kms
, REG_MDP4_OVLP_SIZE(ovlp
),
308 MDP4_OVLP_SIZE_WIDTH(mode
->hdisplay
) |
309 MDP4_OVLP_SIZE_HEIGHT(mode
->vdisplay
));
310 mdp4_write(mdp4_kms
, REG_MDP4_OVLP_STRIDE(ovlp
),
311 crtc
->fb
->pitches
[0]);
313 mdp4_write(mdp4_kms
, REG_MDP4_OVLP_CFG(ovlp
), 1);
315 update_fb(crtc
, false, crtc
->fb
);
317 ret
= mdp4_plane_mode_set(mdp4_crtc
->plane
, crtc
, crtc
->fb
,
318 0, 0, mode
->hdisplay
, mode
->vdisplay
,
320 mode
->hdisplay
<< 16, mode
->vdisplay
<< 16);
322 dev_err(crtc
->dev
->dev
, "%s: failed to set mode on plane: %d\n",
323 mdp4_crtc
->name
, ret
);
328 mdp4_write(mdp4_kms
, REG_MDP4_DMA_E_QUANT(0), 0x00ff0000);
329 mdp4_write(mdp4_kms
, REG_MDP4_DMA_E_QUANT(1), 0x00ff0000);
330 mdp4_write(mdp4_kms
, REG_MDP4_DMA_E_QUANT(2), 0x00ff0000);
336 static void mdp4_crtc_prepare(struct drm_crtc
*crtc
)
338 struct mdp4_crtc
*mdp4_crtc
= to_mdp4_crtc(crtc
);
339 DBG("%s", mdp4_crtc
->name
);
340 /* make sure we hold a ref to mdp clks while setting up mode: */
341 mdp4_enable(get_kms(crtc
));
342 mdp4_crtc_dpms(crtc
, DRM_MODE_DPMS_OFF
);
345 static void mdp4_crtc_commit(struct drm_crtc
*crtc
)
347 mdp4_crtc_dpms(crtc
, DRM_MODE_DPMS_ON
);
349 /* drop the ref to mdp clk's that we got in prepare: */
350 mdp4_disable(get_kms(crtc
));
353 static int mdp4_crtc_mode_set_base(struct drm_crtc
*crtc
, int x
, int y
,
354 struct drm_framebuffer
*old_fb
)
356 struct mdp4_crtc
*mdp4_crtc
= to_mdp4_crtc(crtc
);
357 struct drm_plane
*plane
= mdp4_crtc
->plane
;
358 struct drm_display_mode
*mode
= &crtc
->mode
;
360 update_fb(crtc
, false, crtc
->fb
);
362 return mdp4_plane_mode_set(plane
, crtc
, crtc
->fb
,
363 0, 0, mode
->hdisplay
, mode
->vdisplay
,
365 mode
->hdisplay
<< 16, mode
->vdisplay
<< 16);
368 static void mdp4_crtc_load_lut(struct drm_crtc
*crtc
)
372 static int mdp4_crtc_page_flip(struct drm_crtc
*crtc
,
373 struct drm_framebuffer
*new_fb
,
374 struct drm_pending_vblank_event
*event
,
375 uint32_t page_flip_flags
)
377 struct mdp4_crtc
*mdp4_crtc
= to_mdp4_crtc(crtc
);
378 struct drm_device
*dev
= crtc
->dev
;
379 struct drm_gem_object
*obj
;
381 if (mdp4_crtc
->event
) {
382 dev_err(dev
->dev
, "already pending flip!\n");
386 obj
= msm_framebuffer_bo(new_fb
, 0);
388 mdp4_crtc
->event
= event
;
389 update_fb(crtc
, true, new_fb
);
391 return msm_gem_queue_inactive_work(obj
,
392 &mdp4_crtc
->pageflip_work
);
395 static int mdp4_crtc_set_property(struct drm_crtc
*crtc
,
396 struct drm_property
*property
, uint64_t val
)
402 #define CURSOR_WIDTH 64
403 #define CURSOR_HEIGHT 64
405 /* called from IRQ to update cursor related registers (if needed). The
406 * cursor registers, other than x/y position, appear not to be double
407 * buffered, and changing them other than from vblank seems to trigger
410 static void update_cursor(struct drm_crtc
*crtc
)
412 struct mdp4_crtc
*mdp4_crtc
= to_mdp4_crtc(crtc
);
413 enum mdp4_dma dma
= mdp4_crtc
->dma
;
416 spin_lock_irqsave(&mdp4_crtc
->cursor
.lock
, flags
);
417 if (mdp4_crtc
->cursor
.stale
) {
418 struct mdp4_kms
*mdp4_kms
= get_kms(crtc
);
419 struct drm_gem_object
*next_bo
= mdp4_crtc
->cursor
.next_bo
;
420 struct drm_gem_object
*prev_bo
= mdp4_crtc
->cursor
.scanout_bo
;
421 uint32_t iova
= mdp4_crtc
->cursor
.next_iova
;
424 /* take a obj ref + iova ref when we start scanning out: */
425 drm_gem_object_reference(next_bo
);
426 msm_gem_get_iova_locked(next_bo
, mdp4_kms
->id
, &iova
);
429 mdp4_write(mdp4_kms
, REG_MDP4_DMA_CURSOR_SIZE(dma
),
430 MDP4_DMA_CURSOR_SIZE_WIDTH(mdp4_crtc
->cursor
.width
) |
431 MDP4_DMA_CURSOR_SIZE_HEIGHT(mdp4_crtc
->cursor
.height
));
432 mdp4_write(mdp4_kms
, REG_MDP4_DMA_CURSOR_BASE(dma
), iova
);
433 mdp4_write(mdp4_kms
, REG_MDP4_DMA_CURSOR_BLEND_CONFIG(dma
),
434 MDP4_DMA_CURSOR_BLEND_CONFIG_FORMAT(CURSOR_ARGB
) |
435 MDP4_DMA_CURSOR_BLEND_CONFIG_CURSOR_EN
);
437 /* disable cursor: */
438 mdp4_write(mdp4_kms
, REG_MDP4_DMA_CURSOR_BASE(dma
), 0);
439 mdp4_write(mdp4_kms
, REG_MDP4_DMA_CURSOR_BLEND_CONFIG(dma
),
440 MDP4_DMA_CURSOR_BLEND_CONFIG_FORMAT(CURSOR_ARGB
));
443 /* and drop the iova ref + obj rev when done scanning out: */
445 drm_flip_work_queue(&mdp4_crtc
->unref_cursor_work
, prev_bo
);
447 mdp4_crtc
->cursor
.scanout_bo
= next_bo
;
448 mdp4_crtc
->cursor
.stale
= false;
450 spin_unlock_irqrestore(&mdp4_crtc
->cursor
.lock
, flags
);
453 static int mdp4_crtc_cursor_set(struct drm_crtc
*crtc
,
454 struct drm_file
*file_priv
, uint32_t handle
,
455 uint32_t width
, uint32_t height
)
457 struct mdp4_crtc
*mdp4_crtc
= to_mdp4_crtc(crtc
);
458 struct mdp4_kms
*mdp4_kms
= get_kms(crtc
);
459 struct drm_device
*dev
= crtc
->dev
;
460 struct drm_gem_object
*cursor_bo
, *old_bo
;
465 if ((width
> CURSOR_WIDTH
) || (height
> CURSOR_HEIGHT
)) {
466 dev_err(dev
->dev
, "bad cursor size: %dx%d\n", width
, height
);
471 cursor_bo
= drm_gem_object_lookup(dev
, file_priv
, handle
);
479 ret
= msm_gem_get_iova(cursor_bo
, mdp4_kms
->id
, &iova
);
486 spin_lock_irqsave(&mdp4_crtc
->cursor
.lock
, flags
);
487 old_bo
= mdp4_crtc
->cursor
.next_bo
;
488 mdp4_crtc
->cursor
.next_bo
= cursor_bo
;
489 mdp4_crtc
->cursor
.next_iova
= iova
;
490 mdp4_crtc
->cursor
.width
= width
;
491 mdp4_crtc
->cursor
.height
= height
;
492 mdp4_crtc
->cursor
.stale
= true;
493 spin_unlock_irqrestore(&mdp4_crtc
->cursor
.lock
, flags
);
496 /* drop our previous reference: */
497 msm_gem_put_iova(old_bo
, mdp4_kms
->id
);
498 drm_gem_object_unreference_unlocked(old_bo
);
504 drm_gem_object_unreference_unlocked(cursor_bo
);
508 static int mdp4_crtc_cursor_move(struct drm_crtc
*crtc
, int x
, int y
)
510 struct mdp4_crtc
*mdp4_crtc
= to_mdp4_crtc(crtc
);
511 struct mdp4_kms
*mdp4_kms
= get_kms(crtc
);
512 enum mdp4_dma dma
= mdp4_crtc
->dma
;
514 mdp4_write(mdp4_kms
, REG_MDP4_DMA_CURSOR_POS(dma
),
515 MDP4_DMA_CURSOR_POS_X(x
) |
516 MDP4_DMA_CURSOR_POS_Y(y
));
521 static const struct drm_crtc_funcs mdp4_crtc_funcs
= {
522 .set_config
= drm_crtc_helper_set_config
,
523 .destroy
= mdp4_crtc_destroy
,
524 .page_flip
= mdp4_crtc_page_flip
,
525 .set_property
= mdp4_crtc_set_property
,
526 .cursor_set
= mdp4_crtc_cursor_set
,
527 .cursor_move
= mdp4_crtc_cursor_move
,
530 static const struct drm_crtc_helper_funcs mdp4_crtc_helper_funcs
= {
531 .dpms
= mdp4_crtc_dpms
,
532 .mode_fixup
= mdp4_crtc_mode_fixup
,
533 .mode_set
= mdp4_crtc_mode_set
,
534 .prepare
= mdp4_crtc_prepare
,
535 .commit
= mdp4_crtc_commit
,
536 .mode_set_base
= mdp4_crtc_mode_set_base
,
537 .load_lut
= mdp4_crtc_load_lut
,
540 static void mdp4_crtc_vblank_irq(struct mdp4_irq
*irq
, uint32_t irqstatus
)
542 struct mdp4_crtc
*mdp4_crtc
= container_of(irq
, struct mdp4_crtc
, vblank
);
543 struct drm_crtc
*crtc
= &mdp4_crtc
->base
;
544 struct msm_drm_private
*priv
= crtc
->dev
->dev_private
;
547 complete_flip(crtc
, false);
548 mdp4_irq_unregister(get_kms(crtc
), &mdp4_crtc
->vblank
);
550 drm_flip_work_commit(&mdp4_crtc
->unref_fb_work
, priv
->wq
);
551 drm_flip_work_commit(&mdp4_crtc
->unref_cursor_work
, priv
->wq
);
554 static void mdp4_crtc_err_irq(struct mdp4_irq
*irq
, uint32_t irqstatus
)
556 struct mdp4_crtc
*mdp4_crtc
= container_of(irq
, struct mdp4_crtc
, err
);
557 struct drm_crtc
*crtc
= &mdp4_crtc
->base
;
558 DBG("%s: error: %08x", mdp4_crtc
->name
, irqstatus
);
562 uint32_t mdp4_crtc_vblank(struct drm_crtc
*crtc
)
564 struct mdp4_crtc
*mdp4_crtc
= to_mdp4_crtc(crtc
);
565 return mdp4_crtc
->vblank
.irqmask
;
568 void mdp4_crtc_cancel_pending_flip(struct drm_crtc
*crtc
)
570 complete_flip(crtc
, true);
573 /* set dma config, ie. the format the encoder wants. */
574 void mdp4_crtc_set_config(struct drm_crtc
*crtc
, uint32_t config
)
576 struct mdp4_crtc
*mdp4_crtc
= to_mdp4_crtc(crtc
);
577 struct mdp4_kms
*mdp4_kms
= get_kms(crtc
);
579 mdp4_write(mdp4_kms
, REG_MDP4_DMA_CONFIG(mdp4_crtc
->dma
), config
);
582 /* set interface for routing crtc->encoder: */
583 void mdp4_crtc_set_intf(struct drm_crtc
*crtc
, enum mdp4_intf intf
)
585 struct mdp4_crtc
*mdp4_crtc
= to_mdp4_crtc(crtc
);
586 struct mdp4_kms
*mdp4_kms
= get_kms(crtc
);
589 intf_sel
= mdp4_read(mdp4_kms
, REG_MDP4_DISP_INTF_SEL
);
591 switch (mdp4_crtc
->dma
) {
593 intf_sel
&= ~MDP4_DISP_INTF_SEL_PRIM__MASK
;
594 intf_sel
|= MDP4_DISP_INTF_SEL_PRIM(intf
);
597 intf_sel
&= ~MDP4_DISP_INTF_SEL_SEC__MASK
;
598 intf_sel
|= MDP4_DISP_INTF_SEL_SEC(intf
);
601 intf_sel
&= ~MDP4_DISP_INTF_SEL_EXT__MASK
;
602 intf_sel
|= MDP4_DISP_INTF_SEL_EXT(intf
);
606 if (intf
== INTF_DSI_VIDEO
) {
607 intf_sel
&= ~MDP4_DISP_INTF_SEL_DSI_CMD
;
608 intf_sel
|= MDP4_DISP_INTF_SEL_DSI_VIDEO
;
609 mdp4_crtc
->mixer
= 0;
610 } else if (intf
== INTF_DSI_CMD
) {
611 intf_sel
&= ~MDP4_DISP_INTF_SEL_DSI_VIDEO
;
612 intf_sel
|= MDP4_DISP_INTF_SEL_DSI_CMD
;
613 mdp4_crtc
->mixer
= 0;
614 } else if (intf
== INTF_LCDC_DTV
){
615 mdp4_crtc
->mixer
= 1;
620 DBG("%s: intf_sel=%08x", mdp4_crtc
->name
, intf_sel
);
622 mdp4_write(mdp4_kms
, REG_MDP4_DISP_INTF_SEL
, intf_sel
);
625 static const char *dma_names
[] = {
626 "DMA_P", "DMA_S", "DMA_E",
629 /* initialize crtc */
630 struct drm_crtc
*mdp4_crtc_init(struct drm_device
*dev
,
631 struct drm_plane
*plane
, int id
, int ovlp_id
,
632 enum mdp4_dma dma_id
)
634 struct drm_crtc
*crtc
= NULL
;
635 struct mdp4_crtc
*mdp4_crtc
;
638 mdp4_crtc
= kzalloc(sizeof(*mdp4_crtc
), GFP_KERNEL
);
644 crtc
= &mdp4_crtc
->base
;
646 mdp4_crtc
->plane
= plane
;
647 mdp4_crtc
->plane
->crtc
= crtc
;
649 mdp4_crtc
->ovlp
= ovlp_id
;
650 mdp4_crtc
->dma
= dma_id
;
652 mdp4_crtc
->vblank
.irqmask
= dma2irq(mdp4_crtc
->dma
);
653 mdp4_crtc
->vblank
.irq
= mdp4_crtc_vblank_irq
;
655 mdp4_crtc
->err
.irqmask
= dma2err(mdp4_crtc
->dma
);
656 mdp4_crtc
->err
.irq
= mdp4_crtc_err_irq
;
658 snprintf(mdp4_crtc
->name
, sizeof(mdp4_crtc
->name
), "%s:%d",
659 dma_names
[dma_id
], ovlp_id
);
661 spin_lock_init(&mdp4_crtc
->cursor
.lock
);
663 ret
= drm_flip_work_init(&mdp4_crtc
->unref_fb_work
, 16,
664 "unref fb", unref_fb_worker
);
668 ret
= drm_flip_work_init(&mdp4_crtc
->unref_cursor_work
, 64,
669 "unref cursor", unref_cursor_worker
);
671 INIT_WORK(&mdp4_crtc
->pageflip_work
, pageflip_worker
);
673 drm_crtc_init(dev
, crtc
, &mdp4_crtc_funcs
);
674 drm_crtc_helper_add(crtc
, &mdp4_crtc_helper_funcs
);
676 mdp4_plane_install_properties(mdp4_crtc
->plane
, &crtc
->base
);
682 mdp4_crtc_destroy(crtc
);