diff mbox

[v9,5/8] staging: imx-drm: Use de-active and pixelclk-active display-timings.

Message ID 1394121869-13387-2-git-send-email-denis@eukrea.com (mailing list archive)
State New, archived
Headers show

Commit Message

Denis Carikli March 6, 2014, 4:04 p.m. UTC
If de-active and/or pixelclk-active properties were set in the
display-timings DT node, they were not used.

Instead the data-enable and the pixel data clock polarity
were hardcoded.

The dts were updated to keep the former behaviour.

Signed-off-by: Denis Carikli <denis@eukrea.com>
---
ChangeLog v8->v9:
- Removed the Cc. They are now set in git-send-email directly.
- Rebased on top of the following patch:
  "imx-drm: Match ipu_di_signal_cfg's clk_pol with its description."
- Updated the current dts that were using the ipuv3 accordingly,
  to keep the same hardware settings.
- In the display-timing.txt documentation, the pixelclk-active
  and de-active optional properties have an "ignored" state
  when the property is not set.
  In this new version, the respective bits in the
  display interface's general register are not touched if the
  dt properties are not set.

ChangeLog v7->v8:
- Changed one Cc

ChangeLog v6->v7:
- Shrinked even more the Cc list.
- Rebased the patch
- val is now initialized in imx_pd_connector_get_modes

ChangeLog v5->v6:
- Remove people not concerned by this patch from the Cc list.
- Removed wrong coments from the code.
- Corrected the code style of the "if (!!val)"

ChangeLog v3->v4:
- The old patch was named "staging: imx-drm: ipuv3-crtc: don't harcode some mode".
- Reworked the patch entierly: we now takes the mode flags from the device tree.

ChangeLog v2->v3:
- Added some interested people in the Cc list.
- Ajusted the flags to match the changes in "drm: Add the lacking
  DRM_MODE_FLAG_* for matching the DISPLAY_FLAGS_*"
---
 arch/arm/boot/dts/imx51-babbage.dts         |    2 ++
 arch/arm/boot/dts/imx53-m53evk.dts          |    2 ++
 arch/arm/boot/dts/imx53-tx53-x03x.dts       |    2 +-
 arch/arm/boot/dts/imx6qdl-gw53xx.dtsi       |    2 ++
 arch/arm/boot/dts/imx6qdl-gw54xx.dtsi       |    2 ++
 arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi   |    2 ++
 arch/arm/boot/dts/imx6qdl-sabreauto.dtsi    |    2 ++
 arch/arm/boot/dts/imx6qdl-sabrelite.dtsi    |    2 ++
 arch/arm/boot/dts/imx6qdl-sabresd.dtsi      |    2 ++
 drivers/staging/imx-drm/imx-drm.h           |    5 ++++
 drivers/staging/imx-drm/ipu-v3/imx-ipu-v3.h |    4 ++++
 drivers/staging/imx-drm/ipu-v3/ipu-di.c     |   17 ++++++++++----
 drivers/staging/imx-drm/ipuv3-crtc.c        |   18 ++++++++++++--
 drivers/staging/imx-drm/parallel-display.c  |   34 +++++++++++++++++++++++++++
 14 files changed, 89 insertions(+), 7 deletions(-)

Comments

