All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v4 0/8] drm/vc4: hdmi: Support the 10/12 bit output
@ 2020-12-07 13:39 ` Maxime Ripard
  0 siblings, 0 replies; 32+ messages in thread
From: Maxime Ripard @ 2020-12-07 13:39 UTC (permalink / raw)
  To: Maarten Lankhorst, Thomas Zimmermann, Maxime Ripard,
	Daniel Vetter, David Airlie, Eric Anholt
  Cc: linux-arm-kernel, bcm-kernel-feedback-list, linux-rpi-kernel,
	dri-devel, Dave Stevenson

Hi,

Here's some patches to enable the HDR output in the RPi4/BCM2711 HDMI
controller.

Let me know what you think,
Maxime

Changes from v3:
  - Don't dereference the connector->state pointer if kzalloc failed

Changes from v2:
  - Rebased on current drm-misc-next
  - Fixed a bug that was dropping the refresh rate when the bpc count
    was increased

Changes from v1:
  - Added the coccinelle script to the first patch
  - Fixed the pixel_rate ramp up

Maxime Ripard (8):
  drm/vc4: hvs: Align the HVS atomic hooks to the new API
  drm/vc4: Pass the atomic state to encoder hooks
  drm/vc4: hdmi: Don't access the connector state in reset if kmalloc
    fails
  drm/vc4: hdmi: Create a custom connector state
  drm/vc4: hdmi: Store pixel frequency in the connector state
  drm/vc4: hdmi: Use the connector state pixel rate for the PHY
  drm/vc4: hdmi: Limit the BCM2711 to the max without scrambling
  drm/vc4: hdmi: Enable 10/12 bpc output

 drivers/gpu/drm/vc4/vc4_crtc.c      |  22 ++--
 drivers/gpu/drm/vc4/vc4_drv.h       |  14 +--
 drivers/gpu/drm/vc4/vc4_hdmi.c      | 151 +++++++++++++++++++++++++---
 drivers/gpu/drm/vc4/vc4_hdmi.h      |  21 +++-
 drivers/gpu/drm/vc4/vc4_hdmi_phy.c  |   8 +-
 drivers/gpu/drm/vc4/vc4_hdmi_regs.h |   9 ++
 drivers/gpu/drm/vc4/vc4_hvs.c       |   8 +-
 drivers/gpu/drm/vc4/vc4_txp.c       |   8 +-
 8 files changed, 193 insertions(+), 48 deletions(-)

-- 
2.28.0


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 0/8] drm/vc4: hdmi: Support the 10/12 bit output
@ 2020-12-07 13:39 ` Maxime Ripard
  0 siblings, 0 replies; 32+ messages in thread
From: Maxime Ripard @ 2020-12-07 13:39 UTC (permalink / raw)
  To: Maarten Lankhorst, Thomas Zimmermann, Maxime Ripard,
	Daniel Vetter, David Airlie, Eric Anholt
  Cc: linux-arm-kernel, bcm-kernel-feedback-list, linux-rpi-kernel,
	dri-devel, Dave Stevenson

Hi,

Here's some patches to enable the HDR output in the RPi4/BCM2711 HDMI
controller.

Let me know what you think,
Maxime

Changes from v3:
  - Don't dereference the connector->state pointer if kzalloc failed

Changes from v2:
  - Rebased on current drm-misc-next
  - Fixed a bug that was dropping the refresh rate when the bpc count
    was increased

Changes from v1:
  - Added the coccinelle script to the first patch
  - Fixed the pixel_rate ramp up

Maxime Ripard (8):
  drm/vc4: hvs: Align the HVS atomic hooks to the new API
  drm/vc4: Pass the atomic state to encoder hooks
  drm/vc4: hdmi: Don't access the connector state in reset if kmalloc
    fails
  drm/vc4: hdmi: Create a custom connector state
  drm/vc4: hdmi: Store pixel frequency in the connector state
  drm/vc4: hdmi: Use the connector state pixel rate for the PHY
  drm/vc4: hdmi: Limit the BCM2711 to the max without scrambling
  drm/vc4: hdmi: Enable 10/12 bpc output

 drivers/gpu/drm/vc4/vc4_crtc.c      |  22 ++--
 drivers/gpu/drm/vc4/vc4_drv.h       |  14 +--
 drivers/gpu/drm/vc4/vc4_hdmi.c      | 151 +++++++++++++++++++++++++---
 drivers/gpu/drm/vc4/vc4_hdmi.h      |  21 +++-
 drivers/gpu/drm/vc4/vc4_hdmi_phy.c  |   8 +-
 drivers/gpu/drm/vc4/vc4_hdmi_regs.h |   9 ++
 drivers/gpu/drm/vc4/vc4_hvs.c       |   8 +-
 drivers/gpu/drm/vc4/vc4_txp.c       |   8 +-
 8 files changed, 193 insertions(+), 48 deletions(-)

-- 
2.28.0

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 1/8] drm/vc4: hvs: Align the HVS atomic hooks to the new API
  2020-12-07 13:39 ` Maxime Ripard
@ 2020-12-07 13:39   ` Maxime Ripard
  -1 siblings, 0 replies; 32+ messages in thread
From: Maxime Ripard @ 2020-12-07 13:39 UTC (permalink / raw)
  To: Maarten Lankhorst, Thomas Zimmermann, Maxime Ripard,
	Daniel Vetter, David Airlie, Eric Anholt
  Cc: linux-arm-kernel, bcm-kernel-feedback-list, linux-rpi-kernel,
	dri-devel, Dave Stevenson

Since the CRTC setup in vc4 is split between the PixelValves/TXP and the
HVS, only the PV/TXP atomic hooks were updated in the previous commits, but
it makes sense to update the HVS ones too.

Reviewed-by: Thomas Zimmermann <tzimmermann@suse.de>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_crtc.c | 4 +---
 drivers/gpu/drm/vc4/vc4_drv.h  | 4 ++--
 drivers/gpu/drm/vc4/vc4_hvs.c  | 8 +++++---
 drivers/gpu/drm/vc4/vc4_txp.c  | 8 ++------
 4 files changed, 10 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index 06088854c647..e02e499885ed 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -503,8 +503,6 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc,
 static void vc4_crtc_atomic_enable(struct drm_crtc *crtc,
 				   struct drm_atomic_state *state)
 {
-	struct drm_crtc_state *old_state = drm_atomic_get_old_crtc_state(state,
-									 crtc);
 	struct drm_device *dev = crtc->dev;
 	struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
 	struct drm_encoder *encoder = vc4_get_crtc_encoder(crtc);
@@ -517,7 +515,7 @@ static void vc4_crtc_atomic_enable(struct drm_crtc *crtc,
 	 */
 	drm_crtc_vblank_on(crtc);
 
-	vc4_hvs_atomic_enable(crtc, old_state);
+	vc4_hvs_atomic_enable(crtc, state);
 
 	if (vc4_encoder->pre_crtc_configure)
 		vc4_encoder->pre_crtc_configure(encoder);
diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
index c5f2944d5bc6..c47c85533805 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -918,8 +918,8 @@ extern struct platform_driver vc4_hvs_driver;
 void vc4_hvs_stop_channel(struct drm_device *dev, unsigned int output);
 int vc4_hvs_get_fifo_from_output(struct drm_device *dev, unsigned int output);
 int vc4_hvs_atomic_check(struct drm_crtc *crtc, struct drm_crtc_state *state);
-void vc4_hvs_atomic_enable(struct drm_crtc *crtc, struct drm_crtc_state *old_state);
-void vc4_hvs_atomic_disable(struct drm_crtc *crtc, struct drm_crtc_state *old_state);
+void vc4_hvs_atomic_enable(struct drm_crtc *crtc, struct drm_atomic_state *state);
+void vc4_hvs_atomic_disable(struct drm_crtc *crtc, struct drm_atomic_state *state);
 void vc4_hvs_atomic_flush(struct drm_crtc *crtc, struct drm_crtc_state *state);
 void vc4_hvs_dump_state(struct drm_device *dev);
 void vc4_hvs_unmask_underrun(struct drm_device *dev, int channel);
diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c
index b72b2bd05a81..04396dec63fc 100644
--- a/drivers/gpu/drm/vc4/vc4_hvs.c
+++ b/drivers/gpu/drm/vc4/vc4_hvs.c
@@ -391,11 +391,12 @@ static void vc4_hvs_update_dlist(struct drm_crtc *crtc)
 }
 
 void vc4_hvs_atomic_enable(struct drm_crtc *crtc,
-			   struct drm_crtc_state *old_state)
+			   struct drm_atomic_state *state)
 {
 	struct drm_device *dev = crtc->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
-	struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state);
+	struct drm_crtc_state *new_crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
+	struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(new_crtc_state);
 	struct drm_display_mode *mode = &crtc->state->adjusted_mode;
 	bool oneshot = vc4_state->feed_txp;
 
