linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/2] drm/vc4: Increase timeout for HDMI_SCHEDULER_CONTROL changes.
@ 2016-09-29  2:20 Eric Anholt
  2016-09-29  2:20 ` [PATCH 2/2] drm/vc4: Add support for interlaced modes on HDMI Eric Anholt
  0 siblings, 1 reply; 5+ messages in thread
From: Eric Anholt @ 2016-09-29  2:20 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-kernel, Eric Anholt

Fixes occasional debug spew at boot when connected directly through
HDMI, and probably confusing the HDMI state machine when we go trying
to poke registers for the enable sequence too soon.

Signed-off-by: Eric Anholt <eric@anholt.net>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 4452f3631cac..5770d6704f4b 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -369,7 +369,7 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 			   VC4_HDMI_SCHEDULER_CONTROL_MODE_HDMI);
 
 		ret = wait_for(HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) &
-			       VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE, 1);
+			       VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE, 1000);
 		WARN_ONCE(ret, "Timeout waiting for "
 			  "VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE\n");
 	} else {
@@ -381,7 +381,7 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 			   ~VC4_HDMI_SCHEDULER_CONTROL_MODE_HDMI);
 
 		ret = wait_for(!(HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) &
-				 VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE), 1);
+				 VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE), 1000);
 		WARN_ONCE(ret, "Timeout waiting for "
 			  "!VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE\n");
 	}
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 2/2] drm/vc4: Add support for interlaced modes on HDMI.
  2016-09-29  2:20 [PATCH 1/2] drm/vc4: Increase timeout for HDMI_SCHEDULER_CONTROL changes Eric Anholt
@ 2016-09-29  2:20 ` Eric Anholt
  2016-09-29  2:36   ` Mark yao
  0 siblings, 1 reply; 5+ messages in thread
From: Eric Anholt @ 2016-09-29  2:20 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-kernel, Eric Anholt

We just needed to initialize a few more fields.

Signed-off-by: Eric Anholt <eric@anholt.net>
---
 drivers/gpu/drm/vc4/vc4_crtc.c | 17 ++++++++++++++---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 12 ++++++++----
 drivers/gpu/drm/vc4/vc4_regs.h |  3 +++
 3 files changed, 25 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index 8fc2b731b59a..d575f8aa3273 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -428,13 +428,24 @@ static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc)
 			   VC4_SET_FIELD(mode->vsync_start - mode->vdisplay,
 					 PV_VERTB_VFP) |
 			   VC4_SET_FIELD(vactive, PV_VERTB_VACTIVE));
+
+		/* We set up first field even mode for HDMI.  VEC's
+		 * NTSC mode would want first field odd instead, once
+		 * we support it (to do so, set ODD_FIRST and put the
+		 * delay in VSYNCD_EVEN instead).
+		 */
+		CRTC_WRITE(PV_V_CONTROL,
+			   PV_VCONTROL_CONTINUOUS |
+			   PV_VCONTROL_INTERLACE |
+			   VC4_SET_FIELD(mode->htotal / 2,
+					 PV_VCONTROL_ODD_DELAY));
+		CRTC_WRITE(PV_VSYNCD_EVEN, 0);
+	} else {
+		CRTC_WRITE(PV_V_CONTROL, PV_VCONTROL_CONTINUOUS);
 	}
 
 	CRTC_WRITE(PV_HACT_ACT, mode->hdisplay);
 
-	CRTC_WRITE(PV_V_CONTROL,
-		   PV_VCONTROL_CONTINUOUS |
-		   (interlace ? PV_VCONTROL_INTERLACE : 0));
 
 	CRTC_WRITE(PV_CONTROL,
 		   VC4_SET_FIELD(format, PV_CONTROL_FORMAT) |
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 5770d6704f4b..6095e48fcf46 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -246,7 +246,7 @@ static struct drm_connector *vc4_hdmi_connector_init(struct drm_device *dev,
 	connector->polled = (DRM_CONNECTOR_POLL_CONNECT |
 			     DRM_CONNECTOR_POLL_DISCONNECT);
 
-	connector->interlace_allowed = 0;
+	connector->interlace_allowed = true;
 	connector->doublescan_allowed = 0;
 
 	drm_mode_connector_attach_encoder(connector, encoder);
@@ -278,8 +278,8 @@ static void vc4_hdmi_encoder_mode_set(struct drm_encoder *encoder,
 	bool debug_dump_regs = false;
 	bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC;
 	bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC;
-	u32 vactive = (mode->vdisplay >>
-		       ((mode->flags & DRM_MODE_FLAG_INTERLACE) ? 1 : 0));
+	bool interlaced = mode->flags & DRM_MODE_FLAG_INTERLACE;
+	u32 vactive = mode->vdisplay >> interlaced;
 	u32 verta = (VC4_SET_FIELD(mode->vsync_end - mode->vsync_start,
 				   VC4_HDMI_VERTA_VSP) |
 		     VC4_SET_FIELD(mode->vsync_start - mode->vdisplay,
@@ -288,6 +288,10 @@ static void vc4_hdmi_encoder_mode_set(struct drm_encoder *encoder,
 	u32 vertb = (VC4_SET_FIELD(0, VC4_HDMI_VERTB_VSPO) |
 		     VC4_SET_FIELD(mode->vtotal - mode->vsync_end,
 				   VC4_HDMI_VERTB_VBP));
+	u32 vertb_even = (VC4_SET_FIELD(0, VC4_HDMI_VERTB_VSPO) |
+			  VC4_SET_FIELD(mode->vtotal - mode->vsync_end -
+					interlaced,
+					VC4_HDMI_VERTB_VBP));
 
 	if (debug_dump_regs) {
 		DRM_INFO("HDMI regs before:\n");
@@ -319,7 +323,7 @@ static void vc4_hdmi_encoder_mode_set(struct drm_encoder *encoder,
 	HDMI_WRITE(VC4_HDMI_VERTA0, verta);
 	HDMI_WRITE(VC4_HDMI_VERTA1, verta);
 
-	HDMI_WRITE(VC4_HDMI_VERTB0, vertb);
+	HDMI_WRITE(VC4_HDMI_VERTB0, vertb_even);
 	HDMI_WRITE(VC4_HDMI_VERTB1, vertb);
 
 	HD_WRITE(VC4_HD_VID_CTL,
diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h
index 160942a9180e..fec7b5ef058b 100644
--- a/drivers/gpu/drm/vc4/vc4_regs.h
+++ b/drivers/gpu/drm/vc4/vc4_regs.h
@@ -183,6 +183,9 @@
 # define PV_CONTROL_EN				BIT(0)
 
 #define PV_V_CONTROL				0x04
+# define PV_VCONTROL_ODD_DELAY_MASK		VC4_MASK(22, 6)
+# define PV_VCONTROL_ODD_DELAY_SHIFT		6
+# define PV_VCONTROL_ODD_FIRST			BIT(5)
 # define PV_VCONTROL_INTERLACE			BIT(4)
 # define PV_VCONTROL_CONTINUOUS			BIT(1)
 # define PV_VCONTROL_VIDEN			BIT(0)
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH 2/2] drm/vc4: Add support for interlaced modes on HDMI.
  2016-09-29  2:20 ` [PATCH 2/2] drm/vc4: Add support for interlaced modes on HDMI Eric Anholt
