Skip to content

Commit 7fbd5d7

Browse files
committed
Merge tag 'imx-drm-next-2019-02-22' of git://git.pengutronix.de/pza/linux into drm-next
drm/imx: handle pending updates better, add plane zpos property support - Add a mechanism to only send commit done events once all pending updates have been applied. This closes a small race window where already armed events could fire even though the double buffered hardware update just missed the update window. - Add plane zpos property support to allow placing the overlay plane behind the primary plane. - Allow building imx-drm on all platforms under COMPILE_TEST. Signed-off-by: Dave Airlie <airlied@redhat.com> From: Philipp Zabel <pza@pengutronix.de> Link: https://patchwork.freedesktop.org/patch/msgid/20190222112350.m3ucezilqx6cyest@pengutronix.de
2 parents fbac3c4 + a0ea4ff commit 7fbd5d7

File tree

9 files changed

+109
-33
lines changed

9 files changed

+109
-33
lines changed

drivers/gpu/drm/imx/Kconfig

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ config DRM_IMX
44
select VIDEOMODE_HELPERS
55
select DRM_GEM_CMA_HELPER
66
select DRM_KMS_CMA_HELPER
7-
depends on DRM && (ARCH_MXC || ARCH_MULTIPLATFORM)
7+
depends on DRM && (ARCH_MXC || ARCH_MULTIPLATFORM || COMPILE_TEST)
88
depends on IMX_IPUV3_CORE
99
help
1010
enable i.MX graphics support
@@ -18,6 +18,7 @@ config DRM_IMX_PARALLEL_DISPLAY
1818
config DRM_IMX_TVE
1919
tristate "Support for TV and VGA displays"
2020
depends on DRM_IMX
21+
depends on COMMON_CLK
2122
select REGMAP_MMIO
2223
help
2324
Choose this to enable the internal Television Encoder (TVe)

