From 6457b9716bca99b95a07e85ff8b00f9bf471ac2c Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 3 Jul 2014 17:52:57 +0100 Subject: drm/imx: convert imx-drm to use the generic DRM OF helper Use the generic DRM OF helper to locate the possible CRTCs for the encoder, thereby shrinking the imx-drm driver some more. Signed-off-by: Russell King Signed-off-by: Philipp Zabel --- drivers/gpu/drm/imx/imx-drm-core.c | 84 +++++++++----------------------------- 1 file changed, 19 insertions(+), 65 deletions(-) (limited to 'drivers/gpu/drm/imx/imx-drm-core.c') diff --git a/drivers/gpu/drm/imx/imx-drm-core.c b/drivers/gpu/drm/imx/imx-drm-core.c index b250130debc8..06cd2e516db6 100644 --- a/drivers/gpu/drm/imx/imx-drm-core.c +++ b/drivers/gpu/drm/imx/imx-drm-core.c @@ -25,6 +25,7 @@ #include #include #include +#include #include "imx-drm.h" @@ -46,7 +47,6 @@ struct imx_drm_crtc { struct drm_crtc *crtc; int pipe; struct imx_drm_crtc_helper_funcs imx_drm_helper_funcs; - struct device_node *port; }; static int legacyfb_depth = 16; @@ -365,9 +365,10 @@ int imx_drm_add_crtc(struct drm_device *drm, struct drm_crtc *crtc, imx_drm_crtc->imx_drm_helper_funcs = *imx_drm_helper_funcs; imx_drm_crtc->pipe = imxdrm->pipes++; - imx_drm_crtc->port = port; imx_drm_crtc->crtc = crtc; + crtc->port = port; + imxdrm->crtc[imx_drm_crtc->pipe] = imx_drm_crtc; *new_crtc = imx_drm_crtc; @@ -408,33 +409,28 @@ int imx_drm_remove_crtc(struct imx_drm_crtc *imx_drm_crtc) } EXPORT_SYMBOL_GPL(imx_drm_remove_crtc); -/* - * Find the DRM CRTC possible mask for the connected endpoint. - * - * The encoder possible masks are defined by their position in the - * mode_config crtc_list. This means that CRTCs must not be added - * or removed once the DRM device has been fully initialised. - */ -static uint32_t imx_drm_find_crtc_mask(struct imx_drm_device *imxdrm, - struct device_node *endpoint) +int imx_drm_encoder_parse_of(struct drm_device *drm, + struct drm_encoder *encoder, struct device_node *np) { - struct device_node *port; - unsigned i; + uint32_t crtc_mask = drm_of_find_possible_crtcs(drm, np); - port = of_graph_get_remote_port(endpoint); - if (!port) - return 0; - of_node_put(port); + /* + * If we failed to find the CRTC(s) which this encoder is + * supposed to be connected to, it's because the CRTC has + * not been registered yet. Defer probing, and hope that + * the required CRTC is added later. + */ + if (crtc_mask == 0) + return -EPROBE_DEFER; - for (i = 0; i < MAX_CRTC; i++) { - struct imx_drm_crtc *imx_drm_crtc = imxdrm->crtc[i]; + encoder->possible_crtcs = crtc_mask; - if (imx_drm_crtc && imx_drm_crtc->port == port) - return drm_crtc_mask(imx_drm_crtc->crtc); - } + /* FIXME: this is the mask of outputs which can clone this output. */ + encoder->possible_clones = ~0; return 0; } +EXPORT_SYMBOL_GPL(imx_drm_encoder_parse_of); static struct device_node *imx_drm_of_get_next_endpoint( const struct device_node *parent, struct device_node *prev) @@ -445,48 +441,6 @@ static struct device_node *imx_drm_of_get_next_endpoint( return node; } -int imx_drm_encoder_parse_of(struct drm_device *drm, - struct drm_encoder *encoder, struct device_node *np) -{ - struct imx_drm_device *imxdrm = drm->dev_private; - struct device_node *ep = NULL; - uint32_t crtc_mask = 0; - int i; - - for (i = 0; ; i++) { - u32 mask; - - ep = imx_drm_of_get_next_endpoint(np, ep); - if (!ep) - break; - - mask = imx_drm_find_crtc_mask(imxdrm, ep); - - /* - * If we failed to find the CRTC(s) which this encoder is - * supposed to be connected to, it's because the CRTC has - * not been registered yet. Defer probing, and hope that - * the required CRTC is added later. - */ - if (mask == 0) - return -EPROBE_DEFER; - - crtc_mask |= mask; - } - - of_node_put(ep); - if (i == 0) - return -ENOENT; - - encoder->possible_crtcs = crtc_mask; - - /* FIXME: this is the mask of outputs which can clone this output. */ - encoder->possible_clones = ~0; - - return 0; -} -EXPORT_SYMBOL_GPL(imx_drm_encoder_parse_of); - /* * @node: device tree node containing encoder input ports * @encoder: drm_encoder @@ -510,7 +464,7 @@ int imx_drm_encoder_get_mux_id(struct device_node *node, port = of_graph_get_remote_port(ep); of_node_put(port); - if (port == imx_crtc->port) { + if (port == imx_crtc->crtc->port) { ret = of_graph_parse_endpoint(ep, &endpoint); return ret ? ret : endpoint.port; } -- cgit v1.2.3 From d50141d8072e5322ee0518a8c967b5c9caf463d2 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 21 Dec 2014 15:58:19 +0000 Subject: 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: Russell King Signed-off-by: Philipp Zabel --- drivers/gpu/drm/imx/imx-drm-core.c | 3 +-- drivers/gpu/drm/imx/imx-drm.h | 2 +- drivers/gpu/drm/imx/ipuv3-crtc.c | 40 ++++++++++++++++++++++---------------- 3 files changed, 25 insertions(+), 20 deletions(-) (limited to 'drivers/gpu/drm/imx/imx-drm-core.c') diff --git a/drivers/gpu/drm/imx/imx-drm-core.c b/drivers/gpu/drm/imx/imx-drm-core.c index 06cd2e516db6..a002f53aab0e 100644 --- a/drivers/gpu/drm/imx/imx-drm-core.c +++ b/drivers/gpu/drm/imx/imx-drm-core.c @@ -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); diff --git a/drivers/gpu/drm/imx/imx-drm.h b/drivers/gpu/drm/imx/imx-drm.h index 7453ae00c412..3c559ccd6af0 100644 --- a/drivers/gpu/drm/imx/imx-drm.h +++ b/drivers/gpu/drm/imx/imx-drm.h @@ -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; diff --git a/drivers/gpu/drm/imx/ipuv3-crtc.c b/drivers/gpu/drm/imx/ipuv3-crtc.c index c1fc3735913d..98551e356e12 100644 --- a/drivers/gpu/drm/imx/ipuv3-crtc.c +++ b/drivers/gpu/drm/imx/ipuv3-crtc.c @@ -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; }; @@ -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; @@ -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); @@ -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; } -- cgit v1.2.3