Russell King - ARM Linux March 7, 2014, 4:50 p.m. UTC | #1
On Thu, Mar 06, 2014 at 05:04:26PM +0100, Denis Carikli wrote:
> diff --git a/drivers/staging/imx-drm/ipu-v3/ipu-di.c b/drivers/staging/imx-drm/ipu-v3/ipu-di.c
> index 849b3e1..5d273c1 100644
> --- a/drivers/staging/imx-drm/ipu-v3/ipu-di.c
> +++ b/drivers/staging/imx-drm/ipu-v3/ipu-di.c
> @@ -595,8 +595,12 @@ int ipu_di_init_sync_panel(struct ipu_di *di, struct ipu_di_signal_cfg *sig)
>  		}
>  	}
>  
> -	if (sig->clk_pol)
> -		di_gen |= DI_GEN_POLARITY_DISP_CLK;
> +	if (sig->set_mask & SET_CLK_POL) {
> +		if (sig->clk_pol)
> +			di_gen |= DI_GEN_POLARITY_DISP_CLK;
> +		else
> +			di_gen &= ~DI_GEN_POLARITY_DISP_CLK;
> +	}
>  
>  	ipu_di_write(di, di_gen, DI_GENERAL);
>  
> @@ -606,8 +610,13 @@ int ipu_di_init_sync_panel(struct ipu_di *di, struct ipu_di_signal_cfg *sig)
>  	reg = ipu_di_read(di, DI_POL);
>  	reg &= ~(DI_POL_DRDY_DATA_POLARITY | DI_POL_DRDY_POLARITY_15);
>  
> -	if (sig->enable_pol)
> -		reg |= DI_POL_DRDY_POLARITY_15;
> +	if (sig->set_mask & SET_DE_POL) {
> +		if (sig->enable_pol)
> +			reg |= DI_POL_DRDY_POLARITY_15;
> +		else
> +			reg &= ~DI_POL_DRDY_POLARITY_15;
> +	}
> +
>  	if (sig->data_pol)
>  		reg |= DI_POL_DRDY_DATA_POLARITY;
>  
> diff --git a/drivers/staging/imx-drm/ipuv3-crtc.c b/drivers/staging/imx-drm/ipuv3-crtc.c
> index f506075..71f757f 100644
> --- a/drivers/staging/imx-drm/ipuv3-crtc.c
> +++ b/drivers/staging/imx-drm/ipuv3-crtc.c
> @@ -157,8 +157,22 @@ static int ipu_crtc_mode_set(struct drm_crtc *crtc,
>  	if (mode->flags & DRM_MODE_FLAG_PVSYNC)
>  		sig_cfg.Vsync_pol = 1;
>  
> -	sig_cfg.enable_pol = 1;
> -	sig_cfg.clk_pol = 0;
> +	if (mode->private_flags & IMXDRM_MODE_FLAG_DE_HIGH) {
> +		sig_cfg.enable_pol = 1;
> +		sig_cfg.set_mask |= SET_DE_POL;
> +	} else if (mode->private_flags & IMXDRM_MODE_FLAG_DE_LOW) {
> +		sig_cfg.enable_pol = 0;
> +		sig_cfg.set_mask |= SET_DE_POL;
> +	}
> +
> +	if (mode->private_flags & IMXDRM_MODE_FLAG_PIXDATA_POSEDGE) {
> +		sig_cfg.clk_pol = 1;
> +		sig_cfg.set_mask |= SET_CLK_POL;
> +	} else if (mode->private_flags & IMXDRM_MODE_FLAG_PIXDATA_NEGEDGE) {
> +		sig_cfg.clk_pol = 0;
> +		sig_cfg.set_mask |= SET_CLK_POL;
> +	}

So how does this work for other displays, for example, HDMI, where we need
enable_pol=1 and clk_pol=0 ?

From what I can see, we end up with sig_cfg.enable_pol=0, sig_cfg.clk_pol=0,
sig_cfg.set_mask=0.

What we end up with for enable_pol is this:

	reg = ipu_di_read(di, DI_POL);
	reg &= ~(DI_POL_DRDY_DATA_POLARITY | DI_POL_DRDY_POLARITY_15);

-	if (sig->enable_pol)
-		reg |= DI_POL_DRDY_POLARITY_15;
+	if (sig->set_mask & SET_DE_POL) {
+		if (sig->enable_pol)
+			reg |= DI_POL_DRDY_POLARITY_15;
+		else
+			reg &= ~DI_POL_DRDY_POLARITY_15;
+	}

which is no different from:

	reg = ipu_di_read(di, DI_POL);
	reg &= ~(DI_POL_DRDY_DATA_POLARITY | DI_POL_DRDY_POLARITY_15);

	if (sig->set_mask & SET_DE_POL && sig->enable_pol)
		reg |= DI_POL_DRDY_POLARITY_15;

because even with SET_DE_POL unset, we still end up clearing the bit.

Similar seems to happen with the clock polarity as well - in order for
that bit to be set, buth the set_mask and the clk_pol but must be set.

Dovetailing in to my previous reply, if we want to do this, maybe we
should convert clk_pol and enable_pol to be a tristate (can be an
u8 or enum).  Essentially, it has three values: preserve, active high,
active low.

However, one of the things that really worries me here is the "preserve"
action - what if it's not correctly set initially, and we don't have
anything specifying either polarity, which will happen if the only
encoder/connector you have is imx-hdmi.
diff mbox

Patch

diff --git a/arch/arm/boot/dts/imx51-babbage.dts b/arch/arm/boot/dts/imx51-babbage.dts
index ebe6c1d..fc6032e 100644
--- a/arch/arm/boot/dts/imx51-babbage.dts
+++ b/arch/arm/boot/dts/imx51-babbage.dts
@@ -39,6 +39,8 @@ 
 				vfront-porch = <7>;
 				hsync-len = <60>;
 				vsync-len = <10>;
+				de-active = <1>;
+				pixelclk-active = <0>;
 			};
 		};
 	};