@@ -404,9 +405,10 @@ void vc4_hvs_atomic_enable(struct drm_crtc *crtc,
 }
 
 void vc4_hvs_atomic_disable(struct drm_crtc *crtc,
-			    struct drm_crtc_state *old_state)
+			    struct drm_atomic_state *state)
 {
 	struct drm_device *dev = crtc->dev;
+	struct drm_crtc_state *old_state = drm_atomic_get_old_crtc_state(state, crtc);
 	struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(old_state);
 	unsigned int chan = vc4_state->assigned_channel;
 
diff --git a/drivers/gpu/drm/vc4/vc4_txp.c b/drivers/gpu/drm/vc4/vc4_txp.c
index 34612edcabbd..4a26750b5e93 100644
--- a/drivers/gpu/drm/vc4/vc4_txp.c
+++ b/drivers/gpu/drm/vc4/vc4_txp.c
@@ -406,23 +406,19 @@ static int vc4_txp_atomic_check(struct drm_crtc *crtc,
 static void vc4_txp_atomic_enable(struct drm_crtc *crtc,
 				  struct drm_atomic_state *state)
 {
-	struct drm_crtc_state *old_state = drm_atomic_get_old_crtc_state(state,
-									 crtc);
 	drm_crtc_vblank_on(crtc);
-	vc4_hvs_atomic_enable(crtc, old_state);
+	vc4_hvs_atomic_enable(crtc, state);
 }
 
 static void vc4_txp_atomic_disable(struct drm_crtc *crtc,
 				   struct drm_atomic_state *state)
 {
-	struct drm_crtc_state *old_state = drm_atomic_get_old_crtc_state(state,
-									 crtc);
 	struct drm_device *dev = crtc->dev;
 
 	/* Disable vblank irq handling before crtc is disabled. */
 	drm_crtc_vblank_off(crtc);
 
-	vc4_hvs_atomic_disable(crtc, old_state);
+	vc4_hvs_atomic_disable(crtc, state);
 
 	/*
 	 * Make sure we issue a vblank event after disabling the CRTC if
-- 
2.28.0


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 1/8] drm/vc4: hvs: Align the HVS atomic hooks to the new API
@ 2020-12-07 13:39   ` Maxime Ripard
  0 siblings, 0 replies; 32+ messages in thread
From: Maxime Ripard @ 2020-12-07 13:39 UTC (permalink / raw)
  To: Maarten Lankhorst, Thomas Zimmermann, Maxime Ripard,
	Daniel Vetter, David Airlie, Eric Anholt
  Cc: linux-arm-kernel, bcm-kernel-feedback-list, linux-rpi-kernel,
	dri-devel, Dave Stevenson

Since the CRTC setup in vc4 is split between the PixelValves/TXP and the
HVS, only the PV/TXP atomic hooks were updated in the previous commits, but
it makes sense to update the HVS ones too.

Reviewed-by: Thomas Zimmermann <tzimmermann@suse.de>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_crtc.c | 4 +---
 drivers/gpu/drm/vc4/vc4_drv.h  | 4 ++--
 drivers/gpu/drm/vc4/vc4_hvs.c  | 8 +++++---
 drivers/gpu/drm/vc4/vc4_txp.c  | 8 ++------
 4 files changed, 10 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index 06088854c647..e02e499885ed 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -503,8 +503,6 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc,
 static void vc4_crtc_atomic_enable(struct drm_crtc *crtc,
 				   struct drm_atomic_state *state)
 {
-	struct drm_crtc_state *old_state = drm_atomic_get_old_crtc_state(state,
-									 crtc);
 	struct drm_device *dev = crtc->dev;
 	struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
 	struct drm_encoder *encoder = vc4_get_crtc_encoder(crtc);
@@ -517,7 +515,7 @@ static void vc4_crtc_atomic_enable(struct drm_crtc *crtc,
 	 */
 	drm_crtc_vblank_on(crtc);
 
-	vc4_hvs_atomic_enable(crtc, old_state);
+	vc4_hvs_atomic_enable(crtc, state);
 
 	if (vc4_encoder->pre_crtc_configure)
 		vc4_encoder->pre_crtc_configure(encoder);
diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
index c5f2944d5bc6..c47c85533805 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -918,8 +918,8 @@ extern struct platform_driver vc4_hvs_driver;
 void vc4_hvs_stop_channel(struct drm_device *dev, unsigned int output);
 int vc4_hvs_get_fifo_from_output(struct drm_device *dev, unsigned int output);
 int vc4_hvs_atomic_check(struct drm_crtc *crtc, struct drm_crtc_state *state);
-void vc4_hvs_atomic_enable(struct drm_crtc *crtc, struct drm_crtc_state *old_state);
-void vc4_hvs_atomic_disable(struct drm_crtc *crtc, struct drm_crtc_state *old_state);
+void vc4_hvs_atomic_enable(struct drm_crtc *crtc, struct drm_atomic_state *state);
+void vc4_hvs_atomic_disable(struct drm_crtc *crtc, struct drm_atomic_state *state);
 void vc4_hvs_atomic_flush(struct drm_crtc *crtc, struct drm_crtc_state *state);
 void vc4_hvs_dump_state(struct drm_device *dev);
 void vc4_hvs_unmask_underrun(struct drm_device *dev, int channel);
diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c
index b72b2bd05a81..04396dec63fc 100644
--- a/drivers/gpu/drm/vc4/vc4_hvs.c
+++ b/drivers/gpu/drm/vc4/vc4_hvs.c
@@ -391,11 +391,12 @@ static void vc4_hvs_update_dlist(struct drm_crtc *crtc)
 }
 
 void vc4_hvs_atomic_enable(struct drm_crtc *crtc,
-			   struct drm_crtc_state *old_state)
+			   struct drm_atomic_state *state)
 {
 	struct drm_device *dev = crtc->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
-	struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state);
+	struct drm_crtc_state *new_crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
+	struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(new_crtc_state);
 	struct drm_display_mode *mode = &crtc->state->adjusted_mode;
 	bool oneshot = vc4_state->feed_txp;
 
@@ -404,9 +405,10 @@ void vc4_hvs_atomic_enable(struct drm_crtc *crtc,
 }
 
 void vc4_hvs_atomic_disable(struct drm_crtc *crtc,
-			    struct drm_crtc_state *old_state)
+			    struct drm_atomic_state *state)
 {
 	struct drm_device *dev = crtc->dev;
+	struct drm_crtc_state *old_state = drm_atomic_get_old_crtc_state(state, crtc);
 	struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(old_state);
 	unsigned int chan = vc4_state->assigned_channel;
 
diff --git a/drivers/gpu/drm/vc4/vc4_txp.c b/drivers/gpu/drm/vc4/vc4_txp.c
index 34612edcabbd..4a26750b5e93 100644
--- a/drivers/gpu/drm/vc4/vc4_txp.c
+++ b/drivers/gpu/drm/vc4/vc4_txp.c
@@ -406,23 +406,19 @@ static int vc4_txp_atomic_check(struct drm_crtc *crtc,
 static void vc4_txp_atomic_enable(struct drm_crtc *crtc,
 				  struct drm_atomic_state *state)
 {
-	struct drm_crtc_state *old_state = drm_atomic_get_old_crtc_state(state,
-									 crtc);
 	drm_crtc_vblank_on(crtc);
-	vc4_hvs_atomic_enable(crtc, old_state);
+	vc4_hvs_atomic_enable(crtc, state);
 }
 
 static void vc4_txp_atomic_disable(struct drm_crtc *crtc,
 				   struct drm_atomic_state *state)
 {
-	struct drm_crtc_state *old_state = drm_atomic_get_old_crtc_state(state,
-									 crtc);
 	struct drm_device *dev = crtc->dev;
 
 	/* Disable vblank irq handling before crtc is disabled. */
 	drm_crtc_vblank_off(crtc);
 
-	vc4_hvs_atomic_disable(crtc, old_state);
+	vc4_hvs_atomic_disable(crtc, state);
 
 	/*
 	 * Make sure we issue a vblank event after disabling the CRTC if
-- 
2.28.0

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 2/8] drm/vc4: Pass the atomic state to encoder hooks
  2020-12-07 13:39 ` Maxime Ripard
@ 2020-12-07 13:39   ` Maxime Ripard
  -1 siblings, 0 replies; 32+ messages in thread
From: Maxime Ripard @ 2020-12-07 13:39 UTC (permalink / raw)
  To: Maarten Lankhorst, Thomas Zimmermann, Maxime Ripard,
	Daniel Vetter, David Airlie, Eric Anholt
  Cc: linux-arm-kernel, bcm-kernel-feedback-list, linux-rpi-kernel,
	dri-devel, Dave Stevenson

We'll need to access the connector state in our encoder setup, so let's
just pass the whole DRM state to our private encoder hooks.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_crtc.c | 18 ++++++++++--------
 drivers/gpu/drm/vc4/vc4_drv.h  | 10 +++++-----
 drivers/gpu/drm/vc4/vc4_hdmi.c | 15 ++++++++++-----
 3 files changed, 25 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index e02e499885ed..a3439756594c 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -403,7 +403,9 @@ static void require_hvs_enabled(struct drm_device *dev)
 		     SCALER_DISPCTRL_ENABLE);
 }
 
-static int vc4_crtc_disable(struct drm_crtc *crtc, unsigned int channel)
+static int vc4_crtc_disable(struct drm_crtc *crtc,
+			    struct drm_atomic_state *state,
+			    unsigned int channel)
 {
 	struct drm_encoder *encoder = vc4_get_crtc_encoder(crtc);
 	struct vc4_encoder *vc4_encoder = to_vc4_encoder(encoder);
@@ -435,13 +437,13 @@ static int vc4_crtc_disable(struct drm_crtc *crtc, unsigned int channel)
 	mdelay(20);
 
 	if (vc4_encoder && vc4_encoder->post_crtc_disable)
-		vc4_encoder->post_crtc_disable(encoder);
+		vc4_encoder->post_crtc_disable(encoder, state);
 
 	vc4_crtc_pixelvalve_reset(crtc);
 	vc4_hvs_stop_channel(dev, channel);
 
 	if (vc4_encoder && vc4_encoder->post_crtc_powerdown)
-		vc4_encoder->post_crtc_powerdown(encoder);
+		vc4_encoder->post_crtc_powerdown(encoder, state);
 
 	return 0;
 }
@@ -468,7 +470,7 @@ int vc4_crtc_disable_at_boot(struct drm_crtc *crtc)
 	if (channel < 0)
 		return 0;
 
-	return vc4_crtc_disable(crtc, channel);
+	return vc4_crtc_disable(crtc, NULL, channel);
 }
 
 static void vc4_crtc_atomic_disable(struct drm_crtc *crtc,
@@ -484,7 +486,7 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc,
 	/* Disable vblank irq handling before crtc is disabled. */
 	drm_crtc_vblank_off(crtc);
 
-	vc4_crtc_disable(crtc, old_vc4_state->assigned_channel);
+	vc4_crtc_disable(crtc, state, old_vc4_state->assigned_channel);
 
 	/*
 	 * Make sure we issue a vblank event after disabling the CRTC if
@@ -518,14 +520,14 @@ static void vc4_crtc_atomic_enable(struct drm_crtc *crtc,
 	vc4_hvs_atomic_enable(crtc, state);
 
 	if (vc4_encoder->pre_crtc_configure)
-		vc4_encoder->pre_crtc_configure(encoder);
+		vc4_encoder->pre_crtc_configure(encoder, state);
 
 	vc4_crtc_config_pv(crtc);
 
 	CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) | PV_CONTROL_EN);
 
 	if (vc4_encoder->pre_crtc_enable)
-		vc4_encoder->pre_crtc_enable(encoder);
+		vc4_encoder->pre_crtc_enable(encoder, state);
 
 	/* When feeding the transposer block the pixelvalve is unneeded and
 	 * should not be enabled.
@@ -534,7 +536,7 @@ static void vc4_crtc_atomic_enable(struct drm_crtc *crtc,
 		   CRTC_READ(PV_V_CONTROL) | PV_VCONTROL_VIDEN);
 
 	if (vc4_encoder->post_crtc_enable)
-		vc4_encoder->post_crtc_enable(encoder);
+		vc4_encoder->post_crtc_enable(encoder, state);
 }
 
 static enum drm_mode_status vc4_crtc_mode_valid(struct drm_crtc *crtc,
diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
index c47c85533805..b404cd3ab0d8 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -444,12 +444,12 @@ struct vc4_encoder {
 	enum vc4_encoder_type type;
 	u32 clock_select;
 
-	void (*pre_crtc_configure)(struct drm_encoder *encoder);
-	void (*pre_crtc_enable)(struct drm_encoder *encoder);
-	void (*post_crtc_enable)(struct drm_encoder *encoder);
+	void (*pre_crtc_configure)(struct drm_encoder *encoder, struct drm_atomic_state *state);
+	void (*pre_crtc_enable)(struct drm_encoder *encoder, struct drm_atomic_state *state);
+	void (*post_crtc_enable)(struct drm_encoder *encoder, struct drm_atomic_state *state);
 
-	void (*post_crtc_disable)(struct drm_encoder *encoder);
-	void (*post_crtc_powerdown)(struct drm_encoder *encoder);
+	void (*post_crtc_disable)(struct drm_encoder *encoder, struct drm_atomic_state *state);
+	void (*post_crtc_powerdown)(struct drm_encoder *encoder, struct drm_atomic_state *state);
 };
 
 static inline struct vc4_encoder *
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index afc178b0d89f..5a608ed1d75e 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -357,7 +357,8 @@ static void vc4_hdmi_set_infoframes(struct drm_encoder *encoder)
 		vc4_hdmi_set_audio_infoframe(encoder);
 }
 
-static void vc4_hdmi_encoder_post_crtc_disable(struct drm_encoder *encoder)
+static void vc4_hdmi_encoder_post_crtc_disable(struct drm_encoder *encoder,
+					       struct drm_atomic_state *state)
 {
 	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
 
@@ -370,7 +371,8 @@ static void vc4_hdmi_encoder_post_crtc_disable(struct drm_encoder *encoder)
 		   HDMI_READ(HDMI_VID_CTL) | VC4_HD_VID_CTL_BLANKPIX);
 }
 
-static void vc4_hdmi_encoder_post_crtc_powerdown(struct drm_encoder *encoder)
+static void vc4_hdmi_encoder_post_crtc_powerdown(struct drm_encoder *encoder,
+						 struct drm_atomic_state *state)
 {
 	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
 	int ret;
@@ -584,7 +586,8 @@ static void vc4_hdmi_recenter_fifo(struct vc4_hdmi *vc4_hdmi)
 		  "VC4_HDMI_FIFO_CTL_RECENTER_DONE");
 }
 
-static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder)
+static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder,
+						struct drm_atomic_state *state)
 {
 	struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
 	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
@@ -676,7 +679,8 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder)
 		vc4_hdmi->variant->set_timings(vc4_hdmi, mode);
 }
 
-static void vc4_hdmi_encoder_pre_crtc_enable(struct drm_encoder *encoder)
+static void vc4_hdmi_encoder_pre_crtc_enable(struct drm_encoder *encoder,
+					     struct drm_atomic_state *state)
 {
 	struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
 	struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
@@ -698,7 +702,8 @@ static void vc4_hdmi_encoder_pre_crtc_enable(struct drm_encoder *encoder)
 	HDMI_WRITE(HDMI_FIFO_CTL, VC4_HDMI_FIFO_CTL_MASTER_SLAVE_N);
 }
 
-static void vc4_hdmi_encoder_post_crtc_enable(struct drm_encoder *encoder)
+static void vc4_hdmi_encoder_post_crtc_enable(struct drm_encoder *encoder,
+					      struct drm_atomic_state *state)
 {
 	struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
 	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
-- 
2.28.0


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 2/8] drm/vc4: Pass the atomic state to encoder hooks
@ 2020-12-07 13:39   ` Maxime Ripard
  0 siblings, 0 replies; 32+ messages in thread
From: Maxime Ripard @ 2020-12-07 13:39 UTC (permalink / raw)
  To: Maarten Lankhorst, Thomas Zimmermann, Maxime Ripard,
	Daniel Vetter, David Airlie, Eric Anholt
  Cc: linux-arm-kernel, bcm-kernel-feedback-list, linux-rpi-kernel,
	dri-devel, Dave Stevenson

We'll need to access the connector state in our encoder setup, so let's
just pass the whole DRM state to our private encoder hooks.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_crtc.c | 18 ++++++++++--------
 drivers/gpu/drm/vc4/vc4_drv.h  | 10 +++++-----
 drivers/gpu/drm/vc4/vc4_hdmi.c | 15 ++++++++++-----
 3 files changed, 25 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index e02e499885ed..a3439756594c 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -403,7 +403,9 @@ static void require_hvs_enabled(struct drm_device *dev)
 		     SCALER_DISPCTRL_ENABLE);
 }
 
-static int vc4_crtc_disable(struct drm_crtc *crtc, unsigned int channel)
+static int vc4_crtc_disable(struct drm_crtc *crtc,
+			    struct drm_atomic_state *state,
+			    unsigned int channel)
 {
 	struct drm_encoder *encoder = vc4_get_crtc_encoder(crtc);
 	struct vc4_encoder *vc4_encoder = to_vc4_encoder(encoder);
@@ -435,13 +437,13 @@ static int vc4_crtc_disable(struct drm_crtc *crtc, unsigned int channel)
 	mdelay(20);
 
 	if (vc4_encoder && vc4_encoder->post_crtc_disable)
-		vc4_encoder->post_crtc_disable(encoder);
+		vc4_encoder->post_crtc_disable(encoder, state);
 
 	vc4_crtc_pixelvalve_reset(crtc);
 	vc4_hvs_stop_channel(dev, channel);
 
 	if (vc4_encoder && vc4_encoder->post_crtc_powerdown)
-		vc4_encoder->post_crtc_powerdown(encoder);
+		vc4_encoder->post_crtc_powerdown(encoder, state);
 
 	return 0;
 }
@@ -468,7 +470,7 @@ int vc4_crtc_disable_at_boot(struct drm_crtc *crtc)
 	if (channel < 0)
 		return 0;
 
-	return vc4_crtc_disable(crtc, channel);
+	return vc4_crtc_disable(crtc, NULL, channel);
 }
 
 static void vc4_crtc_atomic_disable(struct drm_crtc *crtc,
@@ -484,7 +486,7 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc,
 	/* Disable vblank irq handling before crtc is disabled. */
 	drm_crtc_vblank_off(crtc);
 
-	vc4_crtc_disable(crtc, old_vc4_state->assigned_channel);
+	vc4_crtc_disable(crtc, state, old_vc4_state->assigned_channel);
 
 	/*
 	 * Make sure we issue a vblank event after disabling the CRTC if
@@ -518,14 +520,14 @@ static void vc4_crtc_atomic_enable(struct drm_crtc *crtc,
 	vc4_hvs_atomic_enable(crtc, state);
 
 	if (vc4_encoder->pre_crtc_configure)
-		vc4_encoder->pre_crtc_configure(encoder);
+		vc4_encoder->pre_crtc_configure(encoder, state);
 
 	vc4_crtc_config_pv(crtc);
 
 	CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) | PV_CONTROL_EN);
 
 	if (vc4_encoder->pre_crtc_enable)
-		vc4_encoder->pre_crtc_enable(encoder);
+		vc4_encoder->pre_crtc_enable(encoder, state);
 
 	/* When feeding the transposer block the pixelvalve is unneeded and
 	 * should not be enabled.
@@ -534,7 +536,7 @@ static void vc4_crtc_atomic_enable(struct drm_crtc *crtc,
 		   CRTC_READ(PV_V_CONTROL) | PV_VCONTROL_VIDEN);
 
 	if (vc4_encoder->post_crtc_enable)
-		vc4_encoder->post_crtc_enable(encoder);
+		vc4_encoder->post_crtc_enable(encoder, state);
 }
 
 static enum drm_mode_status vc4_crtc_mode_valid(struct drm_crtc *crtc,
diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
index c47c85533805..b404cd3ab0d8 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -444,12 +444,12 @@ struct vc4_encoder {
 	enum vc4_encoder_type type;
 	u32 clock_select;
 
-	void (*pre_crtc_configure)(struct drm_encoder *encoder);
-	void (*pre_crtc_enable)(struct drm_encoder *encoder);
-	void (*post_crtc_enable)(struct drm_encoder *encoder);
+	void (*pre_crtc_configure)(struct drm_encoder *encoder, struct drm_atomic_state *state);
+	void (*pre_crtc_enable)(struct drm_encoder *encoder, struct drm_atomic_state *state);
+	void (*post_crtc_enable)(struct drm_encoder *encoder, struct drm_atomic_state *state);
 
-	void (*post_crtc_disable)(struct drm_encoder *encoder);
-	void (*post_crtc_powerdown)(struct drm_encoder *encoder);
+	void (*post_crtc_disable)(struct drm_encoder *encoder, struct drm_atomic_state *state);
+	void (*post_crtc_powerdown)(struct drm_encoder *encoder, struct drm_atomic_state *state);
 };
 
 static inline struct vc4_encoder *
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index afc178b0d89f..5a608ed1d75e 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -357,7 +357,8 @@ static void vc4_hdmi_set_infoframes(struct drm_encoder *encoder)
 		vc4_hdmi_set_audio_infoframe(encoder);
 }
 
-static void vc4_hdmi_encoder_post_crtc_disable(struct drm_encoder *encoder)
+static void vc4_hdmi_encoder_post_crtc_disable(struct drm_encoder *encoder,
+					       struct drm_atomic_state *state)
 {
 	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
 
@@ -370,7 +371,8 @@ static void vc4_hdmi_encoder_post_crtc_disable(struct drm_encoder *encoder)
 		   HDMI_READ(HDMI_VID_CTL) | VC4_HD_VID_CTL_BLANKPIX);
 }
 
-static void vc4_hdmi_encoder_post_crtc_powerdown(struct drm_encoder *encoder)
+static void vc4_hdmi_encoder_post_crtc_powerdown(struct drm_encoder *encoder,
+						 struct drm_atomic_state *state)
 {
 	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
 	int ret;
@@ -584,7 +586,8 @@ static void vc4_hdmi_recenter_fifo(struct vc4_hdmi *vc4_hdmi)
 		  "VC4_HDMI_FIFO_CTL_RECENTER_DONE");
 }
 
-static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder)
+static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder,
+						struct drm_atomic_state *state)
 {
 	struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
 	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
@@ -676,7 +679,8 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder)
 		vc4_hdmi->variant->set_timings(vc4_hdmi, mode);
 }
 
-static void vc4_hdmi_encoder_pre_crtc_enable(struct drm_encoder *encoder)
+static void vc4_hdmi_encoder_pre_crtc_enable(struct drm_encoder *encoder,
+					     struct drm_atomic_state *state)
 {
 	struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
 	struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
@@ -698,7 +702,8 @@ static void vc4_hdmi_encoder_pre_crtc_enable(struct drm_encoder *encoder)
 	HDMI_WRITE(HDMI_FIFO_CTL, VC4_HDMI_FIFO_CTL_MASTER_SLAVE_N);
 }
 
-static void vc4_hdmi_encoder_post_crtc_enable(struct drm_encoder *encoder)
+static void vc4_hdmi_encoder_post_crtc_enable(struct drm_encoder *encoder,
+					      struct drm_atomic_state *state)
 {
 	struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
 	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
-- 
2.28.0

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 3/8] drm/vc4: hdmi: Don't access the connector state in reset if kmalloc fails
  2020-12-07 13:39 ` Maxime Ripard
@ 2020-12-07 13:39   ` Maxime Ripard
  -1 siblings, 0 replies; 32+ messages in thread
From: Maxime Ripard @ 2020-12-07 13:39 UTC (permalink / raw)
  To: Maarten Lankhorst, Thomas Zimmermann, Maxime Ripard,
	Daniel Vetter, David Airlie, Eric Anholt
  Cc: linux-arm-kernel, bcm-kernel-feedback-list, linux-rpi-kernel,
	dri-devel, Dave Stevenson

drm_atomic_helper_connector_reset uses kmalloc which, from an API
standpoint, can fail, and thus setting connector->state to NULL.
However, our reset hook then calls drm_atomic_helper_connector_tv_reset
that will access connector->state without checking if it's a valid
pointer or not.

Make sure we don't end up accessing a NULL pointer.

Suggested-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 5a608ed1d75e..112c09873eb4 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -171,7 +171,9 @@ static int vc4_hdmi_connector_get_modes(struct drm_connector *connector)
 static void vc4_hdmi_connector_reset(struct drm_connector *connector)
 {
 	drm_atomic_helper_connector_reset(connector);
-	drm_atomic_helper_connector_tv_reset(connector);
+
+	if (connector->state)
+		drm_atomic_helper_connector_tv_reset(connector);
 }
 
 static const struct drm_connector_funcs vc4_hdmi_connector_funcs = {
-- 
2.28.0


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 3/8] drm/vc4: hdmi: Don't access the connector state in reset if kmalloc fails
@ 2020-12-07 13:39   ` Maxime Ripard
  0 siblings, 0 replies; 32+ messages in thread
From: Maxime Ripard @ 2020-12-07 13:39 UTC (permalink / raw)
  To: Maarten Lankhorst, Thomas Zimmermann, Maxime Ripard,
	Daniel Vetter, David Airlie, Eric Anholt
  Cc: linux-arm-kernel, bcm-kernel-feedback-list, linux-rpi-kernel,
	dri-devel, Dave Stevenson

drm_atomic_helper_connector_reset uses kmalloc which, from an API
standpoint, can fail, and thus setting connector->state to NULL.
However, our reset hook then calls drm_atomic_helper_connector_tv_reset
that will access connector->state without checking if it's a valid
pointer or not.

Make sure we don't end up accessing a NULL pointer.

Suggested-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 5a608ed1d75e..112c09873eb4 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -171,7 +171,9 @@ static int vc4_hdmi_connector_get_modes(struct drm_connector *connector)
 static void vc4_hdmi_connector_reset(struct drm_connector *connector)
 {
 	drm_atomic_helper_connector_reset(connector);
-	drm_atomic_helper_connector_tv_reset(connector);
+
+	if (connector->state)
+		drm_atomic_helper_connector_tv_reset(connector);
 }
 
 static const struct drm_connector_funcs vc4_hdmi_connector_funcs = {
-- 
2.28.0

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 4/8] drm/vc4: hdmi: Create a custom connector state
  2020-12-07 13:39 ` Maxime Ripard
@ 2020-12-07 13:39   ` Maxime Ripard
  -1 siblings, 0 replies; 32+ messages in thread
From: Maxime Ripard @ 2020-12-07 13:39 UTC (permalink / raw)
  To: Maarten Lankhorst, Thomas Zimmermann, Maxime Ripard,
	Daniel Vetter, David Airlie, Eric Anholt
  Cc: linux-arm-kernel, bcm-kernel-feedback-list, linux-rpi-kernel,
	dri-devel, Dave Stevenson

When run with a higher bpc than 8, the clock of the HDMI controller needs
to be adjusted. Let's create a connector state that will be used at
atomic_check and atomic_enable to compute and store the clock rate
associated to the state.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 27 +++++++++++++++++++++++++--
 drivers/gpu/drm/vc4/vc4_hdmi.h | 10 ++++++++++
 2 files changed, 35 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 112c09873eb4..862c93708e9a 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -170,18 +170,41 @@ static int vc4_hdmi_connector_get_modes(struct drm_connector *connector)
 
 static void vc4_hdmi_connector_reset(struct drm_connector *connector)
 {
-	drm_atomic_helper_connector_reset(connector);
+	struct vc4_hdmi_connector_state *conn_state = kzalloc(sizeof(*conn_state), GFP_KERNEL);
+
+	if (connector->state)
+		__drm_atomic_helper_connector_destroy_state(connector->state);
+
+	kfree(connector->state);
+
+	__drm_atomic_helper_connector_reset(connector, &conn_state->base);
 
 	if (connector->state)
 		drm_atomic_helper_connector_tv_reset(connector);
 }
 
+static struct drm_connector_state *
+vc4_hdmi_connector_duplicate_state(struct drm_connector *connector)
+{
+	struct drm_connector_state *conn_state = connector->state;
+	struct vc4_hdmi_connector_state *vc4_state = conn_state_to_vc4_hdmi_conn_state(conn_state);
+	struct vc4_hdmi_connector_state *new_state;
+
+	new_state = kzalloc(sizeof(*new_state), GFP_KERNEL);
+	if (!new_state)
+		return NULL;
+
+	__drm_atomic_helper_connector_duplicate_state(connector, &new_state->base);
+
+	return &new_state->base;
+}
+
 static const struct drm_connector_funcs vc4_hdmi_connector_funcs = {
 	.detect = vc4_hdmi_connector_detect,
 	.fill_modes = drm_helper_probe_single_connector_modes,
 	.destroy = vc4_hdmi_connector_destroy,
 	.reset = vc4_hdmi_connector_reset,
-	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+	.atomic_duplicate_state = vc4_hdmi_connector_duplicate_state,
 	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
 };
 
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
index 0526a9cf608a..2cf5362052e2 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
@@ -180,6 +180,16 @@ encoder_to_vc4_hdmi(struct drm_encoder *encoder)
 	return container_of(_encoder, struct vc4_hdmi, encoder);
 }
 
+struct vc4_hdmi_connector_state {
+	struct drm_connector_state	base;
+};
+
+static inline struct vc4_hdmi_connector_state *
+conn_state_to_vc4_hdmi_conn_state(struct drm_connector_state *conn_state)
+{
+	return container_of(conn_state, struct vc4_hdmi_connector_state, base);
+}
+
 void vc4_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi,
 		       struct drm_display_mode *mode);
 void vc4_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi);
-- 
2.28.0


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 4/8] drm/vc4: hdmi: Create a custom connector state
@ 2020-12-07 13:39   ` Maxime Ripard
  0 siblings, 0 replies; 32+ messages in thread
From: Maxime Ripard @ 2020-12-07 13:39 UTC (permalink / raw)
  To: Maarten Lankhorst, Thomas Zimmermann, Maxime Ripard,
	Daniel Vetter, David Airlie, Eric Anholt
  Cc: linux-arm-kernel, bcm-kernel-feedback-list, linux-rpi-kernel,
	dri-devel, Dave Stevenson

When run with a higher bpc than 8, the clock of the HDMI controller needs
to be adjusted. Let's create a connector state that will be used at
atomic_check and atomic_enable to compute and store the clock rate
associated to the state.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 27 +++++++++++++++++++++++++--
 drivers/gpu/drm/vc4/vc4_hdmi.h | 10 ++++++++++
 2 files changed, 35 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 112c09873eb4..862c93708e9a 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -170,18 +170,41 @@ static int vc4_hdmi_connector_get_modes(struct drm_connector *connector)
 
 static void vc4_hdmi_connector_reset(struct drm_connector *connector)
 {
-	drm_atomic_helper_connector_reset(connector);
+	struct vc4_hdmi_connector_state *conn_state = kzalloc(sizeof(*conn_state), GFP_KERNEL);
+
+	if (connector->state)
+		__drm_atomic_helper_connector_destroy_state(connector->state);
+
+	kfree(connector->state);
+
+	__drm_atomic_helper_connector_reset(connector, &conn_state->base);
 
 	if (connector->state)
 		drm_atomic_helper_connector_tv_reset(connector);
 }
 
+static struct drm_connector_state *
+vc4_hdmi_connector_duplicate_state(struct drm_connector *connector)
+{
+	struct drm_connector_state *conn_state = connector->state;
+	struct vc4_hdmi_connector_state *vc4_state = conn_state_to_vc4_hdmi_conn_state(conn_state);
+	struct vc4_hdmi_connector_state *new_state;
+
+	new_state = kzalloc(sizeof(*new_state), GFP_KERNEL);
+	if (!new_state)
+		return NULL;
+
+	__drm_atomic_helper_connector_duplicate_state(connector, &new_state->base);
+
+	return &new_state->base;
+}
+
 static const struct drm_connector_funcs vc4_hdmi_connector_funcs = {
 	.detect = vc4_hdmi_connector_detect,
 	.fill_modes = drm_helper_probe_single_connector_modes,
 	.destroy = vc4_hdmi_connector_destroy,
 	.reset = vc4_hdmi_connector_reset,
-	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+	.atomic_duplicate_state = vc4_hdmi_connector_duplicate_state,
 	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
 };
 
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
index 0526a9cf608a..2cf5362052e2 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
@@ -180,6 +180,16 @@ encoder_to_vc4_hdmi(struct drm_encoder *encoder)
 	return container_of(_encoder, struct vc4_hdmi, encoder);
 }
 
+struct vc4_hdmi_connector_state {
+	struct drm_connector_state	base;
+};
+
+static inline struct vc4_hdmi_connector_state *
+conn_state_to_vc4_hdmi_conn_state(struct drm_connector_state *conn_state)
+{
+	return container_of(conn_state, struct vc4_hdmi_connector_state, base);
+}
+
 void vc4_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi,
 		       struct drm_display_mode *mode);
 void vc4_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi);
-- 
2.28.0

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 5/8] drm/vc4: hdmi: Store pixel frequency in the connector state
  2020-12-07 13:39 ` Maxime Ripard
@ 2020-12-07 13:39   ` Maxime Ripard
  -1 siblings, 0 replies; 32+ messages in thread
From: Maxime Ripard @ 2020-12-07 13:39 UTC (permalink / raw)
  To: Maarten Lankhorst, Thomas Zimmermann, Maxime Ripard,
	Daniel Vetter, David Airlie, Eric Anholt
  Cc: linux-arm-kernel, bcm-kernel-feedback-list, linux-rpi-kernel,
	dri-devel, Dave Stevenson

The pixel rate is for now quite simple to compute, but with more features
(30 and 36 bits output, YUV output, etc.) will depend on a bunch of
connectors properties.

Let's store the rate we have to run the pixel clock at in our custom
connector state, and compute it in atomic_check.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 26 +++++++++++++++++++++++++-
 drivers/gpu/drm/vc4/vc4_hdmi.h |  1 +
 2 files changed, 26 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 862c93708e9a..c1667cfe37db 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -194,6 +194,7 @@ vc4_hdmi_connector_duplicate_state(struct drm_connector *connector)
 	if (!new_state)
 		return NULL;
 
+	new_state->pixel_rate = vc4_state->pixel_rate;
 	__drm_atomic_helper_connector_duplicate_state(connector, &new_state->base);
 
 	return &new_state->base;
@@ -611,9 +612,29 @@ static void vc4_hdmi_recenter_fifo(struct vc4_hdmi *vc4_hdmi)
 		  "VC4_HDMI_FIFO_CTL_RECENTER_DONE");
 }
 
+static struct drm_connector_state *
+vc4_hdmi_encoder_get_connector_state(struct drm_encoder *encoder,
+				     struct drm_atomic_state *state)
+{
+	struct drm_connector_state *conn_state;
+	struct drm_connector *connector;
+	unsigned int i;
+
+	for_each_new_connector_in_state(state, connector, conn_state, i) {
+		if (conn_state->best_encoder == encoder)
+			return conn_state;
+	}
+
+	return NULL;
+}
+
 static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder,
 						struct drm_atomic_state *state)
 {
+	struct drm_connector_state *conn_state =
+		vc4_hdmi_encoder_get_connector_state(encoder, state);
+	struct vc4_hdmi_connector_state *vc4_conn_state =
+		conn_state_to_vc4_hdmi_conn_state(conn_state);
 	struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
 	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
 	unsigned long pixel_rate, hsm_rate;
@@ -625,7 +646,7 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder,
 		return;
 	}
 
-	pixel_rate = mode->clock * 1000 * ((mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1);
+	pixel_rate = vc4_conn_state->pixel_rate;
 	ret = clk_set_rate(vc4_hdmi->pixel_clock, pixel_rate);
 	if (ret) {
 		DRM_ERROR("Failed to set pixel clock rate: %d\n", ret);
@@ -797,6 +818,7 @@ static int vc4_hdmi_encoder_atomic_check(struct drm_encoder *encoder,
 					 struct drm_crtc_state *crtc_state,
 					 struct drm_connector_state *conn_state)
 {
+	struct vc4_hdmi_connector_state *vc4_state = conn_state_to_vc4_hdmi_conn_state(conn_state);
 	struct drm_display_mode *mode = &crtc_state->adjusted_mode;
 	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
 	unsigned long long pixel_rate = mode->clock * 1000;
@@ -824,6 +846,8 @@ static int vc4_hdmi_encoder_atomic_check(struct drm_encoder *encoder,
 	if (pixel_rate > vc4_hdmi->variant->max_pixel_clock)
 		return -EINVAL;
 
+	vc4_state->pixel_rate = pixel_rate;
+
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
index 2cf5362052e2..bca6943de884 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
@@ -182,6 +182,7 @@ encoder_to_vc4_hdmi(struct drm_encoder *encoder)
 
 struct vc4_hdmi_connector_state {
 	struct drm_connector_state	base;
+	unsigned long long		pixel_rate;
 };
 
 static inline struct vc4_hdmi_connector_state *
-- 
2.28.0


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 5/8] drm/vc4: hdmi: Store pixel frequency in the connector state
@ 2020-12-07 13:39   ` Maxime Ripard
  0 siblings, 0 replies; 32+ messages in thread
From: Maxime Ripard @ 2020-12-07 13:39 UTC (permalink / raw)
  To: Maarten Lankhorst, Thomas Zimmermann, Maxime Ripard,
	Daniel Vetter, David Airlie, Eric Anholt
  Cc: linux-arm-kernel, bcm-kernel-feedback-list, linux-rpi-kernel,
	dri-devel, Dave Stevenson

The pixel rate is for now quite simple to compute, but with more features
(30 and 36 bits output, YUV output, etc.) will depend on a bunch of
connectors properties.

Let's store the rate we have to run the pixel clock at in our custom
connector state, and compute it in atomic_check.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 26 +++++++++++++++++++++++++-
 drivers/gpu/drm/vc4/vc4_hdmi.h |  1 +
 2 files changed, 26 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 862c93708e9a..c1667cfe37db 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -194,6 +194,7 @@ vc4_hdmi_connector_duplicate_state(struct drm_connector *connector)
 	if (!new_state)
 		return NULL;
 
+	new_state->pixel_rate = vc4_state->pixel_rate;
 	__drm_atomic_helper_connector_duplicate_state(connector, &new_state->base);
 
 	return &new_state->base;
@@ -611,9 +612,29 @@ static void vc4_hdmi_recenter_fifo(struct vc4_hdmi *vc4_hdmi)
 		  "VC4_HDMI_FIFO_CTL_RECENTER_DONE");
 }
 
+static struct drm_connector_state *
+vc4_hdmi_encoder_get_connector_state(struct drm_encoder *encoder,
+				     struct drm_atomic_state *state)
+{
+	struct drm_connector_state *conn_state;
+	struct drm_connector *connector;
+	unsigned int i;
+
+	for_each_new_connector_in_state(state, connector, conn_state, i) {
+		if (conn_state->best_encoder == encoder)
+			return conn_state;
+	}
+
+	return NULL;
+}
+
 static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder,
 						struct drm_atomic_state *state)
 {
+	struct drm_connector_state *conn_state =
+		vc4_hdmi_encoder_get_connector_state(encoder, state);
+	struct vc4_hdmi_connector_state *vc4_conn_state =
+		conn_state_to_vc4_hdmi_conn_state(conn_state);
 	struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
 	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
 	unsigned long pixel_rate, hsm_rate;
@@ -625,7 +646,7 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder,
 		return;
 	}
 
-	pixel_rate = mode->clock * 1000 * ((mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1);
+	pixel_rate = vc4_conn_state->pixel_rate;
 	ret = clk_set_rate(vc4_hdmi->pixel_clock, pixel_rate);
 	if (ret) {
 		DRM_ERROR("Failed to set pixel clock rate: %d\n", ret);
@@ -797,6 +818,7 @@ static int vc4_hdmi_encoder_atomic_check(struct drm_encoder *encoder,
 					 struct drm_crtc_state *crtc_state,
 					 struct drm_connector_state *conn_state)
 {
+	struct vc4_hdmi_connector_state *vc4_state = conn_state_to_vc4_hdmi_conn_state(conn_state);
 	struct drm_display_mode *mode = &crtc_state->adjusted_mode;
 	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
 	unsigned long long pixel_rate = mode->clock * 1000;
@@ -824,6 +846,8 @@ static int vc4_hdmi_encoder_atomic_check(struct drm_encoder *encoder,
 	if (pixel_rate > vc4_hdmi->variant->max_pixel_clock)
 		return -EINVAL;
 
+	vc4_state->pixel_rate = pixel_rate;
+
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
index 2cf5362052e2..bca6943de884 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
@@ -182,6 +182,7 @@ encoder_to_vc4_hdmi(struct drm_encoder *encoder)
 
 struct vc4_hdmi_connector_state {
 	struct drm_connector_state	base;
+	unsigned long long		pixel_rate;
 };
 
 static inline struct vc4_hdmi_connector_state *
-- 
2.28.0

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 6/8] drm/vc4: hdmi: Use the connector state pixel rate for the PHY
  2020-12-07 13:39 ` Maxime Ripard
@ 2020-12-07 13:39   ` Maxime Ripard
  -1 siblings, 0 replies; 32+ messages in thread
From: Maxime Ripard @ 2020-12-07 13:39 UTC (permalink / raw)
  To: Maarten Lankhorst, Thomas Zimmermann, Maxime Ripard,
	Daniel Vetter, David Airlie, Eric Anholt
  Cc: linux-arm-kernel, bcm-kernel-feedback-list, linux-rpi-kernel,
	dri-devel, Dave Stevenson

The PHY initialisation parameters are not based on the pixel clock but
the TMDS clock rate which can be the pixel clock in the standard case,
but could be adjusted based on some parameters like the bits per color.

Since the TMDS clock rate is stored in our custom connector state
already, let's reuse it from there instead of computing it again.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c     | 2 +-
 drivers/gpu/drm/vc4/vc4_hdmi.h     | 9 ++++-----
 drivers/gpu/drm/vc4/vc4_hdmi_phy.c | 8 +++++---
 3 files changed, 10 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index c1667cfe37db..795fd23c8f58 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -714,7 +714,7 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder,
 		vc4_hdmi->variant->reset(vc4_hdmi);
 
 	if (vc4_hdmi->variant->phy_init)
-		vc4_hdmi->variant->phy_init(vc4_hdmi, mode);
+		vc4_hdmi->variant->phy_init(vc4_hdmi, vc4_conn_state);
 
 	HDMI_WRITE(HDMI_SCHEDULER_CONTROL,
 		   HDMI_READ(HDMI_SCHEDULER_CONTROL) |
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
index bca6943de884..6cc5b6652cca 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
@@ -21,10 +21,9 @@ to_vc4_hdmi_encoder(struct drm_encoder *encoder)
 	return container_of(encoder, struct vc4_hdmi_encoder, base.base);
 }
 
-struct drm_display_mode;
-
 struct vc4_hdmi;
 struct vc4_hdmi_register;
+struct vc4_hdmi_connector_state;
 
 enum vc4_hdmi_phy_channel {
 	PHY_LANE_0 = 0,
@@ -82,7 +81,7 @@ struct vc4_hdmi_variant {
 
 	/* Callback to initialize the PHY according to the mode */
 	void (*phy_init)(struct vc4_hdmi *vc4_hdmi,
-			 struct drm_display_mode *mode);
+			 struct vc4_hdmi_connector_state *vc4_conn_state);
 
 	/* Callback to disable the PHY */
 	void (*phy_disable)(struct vc4_hdmi *vc4_hdmi);
@@ -192,13 +191,13 @@ conn_state_to_vc4_hdmi_conn_state(struct drm_connector_state *conn_state)
 }
 
 void vc4_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi,
-		       struct drm_display_mode *mode);
+		       struct vc4_hdmi_connector_state *vc4_conn_state);
 void vc4_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi);
 void vc4_hdmi_phy_rng_enable(struct vc4_hdmi *vc4_hdmi);
 void vc4_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi);
 
 void vc5_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi,
