Commit 41ab70e0 authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge tag 'imx-drm-next-2021-05-12' of git://git.pengutronix.de/git/pza/linux into drm-next



drm/imx: fixes, dma-fence annotation, and color encoding/range plane properties

- Annotate dma-fence critical section in atomic_commit_tail
- Fix PRG modifiers after drmm resource conversion to regain tiled
  scanout capability
- Add 8 pixel alignment fix to support 1366x768 resolution
- Stop advertising YUV formats on planes that don't support them
- Add COLOR_ENCODING and COLOR_RANGE plane properties on planes
  that support them
- Remove unnecessarily exported symbols

Signed-off-by: default avatarDave Airlie <airlied@redhat.com>

From: Philipp Zabel <p.zabel@pengutronix.de>
Link: https://patchwork.freedesktop.org/patch/msgid/858310d193e10fc17221418dee6172af367eb046.camel@pengutronix.de
parents 3a3ca726 fc1e985b
Loading
Loading
Loading
Loading
+20 −1
Original line number Diff line number Diff line
@@ -81,6 +81,7 @@ static void imx_drm_atomic_commit_tail(struct drm_atomic_state *state)
	struct drm_plane_state *old_plane_state, *new_plane_state;
	bool plane_disabling = false;
	int i;
	bool fence_cookie = dma_fence_begin_signalling();

	drm_atomic_helper_commit_modeset_disables(dev, state);

@@ -111,6 +112,7 @@ static void imx_drm_atomic_commit_tail(struct drm_atomic_state *state)
	}

	drm_atomic_helper_commit_hw_done(state);
	dma_fence_end_signalling(fence_cookie);
}

static const struct drm_mode_config_helper_funcs imx_drm_mode_config_helpers = {
@@ -145,9 +147,26 @@ static const struct drm_ioctl_desc imx_drm_ioctls[] = {
	/* none so far */
};

static int imx_drm_dumb_create(struct drm_file *file_priv,
			       struct drm_device *drm,
			       struct drm_mode_create_dumb *args)
{
	u32 width = args->width;
	int ret;

	args->width = ALIGN(width, 8);

	ret = drm_gem_cma_dumb_create(file_priv, drm, args);
	if (ret)
		return ret;

	args->width = width;
	return ret;
}

static const struct drm_driver imx_drm_driver = {
	.driver_features	= DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC,
	DRM_GEM_CMA_DRIVER_OPS,
	DRM_GEM_CMA_DRIVER_OPS_WITH_DUMB_CREATE(imx_drm_dumb_create),
	.ioctls			= imx_drm_ioctls,
	.num_ioctls		= ARRAY_SIZE(imx_drm_ioctls),
	.fops			= &imx_drm_driver_fops,
+5 −0
Original line number Diff line number Diff line
@@ -274,6 +274,11 @@ imx_ldb_encoder_atomic_mode_set(struct drm_encoder *encoder,
			 "%s: mode exceeds 85 MHz pixel clock\n", __func__);
	}

	if (!IS_ALIGNED(mode->hdisplay, 8)) {
		dev_warn(ldb->dev,
			 "%s: hdisplay does not align to 8 byte\n", __func__);
	}

	if (dual) {
		serial_clk = 3500UL * mode->clock;
		imx_ldb_set_clock(ldb, mux, 0, serial_clk, di_clk);
+10 −1
Original line number Diff line number Diff line
@@ -305,10 +305,19 @@ static void ipu_crtc_mode_set_nofb(struct drm_crtc *crtc)
	sig_cfg.vsync_pin = imx_crtc_state->di_vsync_pin;

	drm_display_mode_to_videomode(mode, &sig_cfg.mode);
	if (!IS_ALIGNED(sig_cfg.mode.hactive, 8)) {
		unsigned int new_hactive = ALIGN(sig_cfg.mode.hactive, 8);

		dev_warn(ipu_crtc->dev, "8-pixel align hactive %d -> %d\n",
			 sig_cfg.mode.hactive, new_hactive);

		sig_cfg.mode.hfront_porch = new_hactive - sig_cfg.mode.hactive;
		sig_cfg.mode.hactive = new_hactive;
	}

	ipu_dc_init_sync(ipu_crtc->dc, ipu_crtc->di,
			 mode->flags & DRM_MODE_FLAG_INTERLACE,
			 imx_crtc_state->bus_format, mode->hdisplay);
			 imx_crtc_state->bus_format, sig_cfg.mode.hactive);
	ipu_di_init_sync_panel(ipu_crtc->di, &sig_cfg);
}