drivers/gpu/drm/imx/imx-drm-core.c

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,7 @@ static int imx_drm_atomic_check(struct drm_device *dev,
4949
{
5050
int ret;
5151

52-
ret = drm_atomic_helper_check_modeset(dev, state);
53-
if (ret)
54-
return ret;
55-
56-
ret = drm_atomic_helper_check_planes(dev, state);
52+
ret = drm_atomic_helper_check(dev, state);
5753
if (ret)
5854
return ret;
5955

@@ -229,6 +225,7 @@ static int imx_drm_bind(struct device *dev)
229225
drm->mode_config.funcs = &imx_drm_mode_config_funcs;
230226
drm->mode_config.helper_private = &imx_drm_mode_config_helpers;
231227
drm->mode_config.allow_fb_modifiers = true;
228+
drm->mode_config.normalize_zpos = true;
232229

233230
drm_mode_config_init(drm);
234231

drivers/gpu/drm/imx/ipuv3-crtc.c

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ struct ipu_crtc {
3434
struct ipu_dc *dc;
3535
struct ipu_di *di;
3636
int irq;
37+
struct drm_pending_vblank_event *event;
3738
};
3839

3940
static inline struct ipu_crtc *to_ipu_crtc(struct drm_crtc *crtc)
@@ -173,8 +174,31 @@ static const struct drm_crtc_funcs ipu_crtc_funcs = {
173174
static irqreturn_t ipu_irq_handler(int irq, void *dev_id)
174175
{
175176
struct ipu_crtc *ipu_crtc = dev_id;
177+
struct drm_crtc *crtc = &ipu_crtc->base;
178+
unsigned long flags;
179+
int i;
180+
181+
drm_crtc_handle_vblank(crtc);
182+
183+
if (ipu_crtc->event) {
184+
for (i = 0; i < ARRAY_SIZE(ipu_crtc->plane); i++) {
185+
struct ipu_plane *plane = ipu_crtc->plane[i];
176186

177-
drm_crtc_handle_vblank(&ipu_crtc->base);
187+
if (!plane)
188+
continue;
189+
190+
if (ipu_plane_atomic_update_pending(&plane->base))
191+
break;
192+
}
193+
194+
if (i == ARRAY_SIZE(ipu_crtc->plane)) {
195+
spin_lock_irqsave(&crtc->dev->event_lock, flags);
196+
drm_crtc_send_vblank_event(crtc, ipu_crtc->event);
197+
ipu_crtc->event = NULL;
198+
drm_crtc_vblank_put(crtc);
199+
spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
200+
}
201+
}
178202

179203
return IRQ_HANDLED;
180204
}
@@ -223,8 +247,10 @@ static void ipu_crtc_atomic_flush(struct drm_crtc *crtc,
223247
{
224248
spin_lock_irq(&crtc->dev->event_lock);
225249
if (crtc->state->event) {
250+
struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc);
251+
226252
WARN_ON(drm_crtc_vblank_get(crtc));
227-
drm_crtc_arm_vblank_event(crtc, crtc->state->event);
253+
ipu_crtc->event = crtc->state->event;
228254
crtc->state->event = NULL;
229255
}
230256
spin_unlock_irq(&crtc->dev->event_lock);

drivers/gpu/drm/imx/ipuv3-plane.c

Lines changed: 51 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,7 @@ static void ipu_plane_destroy(struct drm_plane *plane)
273273

274274
static void ipu_plane_state_reset(struct drm_plane *plane)
275275
{
276+
unsigned int zpos = (plane->type == DRM_PLANE_TYPE_PRIMARY) ? 0 : 1;
276277
struct ipu_plane_state *ipu_state;
277278

278279
if (plane->state) {
@@ -284,8 +285,11 @@ static void ipu_plane_state_reset(struct drm_plane *plane)
284285

285286
ipu_state = kzalloc(sizeof(*ipu_state), GFP_KERNEL);
286287

287-
if (ipu_state)
288+
if (ipu_state) {
288289
__drm_atomic_helper_plane_reset(plane, &ipu_state->base);
290+
ipu_state->base.zpos = zpos;
291+
ipu_state->base.normalized_zpos = zpos;
292+
}
289293
}
290294

291295
static struct drm_plane_state *
@@ -560,6 +564,25 @@ static void ipu_plane_atomic_update(struct drm_plane *plane,
560564
if (ipu_plane->dp_flow == IPU_DP_FLOW_SYNC_FG)
561565
ipu_dp_set_window_pos(ipu_plane->dp, dst->x1, dst->y1);
562566

567+
switch (ipu_plane->dp_flow) {
568+
case IPU_DP_FLOW_SYNC_BG:
569+
if (state->normalized_zpos == 1) {
570+
ipu_dp_set_global_alpha(ipu_plane->dp,
571+
!fb->format->has_alpha, 0xff,
572+
true);
573+
} else {
574+
ipu_dp_set_global_alpha(ipu_plane->dp, true, 0, true);
575+
}
576+
break;
577+
case IPU_DP_FLOW_SYNC_FG:
578+
if (state->normalized_zpos == 1) {
579+
ipu_dp_set_global_alpha(ipu_plane->dp,
580+
!fb->format->has_alpha, 0xff,
581+
false);
582+
}
583+
break;
584+
}
585+
563586
eba = drm_plane_state_to_eba(state, 0);
564587

565588
/*
@@ -582,6 +605,7 @@ static void ipu_plane_atomic_update(struct drm_plane *plane,
582605
active = ipu_idmac_get_current_buffer(ipu_plane->ipu_ch);
583606
ipu_cpmem_set_buffer(ipu_plane->ipu_ch, !active, eba);
584607
ipu_idmac_select_buffer(ipu_plane->ipu_ch, !active);
608+
ipu_plane->next_buf = !active;
585609
if (ipu_plane_separate_alpha(ipu_plane)) {
586610
active = ipu_idmac_get_current_buffer(ipu_plane->alpha_ch);
587611
ipu_cpmem_set_buffer(ipu_plane->alpha_ch, !active,
@@ -595,34 +619,11 @@ static void ipu_plane_atomic_update(struct drm_plane *plane,
595619
switch (ipu_plane->dp_flow) {
596620
case IPU_DP_FLOW_SYNC_BG:
597621
ipu_dp_setup_channel(ipu_plane->dp, ics, IPUV3_COLORSPACE_RGB);
598-
ipu_dp_set_global_alpha(ipu_plane->dp, true, 0, true);
599622
break;
600623
case IPU_DP_FLOW_SYNC_FG:
601624
ipu_dp_setup_channel(ipu_plane->dp, ics,
602625
IPUV3_COLORSPACE_UNKNOWN);
603-
/* Enable local alpha on partial plane */
604-
switch (fb->format->format) {
605-
case DRM_FORMAT_ARGB1555:
606-
case DRM_FORMAT_ABGR1555:
607-
case DRM_FORMAT_RGBA5551:
608-
case DRM_FORMAT_BGRA5551:
609-
case DRM_FORMAT_ARGB4444:
610-
case DRM_FORMAT_ARGB8888:
611-
case DRM_FORMAT_ABGR8888:
612-
case DRM_FORMAT_RGBA8888:
613-
case DRM_FORMAT_BGRA8888:
614-
case DRM_FORMAT_RGB565_A8:
615-
case DRM_FORMAT_BGR565_A8:
616-
case DRM_FORMAT_RGB888_A8:
617-
case DRM_FORMAT_BGR888_A8:
618-
case DRM_FORMAT_RGBX8888_A8:
619-
case DRM_FORMAT_BGRX8888_A8:
620-
ipu_dp_set_global_alpha(ipu_plane->dp, false, 0, false);
621-
break;
622-
default:
623-
ipu_dp_set_global_alpha(ipu_plane->dp, true, 0, true);
624-
break;
625-
}
626+
break;
626627
}
627628

628629
ipu_dmfc_config_wait4eot(ipu_plane->dmfc, drm_rect_width(dst));
@@ -709,6 +710,7 @@ static void ipu_plane_atomic_update(struct drm_plane *plane,
709710
ipu_cpmem_set_buffer(ipu_plane->ipu_ch, 1, eba);
710711
ipu_idmac_lock_enable(ipu_plane->ipu_ch, num_bursts);
711712
ipu_plane_enable(ipu_plane);
713+
ipu_plane->next_buf = -1;
712714
}
713715

714716
static const struct drm_plane_helper_funcs ipu_plane_helper_funcs = {
@@ -718,6 +720,24 @@ static const struct drm_plane_helper_funcs ipu_plane_helper_funcs = {
718720
.atomic_update = ipu_plane_atomic_update,
719721
};
720722

723+
bool ipu_plane_atomic_update_pending(struct drm_plane *plane)
724+
{
725+
struct ipu_plane *ipu_plane = to_ipu_plane(plane);
726+
struct drm_plane_state *state = plane->state;
727+
struct ipu_plane_state *ipu_state = to_ipu_plane_state(state);
728+
729+
/* disabled crtcs must not block the update */
730+
if (!state->crtc)
731+
return false;
732+
733+
if (ipu_state->use_pre)
734+
return ipu_prg_channel_configure_pending(ipu_plane->ipu_ch);
735+
else if (ipu_plane->next_buf >= 0)
736+
return ipu_idmac_get_current_buffer(ipu_plane->ipu_ch) !=
737+
ipu_plane->next_buf;
738+
739+
return false;
740+
}
721741
int ipu_planes_assign_pre(struct drm_device *dev,
722742
struct drm_atomic_state *state)
723743
{
@@ -806,6 +826,7 @@ struct ipu_plane *ipu_plane_init(struct drm_device *dev, struct ipu_soc *ipu,
806826
{
807827
struct ipu_plane *ipu_plane;
808828
const uint64_t *modifiers = ipu_format_modifiers;
829+
unsigned int zpos = (type == DRM_PLANE_TYPE_PRIMARY) ? 0 : 1;
809830
int ret;
810831

811832
DRM_DEBUG_KMS("channel %d, dp flow %d, possible_crtcs=0x%x\n",
@@ -836,5 +857,10 @@ struct ipu_plane *ipu_plane_init(struct drm_device *dev, struct ipu_soc *ipu,
836857

837858
drm_plane_helper_add(&ipu_plane->base, &ipu_plane_helper_funcs);
838859

860+
if (dp == IPU_DP_FLOW_SYNC_BG || dp == IPU_DP_FLOW_SYNC_FG)
861+
drm_plane_create_zpos_property(&ipu_plane->base, zpos, 0, 1);
862+
else
863+
drm_plane_create_zpos_immutable_property(&ipu_plane->base, 0);
864+
839865
return ipu_plane;
840866
}

drivers/gpu/drm/imx/ipuv3-plane.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ struct ipu_plane {
2727
int dp_flow;
2828

2929
bool disabling;
30+
int next_buf;
3031
};
3132

3233
struct ipu_plane *ipu_plane_init(struct drm_device *dev, struct ipu_soc *ipu,
@@ -48,5 +49,6 @@ int ipu_plane_irq(struct ipu_plane *plane);
4849

4950
void ipu_plane_disable(struct ipu_plane *ipu_plane, bool disable_dp_channel);
5051
void ipu_plane_disable_deferred(struct drm_plane *plane);
52+
bool ipu_plane_atomic_update_pending(struct drm_plane *plane);
5153

5254
#endif

drivers/gpu/ipu-v3/ipu-pre.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,12 @@ void ipu_pre_update(struct ipu_pre *pre, unsigned int bufaddr)
265265
writel(IPU_PRE_CTRL_SDW_UPDATE, pre->regs + IPU_PRE_CTRL_SET);
266266
}
267267

268+
bool ipu_pre_update_pending(struct ipu_pre *pre)
269+
{
270+
return !!(readl_relaxed(pre->regs + IPU_PRE_CTRL) &
271+
IPU_PRE_CTRL_SDW_UPDATE);
272+
}
273+
268274
u32 ipu_pre_get_baddr(struct ipu_pre *pre)
269275
{
270276
return (u32)pre->buffer_paddr;

drivers/gpu/ipu-v3/ipu-prg.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,22 @@ int ipu_prg_channel_configure(struct ipuv3_channel *ipu_chan,
347347
}
348348
EXPORT_SYMBOL_GPL(ipu_prg_channel_configure);
349349

350+
bool ipu_prg_channel_configure_pending(struct ipuv3_channel *ipu_chan)
351+
{
352+
int prg_chan = ipu_prg_ipu_to_prg_chan(ipu_chan->num);
353+
struct ipu_prg *prg = ipu_chan->ipu->prg_priv;
354+
struct ipu_prg_channel *chan;
355+
356+
if (prg_chan < 0)
357+
return false;
358+
359+
chan = &prg->chan[prg_chan];
360+
WARN_ON(!chan->enabled);
361+
362+
return ipu_pre_update_pending(prg->pres[chan->used_pre]);
363+
}
364+
EXPORT_SYMBOL_GPL(ipu_prg_channel_configure_pending);
365+
350366
static int ipu_prg_probe(struct platform_device *pdev)
351367
{
352368
struct device *dev = &pdev->dev;

drivers/gpu/ipu-v3/ipu-prv.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,7 @@ void ipu_pre_configure(struct ipu_pre *pre, unsigned int width,
272272
unsigned int height, unsigned int stride, u32 format,
273273
uint64_t modifier, unsigned int bufaddr);
274274
void ipu_pre_update(struct ipu_pre *pre, unsigned int bufaddr);
275+
bool ipu_pre_update_pending(struct ipu_pre *pre);
275276

276277
struct ipu_prg *ipu_prg_lookup_by_phandle(struct device *dev, const char *name,
277278
int ipu_id);

include/video/imx-ipu-v3.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,7 @@ int ipu_prg_channel_configure(struct ipuv3_channel *ipu_chan,
348348
unsigned int axi_id, unsigned int width,
349349
unsigned int height, unsigned int stride,
350350
u32 format, uint64_t modifier, unsigned long *eba);
351+
bool ipu_prg_channel_configure_pending(struct ipuv3_channel *ipu_chan);
351352

352353
/*
353354
* IPU CMOS Sensor Interface (csi) functions

0 commit comments

Comments
 (0)