-		       struct drm_display_mode *mode);
+		       struct vc4_hdmi_connector_state *vc4_conn_state);
 void vc5_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi);
 void vc5_hdmi_phy_rng_enable(struct vc4_hdmi *vc4_hdmi);
 void vc5_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi);
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi_phy.c b/drivers/gpu/drm/vc4/vc4_hdmi_phy.c
index 057796b54c51..36535480f8e2 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi_phy.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi_phy.c
@@ -127,7 +127,8 @@
 
 #define OSCILLATOR_FREQUENCY	54000000
 
-void vc4_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi, struct drm_display_mode *mode)
+void vc4_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi,
+		       struct vc4_hdmi_connector_state *conn_state)
 {
 	/* PHY should be in reset, like
 	 * vc4_hdmi_encoder_disable() does.
@@ -339,11 +340,12 @@ static void vc5_hdmi_reset_phy(struct vc4_hdmi *vc4_hdmi)
 	HDMI_WRITE(HDMI_TX_PHY_POWERDOWN_CTL, BIT(10));
 }
 
-void vc5_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi, struct drm_display_mode *mode)
+void vc5_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi,
+		       struct vc4_hdmi_connector_state *conn_state)
 {
 	const struct phy_lane_settings *chan0_settings, *chan1_settings, *chan2_settings, *clock_settings;
 	const struct vc4_hdmi_variant *variant = vc4_hdmi->variant;
-	unsigned long long pixel_freq = mode->clock * 1000;
+	unsigned long long pixel_freq = conn_state->pixel_rate;
 	unsigned long long vco_freq;
 	unsigned char word_sel;
 	u8 vco_sel, vco_div;
-- 
2.28.0


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 6/8] drm/vc4: hdmi: Use the connector state pixel rate for the PHY
@ 2020-12-07 13:39   ` Maxime Ripard
  0 siblings, 0 replies; 32+ messages in thread
From: Maxime Ripard @ 2020-12-07 13:39 UTC (permalink / raw)
  To: Maarten Lankhorst, Thomas Zimmermann, Maxime Ripard,
	Daniel Vetter, David Airlie, Eric Anholt
  Cc: linux-arm-kernel, bcm-kernel-feedback-list, linux-rpi-kernel,
	dri-devel, Dave Stevenson

The PHY initialisation parameters are not based on the pixel clock but
the TMDS clock rate which can be the pixel clock in the standard case,
but could be adjusted based on some parameters like the bits per color.

Since the TMDS clock rate is stored in our custom connector state
already, let's reuse it from there instead of computing it again.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c     | 2 +-
 drivers/gpu/drm/vc4/vc4_hdmi.h     | 9 ++++-----
 drivers/gpu/drm/vc4/vc4_hdmi_phy.c | 8 +++++---
 3 files changed, 10 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index c1667cfe37db..795fd23c8f58 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -714,7 +714,7 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder,
 		vc4_hdmi->variant->reset(vc4_hdmi);
 
 	if (vc4_hdmi->variant->phy_init)
-		vc4_hdmi->variant->phy_init(vc4_hdmi, mode);
+		vc4_hdmi->variant->phy_init(vc4_hdmi, vc4_conn_state);
 
 	HDMI_WRITE(HDMI_SCHEDULER_CONTROL,
 		   HDMI_READ(HDMI_SCHEDULER_CONTROL) |
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
index bca6943de884..6cc5b6652cca 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
@@ -21,10 +21,9 @@ to_vc4_hdmi_encoder(struct drm_encoder *encoder)
 	return container_of(encoder, struct vc4_hdmi_encoder, base.base);
 }
 
-struct drm_display_mode;
-
 struct vc4_hdmi;
 struct vc4_hdmi_register;
+struct vc4_hdmi_connector_state;
 
 enum vc4_hdmi_phy_channel {
 	PHY_LANE_0 = 0,
@@ -82,7 +81,7 @@ struct vc4_hdmi_variant {
 
 	/* Callback to initialize the PHY according to the mode */
 	void (*phy_init)(struct vc4_hdmi *vc4_hdmi,
-			 struct drm_display_mode *mode);
+			 struct vc4_hdmi_connector_state *vc4_conn_state);
 
 	/* Callback to disable the PHY */
 	void (*phy_disable)(struct vc4_hdmi *vc4_hdmi);
