diff options
author | Russell King <rmk+kernel@arm.linux.org.uk> | 2014-12-21 10:58:19 -0500 |
---|---|---|
committer | Philipp Zabel <p.zabel@pengutronix.de> | 2015-01-07 15:32:07 -0500 |
commit | d50141d8072e5322ee0518a8c967b5c9caf463d2 (patch) | |
tree | e03bdbda1b0727dbba0035c6749d2a5c9d0768b8 | |
parent | 503f1631ae8f42a386193c92cc4488d35978352e (diff) |
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 <rmk+kernel@arm.linux.org.uk>
Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
-rw-r--r-- | drivers/gpu/drm/imx/imx-drm-core.c | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/imx/imx-drm.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/imx/ipuv3-crtc.c | 40 |
3 files changed, 25 insertions, 20 deletions
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, | |||
116 | helper = &imx_crtc->imx_drm_helper_funcs; | 116 | helper = &imx_crtc->imx_drm_helper_funcs; |
117 | if (helper->set_interface_pix_fmt) | 117 | if (helper->set_interface_pix_fmt) |
118 | return helper->set_interface_pix_fmt(encoder->crtc, | 118 | return helper->set_interface_pix_fmt(encoder->crtc, |
119 | encoder->encoder_type, interface_pix_fmt, | 119 | interface_pix_fmt, hsync_pin, vsync_pin); |
120 | hsync_pin, vsync_pin); | ||
121 | return 0; | 120 | return 0; |
122 | } | 121 | } |
123 | EXPORT_SYMBOL_GPL(imx_drm_panel_format_pins); | 122 | 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); | |||
17 | struct imx_drm_crtc_helper_funcs { | 17 | struct imx_drm_crtc_helper_funcs { |
18 | int (*enable_vblank)(struct drm_crtc *crtc); | 18 | int (*enable_vblank)(struct drm_crtc *crtc); |
19 | void (*disable_vblank)(struct drm_crtc *crtc); | 19 | void (*disable_vblank)(struct drm_crtc *crtc); |
20 | int (*set_interface_pix_fmt)(struct drm_crtc *crtc, u32 encoder_type, | 20 | int (*set_interface_pix_fmt)(struct drm_crtc *crtc, |
21 | u32 pix_fmt, int hsync_pin, int vsync_pin); | 21 | u32 pix_fmt, int hsync_pin, int vsync_pin); |
22 | const struct drm_crtc_helper_funcs *crtc_helper_funcs; | 22 | const struct drm_crtc_helper_funcs *crtc_helper_funcs; |
23 | const struct drm_crtc_funcs *crtc_funcs; | 23 | 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 { | |||
46 | struct drm_framebuffer *newfb; | 46 | struct drm_framebuffer *newfb; |
47 | int irq; | 47 | int irq; |
48 | u32 interface_pix_fmt; | 48 | u32 interface_pix_fmt; |
49 | unsigned long di_clkflags; | ||
50 | int di_hsync_pin; | 49 | int di_hsync_pin; |
51 | int di_vsync_pin; | 50 | int di_vsync_pin; |
52 | }; | 51 | }; |
@@ -141,22 +140,42 @@ static int ipu_crtc_mode_set(struct drm_crtc *crtc, | |||
141 | int x, int y, | 140 | int x, int y, |
142 | struct drm_framebuffer *old_fb) | 141 | struct drm_framebuffer *old_fb) |
143 | { | 142 | { |
143 | struct drm_device *dev = crtc->dev; | ||
144 | struct drm_encoder *encoder; | ||
144 | struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc); | 145 | struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc); |
145 | int ret; | ||
146 | struct ipu_di_signal_cfg sig_cfg = {}; | 146 | struct ipu_di_signal_cfg sig_cfg = {}; |
147 | unsigned long encoder_types = 0; | ||
147 | u32 out_pixel_fmt; | 148 | u32 out_pixel_fmt; |
149 | int ret; | ||
148 | 150 | ||
149 | dev_dbg(ipu_crtc->dev, "%s: mode->hdisplay: %d\n", __func__, | 151 | dev_dbg(ipu_crtc->dev, "%s: mode->hdisplay: %d\n", __func__, |
150 | mode->hdisplay); | 152 | mode->hdisplay); |
151 | dev_dbg(ipu_crtc->dev, "%s: mode->vdisplay: %d\n", __func__, | 153 | dev_dbg(ipu_crtc->dev, "%s: mode->vdisplay: %d\n", __func__, |
152 | mode->vdisplay); | 154 | mode->vdisplay); |
153 | 155 | ||
156 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) | ||
157 | if (encoder->crtc == crtc) | ||
158 | encoder_types |= BIT(encoder->encoder_type); | ||
159 | |||
160 | dev_dbg(ipu_crtc->dev, "%s: attached to encoder types 0x%lx\n", | ||
161 | __func__, encoder_types); | ||
162 | |||
163 | /* | ||
164 | * If we have DAC, TVDAC or LDB, then we need the IPU DI clock | ||
165 | * to be the same as the LDB DI clock. | ||
166 | */ | ||
167 | if (encoder_types & (BIT(DRM_MODE_ENCODER_DAC) | | ||
168 | BIT(DRM_MODE_ENCODER_TVDAC) | | ||
169 | BIT(DRM_MODE_ENCODER_LVDS))) | ||
170 | sig_cfg.clkflags = IPU_DI_CLKMODE_SYNC | IPU_DI_CLKMODE_EXT; | ||
171 | else | ||
172 | sig_cfg.clkflags = 0; | ||
173 | |||
154 | out_pixel_fmt = ipu_crtc->interface_pix_fmt; | 174 | out_pixel_fmt = ipu_crtc->interface_pix_fmt; |
155 | 175 | ||
156 | sig_cfg.enable_pol = 1; | 176 | sig_cfg.enable_pol = 1; |
157 | sig_cfg.clk_pol = 0; | 177 | sig_cfg.clk_pol = 0; |
158 | sig_cfg.pixel_fmt = out_pixel_fmt; | 178 | sig_cfg.pixel_fmt = out_pixel_fmt; |
159 | sig_cfg.clkflags = ipu_crtc->di_clkflags; | ||
160 | sig_cfg.v_to_h_sync = 0; | 179 | sig_cfg.v_to_h_sync = 0; |
161 | sig_cfg.hsync_pin = ipu_crtc->di_hsync_pin; | 180 | sig_cfg.hsync_pin = ipu_crtc->di_hsync_pin; |
162 | sig_cfg.vsync_pin = ipu_crtc->di_vsync_pin; | 181 | sig_cfg.vsync_pin = ipu_crtc->di_vsync_pin; |
@@ -271,7 +290,7 @@ static void ipu_disable_vblank(struct drm_crtc *crtc) | |||
271 | ipu_crtc->newfb = NULL; | 290 | ipu_crtc->newfb = NULL; |
272 | } | 291 | } |
273 | 292 | ||
274 | static int ipu_set_interface_pix_fmt(struct drm_crtc *crtc, u32 encoder_type, | 293 | static int ipu_set_interface_pix_fmt(struct drm_crtc *crtc, |
275 | u32 pixfmt, int hsync_pin, int vsync_pin) | 294 | u32 pixfmt, int hsync_pin, int vsync_pin) |
276 | { | 295 | { |
277 | struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc); | 296 | 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, | |||
280 | ipu_crtc->di_hsync_pin = hsync_pin; | 299 | ipu_crtc->di_hsync_pin = hsync_pin; |
281 | ipu_crtc->di_vsync_pin = vsync_pin; | 300 | ipu_crtc->di_vsync_pin = vsync_pin; |
282 | 301 | ||
283 | switch (encoder_type) { | ||
284 | case DRM_MODE_ENCODER_DAC: | ||
285 | case DRM_MODE_ENCODER_TVDAC: | ||
286 | case DRM_MODE_ENCODER_LVDS: | ||
287 | ipu_crtc->di_clkflags = IPU_DI_CLKMODE_SYNC | | ||
288 | IPU_DI_CLKMODE_EXT; | ||
289 | break; | ||
290 | case DRM_MODE_ENCODER_TMDS: | ||
291 | case DRM_MODE_ENCODER_NONE: | ||
292 | ipu_crtc->di_clkflags = 0; | ||
293 | break; | ||
294 | } | ||
295 | |||
296 | return 0; | 302 | return 0; |
297 | } | 303 | } |
298 | 304 | ||