+96 −19
Original line number Diff line number Diff line
@@ -30,12 +30,17 @@ to_ipu_plane_state(struct drm_plane_state *p)
	return container_of(p, struct ipu_plane_state, base);
}

static unsigned int ipu_src_rect_width(const struct drm_plane_state *state)
{
	return ALIGN(drm_rect_width(&state->src) >> 16, 8);
}

static inline struct ipu_plane *to_ipu_plane(struct drm_plane *p)
{
	return container_of(p, struct ipu_plane, base);
}

static const uint32_t ipu_plane_formats[] = {
static const uint32_t ipu_plane_all_formats[] = {
	DRM_FORMAT_ARGB1555,
	DRM_FORMAT_XRGB1555,
	DRM_FORMAT_ABGR1555,
@@ -72,6 +77,31 @@ static const uint32_t ipu_plane_formats[] = {
	DRM_FORMAT_BGRX8888_A8,
};

static const uint32_t ipu_plane_rgb_formats[] = {
	DRM_FORMAT_ARGB1555,
	DRM_FORMAT_XRGB1555,
	DRM_FORMAT_ABGR1555,
	DRM_FORMAT_XBGR1555,
	DRM_FORMAT_RGBA5551,
	DRM_FORMAT_BGRA5551,
	DRM_FORMAT_ARGB4444,
	DRM_FORMAT_ARGB8888,
	DRM_FORMAT_XRGB8888,
	DRM_FORMAT_ABGR8888,
	DRM_FORMAT_XBGR8888,
	DRM_FORMAT_RGBA8888,
	DRM_FORMAT_RGBX8888,
	DRM_FORMAT_BGRA8888,
	DRM_FORMAT_BGRX8888,
	DRM_FORMAT_RGB565,
	DRM_FORMAT_RGB565_A8,
	DRM_FORMAT_BGR565_A8,
	DRM_FORMAT_RGB888_A8,
	DRM_FORMAT_BGR888_A8,
	DRM_FORMAT_RGBX8888_A8,
	DRM_FORMAT_BGRX8888_A8,
};

static const uint64_t ipu_format_modifiers[] = {
	DRM_FORMAT_MOD_LINEAR,
	DRM_FORMAT_MOD_INVALID
@@ -264,7 +294,6 @@ void ipu_plane_disable_deferred(struct drm_plane *plane)
		ipu_plane_disable(ipu_plane, false);
	}
}
EXPORT_SYMBOL_GPL(ipu_plane_disable_deferred);

static void ipu_plane_state_reset(struct drm_plane *plane)
{
@@ -284,6 +313,8 @@ static void ipu_plane_state_reset(struct drm_plane *plane)
		__drm_atomic_helper_plane_reset(plane, &ipu_state->base);
		ipu_state->base.zpos = zpos;
		ipu_state->base.normalized_zpos = zpos;
		ipu_state->base.color_encoding = DRM_COLOR_YCBCR_BT601;
		ipu_state->base.color_range = DRM_COLOR_YCBCR_LIMITED_RANGE;
	}
}

@@ -320,10 +351,11 @@ static bool ipu_plane_format_mod_supported(struct drm_plane *plane,
	if (modifier == DRM_FORMAT_MOD_LINEAR)
		return true;

	/* without a PRG there are no supported modifiers */
	if (!ipu_prg_present(ipu))
		return false;

	/*
	 * Without a PRG the possible modifiers list only includes the linear
	 * modifier, so we always take the early return from this function and
	 * only end up here if the PRG is present.
	 */
	return ipu_prg_format_supported(ipu, format, modifier);
}

