Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d50141d8 authored by Russell King's avatar Russell King Committed by Philipp Zabel
Browse files

imx-drm: core: handling of DI clock flags to ipu_crtc_mode_set()



We do not need to track the state of the IPU DI's clock flags by having
each display bridge calling back into imx-drm-core, and then back out
into ipuv3-crtc.c.

ipuv3-crtc can instead just scan the list of encoders to retrieve their
type, and build up a picture of which types of encoders are attached.
We can then use this information to configure the IPU DI clocking mode
without any uncertainty - if we have multiple bridges connected to the
same DI, if one of them requires a synchronous DI clock, that's what we
must use.

Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
Signed-off-by: default avatarPhilipp Zabel <p.zabel@pengutronix.de>
parent 503f1631
Loading
Loading
Loading
Loading
+1 −2
Original line number Original line Diff line number Diff line
@@ -116,8 +116,7 @@ int imx_drm_panel_format_pins(struct drm_encoder *encoder,
	helper = &imx_crtc->imx_drm_helper_funcs;
	helper = &imx_crtc->imx_drm_helper_funcs;
	if (helper->set_interface_pix_fmt)
	if (helper->set_interface_pix_fmt)
		return helper->set_interface_pix_fmt(encoder->crtc,
		return helper->set_interface_pix_fmt(encoder->crtc,
				encoder->encoder_type, interface_pix_fmt,
				interface_pix_fmt, hsync_pin, vsync_pin);
				hsync_pin, vsync_pin);
	return 0;
	return 0;
}
}
EXPORT_SYMBOL_GPL(imx_drm_panel_format_pins);
EXPORT_SYMBOL_GPL(imx_drm_panel_format_pins);
+1 −1
Original line number Original line Diff line number Diff line
@@ -17,7 +17,7 @@ int imx_drm_crtc_id(struct imx_drm_crtc *crtc);
struct imx_drm_crtc_helper_funcs {
struct imx_drm_crtc_helper_funcs {
	int (*enable_vblank)(struct drm_crtc *crtc);
	int (*enable_vblank)(struct drm_crtc *crtc);
	void (*disable_vblank)(struct drm_crtc *crtc);
	void (*disable_vblank)(struct drm_crtc *crtc);
	int (*set_interface_pix_fmt)(struct drm_crtc *crtc, u32 encoder_type,
	int (*set_interface_pix_fmt)(struct drm_crtc *crtc,
			u32 pix_fmt, int hsync_pin, int vsync_pin);
			u32 pix_fmt, int hsync_pin, int vsync_pin);
	const struct drm_crtc_helper_funcs *crtc_helper_funcs;
	const struct drm_crtc_helper_funcs *crtc_helper_funcs;
	const struct drm_crtc_funcs *crtc_funcs;
	const struct drm_crtc_funcs *crtc_funcs;
+23 −17
Original line number Original line Diff line number Diff line
@@ -46,7 +46,6 @@ struct ipu_crtc {
	struct drm_framebuffer	*newfb;
	struct drm_framebuffer	*newfb;
	int			irq;
	int			irq;
	u32			interface_pix_fmt;
	u32			interface_pix_fmt;
	unsigned long		di_clkflags;
	int			di_hsync_pin;
	int			di_hsync_pin;
	int			di_vsync_pin;
	int			di_vsync_pin;
};
};
@@ -141,22 +140,42 @@ static int ipu_crtc_mode_set(struct drm_crtc *crtc,
			       int x, int y,
			       int x, int y,
			       struct drm_framebuffer *old_fb)
			       struct drm_framebuffer *old_fb)
{
{
	struct drm_device *dev = crtc->dev;
	struct drm_encoder *encoder;
	struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc);
	struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc);
	int ret;
	struct ipu_di_signal_cfg sig_cfg = {};
	struct ipu_di_signal_cfg sig_cfg = {};
	unsigned long encoder_types = 0;
	u32 out_pixel_fmt;
	u32 out_pixel_fmt;
	int ret;


	dev_dbg(ipu_crtc->dev, "%s: mode->hdisplay: %d\n", __func__,
	dev_dbg(ipu_crtc->dev, "%s: mode->hdisplay: %d\n", __func__,
			mode->hdisplay);
			mode->hdisplay);
	dev_dbg(ipu_crtc->dev, "%s: mode->vdisplay: %d\n", __func__,
	dev_dbg(ipu_crtc->dev, "%s: mode->vdisplay: %d\n", __func__,
			mode->vdisplay);
			mode->vdisplay);


	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head)
		if (encoder->crtc == crtc)
			encoder_types |= BIT(encoder->encoder_type);

	dev_dbg(ipu_crtc->dev, "%s: attached to encoder types 0x%lx\n",
		__func__, encoder_types);

	/*
	 * If we have DAC, TVDAC or LDB, then we need the IPU DI clock
	 * to be the same as the LDB DI clock.
	 */
	if (encoder_types & (BIT(DRM_MODE_ENCODER_DAC) |
			     BIT(DRM_MODE_ENCODER_TVDAC) |
			     BIT(DRM_MODE_ENCODER_LVDS)))
		sig_cfg.clkflags = IPU_DI_CLKMODE_SYNC | IPU_DI_CLKMODE_EXT;
	else
		sig_cfg.clkflags = 0;

	out_pixel_fmt = ipu_crtc->interface_pix_fmt;
	out_pixel_fmt = ipu_crtc->interface_pix_fmt;


	sig_cfg.enable_pol = 1;
	sig_cfg.enable_pol = 1;
	sig_cfg.clk_pol = 0;
	sig_cfg.clk_pol = 0;
	sig_cfg.pixel_fmt = out_pixel_fmt;
	sig_cfg.pixel_fmt = out_pixel_fmt;
	sig_cfg.clkflags = ipu_crtc->di_clkflags;
	sig_cfg.v_to_h_sync = 0;
	sig_cfg.v_to_h_sync = 0;
	sig_cfg.hsync_pin = ipu_crtc->di_hsync_pin;
	sig_cfg.hsync_pin = ipu_crtc->di_hsync_pin;
	sig_cfg.vsync_pin = ipu_crtc->di_vsync_pin;
	sig_cfg.vsync_pin = ipu_crtc->di_vsync_pin;