@@ -192,13 +191,13 @@ conn_state_to_vc4_hdmi_conn_state(struct drm_connector_state *conn_state)
 }
 
 void vc4_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi,
-		       struct drm_display_mode *mode);
+		       struct vc4_hdmi_connector_state *vc4_conn_state);
 void vc4_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi);
 void vc4_hdmi_phy_rng_enable(struct vc4_hdmi *vc4_hdmi);
 void vc4_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi);
 
 void vc5_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi,
-		       struct drm_display_mode *mode);
+		       struct vc4_hdmi_connector_state *vc4_conn_state);
 void vc5_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi);
 void vc5_hdmi_phy_rng_enable(struct vc4_hdmi *vc4_hdmi);
 void vc5_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi);
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi_phy.c b/drivers/gpu/drm/vc4/vc4_hdmi_phy.c
index 057796b54c51..36535480f8e2 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi_phy.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi_phy.c
@@ -127,7 +127,8 @@
 
 #define OSCILLATOR_FREQUENCY	54000000
 
-void vc4_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi, struct drm_display_mode *mode)
+void vc4_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi,
+		       struct vc4_hdmi_connector_state *conn_state)
 {
 	/* PHY should be in reset, like
 	 * vc4_hdmi_encoder_disable() does.
@@ -339,11 +340,12 @@ static void vc5_hdmi_reset_phy(struct vc4_hdmi *vc4_hdmi)
 	HDMI_WRITE(HDMI_TX_PHY_POWERDOWN_CTL, BIT(10));
 }
 
-void vc5_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi, struct drm_display_mode *mode)
+void vc5_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi,
+		       struct vc4_hdmi_connector_state *conn_state)
 {
 	const struct phy_lane_settings *chan0_settings, *chan1_settings, *chan2_settings, *clock_settings;
 	const struct vc4_hdmi_variant *variant = vc4_hdmi->variant;
-	unsigned long long pixel_freq = mode->clock * 1000;
+	unsigned long long pixel_freq = conn_state->pixel_rate;
 	unsigned long long vco_freq;
 	unsigned char word_sel;
 	u8 vco_sel, vco_div;
-- 
2.28.0

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 7/8] drm/vc4: hdmi: Limit the BCM2711 to the max without scrambling
  2020-12-07 13:39 ` Maxime Ripard
@ 2020-12-07 13:39   ` Maxime Ripard
  -1 siblings, 0 replies; 32+ messages in thread
From: Maxime Ripard @ 2020-12-07 13:39 UTC (permalink / raw)
  To: Maarten Lankhorst, Thomas Zimmermann, Maxime Ripard,
	Daniel Vetter, David Airlie, Eric Anholt
  Cc: linux-arm-kernel, bcm-kernel-feedback-list, linux-rpi-kernel,
	dri-devel, Dave Stevenson

Unlike the previous generations, the HSM clock limitation is way above
what we can reach without scrambling, so let's move the maximum
frequency we support to the maximum clock frequency without scrambling.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 795fd23c8f58..e759ebd5fa34 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -82,6 +82,8 @@
 #define CEC_CLOCK_FREQ 40000
 #define VC4_HSM_MID_CLOCK 149985000
 
+#define HDMI_14_MAX_TMDS_CLK   (340 * 1000 * 1000)
+
 static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused)
 {
 	struct drm_info_node *node = (struct drm_info_node *)m->private;
@@ -1908,7 +1910,7 @@ static const struct vc4_hdmi_variant bcm2711_hdmi0_variant = {
 	.encoder_type		= VC4_ENCODER_TYPE_HDMI0,
 	.debugfs_name		= "hdmi0_regs",
 	.card_name		= "vc4-hdmi-0",
-	.max_pixel_clock	= 297000000,
+	.max_pixel_clock	= HDMI_14_MAX_TMDS_CLK,
 	.registers		= vc5_hdmi_hdmi0_fields,
 	.num_registers		= ARRAY_SIZE(vc5_hdmi_hdmi0_fields),
 	.phy_lane_mapping	= {
@@ -1934,7 +1936,7 @@ static const struct vc4_hdmi_variant bcm2711_hdmi1_variant = {
 	.encoder_type		= VC4_ENCODER_TYPE_HDMI1,
 	.debugfs_name		= "hdmi1_regs",
 	.card_name		= "vc4-hdmi-1",
-	.max_pixel_clock	= 297000000,
+	.max_pixel_clock	= HDMI_14_MAX_TMDS_CLK,
 	.registers		= vc5_hdmi_hdmi1_fields,
 	.num_registers		= ARRAY_SIZE(vc5_hdmi_hdmi1_fields),
 	.phy_lane_mapping	= {
-- 
2.28.0


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 7/8] drm/vc4: hdmi: Limit the BCM2711 to the max without scrambling
@ 2020-12-07 13:39   ` Maxime Ripard
  0 siblings, 0 replies; 32+ messages in thread
From: Maxime Ripard @ 2020-12-07 13:39 UTC (permalink / raw)
  To: Maarten Lankhorst, Thomas Zimmermann, Maxime Ripard,
	Daniel Vetter, David Airlie, Eric Anholt
  Cc: linux-arm-kernel, bcm-kernel-feedback-list, linux-rpi-kernel,
	dri-devel, Dave Stevenson

Unlike the previous generations, the HSM clock limitation is way above
what we can reach without scrambling, so let's move the maximum
frequency we support to the maximum clock frequency without scrambling.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 795fd23c8f58..e759ebd5fa34 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -82,6 +82,8 @@
 #define CEC_CLOCK_FREQ 40000
 #define VC4_HSM_MID_CLOCK 149985000
 
+#define HDMI_14_MAX_TMDS_CLK   (340 * 1000 * 1000)
+
 static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused)
 {
 	struct drm_info_node *node = (struct drm_info_node *)m->private;
@@ -1908,7 +1910,7 @@ static const struct vc4_hdmi_variant bcm2711_hdmi0_variant = {
 	.encoder_type		= VC4_ENCODER_TYPE_HDMI0,
 	.debugfs_name		= "hdmi0_regs",
 	.card_name		= "vc4-hdmi-0",
-	.max_pixel_clock	= 297000000,
+	.max_pixel_clock	= HDMI_14_MAX_TMDS_CLK,
 	.registers		= vc5_hdmi_hdmi0_fields,
 	.num_registers		= ARRAY_SIZE(vc5_hdmi_hdmi0_fields),
 	.phy_lane_mapping	= {
@@ -1934,7 +1936,7 @@ static const struct vc4_hdmi_variant bcm2711_hdmi1_variant = {
 	.encoder_type		= VC4_ENCODER_TYPE_HDMI1,
 	.debugfs_name		= "hdmi1_regs",
 	.card_name		= "vc4-hdmi-1",
-	.max_pixel_clock	= 297000000,
+	.max_pixel_clock	= HDMI_14_MAX_TMDS_CLK,
 	.registers		= vc5_hdmi_hdmi1_fields,
 	.num_registers		= ARRAY_SIZE(vc5_hdmi_hdmi1_fields),
 	.phy_lane_mapping	= {
-- 
2.28.0

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 8/8] drm/vc4: hdmi: Enable 10/12 bpc output
  2020-12-07 13:39 ` Maxime Ripard
@ 2020-12-07 13:39   ` Maxime Ripard
  -1 siblings, 0 replies; 32+ messages in thread
From: Maxime Ripard @ 2020-12-07 13:39 UTC (permalink / raw)
  To: Maarten Lankhorst, Thomas Zimmermann, Maxime Ripard,
	Daniel Vetter, David Airlie, Eric Anholt
  Cc: linux-arm-kernel, bcm-kernel-feedback-list, linux-rpi-kernel,
	dri-devel, Dave Stevenson

The BCM2711 supports higher bpc count than just 8, so let's support it in
our driver.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c      | 71 ++++++++++++++++++++++++++++-
 drivers/gpu/drm/vc4/vc4_hdmi.h      |  1 +
 drivers/gpu/drm/vc4/vc4_hdmi_regs.h |  9 ++++
 3 files changed, 80 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index e759ebd5fa34..8006bddc8fbb 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -76,6 +76,17 @@
 #define VC5_HDMI_VERTB_VSPO_SHIFT		16
 #define VC5_HDMI_VERTB_VSPO_MASK		VC4_MASK(29, 16)
 
+#define VC5_HDMI_DEEP_COLOR_CONFIG_1_INIT_PACK_PHASE_SHIFT	8
+#define VC5_HDMI_DEEP_COLOR_CONFIG_1_INIT_PACK_PHASE_MASK	VC4_MASK(10, 8)
+
+#define VC5_HDMI_DEEP_COLOR_CONFIG_1_COLOR_DEPTH_SHIFT		0
+#define VC5_HDMI_DEEP_COLOR_CONFIG_1_COLOR_DEPTH_MASK		VC4_MASK(3, 0)
+
+#define VC5_HDMI_GCP_CONFIG_GCP_ENABLE		BIT(31)
+
+#define VC5_HDMI_GCP_WORD_1_GCP_SUBPACKET_BYTE_1_SHIFT	8
+#define VC5_HDMI_GCP_WORD_1_GCP_SUBPACKET_BYTE_1_MASK	VC4_MASK(15, 8)
+
 # define VC4_HD_M_SW_RST			BIT(2)
 # define VC4_HD_M_ENABLE			BIT(0)
 
@@ -179,6 +190,9 @@ static void vc4_hdmi_connector_reset(struct drm_connector *connector)
 
 	kfree(connector->state);
 
+	conn_state->base.max_bpc = 8;
+	conn_state->base.max_requested_bpc = 8;
+
 	__drm_atomic_helper_connector_reset(connector, &conn_state->base);
 
 	if (connector->state)
@@ -228,12 +242,20 @@ static int vc4_hdmi_connector_init(struct drm_device *dev,
 				    vc4_hdmi->ddc);
 	drm_connector_helper_add(connector, &vc4_hdmi_connector_helper_funcs);
 
+	/*
+	 * Some of the properties below require access to state, like bpc.
+	 * Allocate some default initial connector state with our reset helper.
+	 */
+	if (connector->funcs->reset)
+		connector->funcs->reset(connector);
+
 	/* Create and attach TV margin props to this connector. */
 	ret = drm_mode_create_tv_margin_properties(dev);
 	if (ret)
 		return ret;
 
 	drm_connector_attach_tv_margin_properties(connector);
+	drm_connector_attach_max_bpc_property(connector, 8, 12);
 
 	connector->polled = (DRM_CONNECTOR_POLL_CONNECT |
 			     DRM_CONNECTOR_POLL_DISCONNECT);
@@ -499,6 +521,7 @@ static void vc5_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, bool enable)
 }
 
 static void vc4_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
+				 struct drm_connector_state *state,
 				 struct drm_display_mode *mode)
 {
 	bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC;
@@ -542,7 +565,9 @@ static void vc4_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
 	HDMI_WRITE(HDMI_VERTB0, vertb_even);
 	HDMI_WRITE(HDMI_VERTB1, vertb);
 }
+
 static void vc5_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
+				 struct drm_connector_state *state,
 				 struct drm_display_mode *mode)
 {
 	bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC;
@@ -562,6 +587,9 @@ static void vc5_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
 					mode->crtc_vsync_end -
 					interlaced,
 					VC4_HDMI_VERTB_VBP));
+	unsigned char gcp;
+	bool gcp_en;
+	u32 reg;
 
 	HDMI_WRITE(HDMI_VEC_INTERFACE_XBAR, 0x354021);
 	HDMI_WRITE(HDMI_HORZA,
@@ -587,6 +615,39 @@ static void vc5_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
 	HDMI_WRITE(HDMI_VERTB0, vertb_even);
 	HDMI_WRITE(HDMI_VERTB1, vertb);
 
+	switch (state->max_bpc) {
+	case 12:
+		gcp = 6;
+		gcp_en = true;
+		break;
+	case 10:
+		gcp = 5;
+		gcp_en = true;
+		break;
+	case 8:
+	default:
+		gcp = 4;
+		gcp_en = false;
+		break;
+	}
+
+	reg = HDMI_READ(HDMI_DEEP_COLOR_CONFIG_1);
+	reg &= ~(VC5_HDMI_DEEP_COLOR_CONFIG_1_INIT_PACK_PHASE_MASK |
+		 VC5_HDMI_DEEP_COLOR_CONFIG_1_COLOR_DEPTH_MASK);
+	reg |= VC4_SET_FIELD(2, VC5_HDMI_DEEP_COLOR_CONFIG_1_INIT_PACK_PHASE) |
+	       VC4_SET_FIELD(gcp, VC5_HDMI_DEEP_COLOR_CONFIG_1_COLOR_DEPTH);
+	HDMI_WRITE(HDMI_DEEP_COLOR_CONFIG_1, reg);
+
+	reg = HDMI_READ(HDMI_GCP_WORD_1);
+	reg &= ~VC5_HDMI_GCP_WORD_1_GCP_SUBPACKET_BYTE_1_MASK;
+	reg |= VC4_SET_FIELD(gcp, VC5_HDMI_GCP_WORD_1_GCP_SUBPACKET_BYTE_1);
+	HDMI_WRITE(HDMI_GCP_WORD_1, reg);
+
+	reg = HDMI_READ(HDMI_GCP_CONFIG);
+	reg &= ~VC5_HDMI_GCP_CONFIG_GCP_ENABLE;
+	reg |= gcp_en ? VC5_HDMI_GCP_CONFIG_GCP_ENABLE : 0;
+	HDMI_WRITE(HDMI_GCP_CONFIG, reg);
+
 	HDMI_WRITE(HDMI_CLOCK_STOP, 0);
 }
 
@@ -724,7 +785,7 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder,
 		   VC4_HDMI_SCHEDULER_CONTROL_IGNORE_VSYNC_PREDICTS);
 
 	if (vc4_hdmi->variant->set_timings)