diff --git a/arch/arm/boot/dts/imx53-m53evk.dts b/arch/arm/boot/dts/imx53-m53evk.dts
index 4250e74..32a6667 100644
--- a/arch/arm/boot/dts/imx53-m53evk.dts
+++ b/arch/arm/boot/dts/imx53-m53evk.dts
@@ -41,6 +41,8 @@ 
 					vfront-porch = <9>;
 					vsync-len = <3>;
 					vsync-active = <1>;
+					de-active = <1>;
+					pixelclk-active = <0>;
 				};
 			};
 		};
diff --git a/arch/arm/boot/dts/imx53-tx53-x03x.dts b/arch/arm/boot/dts/imx53-tx53-x03x.dts
index 0217dde3..4092a81 100644
--- a/arch/arm/boot/dts/imx53-tx53-x03x.dts
+++ b/arch/arm/boot/dts/imx53-tx53-x03x.dts
@@ -93,7 +93,7 @@ 
 					hsync-active = <0>;
 					vsync-active = <0>;
 					de-active = <1>;
-					pixelclk-active = <1>;
+					pixelclk-active = <0>;
 				};
 
 				ET0500 {
diff --git a/arch/arm/boot/dts/imx6qdl-gw53xx.dtsi b/arch/arm/boot/dts/imx6qdl-gw53xx.dtsi
index c8e5ae0..43f48f2 100644
--- a/arch/arm/boot/dts/imx6qdl-gw53xx.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-gw53xx.dtsi
@@ -494,6 +494,8 @@ 
 				vfront-porch = <7>;
 				hsync-len = <60>;
 				vsync-len = <10>;
+				de-active = <1>;
+				pixelclk-active = <0>;
 			};
 		};
 	};
diff --git a/arch/arm/boot/dts/imx6qdl-gw54xx.dtsi b/arch/arm/boot/dts/imx6qdl-gw54xx.dtsi
index 2795dfc..59ecfd1 100644
--- a/arch/arm/boot/dts/imx6qdl-gw54xx.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-gw54xx.dtsi
@@ -516,6 +516,8 @@ 
 				vfront-porch = <7>;
 				hsync-len = <60>;
 				vsync-len = <10>;
+				de-active = <1>;
+				pixelclk-active = <0>;
 			};
 		};
 	};
diff --git a/arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi b/arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi
index 99be301..e9419a2 100644
--- a/arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi
@@ -349,6 +349,8 @@ 
 				vfront-porch = <7>;
 				hsync-len = <60>;
 				vsync-len = <10>;
+				de-active = <1>;
+				pixelclk-active = <0>;
 			};
 		};
 	};
diff --git a/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi b/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi
index 009abd6..230bbc6 100644
--- a/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi
@@ -405,6 +405,8 @@ 
 				vfront-porch = <7>;
 				hsync-len = <60>;
 				vsync-len = <10>;
+				de-active = <1>;
+				pixelclk-active = <0>;
 			};
 		};
 	};