@ 2016-09-29  2:36   ` Mark yao
  2016-09-29  2:53     ` Eric Anholt
  0 siblings, 1 reply; 5+ messages in thread
From: Mark yao @ 2016-09-29  2:36 UTC (permalink / raw)
  To: Eric Anholt, dri-devel; +Cc: linux-kernel

On 2016年09月29日 10:20, Eric Anholt wrote:
> We just needed to initialize a few more fields.
>
> Signed-off-by: Eric Anholt <eric@anholt.net>
> ---
>   drivers/gpu/drm/vc4/vc4_crtc.c | 17 ++++++++++++++---
>   drivers/gpu/drm/vc4/vc4_hdmi.c | 12 ++++++++----
>   drivers/gpu/drm/vc4/vc4_regs.h |  3 +++
>   3 files changed, 25 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
> index 8fc2b731b59a..d575f8aa3273 100644
> --- a/drivers/gpu/drm/vc4/vc4_crtc.c
> +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
> @@ -428,13 +428,24 @@ static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc)
>   			   VC4_SET_FIELD(mode->vsync_start - mode->vdisplay,
>   					 PV_VERTB_VFP) |
>   			   VC4_SET_FIELD(vactive, PV_VERTB_VACTIVE));
> +
> +		/* We set up first field even mode for HDMI.  VEC's
> +		 * NTSC mode would want first field odd instead, once
> +		 * we support it (to do so, set ODD_FIRST and put the
> +		 * delay in VSYNCD_EVEN instead).
> +		 */
> +		CRTC_WRITE(PV_V_CONTROL,
> +			   PV_VCONTROL_CONTINUOUS |
> +			   PV_VCONTROL_INTERLACE |
> +			   VC4_SET_FIELD(mode->htotal / 2,
> +					 PV_VCONTROL_ODD_DELAY));
> +		CRTC_WRITE(PV_VSYNCD_EVEN, 0);
> +	} else {
> +		CRTC_WRITE(PV_V_CONTROL, PV_VCONTROL_CONTINUOUS);
>   	}
>   
>   	CRTC_WRITE(PV_HACT_ACT, mode->hdisplay);
>   
> -	CRTC_WRITE(PV_V_CONTROL,
> -		   PV_VCONTROL_CONTINUOUS |
> -		   (interlace ? PV_VCONTROL_INTERLACE : 0));
>   
>   	CRTC_WRITE(PV_CONTROL,
>   		   VC4_SET_FIELD(format, PV_CONTROL_FORMAT) |
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index 5770d6704f4b..6095e48fcf46 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -246,7 +246,7 @@ static struct drm_connector *vc4_hdmi_connector_init(struct drm_device *dev,
>   	connector->polled = (DRM_CONNECTOR_POLL_CONNECT |
>   			     DRM_CONNECTOR_POLL_DISCONNECT);
>   
> -	connector->interlace_allowed = 0;
> +	connector->interlace_allowed = true;
>   	connector->doublescan_allowed = 0;
>   
>   	drm_mode_connector_attach_encoder(connector, encoder);
> @@ -278,8 +278,8 @@ static void vc4_hdmi_encoder_mode_set(struct drm_encoder *encoder,
>   	bool debug_dump_regs = false;
>   	bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC;
>   	bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC;
> -	u32 vactive = (mode->vdisplay >>
> -		       ((mode->flags & DRM_MODE_FLAG_INTERLACE) ? 1 : 0));
> +	bool interlaced = mode->flags & DRM_MODE_FLAG_INTERLACE;
> +	u32 vactive = mode->vdisplay >> interlaced;

How about use mode->crtc_vdisplay:

see this:
drm_mode_set_crtcinfo()

     if (p->flags & DRM_MODE_FLAG_INTERLACE) {
         if (adjust_flags & CRTC_INTERLACE_HALVE_V) {
             p->crtc_vdisplay /= 2;
             p->crtc_vsync_start /= 2;
             p->crtc_vsync_end /= 2;
             p->crtc_vtotal /= 2;
         }
     }

Thanks

>   	u32 verta = (VC4_SET_FIELD(mode->vsync_end - mode->vsync_start,
>   				   VC4_HDMI_VERTA_VSP) |
>   		     VC4_SET_FIELD(mode->vsync_start - mode->vdisplay,
> @@ -288,6 +288,10 @@ static void vc4_hdmi_encoder_mode_set(struct drm_encoder *encoder,
>   	u32 vertb = (VC4_SET_FIELD(0, VC4_HDMI_VERTB_VSPO) |
>   		     VC4_SET_FIELD(mode->vtotal - mode->vsync_end,
>   				   VC4_HDMI_VERTB_VBP));
> +	u32 vertb_even = (VC4_SET_FIELD(0, VC4_HDMI_VERTB_VSPO) |
> +			  VC4_SET_FIELD(mode->vtotal - mode->vsync_end -
> +					interlaced,
> +					VC4_HDMI_VERTB_VBP));
>   
>   	if (debug_dump_regs) {
>   		DRM_INFO("HDMI regs before:\n");
> @@ -319,7 +323,7 @@ static void vc4_hdmi_encoder_mode_set(struct drm_encoder *encoder,
>   	HDMI_WRITE(VC4_HDMI_VERTA0, verta);
>   	HDMI_WRITE(VC4_HDMI_VERTA1, verta);
>   
> -	HDMI_WRITE(VC4_HDMI_VERTB0, vertb);
> +	HDMI_WRITE(VC4_HDMI_VERTB0, vertb_even);
>   	HDMI_WRITE(VC4_HDMI_VERTB1, vertb);
>   
>   	HD_WRITE(VC4_HD_VID_CTL,
> diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h
> index 160942a9180e..fec7b5ef058b 100644
> --- a/drivers/gpu/drm/vc4/vc4_regs.h
> +++ b/drivers/gpu/drm/vc4/vc4_regs.h
> @@ -183,6 +183,9 @@
>   # define PV_CONTROL_EN				BIT(0)
>   
>   #define PV_V_CONTROL				0x04
> +# define PV_VCONTROL_ODD_DELAY_MASK		VC4_MASK(22, 6)
> +# define PV_VCONTROL_ODD_DELAY_SHIFT		6
> +# define PV_VCONTROL_ODD_FIRST			BIT(5)
>   # define PV_VCONTROL_INTERLACE			BIT(4)
>   # define PV_VCONTROL_CONTINUOUS			BIT(1)
>   # define PV_VCONTROL_VIDEN			BIT(0)


-- 
Mark Yao

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH 2/2] drm/vc4: Add support for interlaced modes on HDMI.
  2016-09-29  2:36   ` Mark yao
@ 2016-09-29  2:53     ` Eric Anholt
  2016-09-29 22:22       ` [PATCH 2/2 v2] drm/vc4: Fix " Eric Anholt
  0 siblings, 1 reply; 5+ messages in thread
From: Eric Anholt @ 2016-09-29  2:53 UTC (permalink / raw)
  To: Mark yao, dri-devel; +Cc: linux-kernel

[-- Attachment #1: Type: text/plain, Size: 3327 bytes --]

Mark yao <mark.yao@rock-chips.com> writes:

> On 2016年09月29日 10:20, Eric Anholt wrote:
>> We just needed to initialize a few more fields.
>>
>> Signed-off-by: Eric Anholt <eric@anholt.net>
>> ---
>>   drivers/gpu/drm/vc4/vc4_crtc.c | 17 ++++++++++++++---
>>   drivers/gpu/drm/vc4/vc4_hdmi.c | 12 ++++++++----
>>   drivers/gpu/drm/vc4/vc4_regs.h |  3 +++
>>   3 files changed, 25 insertions(+), 7 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
>> index 8fc2b731b59a..d575f8aa3273 100644
>> --- a/drivers/gpu/drm/vc4/vc4_crtc.c
>> +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
>> @@ -428,13 +428,24 @@ static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc)
>>   			   VC4_SET_FIELD(mode->vsync_start - mode->vdisplay,
>>   					 PV_VERTB_VFP) |
>>   			   VC4_SET_FIELD(vactive, PV_VERTB_VACTIVE));
>> +
>> +		/* We set up first field even mode for HDMI.  VEC's
>> +		 * NTSC mode would want first field odd instead, once
>> +		 * we support it (to do so, set ODD_FIRST and put the
>> +		 * delay in VSYNCD_EVEN instead).
>> +		 */
>> +		CRTC_WRITE(PV_V_CONTROL,
>> +			   PV_VCONTROL_CONTINUOUS |
>> +			   PV_VCONTROL_INTERLACE |
>> +			   VC4_SET_FIELD(mode->htotal / 2,
>> +					 PV_VCONTROL_ODD_DELAY));
>> +		CRTC_WRITE(PV_VSYNCD_EVEN, 0);
>> +	} else {
>> +		CRTC_WRITE(PV_V_CONTROL, PV_VCONTROL_CONTINUOUS);
>>   	}
>>   
>>   	CRTC_WRITE(PV_HACT_ACT, mode->hdisplay);
>>   
>> -	CRTC_WRITE(PV_V_CONTROL,
>> -		   PV_VCONTROL_CONTINUOUS |
>> -		   (interlace ? PV_VCONTROL_INTERLACE : 0));
>>   
>>   	CRTC_WRITE(PV_CONTROL,
>>   		   VC4_SET_FIELD(format, PV_CONTROL_FORMAT) |
>> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
>> index 5770d6704f4b..6095e48fcf46 100644
>> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
>> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
>> @@ -246,7 +246,7 @@ static struct drm_connector *vc4_hdmi_connector_init(struct drm_device *dev,
>>   	connector->polled = (DRM_CONNECTOR_POLL_CONNECT |
>>   			     DRM_CONNECTOR_POLL_DISCONNECT);
>>   
>> -	connector->interlace_allowed = 0;
>> +	connector->interlace_allowed = true;
>>   	connector->doublescan_allowed = 0;
>>   
>>   	drm_mode_connector_attach_encoder(connector, encoder);
>> @@ -278,8 +278,8 @@ static void vc4_hdmi_encoder_mode_set(struct drm_encoder *encoder,
>>   	bool debug_dump_regs = false;
>>   	bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC;
>>   	bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC;
>> -	u32 vactive = (mode->vdisplay >>
>> -		       ((mode->flags & DRM_MODE_FLAG_INTERLACE) ? 1 : 0));
>> +	bool interlaced = mode->flags & DRM_MODE_FLAG_INTERLACE;
>> +	u32 vactive = mode->vdisplay >> interlaced;
>
> How about use mode->crtc_vdisplay:
>
> see this:
> drm_mode_set_crtcinfo()
>
>      if (p->flags & DRM_MODE_FLAG_INTERLACE) {
>          if (adjust_flags & CRTC_INTERLACE_HALVE_V) {
>              p->crtc_vdisplay /= 2;
>              p->crtc_vsync_start /= 2;
>              p->crtc_vsync_end /= 2;
>              p->crtc_vtotal /= 2;
>          }
>      }

That would require setting up the adjust_flags, and I thought in the DRM
we were trying to move away from using it.  Also it would be pretty
strange to use just this one field from crtc_*.


[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 800 bytes --]

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH 2/2 v2] drm/vc4: Fix support for interlaced modes on HDMI.
  2016-09-29  2:53     ` Eric Anholt
@ 2016-09-29 22:22       ` Eric Anholt
  0 siblings, 0 replies; 5+ messages in thread
From: Eric Anholt @ 2016-09-29 22:22 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-kernel, Eric Anholt, mario.kleiner.de

We really do need to be using the halved V fields.  I had been
confused by the code I was using as a reference because it stored
halved vsync fields but not halved vdisplay, so it looked like I only
needed to divide vdisplay by 2.

This reverts part of Mario's timestamping fixes that prevented
CRTC_HALVE_V from applying, and instead adjusts the timestamping code
to not use the crtc field in that case.

Fixes locking of 1920x1080x60i on my Dell 2408WFP.  There are black
bars on the top and bottom, but I suspect that might be an
under/overscan flags problem as opposed to video timings.

Signed-off-by: Eric Anholt <eric@anholt.net>
---

After noting that we only used the one halved field last night and
spending some more of today debugging interlaced modes, I went and
looked and apparently the PV and HDMI *do* want CRTC_INTERLACE_HALVE_V
behavior.  This doesn't fix the problems I had, but it should correct
our timings, and also simplifies things and makes us look more like
other drivers.

 drivers/gpu/drm/vc4/vc4_crtc.c | 49 ++++++++++++++++++++++--------------------
 drivers/gpu/drm/vc4/vc4_hdmi.c | 45 +++++++++++---------------------------
 drivers/gpu/drm/vc4/vc4_regs.h |  3 +++
 3 files changed, 41 insertions(+), 56 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index 2682f07d8f1e..83cafea03eff 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -229,7 +229,7 @@ int vc4_crtc_get_scanoutpos(struct drm_device *dev, unsigned int crtc_id,
 	 * and need to make things up in a approximative but consistent way.
 	 */
 	ret |= DRM_SCANOUTPOS_IN_VBLANK;
-	vblank_lines = mode->crtc_vtotal - mode->crtc_vdisplay;
+	vblank_lines = mode->vtotal - mode->vdisplay;
 
 	if (flags & DRM_CALLED_FROM_VBLIRQ) {
 		/*
@@ -378,7 +378,6 @@ static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc)
 	struct drm_crtc_state *state = crtc->state;
 	struct drm_display_mode *mode = &state->adjusted_mode;
 	bool interlace = mode->flags & DRM_MODE_FLAG_INTERLACE;
-	u32 vactive = (mode->vdisplay >> (interlace ? 1 : 0));
 	u32 format = PV_CONTROL_FORMAT_24;
 	bool debug_dump_regs = false;
 	int clock_select = vc4_get_clock_select(crtc);
@@ -404,32 +403,46 @@ static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc)
 		   VC4_SET_FIELD(mode->hdisplay, PV_HORZB_HACTIVE));
 
 	CRTC_WRITE(PV_VERTA,
-		   VC4_SET_FIELD(mode->vtotal - mode->vsync_end,
+		   VC4_SET_FIELD(mode->crtc_vtotal - mode->crtc_vsync_end,
 				 PV_VERTA_VBP) |
-		   VC4_SET_FIELD(mode->vsync_end - mode->vsync_start,
+		   VC4_SET_FIELD(mode->crtc_vsync_end - mode->crtc_vsync_start,
 				 PV_VERTA_VSYNC));
 	CRTC_WRITE(PV_VERTB,
-		   VC4_SET_FIELD(mode->vsync_start - mode->vdisplay,
+		   VC4_SET_FIELD(mode->crtc_vsync_start - mode->crtc_vdisplay,
 				 PV_VERTB_VFP) |
-		   VC4_SET_FIELD(vactive, PV_VERTB_VACTIVE));
+		   VC4_SET_FIELD(mode->crtc_vdisplay, PV_VERTB_VACTIVE));
 
 	if (interlace) {
 		CRTC_WRITE(PV_VERTA_EVEN,
-			   VC4_SET_FIELD(mode->vtotal - mode->vsync_end - 1,
+			   VC4_SET_FIELD(mode->crtc_vtotal -
+					 mode->crtc_vsync_end - 1,
 					 PV_VERTA_VBP) |
-			   VC4_SET_FIELD(mode->vsync_end - mode->vsync_start,
+			   VC4_SET_FIELD(mode->crtc_vsync_end -
+					 mode->crtc_vsync_start,
 					 PV_VERTA_VSYNC));
 		CRTC_WRITE(PV_VERTB_EVEN,
-			   VC4_SET_FIELD(mode->vsync_start - mode->vdisplay,
+			   VC4_SET_FIELD(mode->crtc_vsync_start -
+					 mode->crtc_vdisplay,
 					 PV_VERTB_VFP) |
-			   VC4_SET_FIELD(vactive, PV_VERTB_VACTIVE));
+			   VC4_SET_FIELD(mode->crtc_vdisplay, PV_VERTB_VACTIVE));
+
+		/* We set up first field even mode for HDMI.  VEC's
+		 * NTSC mode would want first field odd instead, once
+		 * we support it (to do so, set ODD_FIRST and put the
+		 * delay in VSYNCD_EVEN instead).
+		 */
+		CRTC_WRITE(PV_V_CONTROL,
+			   PV_VCONTROL_CONTINUOUS |
+			   PV_VCONTROL_INTERLACE |
+			   VC4_SET_FIELD(mode->htotal / 2,
+					 PV_VCONTROL_ODD_DELAY));
+		CRTC_WRITE(PV_VSYNCD_EVEN, 0);
+	} else {
+		CRTC_WRITE(PV_V_CONTROL, PV_VCONTROL_CONTINUOUS);
 	}
 
 	CRTC_WRITE(PV_HACT_ACT, mode->hdisplay);
 
-	CRTC_WRITE(PV_V_CONTROL,
-		   PV_VCONTROL_CONTINUOUS |
-		   (interlace ? PV_VCONTROL_INTERLACE : 0));
 
 	CRTC_WRITE(PV_CONTROL,
 		   VC4_SET_FIELD(format, PV_CONTROL_FORMAT) |
@@ -544,16 +557,6 @@ static bool vc4_crtc_mode_fixup(struct drm_crtc *crtc,
 		return false;
 	}
 
-	/*
-	 * Interlaced video modes got CRTC_INTERLACE_HALVE_V applied when
-	 * coming from user space. We don't want this, as it screws up
-	 * vblank timestamping, so fix it up.
-	 */
-	drm_mode_set_crtcinfo(adjusted_mode, 0);
-
-	DRM_DEBUG_KMS("[CRTC:%d] adjusted_mode :\n", crtc->base.id);
-	drm_mode_debug_printmodeline(adjusted_mode);
-
 	return true;
 }
 
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index fe1c4e35e681..d94108ca961d 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -211,35 +211,10 @@ static int vc4_hdmi_connector_get_modes(struct drm_connector *connector)
 	return ret;
 }
 
-/*
- * drm_helper_probe_single_connector_modes() applies drm_mode_set_crtcinfo to
- * all modes with flag CRTC_INTERLACE_HALVE_V. We don't want this, as it
- * screws up vblank timestamping for interlaced modes, so fix it up.
- */
-static int vc4_hdmi_connector_probe_modes(struct drm_connector *connector,
-					  uint32_t maxX, uint32_t maxY)
-{
-	struct drm_display_mode *mode;
-	int count;
-
-	count = drm_helper_probe_single_connector_modes(connector, maxX, maxY);
-	if (count == 0)
-		return 0;
-
-	DRM_DEBUG_KMS("[CONNECTOR:%d:%s] probed adapted modes :\n",
-		      connector->base.id, connector->name);
-	list_for_each_entry(mode, &connector->modes, head) {
-		drm_mode_set_crtcinfo(mode, 0);
-		drm_mode_debug_printmodeline(mode);
-	}
-
-	return count;
-}
-
 static const struct drm_connector_funcs vc4_hdmi_connector_funcs = {
 	.dpms = drm_atomic_helper_connector_dpms,
 	.detect = vc4_hdmi_connector_detect,
-	.fill_modes = vc4_hdmi_connector_probe_modes,
+	.fill_modes = drm_helper_probe_single_connector_modes,
 	.destroy = vc4_hdmi_connector_destroy,
 	.reset = drm_atomic_helper_connector_reset,
 	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
@@ -307,16 +282,20 @@ static void vc4_hdmi_encoder_mode_set(struct drm_encoder *encoder,
 	bool debug_dump_regs = false;
 	bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC;
 	bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC;
-	u32 vactive = (mode->vdisplay >>
-		       ((mode->flags & DRM_MODE_FLAG_INTERLACE) ? 1 : 0));
-	u32 verta = (VC4_SET_FIELD(mode->vsync_end - mode->vsync_start,
+	bool interlaced = mode->flags & DRM_MODE_FLAG_INTERLACE;
+	u32 verta = (VC4_SET_FIELD(mode->crtc_vsync_end - mode->crtc_vsync_start,
 				   VC4_HDMI_VERTA_VSP) |
-		     VC4_SET_FIELD(mode->vsync_start - mode->vdisplay,
+		     VC4_SET_FIELD(mode->crtc_vsync_start - mode->crtc_vdisplay,
 				   VC4_HDMI_VERTA_VFP) |
-		     VC4_SET_FIELD(vactive, VC4_HDMI_VERTA_VAL));
+		     VC4_SET_FIELD(mode->crtc_vdisplay, VC4_HDMI_VERTA_VAL));
 	u32 vertb = (VC4_SET_FIELD(0, VC4_HDMI_VERTB_VSPO) |
-		     VC4_SET_FIELD(mode->vtotal - mode->vsync_end,
+		     VC4_SET_FIELD(mode->crtc_vtotal - mode->crtc_vsync_end,
 				   VC4_HDMI_VERTB_VBP));
+	u32 vertb_even = (VC4_SET_FIELD(0, VC4_HDMI_VERTB_VSPO) |
+			  VC4_SET_FIELD(mode->crtc_vtotal -
+					mode->crtc_vsync_end -
+					interlaced,
+					VC4_HDMI_VERTB_VBP));
 	u32 csc_ctl;
 
 	if (debug_dump_regs) {
@@ -349,7 +328,7 @@ static void vc4_hdmi_encoder_mode_set(struct drm_encoder *encoder,
 	HDMI_WRITE(VC4_HDMI_VERTA0, verta);
 	HDMI_WRITE(VC4_HDMI_VERTA1, verta);
 
-	HDMI_WRITE(VC4_HDMI_VERTB0, vertb);
+	HDMI_WRITE(VC4_HDMI_VERTB0, vertb_even);
 	HDMI_WRITE(VC4_HDMI_VERTB1, vertb);
 
 	HD_WRITE(VC4_HD_VID_CTL,
diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h
index 9ecd6ff3d493..c5a423ead86f 100644
--- a/drivers/gpu/drm/vc4/vc4_regs.h
+++ b/drivers/gpu/drm/vc4/vc4_regs.h
@@ -183,6 +183,9 @@
 # define PV_CONTROL_EN				BIT(0)
 
 #define PV_V_CONTROL				0x04
+# define PV_VCONTROL_ODD_DELAY_MASK		VC4_MASK(22, 6)
+# define PV_VCONTROL_ODD_DELAY_SHIFT		6
+# define PV_VCONTROL_ODD_FIRST			BIT(5)
 # define PV_VCONTROL_INTERLACE			BIT(4)
 # define PV_VCONTROL_CONTINUOUS			BIT(1)
 # define PV_VCONTROL_VIDEN			BIT(0)
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2016-09-29 22:22 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-09-29  2:20 [PATCH 1/2] drm/vc4: Increase timeout for HDMI_SCHEDULER_CONTROL changes Eric Anholt
2016-09-29  2:20 ` [PATCH 2/2] drm/vc4: Add support for interlaced modes on HDMI Eric Anholt
2016-09-29  2:36   ` Mark yao
2016-09-29  2:53     ` Eric Anholt
2016-09-29 22:22       ` [PATCH 2/2 v2] drm/vc4: Fix " Eric Anholt

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).