-		vc4_hdmi->variant->set_timings(vc4_hdmi, mode);
+		vc4_hdmi->variant->set_timings(vc4_hdmi, conn_state, mode);
 }
 
 static void vc4_hdmi_encoder_pre_crtc_enable(struct drm_encoder *encoder,
@@ -845,6 +906,14 @@ static int vc4_hdmi_encoder_atomic_check(struct drm_encoder *encoder,
 		pixel_rate = mode->clock * 1000;
 	}
 
+	if (conn_state->max_bpc == 12) {
+		pixel_rate = pixel_rate * 150;
+		do_div(pixel_rate, 100);
+	} else if (conn_state->max_bpc == 10) {
+		pixel_rate = pixel_rate * 125;
+		do_div(pixel_rate, 100);
+	}
+
 	if (pixel_rate > vc4_hdmi->variant->max_pixel_clock)
 		return -EINVAL;
 
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
index 6cc5b6652cca..720914761261 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
@@ -77,6 +77,7 @@ struct vc4_hdmi_variant {
 
 	/* Callback to configure the video timings in the HDMI block */
 	void (*set_timings)(struct vc4_hdmi *vc4_hdmi,
+			    struct drm_connector_state *state,
 			    struct drm_display_mode *mode);
 
 	/* Callback to initialize the PHY according to the mode */
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi_regs.h b/drivers/gpu/drm/vc4/vc4_hdmi_regs.h
index 7c6b4818f245..013fd57febd8 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi_regs.h
+++ b/drivers/gpu/drm/vc4/vc4_hdmi_regs.h
@@ -59,9 +59,12 @@ enum vc4_hdmi_field {
 	 */
 	HDMI_CTS_0,
 	HDMI_CTS_1,
+	HDMI_DEEP_COLOR_CONFIG_1,
 	HDMI_DVP_CTL,
 	HDMI_FIFO_CTL,
 	HDMI_FRAME_COUNT,
+	HDMI_GCP_CONFIG,
+	HDMI_GCP_WORD_1,
 	HDMI_HORZA,
 	HDMI_HORZB,
 	HDMI_HOTPLUG,
@@ -229,6 +232,9 @@ static const struct vc4_hdmi_register vc5_hdmi_hdmi0_fields[] = {
 	VC4_HDMI_REG(HDMI_VERTB1, 0x0f8),
 	VC4_HDMI_REG(HDMI_MAI_CHANNEL_MAP, 0x09c),
 	VC4_HDMI_REG(HDMI_MAI_CONFIG, 0x0a0),
+	VC4_HDMI_REG(HDMI_DEEP_COLOR_CONFIG_1, 0x170),
+	VC4_HDMI_REG(HDMI_GCP_CONFIG, 0x178),
+	VC4_HDMI_REG(HDMI_GCP_WORD_1, 0x17c),
 	VC4_HDMI_REG(HDMI_HOTPLUG, 0x1a8),
 
 	VC5_DVP_REG(HDMI_CLOCK_STOP, 0x0bc),
@@ -305,6 +311,9 @@ static const struct vc4_hdmi_register vc5_hdmi_hdmi1_fields[] = {
 	VC4_HDMI_REG(HDMI_VERTB1, 0x0f8),
 	VC4_HDMI_REG(HDMI_MAI_CHANNEL_MAP, 0x09c),
 	VC4_HDMI_REG(HDMI_MAI_CONFIG, 0x0a0),
+	VC4_HDMI_REG(HDMI_DEEP_COLOR_CONFIG_1, 0x170),
+	VC4_HDMI_REG(HDMI_GCP_CONFIG, 0x178),
+	VC4_HDMI_REG(HDMI_GCP_WORD_1, 0x17c),
 	VC4_HDMI_REG(HDMI_HOTPLUG, 0x1a8),
 
 	VC5_DVP_REG(HDMI_CLOCK_STOP, 0x0bc),
-- 
2.28.0


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 8/8] drm/vc4: hdmi: Enable 10/12 bpc output
@ 2020-12-07 13:39   ` Maxime Ripard
  0 siblings, 0 replies; 32+ messages in thread
From: Maxime Ripard @ 2020-12-07 13:39 UTC (permalink / raw)
  To: Maarten Lankhorst, Thomas Zimmermann, Maxime Ripard,
	Daniel Vetter, David Airlie, Eric Anholt
  Cc: linux-arm-kernel, bcm-kernel-feedback-list, linux-rpi-kernel,
	dri-devel, Dave Stevenson

The BCM2711 supports higher bpc count than just 8, so let's support it in
our driver.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c      | 71 ++++++++++++++++++++++++++++-
 drivers/gpu/drm/vc4/vc4_hdmi.h      |  1 +
 drivers/gpu/drm/vc4/vc4_hdmi_regs.h |  9 ++++
 3 files changed, 80 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index e759ebd5fa34..8006bddc8fbb 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -76,6 +76,17 @@
 #define VC5_HDMI_VERTB_VSPO_SHIFT		16
 #define VC5_HDMI_VERTB_VSPO_MASK		VC4_MASK(29, 16)
 
+#define VC5_HDMI_DEEP_COLOR_CONFIG_1_INIT_PACK_PHASE_SHIFT	8
+#define VC5_HDMI_DEEP_COLOR_CONFIG_1_INIT_PACK_PHASE_MASK	VC4_MASK(10, 8)
+
+#define VC5_HDMI_DEEP_COLOR_CONFIG_1_COLOR_DEPTH_SHIFT		0
+#define VC5_HDMI_DEEP_COLOR_CONFIG_1_COLOR_DEPTH_MASK		VC4_MASK(3, 0)
+
+#define VC5_HDMI_GCP_CONFIG_GCP_ENABLE		BIT(31)
+
+#define VC5_HDMI_GCP_WORD_1_GCP_SUBPACKET_BYTE_1_SHIFT	8
+#define VC5_HDMI_GCP_WORD_1_GCP_SUBPACKET_BYTE_1_MASK	VC4_MASK(15, 8)
+
 # define VC4_HD_M_SW_RST			BIT(2)
 # define VC4_HD_M_ENABLE			BIT(0)
 
@@ -179,6 +190,9 @@ static void vc4_hdmi_connector_reset(struct drm_connector *connector)
 
 	kfree(connector->state);
 
+	conn_state->base.max_bpc = 8;
+	conn_state->base.max_requested_bpc = 8;
+
 	__drm_atomic_helper_connector_reset(connector, &conn_state->base);
 
 	if (connector->state)
@@ -228,12 +242,20 @@ static int vc4_hdmi_connector_init(struct drm_device *dev,
 				    vc4_hdmi->ddc);
 	drm_connector_helper_add(connector, &vc4_hdmi_connector_helper_funcs);
 
+	/*
+	 * Some of the properties below require access to state, like bpc.
+	 * Allocate some default initial connector state with our reset helper.
+	 */
+	if (connector->funcs->reset)
+		connector->funcs->reset(connector);
+
 	/* Create and attach TV margin props to this connector. */
 	ret = drm_mode_create_tv_margin_properties(dev);
 	if (ret)
 		return ret;
 
 	drm_connector_attach_tv_margin_properties(connector);
+	drm_connector_attach_max_bpc_property(connector, 8, 12);
 
 	connector->polled = (DRM_CONNECTOR_POLL_CONNECT |
 			     DRM_CONNECTOR_POLL_DISCONNECT);
@@ -499,6 +521,7 @@ static void vc5_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, bool enable)
 }
 
 static void vc4_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
+				 struct drm_connector_state *state,
 				 struct drm_display_mode *mode)
 {
 	bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC;
@@ -542,7 +565,9 @@ static void vc4_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
 	HDMI_WRITE(HDMI_VERTB0, vertb_even);
 	HDMI_WRITE(HDMI_VERTB1, vertb);
 }
+
 static void vc5_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
+				 struct drm_connector_state *state,
 				 struct drm_display_mode *mode)
 {
 	bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC;
@@ -562,6 +587,9 @@ static void vc5_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
 					mode->crtc_vsync_end -
 					interlaced,
 					VC4_HDMI_VERTB_VBP));
+	unsigned char gcp;
+	bool gcp_en;
+	u32 reg;
 
 	HDMI_WRITE(HDMI_VEC_INTERFACE_XBAR, 0x354021);
 	HDMI_WRITE(HDMI_HORZA,
@@ -587,6 +615,39 @@ static void vc5_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
 	HDMI_WRITE(HDMI_VERTB0, vertb_even);
 	HDMI_WRITE(HDMI_VERTB1, vertb);
 
+	switch (state->max_bpc) {
+	case 12:
+		gcp = 6;
+		gcp_en = true;
+		break;
+	case 10:
+		gcp = 5;
+		gcp_en = true;
+		break;
+	case 8:
+	default:
+		gcp = 4;
+		gcp_en = false;
+		break;
+	}
+
+	reg = HDMI_READ(HDMI_DEEP_COLOR_CONFIG_1);
+	reg &= ~(VC5_HDMI_DEEP_COLOR_CONFIG_1_INIT_PACK_PHASE_MASK |
+		 VC5_HDMI_DEEP_COLOR_CONFIG_1_COLOR_DEPTH_MASK);
+	reg |= VC4_SET_FIELD(2, VC5_HDMI_DEEP_COLOR_CONFIG_1_INIT_PACK_PHASE) |
+	       VC4_SET_FIELD(gcp, VC5_HDMI_DEEP_COLOR_CONFIG_1_COLOR_DEPTH);
+	HDMI_WRITE(HDMI_DEEP_COLOR_CONFIG_1, reg);
+
+	reg = HDMI_READ(HDMI_GCP_WORD_1);
+	reg &= ~VC5_HDMI_GCP_WORD_1_GCP_SUBPACKET_BYTE_1_MASK;
+	reg |= VC4_SET_FIELD(gcp, VC5_HDMI_GCP_WORD_1_GCP_SUBPACKET_BYTE_1);
+	HDMI_WRITE(HDMI_GCP_WORD_1, reg);
+
+	reg = HDMI_READ(HDMI_GCP_CONFIG);
+	reg &= ~VC5_HDMI_GCP_CONFIG_GCP_ENABLE;
+	reg |= gcp_en ? VC5_HDMI_GCP_CONFIG_GCP_ENABLE : 0;
+	HDMI_WRITE(HDMI_GCP_CONFIG, reg);
+
 	HDMI_WRITE(HDMI_CLOCK_STOP, 0);
 }
 
@@ -724,7 +785,7 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder,
 		   VC4_HDMI_SCHEDULER_CONTROL_IGNORE_VSYNC_PREDICTS);
 
 	if (vc4_hdmi->variant->set_timings)
-		vc4_hdmi->variant->set_timings(vc4_hdmi, mode);
+		vc4_hdmi->variant->set_timings(vc4_hdmi, conn_state, mode);
 }
 
 static void vc4_hdmi_encoder_pre_crtc_enable(struct drm_encoder *encoder,
@@ -845,6 +906,14 @@ static int vc4_hdmi_encoder_atomic_check(struct drm_encoder *encoder,
 		pixel_rate = mode->clock * 1000;
 	}
 
+	if (conn_state->max_bpc == 12) {
+		pixel_rate = pixel_rate * 150;
+		do_div(pixel_rate, 100);
+	} else if (conn_state->max_bpc == 10) {
+		pixel_rate = pixel_rate * 125;
+		do_div(pixel_rate, 100);
+	}
+
 	if (pixel_rate > vc4_hdmi->variant->max_pixel_clock)
 		return -EINVAL;
 
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
index 6cc5b6652cca..720914761261 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
@@ -77,6 +77,7 @@ struct vc4_hdmi_variant {
 
 	/* Callback to configure the video timings in the HDMI block */
 	void (*set_timings)(struct vc4_hdmi *vc4_hdmi,
+			    struct drm_connector_state *state,
 			    struct drm_display_mode *mode);
 
 	/* Callback to initialize the PHY according to the mode */
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi_regs.h b/drivers/gpu/drm/vc4/vc4_hdmi_regs.h
index 7c6b4818f245..013fd57febd8 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi_regs.h
+++ b/drivers/gpu/drm/vc4/vc4_hdmi_regs.h
@@ -59,9 +59,12 @@ enum vc4_hdmi_field {
 	 */
 	HDMI_CTS_0,
 	HDMI_CTS_1,
+	HDMI_DEEP_COLOR_CONFIG_1,
 	HDMI_DVP_CTL,
 	HDMI_FIFO_CTL,
 	HDMI_FRAME_COUNT,
+	HDMI_GCP_CONFIG,
+	HDMI_GCP_WORD_1,
 	HDMI_HORZA,
 	HDMI_HORZB,
 	HDMI_HOTPLUG,
@@ -229,6 +232,9 @@ static const struct vc4_hdmi_register vc5_hdmi_hdmi0_fields[] = {
 	VC4_HDMI_REG(HDMI_VERTB1, 0x0f8),
 	VC4_HDMI_REG(HDMI_MAI_CHANNEL_MAP, 0x09c),
 	VC4_HDMI_REG(HDMI_MAI_CONFIG, 0x0a0),
+	VC4_HDMI_REG(HDMI_DEEP_COLOR_CONFIG_1, 0x170),
+	VC4_HDMI_REG(HDMI_GCP_CONFIG, 0x178),
+	VC4_HDMI_REG(HDMI_GCP_WORD_1, 0x17c),
 	VC4_HDMI_REG(HDMI_HOTPLUG, 0x1a8),
 
 	VC5_DVP_REG(HDMI_CLOCK_STOP, 0x0bc),
@@ -305,6 +311,9 @@ static const struct vc4_hdmi_register vc5_hdmi_hdmi1_fields[] = {
 	VC4_HDMI_REG(HDMI_VERTB1, 0x0f8),
 	VC4_HDMI_REG(HDMI_MAI_CHANNEL_MAP, 0x09c),
 	VC4_HDMI_REG(HDMI_MAI_CONFIG, 0x0a0),
+	VC4_HDMI_REG(HDMI_DEEP_COLOR_CONFIG_1, 0x170),
+	VC4_HDMI_REG(HDMI_GCP_CONFIG, 0x178),
+	VC4_HDMI_REG(HDMI_GCP_WORD_1, 0x17c),
 	VC4_HDMI_REG(HDMI_HOTPLUG, 0x1a8),
 
 	VC5_DVP_REG(HDMI_CLOCK_STOP, 0x0bc),
-- 
2.28.0

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v4 3/8] drm/vc4: hdmi: Don't access the connector state in reset if kmalloc fails
  2020-12-07 13:39   ` Maxime Ripard
@ 2020-12-07 14:05     ` Thomas Zimmermann
  -1 siblings, 0 replies; 32+ messages in thread
From: Thomas Zimmermann @ 2020-12-07 14:05 UTC (permalink / raw)
  To: Maxime Ripard, Maarten Lankhorst, Daniel Vetter, David Airlie,
	Eric Anholt
  Cc: linux-arm-kernel, bcm-kernel-feedback-list, linux-rpi-kernel,
	dri-devel, Dave Stevenson


[-- Attachment #1.1.1: Type: text/plain, Size: 1558 bytes --]



Am 07.12.20 um 14:39 schrieb Maxime Ripard:
> drm_atomic_helper_connector_reset uses kmalloc which, from an API
> standpoint, can fail, and thus setting connector->state to NULL.
> However, our reset hook then calls drm_atomic_helper_connector_tv_reset
> that will access connector->state without checking if it's a valid
> pointer or not.
> 
> Make sure we don't end up accessing a NULL pointer.
> 
> Suggested-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Acked-by: Thomas Zimmermann <tzimmermann@suse.de>

> ---
>   drivers/gpu/drm/vc4/vc4_hdmi.c | 4 +++-
>   1 file changed, 3 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index 5a608ed1d75e..112c09873eb4 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -171,7 +171,9 @@ static int vc4_hdmi_connector_get_modes(struct drm_connector *connector)
>   static void vc4_hdmi_connector_reset(struct drm_connector *connector)
>   {
>   	drm_atomic_helper_connector_reset(connector);
> -	drm_atomic_helper_connector_tv_reset(connector);
> +
> +	if (connector->state)
> +		drm_atomic_helper_connector_tv_reset(connector);
>   }
>   
>   static const struct drm_connector_funcs vc4_hdmi_connector_funcs = {
> 

-- 
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Maxfeldstr. 5, 90409 Nürnberg, Germany
(HRB 36809, AG Nürnberg)
Geschäftsführer: Felix Imendörffer


[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 840 bytes --]

[-- Attachment #2: Type: text/plain, Size: 176 bytes --]

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v4 3/8] drm/vc4: hdmi: Don't access the connector state in reset if kmalloc fails
@ 2020-12-07 14:05     ` Thomas Zimmermann
  0 siblings, 0 replies; 32+ messages in thread
From: Thomas Zimmermann @ 2020-12-07 14:05 UTC (permalink / raw)
  To: Maxime Ripard, Maarten Lankhorst, Daniel Vetter, David Airlie,
	Eric Anholt
  Cc: linux-arm-kernel, bcm-kernel-feedback-list, linux-rpi-kernel,
	dri-devel, Dave Stevenson


[-- Attachment #1.1.1: Type: text/plain, Size: 1558 bytes --]



Am 07.12.20 um 14:39 schrieb Maxime Ripard:
> drm_atomic_helper_connector_reset uses kmalloc which, from an API
> standpoint, can fail, and thus setting connector->state to NULL.
> However, our reset hook then calls drm_atomic_helper_connector_tv_reset
> that will access connector->state without checking if it's a valid
> pointer or not.
> 
> Make sure we don't end up accessing a NULL pointer.
> 
> Suggested-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Acked-by: Thomas Zimmermann <tzimmermann@suse.de>

> ---
>   drivers/gpu/drm/vc4/vc4_hdmi.c | 4 +++-
>   1 file changed, 3 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index 5a608ed1d75e..112c09873eb4 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -171,7 +171,9 @@ static int vc4_hdmi_connector_get_modes(struct drm_connector *connector)
>   static void vc4_hdmi_connector_reset(struct drm_connector *connector)
>   {
>   	drm_atomic_helper_connector_reset(connector);
> -	drm_atomic_helper_connector_tv_reset(connector);
> +
> +	if (connector->state)
> +		drm_atomic_helper_connector_tv_reset(connector);
>   }
>   
>   static const struct drm_connector_funcs vc4_hdmi_connector_funcs = {
> 

-- 
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Maxfeldstr. 5, 90409 Nürnberg, Germany
(HRB 36809, AG Nürnberg)
Geschäftsführer: Felix Imendörffer


[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 840 bytes --]

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v4 4/8] drm/vc4: hdmi: Create a custom connector state
  2020-12-07 13:39   ` Maxime Ripard
@ 2020-12-07 14:07     ` Thomas Zimmermann
  -1 siblings, 0 replies; 32+ messages in thread
From: Thomas Zimmermann @ 2020-12-07 14:07 UTC (permalink / raw)
  To: Maxime Ripard, Maarten Lankhorst, Daniel Vetter, David Airlie,
	Eric Anholt
  Cc: linux-arm-kernel, bcm-kernel-feedback-list, linux-rpi-kernel,
	dri-devel, Dave Stevenson


[-- Attachment #1.1.1: Type: text/plain, Size: 3527 bytes --]



Am 07.12.20 um 14:39 schrieb Maxime Ripard:
> When run with a higher bpc than 8, the clock of the HDMI controller needs
> to be adjusted. Let's create a connector state that will be used at
> atomic_check and atomic_enable to compute and store the clock rate
> associated to the state.
> 
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Acked-by: Thomas Zimmermann <tzimmermann@suse.de>

> ---
>   drivers/gpu/drm/vc4/vc4_hdmi.c | 27 +++++++++++++++++++++++++--
>   drivers/gpu/drm/vc4/vc4_hdmi.h | 10 ++++++++++
>   2 files changed, 35 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index 112c09873eb4..862c93708e9a 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -170,18 +170,41 @@ static int vc4_hdmi_connector_get_modes(struct drm_connector *connector)
>   
>   static void vc4_hdmi_connector_reset(struct drm_connector *connector)
>   {
> -	drm_atomic_helper_connector_reset(connector);
> +	struct vc4_hdmi_connector_state *conn_state = kzalloc(sizeof(*conn_state), GFP_KERNEL);
> +
> +	if (connector->state)
> +		__drm_atomic_helper_connector_destroy_state(connector->state);
> +
> +	kfree(connector->state);
> +
> +	__drm_atomic_helper_connector_reset(connector, &conn_state->base);
>   
>   	if (connector->state)
>   		drm_atomic_helper_connector_tv_reset(connector);
>   }
>   
> +static struct drm_connector_state *
> +vc4_hdmi_connector_duplicate_state(struct drm_connector *connector)
> +{
> +	struct drm_connector_state *conn_state = connector->state;
> +	struct vc4_hdmi_connector_state *vc4_state = conn_state_to_vc4_hdmi_conn_state(conn_state);
> +	struct vc4_hdmi_connector_state *new_state;
> +
> +	new_state = kzalloc(sizeof(*new_state), GFP_KERNEL);
> +	if (!new_state)
> +		return NULL;
> +
> +	__drm_atomic_helper_connector_duplicate_state(connector, &new_state->base);
> +
> +	return &new_state->base;
> +}
> +
>   static const struct drm_connector_funcs vc4_hdmi_connector_funcs = {
>   	.detect = vc4_hdmi_connector_detect,
>   	.fill_modes = drm_helper_probe_single_connector_modes,
>   	.destroy = vc4_hdmi_connector_destroy,
>   	.reset = vc4_hdmi_connector_reset,
> -	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
> +	.atomic_duplicate_state = vc4_hdmi_connector_duplicate_state,
>   	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
>   };
>   
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
> index 0526a9cf608a..2cf5362052e2 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.h
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
> @@ -180,6 +180,16 @@ encoder_to_vc4_hdmi(struct drm_encoder *encoder)
>   	return container_of(_encoder, struct vc4_hdmi, encoder);
>   }
>   
> +struct vc4_hdmi_connector_state {
> +	struct drm_connector_state	base;
> +};
> +
> +static inline struct vc4_hdmi_connector_state *
> +conn_state_to_vc4_hdmi_conn_state(struct drm_connector_state *conn_state)
> +{
> +	return container_of(conn_state, struct vc4_hdmi_connector_state, base);
> +}
> +
>   void vc4_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi,
>   		       struct drm_display_mode *mode);
>   void vc4_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi);
> 

-- 
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Maxfeldstr. 5, 90409 Nürnberg, Germany
(HRB 36809, AG Nürnberg)
Geschäftsführer: Felix Imendörffer


[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 840 bytes --]

[-- Attachment #2: Type: text/plain, Size: 176 bytes --]

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v4 4/8] drm/vc4: hdmi: Create a custom connector state
@ 2020-12-07 14:07     ` Thomas Zimmermann
  0 siblings, 0 replies; 32+ messages in thread
From: Thomas Zimmermann @ 2020-12-07 14:07 UTC (permalink / raw)
  To: Maxime Ripard, Maarten Lankhorst, Daniel Vetter, David Airlie,
	Eric Anholt
  Cc: linux-arm-kernel, bcm-kernel-feedback-list, linux-rpi-kernel,
	dri-devel, Dave Stevenson


[-- Attachment #1.1.1: Type: text/plain, Size: 3527 bytes --]



Am 07.12.20 um 14:39 schrieb Maxime Ripard:
> When run with a higher bpc than 8, the clock of the HDMI controller needs
> to be adjusted. Let's create a connector state that will be used at
> atomic_check and atomic_enable to compute and store the clock rate
> associated to the state.
> 
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Acked-by: Thomas Zimmermann <tzimmermann@suse.de>

> ---
>   drivers/gpu/drm/vc4/vc4_hdmi.c | 27 +++++++++++++++++++++++++--
>   drivers/gpu/drm/vc4/vc4_hdmi.h | 10 ++++++++++
>   2 files changed, 35 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index 112c09873eb4..862c93708e9a 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -170,18 +170,41 @@ static int vc4_hdmi_connector_get_modes(struct drm_connector *connector)
>   
>   static void vc4_hdmi_connector_reset(struct drm_connector *connector)
>   {
> -	drm_atomic_helper_connector_reset(connector);
> +	struct vc4_hdmi_connector_state *conn_state = kzalloc(sizeof(*conn_state), GFP_KERNEL);
> +
> +	if (connector->state)
> +		__drm_atomic_helper_connector_destroy_state(connector->state);
> +
> +	kfree(connector->state);
> +
> +	__drm_atomic_helper_connector_reset(connector, &conn_state->base);
>   
>   	if (connector->state)
>   		drm_atomic_helper_connector_tv_reset(connector);
>   }
>   
> +static struct drm_connector_state *
> +vc4_hdmi_connector_duplicate_state(struct drm_connector *connector)
> +{
> +	struct drm_connector_state *conn_state = connector->state;
> +	struct vc4_hdmi_connector_state *vc4_state = conn_state_to_vc4_hdmi_conn_state(conn_state);
> +	struct vc4_hdmi_connector_state *new_state;
> +
> +	new_state = kzalloc(sizeof(*new_state), GFP_KERNEL);
> +	if (!new_state)
> +		return NULL;
> +
> +	__drm_atomic_helper_connector_duplicate_state(connector, &new_state->base);
> +
> +	return &new_state->base;
> +}
> +
>   static const struct drm_connector_funcs vc4_hdmi_connector_funcs = {
>   	.detect = vc4_hdmi_connector_detect,
>   	.fill_modes = drm_helper_probe_single_connector_modes,
>   	.destroy = vc4_hdmi_connector_destroy,
>   	.reset = vc4_hdmi_connector_reset,
> -	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
> +	.atomic_duplicate_state = vc4_hdmi_connector_duplicate_state,
>   	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
>   };
>   
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
> index 0526a9cf608a..2cf5362052e2 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.h
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
> @@ -180,6 +180,16 @@ encoder_to_vc4_hdmi(struct drm_encoder *encoder)
>   	return container_of(_encoder, struct vc4_hdmi, encoder);
>   }
>   
> +struct vc4_hdmi_connector_state {
> +	struct drm_connector_state	base;
> +};
> +
> +static inline struct vc4_hdmi_connector_state *
> +conn_state_to_vc4_hdmi_conn_state(struct drm_connector_state *conn_state)
> +{
> +	return container_of(conn_state, struct vc4_hdmi_connector_state, base);
> +}
> +
>   void vc4_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi,
>   		       struct drm_display_mode *mode);
>   void vc4_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi);
> 

-- 
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Maxfeldstr. 5, 90409 Nürnberg, Germany
(HRB 36809, AG Nürnberg)
Geschäftsführer: Felix Imendörffer


[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 840 bytes --]

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v4 5/8] drm/vc4: hdmi: Store pixel frequency in the connector state
  2020-12-07 13:39   ` Maxime Ripard
@ 2020-12-07 14:14     ` Thomas Zimmermann
  -1 siblings, 0 replies; 32+ messages in thread
From: Thomas Zimmermann @ 2020-12-07 14:14 UTC (permalink / raw)
  To: Maxime Ripard, Maarten Lankhorst, Daniel Vetter, David Airlie,
	Eric Anholt
  Cc: linux-arm-kernel, bcm-kernel-feedback-list, linux-rpi-kernel,
	dri-devel, Dave Stevenson


[-- Attachment #1.1.1: Type: text/plain, Size: 4204 bytes --]

Hi

Am 07.12.20 um 14:39 schrieb Maxime Ripard:
> The pixel rate is for now quite simple to compute, but with more features
> (30 and 36 bits output, YUV output, etc.) will depend on a bunch of
> connectors properties.
> 
> Let's store the rate we have to run the pixel clock at in our custom
> connector state, and compute it in atomic_check.
> 
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>
> ---
>   drivers/gpu/drm/vc4/vc4_hdmi.c | 26 +++++++++++++++++++++++++-
>   drivers/gpu/drm/vc4/vc4_hdmi.h |  1 +
>   2 files changed, 26 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index 862c93708e9a..c1667cfe37db 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -194,6 +194,7 @@ vc4_hdmi_connector_duplicate_state(struct drm_connector *connector)
>   	if (!new_state)
>   		return NULL;
>   
> +	new_state->pixel_rate = vc4_state->pixel_rate;
>   	__drm_atomic_helper_connector_duplicate_state(connector, &new_state->base);
>   
>   	return &new_state->base;
> @@ -611,9 +612,29 @@ static void vc4_hdmi_recenter_fifo(struct vc4_hdmi *vc4_hdmi)
>   		  "VC4_HDMI_FIFO_CTL_RECENTER_DONE");
>   }
>   
> +static struct drm_connector_state *
> +vc4_hdmi_encoder_get_connector_state(struct drm_encoder *encoder,
> +				     struct drm_atomic_state *state)
> +{
> +	struct drm_connector_state *conn_state;
> +	struct drm_connector *connector;
> +	unsigned int i;
> +
> +	for_each_new_connector_in_state(state, connector, conn_state, i) {
> +		if (conn_state->best_encoder == encoder)
> +			return conn_state;
> +	}
> +
> +	return NULL;
> +}
> +
>   static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder,
>   						struct drm_atomic_state *state)
>   {
> +	struct drm_connector_state *conn_state =
> +		vc4_hdmi_encoder_get_connector_state(encoder, state);
> +	struct vc4_hdmi_connector_state *vc4_conn_state =
> +		conn_state_to_vc4_hdmi_conn_state(conn_state);
>   	struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
>   	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
>   	unsigned long pixel_rate, hsm_rate;
> @@ -625,7 +646,7 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder,
>   		return;
>   	}
>   
> -	pixel_rate = mode->clock * 1000 * ((mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1);

Has (mode->flags & DRM_MODE_FLAG_DBLCLK) been lost? I cannot find it any 
longer. The code in atomic_check() looks significantly different.

Best regards
Thomas

> +	pixel_rate = vc4_conn_state->pixel_rate;
>   	ret = clk_set_rate(vc4_hdmi->pixel_clock, pixel_rate);
>   	if (ret) {
>   		DRM_ERROR("Failed to set pixel clock rate: %d\n", ret);
> @@ -797,6 +818,7 @@ static int vc4_hdmi_encoder_atomic_check(struct drm_encoder *encoder,
>   					 struct drm_crtc_state *crtc_state,
>   					 struct drm_connector_state *conn_state)
>   {
> +	struct vc4_hdmi_connector_state *vc4_state = conn_state_to_vc4_hdmi_conn_state(conn_state);
>   	struct drm_display_mode *mode = &crtc_state->adjusted_mode;
>   	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
>   	unsigned long long pixel_rate = mode->clock * 1000;
> @@ -824,6 +846,8 @@ static int vc4_hdmi_encoder_atomic_check(struct drm_encoder *encoder,
>   	if (pixel_rate > vc4_hdmi->variant->max_pixel_clock)
>   		return -EINVAL;
>   
> +	vc4_state->pixel_rate = pixel_rate;
> +
>   	return 0;
>   }
>   
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
> index 2cf5362052e2..bca6943de884 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.h
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
> @@ -182,6 +182,7 @@ encoder_to_vc4_hdmi(struct drm_encoder *encoder)
>   
>   struct vc4_hdmi_connector_state {
>   	struct drm_connector_state	base;
> +	unsigned long long		pixel_rate;
>   };
>   
>   static inline struct vc4_hdmi_connector_state *
> 

-- 
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Maxfeldstr. 5, 90409 Nürnberg, Germany
(HRB 36809, AG Nürnberg)
Geschäftsführer: Felix Imendörffer


[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 840 bytes --]

[-- Attachment #2: Type: text/plain, Size: 176 bytes --]

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v4 5/8] drm/vc4: hdmi: Store pixel frequency in the connector state
@ 2020-12-07 14:14     ` Thomas Zimmermann
  0 siblings, 0 replies; 32+ messages in thread
From: Thomas Zimmermann @ 2020-12-07 14:14 UTC (permalink / raw)
  To: Maxime Ripard, Maarten Lankhorst, Daniel Vetter, David Airlie,
	Eric Anholt
  Cc: linux-arm-kernel, bcm-kernel-feedback-list, linux-rpi-kernel,
	dri-devel, Dave Stevenson


[-- Attachment #1.1.1: Type: text/plain, Size: 4204 bytes --]

Hi

Am 07.12.20 um 14:39 schrieb Maxime Ripard:
> The pixel rate is for now quite simple to compute, but with more features
> (30 and 36 bits output, YUV output, etc.) will depend on a bunch of
> connectors properties.
> 
> Let's store the rate we have to run the pixel clock at in our custom
> connector state, and compute it in atomic_check.
> 
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>
> ---
>   drivers/gpu/drm/vc4/vc4_hdmi.c | 26 +++++++++++++++++++++++++-
>   drivers/gpu/drm/vc4/vc4_hdmi.h |  1 +
>   2 files changed, 26 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index 862c93708e9a..c1667cfe37db 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -194,6 +194,7 @@ vc4_hdmi_connector_duplicate_state(struct drm_connector *connector)
>   	if (!new_state)
>   		return NULL;
>   
> +	new_state->pixel_rate = vc4_state->pixel_rate;
>   	__drm_atomic_helper_connector_duplicate_state(connector, &new_state->base);
>   
>   	return &new_state->base;
> @@ -611,9 +612,29 @@ static void vc4_hdmi_recenter_fifo(struct vc4_hdmi *vc4_hdmi)
>   		  "VC4_HDMI_FIFO_CTL_RECENTER_DONE");
>   }
>   
> +static struct drm_connector_state *
> +vc4_hdmi_encoder_get_connector_state(struct drm_encoder *encoder,
> +				     struct drm_atomic_state *state)
> +{
> +	struct drm_connector_state *conn_state;
> +	struct drm_connector *connector;
> +	unsigned int i;
> +
> +	for_each_new_connector_in_state(state, connector, conn_state, i) {
> +		if (conn_state->best_encoder == encoder)
> +			return conn_state;
> +	}
> +
> +	return NULL;
> +}
> +
>   static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder,
>   						struct drm_atomic_state *state)
>   {
> +	struct drm_connector_state *conn_state =
> +		vc4_hdmi_encoder_get_connector_state(encoder, state);
> +	struct vc4_hdmi_connector_state *vc4_conn_state =
> +		conn_state_to_vc4_hdmi_conn_state(conn_state);
>   	struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
>   	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
>   	unsigned long pixel_rate, hsm_rate;
> @@ -625,7 +646,7 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder,
>   		return;
>   	}
>   
> -	pixel_rate = mode->clock * 1000 * ((mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1);

Has (mode->flags & DRM_MODE_FLAG_DBLCLK) been lost? I cannot find it any 
longer. The code in atomic_check() looks significantly different.

Best regards
Thomas

> +	pixel_rate = vc4_conn_state->pixel_rate;
>   	ret = clk_set_rate(vc4_hdmi->pixel_clock, pixel_rate);
>   	if (ret) {
>   		DRM_ERROR("Failed to set pixel clock rate: %d\n", ret);
> @@ -797,6 +818,7 @@ static int vc4_hdmi_encoder_atomic_check(struct drm_encoder *encoder,
>   					 struct drm_crtc_state *crtc_state,
>   					 struct drm_connector_state *conn_state)
>   {
> +	struct vc4_hdmi_connector_state *vc4_state = conn_state_to_vc4_hdmi_conn_state(conn_state);
>   	struct drm_display_mode *mode = &crtc_state->adjusted_mode;
>   	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
>   	unsigned long long pixel_rate = mode->clock * 1000;
> @@ -824,6 +846,8 @@ static int vc4_hdmi_encoder_atomic_check(struct drm_encoder *encoder,
>   	if (pixel_rate > vc4_hdmi->variant->max_pixel_clock)
>   		return -EINVAL;
>   
> +	vc4_state->pixel_rate = pixel_rate;
> +
>   	return 0;
>   }
>   
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
> index 2cf5362052e2..bca6943de884 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.h
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
> @@ -182,6 +182,7 @@ encoder_to_vc4_hdmi(struct drm_encoder *encoder)
>   
>   struct vc4_hdmi_connector_state {
>   	struct drm_connector_state	base;
> +	unsigned long long		pixel_rate;
>   };
>   
>   static inline struct vc4_hdmi_connector_state *
> 

-- 
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Maxfeldstr. 5, 90409 Nürnberg, Germany
(HRB 36809, AG Nürnberg)
Geschäftsführer: Felix Imendörffer


[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 840 bytes --]

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v4 2/8] drm/vc4: Pass the atomic state to encoder hooks
  2020-12-07 13:39   ` Maxime Ripard
@ 2020-12-07 14:16     ` Thomas Zimmermann
  -1 siblings, 0 replies; 32+ messages in thread
From: Thomas Zimmermann @ 2020-12-07 14:16 UTC (permalink / raw)
  To: Maxime Ripard, Maarten Lankhorst, Daniel Vetter, David Airlie,
	Eric Anholt
  Cc: linux-arm-kernel, bcm-kernel-feedback-list, linux-rpi-kernel,
	dri-devel, Dave Stevenson


[-- Attachment #1.1.1: Type: text/plain, Size: 7538 bytes --]



Am 07.12.20 um 14:39 schrieb Maxime Ripard:
> We'll need to access the connector state in our encoder setup, so let's
> just pass the whole DRM state to our private encoder hooks.
> 
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

This becomes relevant in patch 5, I guess? If so

Acked-by: Thomas Zimmermann <tzimmermann@suse.de>

> ---
>   drivers/gpu/drm/vc4/vc4_crtc.c | 18 ++++++++++--------
>   drivers/gpu/drm/vc4/vc4_drv.h  | 10 +++++-----
>   drivers/gpu/drm/vc4/vc4_hdmi.c | 15 ++++++++++-----
>   3 files changed, 25 insertions(+), 18 deletions(-)
> 
> diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
> index e02e499885ed..a3439756594c 100644
> --- a/drivers/gpu/drm/vc4/vc4_crtc.c
> +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
> @@ -403,7 +403,9 @@ static void require_hvs_enabled(struct drm_device *dev)
>   		     SCALER_DISPCTRL_ENABLE);
>   }
>   
> -static int vc4_crtc_disable(struct drm_crtc *crtc, unsigned int channel)
> +static int vc4_crtc_disable(struct drm_crtc *crtc,
> +			    struct drm_atomic_state *state,
> +			    unsigned int channel)
>   {
>   	struct drm_encoder *encoder = vc4_get_crtc_encoder(crtc);
>   	struct vc4_encoder *vc4_encoder = to_vc4_encoder(encoder);
> @@ -435,13 +437,13 @@ static int vc4_crtc_disable(struct drm_crtc *crtc, unsigned int channel)
>   	mdelay(20);
>   
>   	if (vc4_encoder && vc4_encoder->post_crtc_disable)
> -		vc4_encoder->post_crtc_disable(encoder);
> +		vc4_encoder->post_crtc_disable(encoder, state);
>   
>   	vc4_crtc_pixelvalve_reset(crtc);
>   	vc4_hvs_stop_channel(dev, channel);
>   
>   	if (vc4_encoder && vc4_encoder->post_crtc_powerdown)
> -		vc4_encoder->post_crtc_powerdown(encoder);
> +		vc4_encoder->post_crtc_powerdown(encoder, state);
>   
>   	return 0;
>   }
> @@ -468,7 +470,7 @@ int vc4_crtc_disable_at_boot(struct drm_crtc *crtc)
>   	if (channel < 0)
>   		return 0;
>   
> -	return vc4_crtc_disable(crtc, channel);
> +	return vc4_crtc_disable(crtc, NULL, channel);
>   }
>   
>   static void vc4_crtc_atomic_disable(struct drm_crtc *crtc,
> @@ -484,7 +486,7 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc,
>   	/* Disable vblank irq handling before crtc is disabled. */
>   	drm_crtc_vblank_off(crtc);
>   
> -	vc4_crtc_disable(crtc, old_vc4_state->assigned_channel);
> +	vc4_crtc_disable(crtc, state, old_vc4_state->assigned_channel);
>   
>   	/*
>   	 * Make sure we issue a vblank event after disabling the CRTC if
> @@ -518,14 +520,14 @@ static void vc4_crtc_atomic_enable(struct drm_crtc *crtc,
>   	vc4_hvs_atomic_enable(crtc, state);
>   
>   	if (vc4_encoder->pre_crtc_configure)
> -		vc4_encoder->pre_crtc_configure(encoder);
> +		vc4_encoder->pre_crtc_configure(encoder, state);
>   
>   	vc4_crtc_config_pv(crtc);
>   
>   	CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) | PV_CONTROL_EN);
>   
>   	if (vc4_encoder->pre_crtc_enable)
> -		vc4_encoder->pre_crtc_enable(encoder);
> +		vc4_encoder->pre_crtc_enable(encoder, state);
>   
>   	/* When feeding the transposer block the pixelvalve is unneeded and
>   	 * should not be enabled.
> @@ -534,7 +536,7 @@ static void vc4_crtc_atomic_enable(struct drm_crtc *crtc,
>   		   CRTC_READ(PV_V_CONTROL) | PV_VCONTROL_VIDEN);
>   
>   	if (vc4_encoder->post_crtc_enable)
> -		vc4_encoder->post_crtc_enable(encoder);
> +		vc4_encoder->post_crtc_enable(encoder, state);
>   }
>   
>   static enum drm_mode_status vc4_crtc_mode_valid(struct drm_crtc *crtc,
> diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
> index c47c85533805..b404cd3ab0d8 100644
> --- a/drivers/gpu/drm/vc4/vc4_drv.h
> +++ b/drivers/gpu/drm/vc4/vc4_drv.h
> @@ -444,12 +444,12 @@ struct vc4_encoder {
>   	enum vc4_encoder_type type;
>   	u32 clock_select;
>   
> -	void (*pre_crtc_configure)(struct drm_encoder *encoder);
> -	void (*pre_crtc_enable)(struct drm_encoder *encoder);
> -	void (*post_crtc_enable)(struct drm_encoder *encoder);
> +	void (*pre_crtc_configure)(struct drm_encoder *encoder, struct drm_atomic_state *state);
> +	void (*pre_crtc_enable)(struct drm_encoder *encoder, struct drm_atomic_state *state);
> +	void (*post_crtc_enable)(struct drm_encoder *encoder, struct drm_atomic_state *state);
>   
> -	void (*post_crtc_disable)(struct drm_encoder *encoder);
> -	void (*post_crtc_powerdown)(struct drm_encoder *encoder);
> +	void (*post_crtc_disable)(struct drm_encoder *encoder, struct drm_atomic_state *state);
> +	void (*post_crtc_powerdown)(struct drm_encoder *encoder, struct drm_atomic_state *state);
>   };
>   
>   static inline struct vc4_encoder *
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index afc178b0d89f..5a608ed1d75e 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -357,7 +357,8 @@ static void vc4_hdmi_set_infoframes(struct drm_encoder *encoder)
>   		vc4_hdmi_set_audio_infoframe(encoder);
>   }
>   
> -static void vc4_hdmi_encoder_post_crtc_disable(struct drm_encoder *encoder)
> +static void vc4_hdmi_encoder_post_crtc_disable(struct drm_encoder *encoder,
> +					       struct drm_atomic_state *state)
>   {
>   	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
>   
> @@ -370,7 +371,8 @@ static void vc4_hdmi_encoder_post_crtc_disable(struct drm_encoder *encoder)
>   		   HDMI_READ(HDMI_VID_CTL) | VC4_HD_VID_CTL_BLANKPIX);
>   }
>   
> -static void vc4_hdmi_encoder_post_crtc_powerdown(struct drm_encoder *encoder)
> +static void vc4_hdmi_encoder_post_crtc_powerdown(struct drm_encoder *encoder,
> +						 struct drm_atomic_state *state)
>   {
>   	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
>   	int ret;
> @@ -584,7 +586,8 @@ static void vc4_hdmi_recenter_fifo(struct vc4_hdmi *vc4_hdmi)
>   		  "VC4_HDMI_FIFO_CTL_RECENTER_DONE");
>   }
>   
> -static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder)
> +static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder,
> +						struct drm_atomic_state *state)
>   {
>   	struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
>   	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
> @@ -676,7 +679,8 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder)
>   		vc4_hdmi->variant->set_timings(vc4_hdmi, mode);
>   }
>   
> -static void vc4_hdmi_encoder_pre_crtc_enable(struct drm_encoder *encoder)
> +static void vc4_hdmi_encoder_pre_crtc_enable(struct drm_encoder *encoder,
> +					     struct drm_atomic_state *state)
>   {
>   	struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
>   	struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
> @@ -698,7 +702,8 @@ static void vc4_hdmi_encoder_pre_crtc_enable(struct drm_encoder *encoder)
>   	HDMI_WRITE(HDMI_FIFO_CTL, VC4_HDMI_FIFO_CTL_MASTER_SLAVE_N);
>   }
>   
> -static void vc4_hdmi_encoder_post_crtc_enable(struct drm_encoder *encoder)
> +static void vc4_hdmi_encoder_post_crtc_enable(struct drm_encoder *encoder,
> +					      struct drm_atomic_state *state)
>   {
>   	struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
>   	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
> 

-- 
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Maxfeldstr. 5, 90409 Nürnberg, Germany
(HRB 36809, AG Nürnberg)
Geschäftsführer: Felix Imendörffer


[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 840 bytes --]

[-- Attachment #2: Type: text/plain, Size: 176 bytes --]

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v4 2/8] drm/vc4: Pass the atomic state to encoder hooks
@ 2020-12-07 14:16     ` Thomas Zimmermann
  0 siblings, 0 replies; 32+ messages in thread
From: Thomas Zimmermann @ 2020-12-07 14:16 UTC (permalink / raw)
  To: Maxime Ripard, Maarten Lankhorst, Daniel Vetter, David Airlie,
	Eric Anholt
  Cc: linux-arm-kernel, bcm-kernel-feedback-list, linux-rpi-kernel,
	dri-devel, Dave Stevenson


[-- Attachment #1.1.1: Type: text/plain, Size: 7538 bytes --]



Am 07.12.20 um 14:39 schrieb Maxime Ripard:
> We'll need to access the connector state in our encoder setup, so let's
> just pass the whole DRM state to our private encoder hooks.
> 
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

This becomes relevant in patch 5, I guess? If so

Acked-by: Thomas Zimmermann <tzimmermann@suse.de>

> ---
>   drivers/gpu/drm/vc4/vc4_crtc.c | 18 ++++++++++--------
>   drivers/gpu/drm/vc4/vc4_drv.h  | 10 +++++-----
>   drivers/gpu/drm/vc4/vc4_hdmi.c | 15 ++++++++++-----
>   3 files changed, 25 insertions(+), 18 deletions(-)
> 
> diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
> index e02e499885ed..a3439756594c 100644
> --- a/drivers/gpu/drm/vc4/vc4_crtc.c
> +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
> @@ -403,7 +403,9 @@ static void require_hvs_enabled(struct drm_device *dev)
>   		     SCALER_DISPCTRL_ENABLE);
>   }
>   
> -static int vc4_crtc_disable(struct drm_crtc *crtc, unsigned int channel)
> +static int vc4_crtc_disable(struct drm_crtc *crtc,
> +			    struct drm_atomic_state *state,
> +			    unsigned int channel)
>   {
>   	struct drm_encoder *encoder = vc4_get_crtc_encoder(crtc);
>   	struct vc4_encoder *vc4_encoder = to_vc4_encoder(encoder);
> @@ -435,13 +437,13 @@ static int vc4_crtc_disable(struct drm_crtc *crtc, unsigned int channel)
>   	mdelay(20);
>   
>   	if (vc4_encoder && vc4_encoder->post_crtc_disable)
> -		vc4_encoder->post_crtc_disable(encoder);
> +		vc4_encoder->post_crtc_disable(encoder, state);
>   
>   	vc4_crtc_pixelvalve_reset(crtc);
>   	vc4_hvs_stop_channel(dev, channel);
>   
>   	if (vc4_encoder && vc4_encoder->post_crtc_powerdown)
> -		vc4_encoder->post_crtc_powerdown(encoder);
> +		vc4_encoder->post_crtc_powerdown(encoder, state);
>   
>   	return 0;
>   }
> @@ -468,7 +470,7 @@ int vc4_crtc_disable_at_boot(struct drm_crtc *crtc)
>   	if (channel < 0)
>   		return 0;
>   
> -	return vc4_crtc_disable(crtc, channel);
> +	return vc4_crtc_disable(crtc, NULL, channel);
>   }
>   
>   static void vc4_crtc_atomic_disable(struct drm_crtc *crtc,
> @@ -484,7 +486,7 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc,
>   	/* Disable vblank irq handling before crtc is disabled. */
>   	drm_crtc_vblank_off(crtc);
>   
> -	vc4_crtc_disable(crtc, old_vc4_state->assigned_channel);
> +	vc4_crtc_disable(crtc, state, old_vc4_state->assigned_channel);
>   
>   	/*
>   	 * Make sure we issue a vblank event after disabling the CRTC if
> @@ -518,14 +520,14 @@ static void vc4_crtc_atomic_enable(struct drm_crtc *crtc,
>   	vc4_hvs_atomic_enable(crtc, state);
>   
>   	if (vc4_encoder->pre_crtc_configure)
> -		vc4_encoder->pre_crtc_configure(encoder);
> +		vc4_encoder->pre_crtc_configure(encoder, state);
>   
>   	vc4_crtc_config_pv(crtc);
>   
>   	CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) | PV_CONTROL_EN);
>   
>   	if (vc4_encoder->pre_crtc_enable)
> -		vc4_encoder->pre_crtc_enable(encoder);
> +		vc4_encoder->pre_crtc_enable(encoder, state);
>   
>   	/* When feeding the transposer block the pixelvalve is unneeded and
>   	 * should not be enabled.
> @@ -534,7 +536,7 @@ static void vc4_crtc_atomic_enable(struct drm_crtc *crtc,
>   		   CRTC_READ(PV_V_CONTROL) | PV_VCONTROL_VIDEN);
>   
>   	if (vc4_encoder->post_crtc_enable)
> -		vc4_encoder->post_crtc_enable(encoder);
> +		vc4_encoder->post_crtc_enable(encoder, state);
>   }
>   
>   static enum drm_mode_status vc4_crtc_mode_valid(struct drm_crtc *crtc,
> diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
> index c47c85533805..b404cd3ab0d8 100644
> --- a/drivers/gpu/drm/vc4/vc4_drv.h
> +++ b/drivers/gpu/drm/vc4/vc4_drv.h
> @@ -444,12 +444,12 @@ struct vc4_encoder {
>   	enum vc4_encoder_type type;
>   	u32 clock_select;
>   
> -	void (*pre_crtc_configure)(struct drm_encoder *encoder);
> -	void (*pre_crtc_enable)(struct drm_encoder *encoder);
> -	void (*post_crtc_enable)(struct drm_encoder *encoder);
> +	void (*pre_crtc_configure)(struct drm_encoder *encoder, struct drm_atomic_state *state);
> +	void (*pre_crtc_enable)(struct drm_encoder *encoder, struct drm_atomic_state *state);
> +	void (*post_crtc_enable)(struct drm_encoder *encoder, struct drm_atomic_state *state);
>   
> -	void (*post_crtc_disable)(struct drm_encoder *encoder);
> -	void (*post_crtc_powerdown)(struct drm_encoder *encoder);
> +	void (*post_crtc_disable)(struct drm_encoder *encoder, struct drm_atomic_state *state);
> +	void (*post_crtc_powerdown)(struct drm_encoder *encoder, struct drm_atomic_state *state);
>   };
>   
>   static inline struct vc4_encoder *
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index afc178b0d89f..5a608ed1d75e 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -357,7 +357,8 @@ static void vc4_hdmi_set_infoframes(struct drm_encoder *encoder)
>   		vc4_hdmi_set_audio_infoframe(encoder);
>   }
>   
> -static void vc4_hdmi_encoder_post_crtc_disable(struct drm_encoder *encoder)
> +static void vc4_hdmi_encoder_post_crtc_disable(struct drm_encoder *encoder,
> +					       struct drm_atomic_state *state)
>   {
>   	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
>   
> @@ -370,7 +371,8 @@ static void vc4_hdmi_encoder_post_crtc_disable(struct drm_encoder *encoder)
>   		   HDMI_READ(HDMI_VID_CTL) | VC4_HD_VID_CTL_BLANKPIX);
>   }
>   
> -static void vc4_hdmi_encoder_post_crtc_powerdown(struct drm_encoder *encoder)
> +static void vc4_hdmi_encoder_post_crtc_powerdown(struct drm_encoder *encoder,
> +						 struct drm_atomic_state *state)
>   {
>   	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
>   	int ret;
> @@ -584,7 +586,8 @@ static void vc4_hdmi_recenter_fifo(struct vc4_hdmi *vc4_hdmi)
>   		  "VC4_HDMI_FIFO_CTL_RECENTER_DONE");
>   }
>   
> -static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder)
> +static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder,
> +						struct drm_atomic_state *state)
>   {
>   	struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
>   	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
> @@ -676,7 +679,8 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder)
>   		vc4_hdmi->variant->set_timings(vc4_hdmi, mode);
>   }
>   
> -static void vc4_hdmi_encoder_pre_crtc_enable(struct drm_encoder *encoder)
> +static void vc4_hdmi_encoder_pre_crtc_enable(struct drm_encoder *encoder,
> +					     struct drm_atomic_state *state)
>   {
>   	struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
>   	struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
> @@ -698,7 +702,8 @@ static void vc4_hdmi_encoder_pre_crtc_enable(struct drm_encoder *encoder)
>   	HDMI_WRITE(HDMI_FIFO_CTL, VC4_HDMI_FIFO_CTL_MASTER_SLAVE_N);
>   }
>   
> -static void vc4_hdmi_encoder_post_crtc_enable(struct drm_encoder *encoder)
> +static void vc4_hdmi_encoder_post_crtc_enable(struct drm_encoder *encoder,
> +					      struct drm_atomic_state *state)
>   {
>   	struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
>   	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
> 

-- 
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Maxfeldstr. 5, 90409 Nürnberg, Germany
(HRB 36809, AG Nürnberg)
Geschäftsführer: Felix Imendörffer


[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 840 bytes --]

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v4 6/8] drm/vc4: hdmi: Use the connector state pixel rate for the PHY
  2020-12-07 13:39   ` Maxime Ripard
@ 2020-12-07 14:20     ` Thomas Zimmermann
  -1 siblings, 0 replies; 32+ messages in thread
From: Thomas Zimmermann @ 2020-12-07 14:20 UTC (permalink / raw)
  To: Maxime Ripard, Maarten Lankhorst, Daniel Vetter, David Airlie,
	Eric Anholt
  Cc: linux-arm-kernel, bcm-kernel-feedback-list, linux-rpi-kernel,
	dri-devel, Dave Stevenson


[-- Attachment #1.1.1: Type: text/plain, Size: 4744 bytes --]



Am 07.12.20 um 14:39 schrieb Maxime Ripard:
> The PHY initialisation parameters are not based on the pixel clock but
> the TMDS clock rate which can be the pixel clock in the standard case,
> but could be adjusted based on some parameters like the bits per color.
> 
> Since the TMDS clock rate is stored in our custom connector state
> already, let's reuse it from there instead of computing it again.
> 
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>
> ---
>   drivers/gpu/drm/vc4/vc4_hdmi.c     | 2 +-
>   drivers/gpu/drm/vc4/vc4_hdmi.h     | 9 ++++-----
>   drivers/gpu/drm/vc4/vc4_hdmi_phy.c | 8 +++++---
>   3 files changed, 10 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index c1667cfe37db..795fd23c8f58 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -714,7 +714,7 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder,
>   		vc4_hdmi->variant->reset(vc4_hdmi);
>   
>   	if (vc4_hdmi->variant->phy_init)
> -		vc4_hdmi->variant->phy_init(vc4_hdmi, mode);
> +		vc4_hdmi->variant->phy_init(vc4_hdmi, vc4_conn_state);
>   
>   	HDMI_WRITE(HDMI_SCHEDULER_CONTROL,
>   		   HDMI_READ(HDMI_SCHEDULER_CONTROL) |
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
> index bca6943de884..6cc5b6652cca 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.h
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
> @@ -21,10 +21,9 @@ to_vc4_hdmi_encoder(struct drm_encoder *encoder)
>   	return container_of(encoder, struct vc4_hdmi_encoder, base.base);
>   }
>   
> -struct drm_display_mode;
> -
>   struct vc4_hdmi;
>   struct vc4_hdmi_register;
> +struct vc4_hdmi_connector_state;
>   
>   enum vc4_hdmi_phy_channel {
>   	PHY_LANE_0 = 0,
> @@ -82,7 +81,7 @@ struct vc4_hdmi_variant {
>   
>   	/* Callback to initialize the PHY according to the mode */

Rather 'according to the connector state'? OTOH these comments don't 
seem to add any information. They might just be removed. :)

The patch in general is

Acked-by: Thomas Zimmermann <tzimmermann@suse.de>

>   	void (*phy_init)(struct vc4_hdmi *vc4_hdmi,
> -			 struct drm_display_mode *mode);
> +			 struct vc4_hdmi_connector_state *vc4_conn_state);
>   
>   	/* Callback to disable the PHY */
>   	void (*phy_disable)(struct vc4_hdmi *vc4_hdmi);
> @@ -192,13 +191,13 @@ conn_state_to_vc4_hdmi_conn_state(struct drm_connector_state *conn_state)
>   }
>   
>   void vc4_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi,
> -		       struct drm_display_mode *mode);
> +		       struct vc4_hdmi_connector_state *vc4_conn_state);
>   void vc4_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi);
>   void vc4_hdmi_phy_rng_enable(struct vc4_hdmi *vc4_hdmi);
>   void vc4_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi);
>   
>   void vc5_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi,
> -		       struct drm_display_mode *mode);
> +		       struct vc4_hdmi_connector_state *vc4_conn_state);
>   void vc5_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi);
>   void vc5_hdmi_phy_rng_enable(struct vc4_hdmi *vc4_hdmi);
>   void vc5_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi);
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi_phy.c b/drivers/gpu/drm/vc4/vc4_hdmi_phy.c
> index 057796b54c51..36535480f8e2 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi_phy.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi_phy.c
> @@ -127,7 +127,8 @@
>   
>   #define OSCILLATOR_FREQUENCY	54000000
>   
> -void vc4_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi, struct drm_display_mode *mode)
> +void vc4_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi,
> +		       struct vc4_hdmi_connector_state *conn_state)
>   {
>   	/* PHY should be in reset, like
>   	 * vc4_hdmi_encoder_disable() does.
> @@ -339,11 +340,12 @@ static void vc5_hdmi_reset_phy(struct vc4_hdmi *vc4_hdmi)
>   	HDMI_WRITE(HDMI_TX_PHY_POWERDOWN_CTL, BIT(10));
>   }
>   
> -void vc5_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi, struct drm_display_mode *mode)
> +void vc5_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi,
> +		       struct vc4_hdmi_connector_state *conn_state)
>   {
>   	const struct phy_lane_settings *chan0_settings, *chan1_settings, *chan2_settings, *clock_settings;
>   	const struct vc4_hdmi_variant *variant = vc4_hdmi->variant;
> -	unsigned long long pixel_freq = mode->clock * 1000;
> +	unsigned long long pixel_freq = conn_state->pixel_rate;
>   	unsigned long long vco_freq;
>   	unsigned char word_sel;
>   	u8 vco_sel, vco_div;
> 

-- 
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Maxfeldstr. 5, 90409 Nürnberg, Germany
(HRB 36809, AG Nürnberg)
Geschäftsführer: Felix Imendörffer


[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 840 bytes --]

[-- Attachment #2: Type: text/plain, Size: 176 bytes --]

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v4 6/8] drm/vc4: hdmi: Use the connector state pixel rate for the PHY
@ 2020-12-07 14:20     ` Thomas Zimmermann
  0 siblings, 0 replies; 32+ messages in thread
From: Thomas Zimmermann @ 2020-12-07 14:20 UTC (permalink / raw)
  To: Maxime Ripard, Maarten Lankhorst, Daniel Vetter, David Airlie,
	Eric Anholt
  Cc: linux-arm-kernel, bcm-kernel-feedback-list, linux-rpi-kernel,
	dri-devel, Dave Stevenson


[-- Attachment #1.1.1: Type: text/plain, Size: 4744 bytes --]



Am 07.12.20 um 14:39 schrieb Maxime Ripard:
> The PHY initialisation parameters are not based on the pixel clock but
> the TMDS clock rate which can be the pixel clock in the standard case,
> but could be adjusted based on some parameters like the bits per color.
> 
> Since the TMDS clock rate is stored in our custom connector state
> already, let's reuse it from there instead of computing it again.
> 
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>
> ---
>   drivers/gpu/drm/vc4/vc4_hdmi.c     | 2 +-
>   drivers/gpu/drm/vc4/vc4_hdmi.h     | 9 ++++-----
>   drivers/gpu/drm/vc4/vc4_hdmi_phy.c | 8 +++++---
>   3 files changed, 10 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index c1667cfe37db..795fd23c8f58 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -714,7 +714,7 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder,
>   		vc4_hdmi->variant->reset(vc4_hdmi);
>   
>   	if (vc4_hdmi->variant->phy_init)
> -		vc4_hdmi->variant->phy_init(vc4_hdmi, mode);
> +		vc4_hdmi->variant->phy_init(vc4_hdmi, vc4_conn_state);
>   
>   	HDMI_WRITE(HDMI_SCHEDULER_CONTROL,
>   		   HDMI_READ(HDMI_SCHEDULER_CONTROL) |
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
> index bca6943de884..6cc5b6652cca 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.h
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
> @@ -21,10 +21,9 @@ to_vc4_hdmi_encoder(struct drm_encoder *encoder)
>   	return container_of(encoder, struct vc4_hdmi_encoder, base.base);
>   }
>   
> -struct drm_display_mode;
> -
>   struct vc4_hdmi;
>   struct vc4_hdmi_register;
> +struct vc4_hdmi_connector_state;
>   
>   enum vc4_hdmi_phy_channel {
>   	PHY_LANE_0 = 0,
> @@ -82,7 +81,7 @@ struct vc4_hdmi_variant {
>   
>   	/* Callback to initialize the PHY according to the mode */

Rather 'according to the connector state'? OTOH these comments don't 
seem to add any information. They might just be removed. :)