diff --git a/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi b/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi
index 3bec128..ed4c72f 100644
--- a/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi
@@ -349,6 +349,8 @@ 
 				vfront-porch = <7>;
 				hsync-len = <60>;
 				vsync-len = <10>;
+				de-active = <1>;
+				pixelclk-active = <0>;
 			};
 		};
 	};
diff --git a/arch/arm/boot/dts/imx6qdl-sabresd.dtsi b/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
index 04487cb..c89d64b 100644
--- a/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
@@ -450,6 +450,8 @@ 
 				vfront-porch = <7>;
 				hsync-len = <60>;
 				vsync-len = <10>;
+				de-active = <1>;
+				pixelclk-active = <0>;
 			};
 		};
 	};
diff --git a/drivers/staging/imx-drm/imx-drm.h b/drivers/staging/imx-drm/imx-drm.h
index 035ab62..a479738 100644
--- a/drivers/staging/imx-drm/imx-drm.h
+++ b/drivers/staging/imx-drm/imx-drm.h
@@ -1,6 +1,11 @@ 
 #ifndef _IMX_DRM_H_
 #define _IMX_DRM_H_
 
+#define IMXDRM_MODE_FLAG_DE_HIGH		(1 << 0)
+#define IMXDRM_MODE_FLAG_DE_LOW			(1 << 1)
+#define IMXDRM_MODE_FLAG_PIXDATA_POSEDGE	(1 << 2)
+#define IMXDRM_MODE_FLAG_PIXDATA_NEGEDGE	(1 << 3)
+
 struct device_node;
 struct drm_crtc;
 struct drm_connector;
diff --git a/drivers/staging/imx-drm/ipu-v3/imx-ipu-v3.h b/drivers/staging/imx-drm/ipu-v3/imx-ipu-v3.h
index c4d14ea..fc863e4 100644
--- a/drivers/staging/imx-drm/ipu-v3/imx-ipu-v3.h
+++ b/drivers/staging/imx-drm/ipu-v3/imx-ipu-v3.h
@@ -27,6 +27,9 @@  enum ipuv3_type {
 
 #define IPU_PIX_FMT_GBR24	v4l2_fourcc('G', 'B', 'R', '3')
 
+#define SET_CLK_POL	(1 << 0)
+#define SET_DE_POL	(1 << 1)
+
 /*
  * Bitfield of Display Interface signal polarities.
  */
@@ -41,6 +44,7 @@  struct ipu_di_signal_cfg {
 	unsigned enable_pol:1;
 	unsigned Hsync_pol:1;	/* true = active high */
 	unsigned Vsync_pol:1;
+	unsigned set_mask:2;
 
 	u16 width;
 	u16 height;
diff --git a/drivers/staging/imx-drm/ipu-v3/ipu-di.c b/drivers/staging/imx-drm/ipu-v3/ipu-di.c
index 849b3e1..5d273c1 100644
--- a/drivers/staging/imx-drm/ipu-v3/ipu-di.c
+++ b/drivers/staging/imx-drm/ipu-v3/ipu-di.c
@@ -595,8 +595,12 @@  int ipu_di_init_sync_panel(struct ipu_di *di, struct ipu_di_signal_cfg *sig)
 		}
 	}
 
-	if (sig->clk_pol)
-		di_gen |= DI_GEN_POLARITY_DISP_CLK;
+	if (sig->set_mask & SET_CLK_POL) {
+		if (sig->clk_pol)
+			di_gen |= DI_GEN_POLARITY_DISP_CLK;
+		else
+			di_gen &= ~DI_GEN_POLARITY_DISP_CLK;
+	}
 
 	ipu_di_write(di, di_gen, DI_GENERAL);
 
@@ -606,8 +610,13 @@  int ipu_di_init_sync_panel(struct ipu_di *di, struct ipu_di_signal_cfg *sig)
 	reg = ipu_di_read(di, DI_POL);
 	reg &= ~(DI_POL_DRDY_DATA_POLARITY | DI_POL_DRDY_POLARITY_15);
 