@@ -271,7 +290,7 @@ static void ipu_disable_vblank(struct drm_crtc *crtc)
	ipu_crtc->newfb = NULL;
	ipu_crtc->newfb = NULL;
}
}


static int ipu_set_interface_pix_fmt(struct drm_crtc *crtc, u32 encoder_type,
static int ipu_set_interface_pix_fmt(struct drm_crtc *crtc,
		u32 pixfmt, int hsync_pin, int vsync_pin)
		u32 pixfmt, int hsync_pin, int vsync_pin)
{
{
	struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc);
	struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc);
@@ -280,19 +299,6 @@ static int ipu_set_interface_pix_fmt(struct drm_crtc *crtc, u32 encoder_type,
	ipu_crtc->di_hsync_pin = hsync_pin;
	ipu_crtc->di_hsync_pin = hsync_pin;
	ipu_crtc->di_vsync_pin = vsync_pin;
	ipu_crtc->di_vsync_pin = vsync_pin;


	switch (encoder_type) {
	case DRM_MODE_ENCODER_DAC:
	case DRM_MODE_ENCODER_TVDAC:
	case DRM_MODE_ENCODER_LVDS:
		ipu_crtc->di_clkflags = IPU_DI_CLKMODE_SYNC |
			IPU_DI_CLKMODE_EXT;
		break;
	case DRM_MODE_ENCODER_TMDS:
	case DRM_MODE_ENCODER_NONE:
		ipu_crtc->di_clkflags = 0;
		break;
	}

	return 0;
	return 0;
}
}