The patch in general is

Acked-by: Thomas Zimmermann <tzimmermann@suse.de>

>   	void (*phy_init)(struct vc4_hdmi *vc4_hdmi,
> -			 struct drm_display_mode *mode);
> +			 struct vc4_hdmi_connector_state *vc4_conn_state);
>   
>   	/* Callback to disable the PHY */
>   	void (*phy_disable)(struct vc4_hdmi *vc4_hdmi);
> @@ -192,13 +191,13 @@ conn_state_to_vc4_hdmi_conn_state(struct drm_connector_state *conn_state)
>   }
>   
>   void vc4_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi,
> -		       struct drm_display_mode *mode);
> +		       struct vc4_hdmi_connector_state *vc4_conn_state);
>   void vc4_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi);
>   void vc4_hdmi_phy_rng_enable(struct vc4_hdmi *vc4_hdmi);
>   void vc4_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi);
>   
>   void vc5_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi,
> -		       struct drm_display_mode *mode);
> +		       struct vc4_hdmi_connector_state *vc4_conn_state);
>   void vc5_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi);
>   void vc5_hdmi_phy_rng_enable(struct vc4_hdmi *vc4_hdmi);
>   void vc5_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi);
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi_phy.c b/drivers/gpu/drm/vc4/vc4_hdmi_phy.c
> index 057796b54c51..36535480f8e2 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi_phy.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi_phy.c
> @@ -127,7 +127,8 @@
>   
>   #define OSCILLATOR_FREQUENCY	54000000
>   
> -void vc4_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi, struct drm_display_mode *mode)
> +void vc4_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi,
> +		       struct vc4_hdmi_connector_state *conn_state)
>   {
>   	/* PHY should be in reset, like
>   	 * vc4_hdmi_encoder_disable() does.
> @@ -339,11 +340,12 @@ static void vc5_hdmi_reset_phy(struct vc4_hdmi *vc4_hdmi)
>   	HDMI_WRITE(HDMI_TX_PHY_POWERDOWN_CTL, BIT(10));
>   }
>   
> -void vc5_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi, struct drm_display_mode *mode)
> +void vc5_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi,
> +		       struct vc4_hdmi_connector_state *conn_state)
>   {
>   	const struct phy_lane_settings *chan0_settings, *chan1_settings, *chan2_settings, *clock_settings;
>   	const struct vc4_hdmi_variant *variant = vc4_hdmi->variant;
> -	unsigned long long pixel_freq = mode->clock * 1000;
> +	unsigned long long pixel_freq = conn_state->pixel_rate;
>   	unsigned long long vco_freq;
>   	unsigned char word_sel;
>   	u8 vco_sel, vco_div;
> 

-- 
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Maxfeldstr. 5, 90409 Nürnberg, Germany
(HRB 36809, AG Nürnberg)
Geschäftsführer: Felix Imendörffer


[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 840 bytes --]

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v4 5/8] drm/vc4: hdmi: Store pixel frequency in the connector state
  2020-12-07 14:14     ` Thomas Zimmermann
@ 2020-12-07 15:44       ` Maxime Ripard
  -1 siblings, 0 replies; 32+ messages in thread
From: Maxime Ripard @ 2020-12-07 15:44 UTC (permalink / raw)
  To: Thomas Zimmermann
  Cc: Dave Stevenson, David Airlie, Maarten Lankhorst, dri-devel,
	Eric Anholt, bcm-kernel-feedback-list, linux-rpi-kernel,
	Daniel Vetter, linux-arm-kernel


[-- Attachment #1.1: Type: text/plain, Size: 2859 bytes --]

Hi Thomas,

On Mon, Dec 07, 2020 at 03:14:49PM +0100, Thomas Zimmermann wrote:
> Am 07.12.20 um 14:39 schrieb Maxime Ripard:
> > The pixel rate is for now quite simple to compute, but with more features
> > (30 and 36 bits output, YUV output, etc.) will depend on a bunch of
> > connectors properties.
> > 
> > Let's store the rate we have to run the pixel clock at in our custom
> > connector state, and compute it in atomic_check.
> > 
> > Signed-off-by: Maxime Ripard <maxime@cerno.tech>
> > ---
> >   drivers/gpu/drm/vc4/vc4_hdmi.c | 26 +++++++++++++++++++++++++-
> >   drivers/gpu/drm/vc4/vc4_hdmi.h |  1 +
> >   2 files changed, 26 insertions(+), 1 deletion(-)
> > 
> > diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> > index 862c93708e9a..c1667cfe37db 100644
> > --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> > +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> > @@ -194,6 +194,7 @@ vc4_hdmi_connector_duplicate_state(struct drm_connector *connector)
> >   	if (!new_state)
> >   		return NULL;
> > +	new_state->pixel_rate = vc4_state->pixel_rate;
> >   	__drm_atomic_helper_connector_duplicate_state(connector, &new_state->base);
> >   	return &new_state->base;
> > @@ -611,9 +612,29 @@ static void vc4_hdmi_recenter_fifo(struct vc4_hdmi *vc4_hdmi)
> >   		  "VC4_HDMI_FIFO_CTL_RECENTER_DONE");
> >   }
> > +static struct drm_connector_state *
> > +vc4_hdmi_encoder_get_connector_state(struct drm_encoder *encoder,
> > +				     struct drm_atomic_state *state)
> > +{
> > +	struct drm_connector_state *conn_state;
> > +	struct drm_connector *connector;
> > +	unsigned int i;
> > +
> > +	for_each_new_connector_in_state(state, connector, conn_state, i) {
> > +		if (conn_state->best_encoder == encoder)
> > +			return conn_state;
> > +	}
> > +
> > +	return NULL;
> > +}
> > +
> >   static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder,
> >   						struct drm_atomic_state *state)
> >   {
> > +	struct drm_connector_state *conn_state =
> > +		vc4_hdmi_encoder_get_connector_state(encoder, state);
> > +	struct vc4_hdmi_connector_state *vc4_conn_state =
> > +		conn_state_to_vc4_hdmi_conn_state(conn_state);
> >   	struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
> >   	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
> >   	unsigned long pixel_rate, hsm_rate;
> > @@ -625,7 +646,7 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder,
> >   		return;
> >   	}
> > -	pixel_rate = mode->clock * 1000 * ((mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1);
> 
> Has (mode->flags & DRM_MODE_FLAG_DBLCLK) been lost? I cannot find it any
> longer. The code in atomic_check() looks significantly different.

Indeed, it's a mistake from a previous patch. I'll send a fix for that one too.

Thanks!
Maxime

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

[-- Attachment #2: Type: text/plain, Size: 176 bytes --]

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v4 5/8] drm/vc4: hdmi: Store pixel frequency in the connector state
@ 2020-12-07 15:44       ` Maxime Ripard
  0 siblings, 0 replies; 32+ messages in thread
From: Maxime Ripard @ 2020-12-07 15:44 UTC (permalink / raw)
  To: Thomas Zimmermann
  Cc: Dave Stevenson, David Airlie, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Daniel Vetter,
	linux-arm-kernel


[-- Attachment #1.1: Type: text/plain, Size: 2859 bytes --]

Hi Thomas,

On Mon, Dec 07, 2020 at 03:14:49PM +0100, Thomas Zimmermann wrote:
> Am 07.12.20 um 14:39 schrieb Maxime Ripard:
> > The pixel rate is for now quite simple to compute, but with more features
> > (30 and 36 bits output, YUV output, etc.) will depend on a bunch of
> > connectors properties.
> > 
> > Let's store the rate we have to run the pixel clock at in our custom
> > connector state, and compute it in atomic_check.
> > 
> > Signed-off-by: Maxime Ripard <maxime@cerno.tech>
> > ---
> >   drivers/gpu/drm/vc4/vc4_hdmi.c | 26 +++++++++++++++++++++++++-
> >   drivers/gpu/drm/vc4/vc4_hdmi.h |  1 +
> >   2 files changed, 26 insertions(+), 1 deletion(-)
> > 
> > diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> > index 862c93708e9a..c1667cfe37db 100644
> > --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> > +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> > @@ -194,6 +194,7 @@ vc4_hdmi_connector_duplicate_state(struct drm_connector *connector)
> >   	if (!new_state)
> >   		return NULL;
> > +	new_state->pixel_rate = vc4_state->pixel_rate;
> >   	__drm_atomic_helper_connector_duplicate_state(connector, &new_state->base);
> >   	return &new_state->base;
> > @@ -611,9 +612,29 @@ static void vc4_hdmi_recenter_fifo(struct vc4_hdmi *vc4_hdmi)
> >   		  "VC4_HDMI_FIFO_CTL_RECENTER_DONE");
> >   }
> > +static struct drm_connector_state *
> > +vc4_hdmi_encoder_get_connector_state(struct drm_encoder *encoder,
> > +				     struct drm_atomic_state *state)
> > +{
> > +	struct drm_connector_state *conn_state;
> > +	struct drm_connector *connector;
> > +	unsigned int i;
> > +
> > +	for_each_new_connector_in_state(state, connector, conn_state, i) {
> > +		if (conn_state->best_encoder == encoder)
> > +			return conn_state;
> > +	}
> > +
> > +	return NULL;
> > +}
> > +
> >   static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder,
> >   						struct drm_atomic_state *state)
> >   {
> > +	struct drm_connector_state *conn_state =
> > +		vc4_hdmi_encoder_get_connector_state(encoder, state);
> > +	struct vc4_hdmi_connector_state *vc4_conn_state =
> > +		conn_state_to_vc4_hdmi_conn_state(conn_state);
> >   	struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
> >   	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
> >   	unsigned long pixel_rate, hsm_rate;
> > @@ -625,7 +646,7 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder,
> >   		return;
> >   	}
> > -	pixel_rate = mode->clock * 1000 * ((mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1);
> 
> Has (mode->flags & DRM_MODE_FLAG_DBLCLK) been lost? I cannot find it any
> longer. The code in atomic_check() looks significantly different.

Indeed, it's a mistake from a previous patch. I'll send a fix for that one too.

Thanks!
Maxime

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

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v4 2/8] drm/vc4: Pass the atomic state to encoder hooks
  2020-12-07 14:16     ` Thomas Zimmermann
@ 2020-12-07 15:56       ` Maxime Ripard
  -1 siblings, 0 replies; 32+ messages in thread
From: Maxime Ripard @ 2020-12-07 15:56 UTC (permalink / raw)
  To: Thomas Zimmermann
  Cc: Dave Stevenson, David Airlie, Maarten Lankhorst, dri-devel,
	Eric Anholt, bcm-kernel-feedback-list, linux-rpi-kernel,
	Daniel Vetter, linux-arm-kernel


[-- Attachment #1.1: Type: text/plain, Size: 566 bytes --]

On Mon, Dec 07, 2020 at 03:16:40PM +0100, Thomas Zimmermann wrote:
> 
> 
> Am 07.12.20 um 14:39 schrieb Maxime Ripard:
> > We'll need to access the connector state in our encoder setup, so let's
> > just pass the whole DRM state to our private encoder hooks.
> > 
> > Signed-off-by: Maxime Ripard <maxime@cerno.tech>
> 
> This becomes relevant in patch 5, I guess?

Yep, we can't access the connector state from the crtc state alone,
hence why the change is needed.

> If so
> 
> Acked-by: Thomas Zimmermann <tzimmermann@suse.de>

Thanks!
Maxime

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

[-- Attachment #2: Type: text/plain, Size: 176 bytes --]

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v4 2/8] drm/vc4: Pass the atomic state to encoder hooks
@ 2020-12-07 15:56       ` Maxime Ripard
  0 siblings, 0 replies; 32+ messages in thread
From: Maxime Ripard @ 2020-12-07 15:56 UTC (permalink / raw)
  To: Thomas Zimmermann
  Cc: Dave Stevenson, David Airlie, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Daniel Vetter,
	linux-arm-kernel


[-- Attachment #1.1: Type: text/plain, Size: 566 bytes --]

On Mon, Dec 07, 2020 at 03:16:40PM +0100, Thomas Zimmermann wrote:
> 
> 
> Am 07.12.20 um 14:39 schrieb Maxime Ripard:
> > We'll need to access the connector state in our encoder setup, so let's
> > just pass the whole DRM state to our private encoder hooks.
> > 
> > Signed-off-by: Maxime Ripard <maxime@cerno.tech>
> 
> This becomes relevant in patch 5, I guess?

Yep, we can't access the connector state from the crtc state alone,
hence why the change is needed.

> If so
> 
> Acked-by: Thomas Zimmermann <tzimmermann@suse.de>

Thanks!
Maxime

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

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

end of thread, other threads:[~2020-12-08  8:34 UTC | newest]

Thread overview: 32+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-12-07 13:39 [PATCH v4 0/8] drm/vc4: hdmi: Support the 10/12 bit output Maxime Ripard
2020-12-07 13:39 ` Maxime Ripard
2020-12-07 13:39 ` [PATCH v4 1/8] drm/vc4: hvs: Align the HVS atomic hooks to the new API Maxime Ripard
2020-12-07 13:39   ` Maxime Ripard
2020-12-07 13:39 ` [PATCH v4 2/8] drm/vc4: Pass the atomic state to encoder hooks Maxime Ripard
2020-12-07 13:39   ` Maxime Ripard
2020-12-07 14:16   ` Thomas Zimmermann
2020-12-07 14:16     ` Thomas Zimmermann
2020-12-07 15:56     ` Maxime Ripard
2020-12-07 15:56       ` Maxime Ripard
2020-12-07 13:39 ` [PATCH v4 3/8] drm/vc4: hdmi: Don't access the connector state in reset if kmalloc fails Maxime Ripard
2020-12-07 13:39   ` Maxime Ripard
2020-12-07 14:05   ` Thomas Zimmermann
2020-12-07 14:05     ` Thomas Zimmermann
2020-12-07 13:39 ` [PATCH v4 4/8] drm/vc4: hdmi: Create a custom connector state Maxime Ripard
2020-12-07 13:39   ` Maxime Ripard
2020-12-07 14:07   ` Thomas Zimmermann
2020-12-07 14:07     ` Thomas Zimmermann
2020-12-07 13:39 ` [PATCH v4 5/8] drm/vc4: hdmi: Store pixel frequency in the " Maxime Ripard
2020-12-07 13:39   ` Maxime Ripard
2020-12-07 14:14   ` Thomas Zimmermann
2020-12-07 14:14     ` Thomas Zimmermann
2020-12-07 15:44     ` Maxime Ripard
2020-12-07 15:44       ` Maxime Ripard
2020-12-07 13:39 ` [PATCH v4 6/8] drm/vc4: hdmi: Use the connector state pixel rate for the PHY Maxime Ripard
2020-12-07 13:39   ` Maxime Ripard
2020-12-07 14:20   ` Thomas Zimmermann
2020-12-07 14:20     ` Thomas Zimmermann
2020-12-07 13:39 ` [PATCH v4 7/8] drm/vc4: hdmi: Limit the BCM2711 to the max without scrambling Maxime Ripard
2020-12-07 13:39   ` Maxime Ripard
2020-12-07 13:39 ` [PATCH v4 8/8] drm/vc4: hdmi: Enable 10/12 bpc output Maxime Ripard
2020-12-07 13:39   ` Maxime Ripard

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.