@@ -415,6 +447,12 @@ static int ipu_plane_atomic_check(struct drm_plane *plane,
	if (old_fb && fb->pitches[0] != old_fb->pitches[0])
		crtc_state->mode_changed = true;

	if (ALIGN(fb->width, 8) * fb->format->cpp[0] >
	    fb->pitches[0] + fb->offsets[0]) {
		dev_warn(dev, "pitch is not big enough for 8 pixels alignment");
		return -EINVAL;
	}

	switch (fb->format->format) {
	case DRM_FORMAT_YUV420:
	case DRM_FORMAT_YVU420:
@@ -590,12 +628,31 @@ static void ipu_plane_atomic_update(struct drm_plane *plane,
	if (ipu_state->use_pre) {
		axi_id = ipu_chan_assign_axi_id(ipu_plane->dma);
		ipu_prg_channel_configure(ipu_plane->ipu_ch, axi_id,
					  drm_rect_width(&new_state->src) >> 16,
					  ipu_src_rect_width(new_state),
					  drm_rect_height(&new_state->src) >> 16,
					  fb->pitches[0], fb->format->format,
					  fb->modifier, &eba);
	}

	if (!old_state->fb ||
	    old_state->fb->format->format != fb->format->format ||
	    old_state->color_encoding != new_state->color_encoding ||
	    old_state->color_range != new_state->color_range) {
		ics = ipu_drm_fourcc_to_colorspace(fb->format->format);
		switch (ipu_plane->dp_flow) {
		case IPU_DP_FLOW_SYNC_BG:
			ipu_dp_setup_channel(ipu_plane->dp, new_state->color_encoding,
					     new_state->color_range, ics,
					     IPUV3_COLORSPACE_RGB);
			break;
		case IPU_DP_FLOW_SYNC_FG:
			ipu_dp_setup_channel(ipu_plane->dp, new_state->color_encoding,
					     new_state->color_range, ics,
					     IPUV3_COLORSPACE_UNKNOWN);
			break;
		}
	}

	if (old_state->fb && !drm_atomic_crtc_needs_modeset(crtc_state)) {
		/* nothing to do if PRE is used */
		if (ipu_state->use_pre)
@@ -615,17 +672,20 @@ static void ipu_plane_atomic_update(struct drm_plane *plane,
	ics = ipu_drm_fourcc_to_colorspace(fb->format->format);
	switch (ipu_plane->dp_flow) {
	case IPU_DP_FLOW_SYNC_BG:
		ipu_dp_setup_channel(ipu_plane->dp, ics, IPUV3_COLORSPACE_RGB);
		ipu_dp_setup_channel(ipu_plane->dp, DRM_COLOR_YCBCR_BT601,
				     DRM_COLOR_YCBCR_LIMITED_RANGE, ics,
				     IPUV3_COLORSPACE_RGB);
		break;
	case IPU_DP_FLOW_SYNC_FG:
		ipu_dp_setup_channel(ipu_plane->dp, ics,
		ipu_dp_setup_channel(ipu_plane->dp, DRM_COLOR_YCBCR_BT601,
				     DRM_COLOR_YCBCR_LIMITED_RANGE, ics,
				     IPUV3_COLORSPACE_UNKNOWN);
		break;
	}

	ipu_dmfc_config_wait4eot(ipu_plane->dmfc, drm_rect_width(dst));

	width = drm_rect_width(&new_state->src) >> 16;
	width = ipu_src_rect_width(new_state);
	height = drm_rect_height(&new_state->src) >> 16;
	info = drm_format_info(fb->format->format);
	ipu_calculate_bursts(width, info->cpp[0], fb->pitches[0],
@@ -690,7 +750,7 @@ static void ipu_plane_atomic_update(struct drm_plane *plane,

		ipu_cpmem_zero(ipu_plane->alpha_ch);
		ipu_cpmem_set_resolution(ipu_plane->alpha_ch,
					 drm_rect_width(&new_state->src) >> 16,
					 ipu_src_rect_width(new_state),
					 drm_rect_height(&new_state->src) >> 16);
		ipu_cpmem_set_format_passthrough(ipu_plane->alpha_ch, 8);
		ipu_cpmem_set_high_priority(ipu_plane->alpha_ch);
@@ -821,7 +881,6 @@ int ipu_planes_assign_pre(struct drm_device *dev,

	return 0;
}
EXPORT_SYMBOL_GPL(ipu_planes_assign_pre);

struct ipu_plane *ipu_plane_init(struct drm_device *dev, struct ipu_soc *ipu,
				 int dma, int dp, unsigned int possible_crtcs,
@@ -830,16 +889,28 @@ struct ipu_plane *ipu_plane_init(struct drm_device *dev, struct ipu_soc *ipu,
	struct ipu_plane *ipu_plane;
	const uint64_t *modifiers = ipu_format_modifiers;
	unsigned int zpos = (type == DRM_PLANE_TYPE_PRIMARY) ? 0 : 1;
	unsigned int format_count;
	const uint32_t *formats;
	int ret;

	DRM_DEBUG_KMS("channel %d, dp flow %d, possible_crtcs=0x%x\n",
		      dma, dp, possible_crtcs);

	if (dp == IPU_DP_FLOW_SYNC_BG || dp == IPU_DP_FLOW_SYNC_FG) {
		formats = ipu_plane_all_formats;
		format_count = ARRAY_SIZE(ipu_plane_all_formats);
	} else {
		formats = ipu_plane_rgb_formats;
		format_count = ARRAY_SIZE(ipu_plane_rgb_formats);
	}

	if (ipu_prg_present(ipu))
		modifiers = pre_format_modifiers;

	ipu_plane = drmm_universal_plane_alloc(dev, struct ipu_plane, base,
					       possible_crtcs, &ipu_plane_funcs,
					       ipu_plane_formats,
					       ARRAY_SIZE(ipu_plane_formats),
					       modifiers, type, NULL);
					       formats, format_count, modifiers,
					       type, NULL);
	if (IS_ERR(ipu_plane)) {
		DRM_ERROR("failed to allocate and initialize %s plane\n",
			  zpos ? "overlay" : "primary");
@@ -850,9 +921,6 @@ struct ipu_plane *ipu_plane_init(struct drm_device *dev, struct ipu_soc *ipu,
	ipu_plane->dma = dma;
	ipu_plane->dp_flow = dp;

	if (ipu_prg_present(ipu))
		modifiers = pre_format_modifiers;

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

	if (dp == IPU_DP_FLOW_SYNC_BG || dp == IPU_DP_FLOW_SYNC_FG)
@@ -864,6 +932,15 @@ struct ipu_plane *ipu_plane_init(struct drm_device *dev, struct ipu_soc *ipu,
	if (ret)
		return ERR_PTR(ret);

	ret = drm_plane_create_color_properties(&ipu_plane->base,
			BIT(DRM_COLOR_YCBCR_BT601) |
			BIT(DRM_COLOR_YCBCR_BT709),
			BIT(DRM_COLOR_YCBCR_LIMITED_RANGE),
			DRM_COLOR_YCBCR_BT601,
			DRM_COLOR_YCBCR_LIMITED_RANGE);
	if (ret)
		return ERR_PTR(ret);

	ret = ipu_plane_get_resources(dev, ipu_plane);
	if (ret) {
		DRM_ERROR("failed to get %s plane resources: %pe\n",
+5 −0
Original line number Diff line number Diff line
@@ -167,6 +167,11 @@ int ipu_dc_init_sync(struct ipu_dc *dc, struct ipu_di *di, bool interlaced,

	dc->di = ipu_di_get_num(di);

	if (!IS_ALIGNED(width, 8)) {
		dev_warn(priv->dev,
			 "%s: hactive does not align to 8 byte\n", __func__);
	}

	map = ipu_bus_format_to_map(bus_format);

	/*
Loading