-	if (sig->enable_pol)
-		reg |= DI_POL_DRDY_POLARITY_15;
+	if (sig->set_mask & SET_DE_POL) {
+		if (sig->enable_pol)
+			reg |= DI_POL_DRDY_POLARITY_15;
+		else
+			reg &= ~DI_POL_DRDY_POLARITY_15;
+	}
+
 	if (sig->data_pol)
 		reg |= DI_POL_DRDY_DATA_POLARITY;
 
diff --git a/drivers/staging/imx-drm/ipuv3-crtc.c b/drivers/staging/imx-drm/ipuv3-crtc.c
index f506075..71f757f 100644
--- a/drivers/staging/imx-drm/ipuv3-crtc.c
+++ b/drivers/staging/imx-drm/ipuv3-crtc.c
@@ -157,8 +157,22 @@  static int ipu_crtc_mode_set(struct drm_crtc *crtc,
 	if (mode->flags & DRM_MODE_FLAG_PVSYNC)
 		sig_cfg.Vsync_pol = 1;
 
-	sig_cfg.enable_pol = 1;
-	sig_cfg.clk_pol = 0;
+	if (mode->private_flags & IMXDRM_MODE_FLAG_DE_HIGH) {
+		sig_cfg.enable_pol = 1;
+		sig_cfg.set_mask |= SET_DE_POL;
+	} else if (mode->private_flags & IMXDRM_MODE_FLAG_DE_LOW) {
+		sig_cfg.enable_pol = 0;
+		sig_cfg.set_mask |= SET_DE_POL;
+	}
+
+	if (mode->private_flags & IMXDRM_MODE_FLAG_PIXDATA_POSEDGE) {
+		sig_cfg.clk_pol = 1;
+		sig_cfg.set_mask |= SET_CLK_POL;
+	} else if (mode->private_flags & IMXDRM_MODE_FLAG_PIXDATA_NEGEDGE) {
+		sig_cfg.clk_pol = 0;
+		sig_cfg.set_mask |= SET_CLK_POL;
+	}
+
 	sig_cfg.width = mode->hdisplay;
 	sig_cfg.height = mode->vdisplay;
 	sig_cfg.pixel_fmt = out_pixel_fmt;
diff --git a/drivers/staging/imx-drm/parallel-display.c b/drivers/staging/imx-drm/parallel-display.c
index 01b7ce5..084500b 100644
--- a/drivers/staging/imx-drm/parallel-display.c
+++ b/drivers/staging/imx-drm/parallel-display.c
@@ -80,9 +80,43 @@  static int imx_pd_connector_get_modes(struct drm_connector *connector)
 
 	if (np) {
 		struct drm_display_mode *mode = drm_mode_create(connector->dev);
+		struct device_node *timings_np;
+		struct device_node *mode_np;
+		u32 val;
+
 		if (!mode)
 			return -EINVAL;
 		of_get_drm_display_mode(np, &imxpd->mode, OF_USE_NATIVE_MODE);
+
+		timings_np = of_get_child_by_name(np, "display-timings");
+		if (timings_np) {
+			/* get the display mode node */
+			mode_np = of_parse_phandle(timings_np,
+						   "native-mode", 0);
+			if (!mode_np)
+				mode_np = of_get_next_child(timings_np, NULL);
+
+			if (!of_property_read_u32(mode_np, "de-active", &val)) {
+				if (val) {
+					imxpd->mode.private_flags |=
+						IMXDRM_MODE_FLAG_DE_HIGH;
+				} else {
+					imxpd->mode.private_flags |=
+						IMXDRM_MODE_FLAG_DE_LOW;
+				}
+			}
+
+			if (!of_property_read_u32(mode_np, "pixelclk-active",
+						  &val)) {
+				if (val) {
+					imxpd->mode.private_flags |=
+						IMXDRM_MODE_FLAG_PIXDATA_POSEDGE;
+				} else {
+					imxpd->mode.private_flags |=
+						IMXDRM_MODE_FLAG_PIXDATA_NEGEDGE;
+				}
+			}
+		}
 		drm_mode_copy(mode, &imxpd->mode);
 		mode->type |= DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
 		drm_mode_probed_add(connector, mode);