Re: [PATCH v5 9/9] drm/vc4: hdmi: Enable 10/12 bpc output

2020-12-10 Thread Maxime Ripard
Hi Dave,

On Wed, Dec 09, 2020 at 03:27:05PM +, Dave Stevenson wrote:
> Hi Maxime
> 
> On Mon, 7 Dec 2020 at 15:57, Maxime Ripard  wrote:
> >
> > The BCM2711 supports higher bpc count than just 8, so let's support it in
> > our driver.
> >
> > Signed-off-by: Maxime Ripard 
> > ---
> >  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 f4ff6b5db484..fb30ddd842b1 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;
> > +
> 
> Having added protection from the kzalloc failing in 4/9, this adds
> back in dereferencing conn_state without having checked it succeeded
> first :(

Yeah, you're right :/

I also noticed that we kfree the connector->state pointer, but nothing
really guarantees that the base field in our structure is at the offset
0

I've fixed both issues, I'll send a new iteration

Thanks!
Maxime


signature.asc
Description: PGP signature
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCH v5 9/9] drm/vc4: hdmi: Enable 10/12 bpc output

2020-12-09 Thread Dave Stevenson
Hi Maxime

On Mon, 7 Dec 2020 at 15:57, Maxime Ripard  wrote:
>
> The BCM2711 supports higher bpc count than just 8, so let's support it in
> our driver.
>
> Signed-off-by: Maxime Ripard 
> ---
>  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 f4ff6b5db484..fb30ddd842b1 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;
> +

Having added protection from the kzalloc failing in 4/9, this adds
back in dereferencing conn_state without having checked it succeeded
first :(

Otherwise this looks fine.

  Dave

> __drm_atomic_helper_connector_reset(connector, _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, _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, 

[PATCH v5 9/9] drm/vc4: hdmi: Enable 10/12 bpc output

2020-12-08 Thread Maxime Ripard
The BCM2711 supports higher bpc count than just 8, so let's support it in
our driver.

Signed-off-by: Maxime Ripard 
---
 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 f4ff6b5db484..fb30ddd842b1 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, _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, _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);