Skip to content

Commit

Permalink
imx-drm: core: handling of DI clock flags to ipu_crtc_mode_set()
Browse files Browse the repository at this point in the history
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: Russell King <rmk+kernel@arm.linux.org.uk>
Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
  • Loading branch information
Russell King authored and Philipp Zabel committed Jan 7, 2015
1 parent 503f163 commit d50141d
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 20 deletions.
3 changes: 1 addition & 2 deletions drivers/gpu/drm/imx/imx-drm-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,7 @@ int imx_drm_panel_format_pins(struct drm_encoder *encoder,
helper = &imx_crtc->imx_drm_helper_funcs;
if (helper->set_interface_pix_fmt)
return helper->set_interface_pix_fmt(encoder->crtc,
encoder->encoder_type, interface_pix_fmt,
hsync_pin, vsync_pin);
interface_pix_fmt, hsync_pin, vsync_pin);
return 0;
}
EXPORT_SYMBOL_GPL(imx_drm_panel_format_pins);
Expand Down
2 changes: 1 addition & 1 deletion drivers/gpu/drm/imx/imx-drm.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ int imx_drm_crtc_id(struct imx_drm_crtc *crtc);
struct imx_drm_crtc_helper_funcs {
int (*enable_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);
const struct drm_crtc_helper_funcs *crtc_helper_funcs;
const struct drm_crtc_funcs *crtc_funcs;
Expand Down
40 changes: 23 additions & 17 deletions drivers/gpu/drm/imx/ipuv3-crtc.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ struct ipu_crtc {
struct drm_framebuffer *newfb;
int irq;
u32 interface_pix_fmt;
unsigned long di_clkflags;
int di_hsync_pin;
int di_vsync_pin;
};
Expand Down Expand Up @@ -141,22 +140,42 @@ static int ipu_crtc_mode_set(struct drm_crtc *crtc,
int x, int y,
struct drm_framebuffer *old_fb)
{
struct drm_device *dev = crtc->dev;
struct drm_encoder *encoder;
struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc);
int ret;
struct ipu_di_signal_cfg sig_cfg = {};
unsigned long encoder_types = 0;
u32 out_pixel_fmt;
int ret;

dev_dbg(ipu_crtc->dev, "%s: mode->hdisplay: %d\n", __func__,
mode->hdisplay);
dev_dbg(ipu_crtc->dev, "%s: mode->vdisplay: %d\n", __func__,
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;

sig_cfg.enable_pol = 1;
sig_cfg.clk_pol = 0;
sig_cfg.pixel_fmt = out_pixel_fmt;
sig_cfg.clkflags = ipu_crtc->di_clkflags;
sig_cfg.v_to_h_sync = 0;
sig_cfg.hsync_pin = ipu_crtc->di_hsync_pin;
sig_cfg.vsync_pin = ipu_crtc->di_vsync_pin;
Expand Down Expand Up @@ -271,7 +290,7 @@ static void ipu_disable_vblank(struct drm_crtc *crtc)
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)
{
struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc);
Expand All @@ -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_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;
}

Expand Down

0 comments on commit d50141d

Please sign in to comment.