Re: UAPI Re: [PATCH 1/3] drm: Add DRM_MODE_TV_MODE_MONOCHROME

2024-02-26 Thread Dave Stevenson
Hi Pekka

Sorry for the slight delay in replying.

On Mon, 26 Feb 2024 at 15:11, Pekka Paalanen
 wrote:
>
> On Mon, 26 Feb 2024 15:10:45 +0100
> Maxime Ripard  wrote:
>
> > Hi Pekka,
> >
> > On Wed, Feb 21, 2024 at 11:07:51AM +0200, Pekka Paalanen wrote:
> > > On Fri, 16 Feb 2024 18:48:55 +
> > > Dave Stevenson  wrote:
> > >
> > > > From: Nick Hollinghurst 
> > > >
> > > > Add this as a value for enum_drm_connector_tv_mode, represented
> > > > by the string "Mono", to generate video with no colour encoding
> > > > or bursts. Define it to have no pedestal (since only NTSC-M calls
> > > > for a pedestal).
> > > >
> > > > Change default mode creation to acommodate the new tv_mode value
> > > > which comprises both 525-line and 625-line formats.
> > > >
> > > > Signed-off-by: Nick Hollinghurst 
> > > > Signed-off-by: Dave Stevenson 
> > >
> > > since no-one else commented yet, I'd like to remind of the new UAPI
> > > requirements:
> > > https://dri.freedesktop.org/docs/drm/gpu/drm-uapi.html#open-source-userspace-requirements
> > >
> > > AFAIU, adding a new value to an existing enum still counts as new UAPI.
> > >
> > > Maybe there is no need for the full treatment here, or maybe there is,
> > > I'm not sure. I think you should make some statement about how the new
> > > UAPI requirements have been addressed.
> >
> > That property was meant to provide legacy display handling, so I don't
> > expect any reasonably recent codebase like Weston to suppport it, ever
> > :)
> >
> > That being said, from the beginning, that property was meant to be
> > handled as a "mode-setting" property, and thus handled by either the
> > kernel command-line, xrandr, or any similar mechanism.
> >
> > I would expect that new enum variant to be handled under the same terms:
> > it'll probably only show up in distro scripts or configuration files,
> > and never in any actual code base.
> >
> > Is it what you were expecting, or did you mean something else?
>
> Maybe? Let's have it in the commit message and see if DRM maintainers
> agree.

You want the commit text for a patch adding a new enum to state that
the whole property isn't expected to be used through the UAPI? OK, I
can roll a v2 if that is your desire.

> You should expect that all KMS clients will work towards programming
> all exposed KMS properties into known values. That's the only way to
> achieve repeatable KMS behaviour, because there is no KMS reset ioctl.
>
> There are no two tiers of KMS properties AFAIK. You have to be the DRM
> master to change anything. So, people cannot force any settings from
> outside of a KMS client, they have to go through the KMS client, like
> xrandr goes through Xorg (and only Xorg).
>
> I do fully expect Weston to gain support for this property, if anyone
> cares of its value. That goes for all Wayland compositors.

I don't know about Weston, but Wayfire / wlroots / sway have currently
chosen to ignore all interlaced display modes [1].
[2] is the wlroots devs basically calling interlaced output a dead end.

That makes the debate for controlling the colour encoding on a
composite video rather redundant as they're almost always interlaced.

[1] https://github.com/swaywm/sway/issues/3167
[2] https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/3038

> You're correct in that a KMS client would probably not know to control
> the value of this property automatically but it needs to come from
> configuration. That would be each KMS client's configuration. I don't
> understand how a script could achieve that.
>
> However, if you feel it is important to have KMS properties that
> display servers must not touch, then they should be documented as such.
> I do not know if that would actually lift the new-UAPI requirements,
> that is for the DRM maintainers to decide and document. Is there such a
> thing already?
>
> What are those "similar to xrandr" mechanisms? I don't think I've heard
> of any,

Boot to the console and run
modetest -w :"tv_mode":"NTSC"
There is no reset mechanism for all properties, so that setting
persists after modetest quits.

> and I've also completely missed any kernel command line
> arguments manipulating KMS properties.

"tv_mode" on the command line is handled in
drm_mode_parse_cmdline_options() [3], as are rotate, reflect_x,
reflect_y, margin_[left|right|top|bottom], and panel_orientation all
to set the relevant KMS properties.

Having "video=Composite-1:PAL,tv_mode=Mono" on the kernel comm

Re: [PATCH] drm/edid/firmware: Remove built-in EDIDs

2024-02-20 Thread Dave Stevenson
Hi Maxime

On Tue, 20 Feb 2024 at 16:10, Maxime Ripard  wrote:
>
> The EDID firmware loading mechanism introduced a few built-in EDIDs that
> could be forced on any connector, bypassing the EDIDs it exposes.
>
> While convenient, this limited set of EDIDs doesn't take into account
> the connector type, and we can end up with an EDID that is completely
> invalid for a given connector.
>
> For example, the edid/800x600.bin file matches the following EDID:
>
>   edid-decode (hex):
>
>   00 ff ff ff ff ff ff 00 31 d8 00 00 00 00 00 00
>   05 16 01 03 6d 1b 14 78 ea 5e c0 a4 59 4a 98 25
>   20 50 54 01 00 00 45 40 01 01 01 01 01 01 01 01
>   01 01 01 01 01 01 a0 0f 20 00 31 58 1c 20 28 80
>   14 00 15 d0 10 00 00 1e 00 00 00 ff 00 4c 69 6e
>   75 78 20 23 30 0a 20 20 20 20 00 00 00 fd 00 3b
>   3d 24 26 05 00 0a 20 20 20 20 20 20 00 00 00 fc
>   00 4c 69 6e 75 78 20 53 56 47 41 0a 20 20 00 c2
>
>   
>
>   Block 0, Base EDID:
> EDID Structure Version & Revision: 1.3
> Vendor & Product Identification:
>   Manufacturer: LNX
>   Model: 0
>   Made in: week 5 of 2012
> Basic Display Parameters & Features:
>   Analog display
>   Signal Level Standard: 0.700 : 0.000 : 0.700 V p-p
>   Blank level equals black level
>   Sync: Separate Composite Serration
>   Maximum image size: 27 cm x 20 cm
>   Gamma: 2.20
>   DPMS levels: Standby Suspend Off
>   RGB color display
>   First detailed timing is the preferred timing
> Color Characteristics:
>   Red  : 0.6416, 0.3486
>   Green: 0.2919, 0.5957
>   Blue : 0.1474, 0.1250
>   White: 0.3125, 0.3281
> Established Timings I & II:
>   DMT 0x09:   800x60060.316541 Hz   4:3 37.879 kHz 40.00 
> MHz
> Standard Timings:
>   DMT 0x09:   800x60060.316541 Hz   4:3 37.879 kHz 40.00 
> MHz
> Detailed Timing Descriptors:
>   DTD 1:   800x60060.316541 Hz   4:3 37.879 kHz 40.00 MHz 
> (277 mm x 208 mm)
>Hfront   40 Hsync 128 Hback   88 Hpol P
>Vfront1 Vsync   4 Vback   23 Vpol P
>   Display Product Serial Number: 'Linux #0'
>   Display Range Limits:
> Monitor ranges (GTF): 59-61 Hz V, 36-38 kHz H, max dotclock 50 MHz
>   Display Product Name: 'Linux SVGA'
>   Checksum: 0xc2
>
> So, an analog monitor EDID. However, if the connector was an HDMI
> monitor for example, it breaks the HDMI specification that requires,
> among other things, a digital display, the VIC 1 mode and an HDMI Forum
> Vendor Specific Data Block in an CTA-861 extension.
>
> We thus end up with a completely invalid EDID, which thus might confuse
> HDMI-related code that could parse it.
>
> After some discussions on IRC, we identified mainly two ways to fix
> this:
>
>   - We can either create more EDIDs for each connector type to provide
> a built-in EDID that matches the resolution passed in the name, and
> still be a sensible EDID for that connector type;
>
>   - Or we can just prevent the EDID to be exposed to userspace if it's
> built-in.
>
> Or possibly both.
>
> However, the conclusion was that maybe we just don't need the built-in
> EDIDs at all and we should just get rid of them. So here we are.
>
> Signed-off-by: Maxime Ripard 
> ---
>  drivers/gpu/drm/drm_edid_load.c | 160 +++-

Needs to be removed from the docs too:

"The code (see drivers/gpu/drm/drm_edid_load.c) contains built-in data
sets for commonly used screen resolutions (800x600, 1024x768,
1280x1024, 1600x1200, 1680x1050, 1920x1080) as binary blobs,..."

https://github.com/torvalds/linux/blob/master/Documentation/admin-guide/edid.rst

I'm sad to see these go, but c'est la vie. Descriptions of using these
built in EDIDs abound in various tutorials, so those are all now
invalid :/

  Dave

>  1 file changed, 13 insertions(+), 147 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_edid_load.c b/drivers/gpu/drm/drm_edid_load.c
> index 60fcb80bce61..d1c7e8298702 100644
> --- a/drivers/gpu/drm/drm_edid_load.c
> +++ b/drivers/gpu/drm/drm_edid_load.c
> @@ -20,162 +20,28 @@
>
>  static char edid_firmware[PATH_MAX];
>  module_param_string(edid_firmware, edid_firmware, sizeof(edid_firmware), 
> 0644);
> -MODULE_PARM_DESC(edid_firmware, "Do not probe monitor, use specified EDID 
> blob "
> -   "from built-in data or /lib/firmware instead. ");
> -
> -#define GENERIC_EDIDS 6
> -static const char * const generic_edid_name[GENERIC_EDIDS] = {
> -   "edid/800x600.bin",
> -   "edid/1024x768.bin",
> -   "edid/1280x1024.bin",
> -   "edid/1600x1200.bin",
> -   "edid/1680x1050.bin",
> -   "edid/1920x1080.bin",
> -};
> -
> -static const u8 generic_edid[GENERIC_EDIDS][128] = {
> -   {
> -   0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
> -   0x31, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -   0x05, 0x16, 0x01, 0x03, 0x6d, 0x1b, 0x14, 0x78,
> -   0xea, 0x5e, 0xc0, 

[PATCH 3/3] drm/vc4: vec: Add the margin properties to the connector

2024-02-16 Thread Dave Stevenson
All the handling for the properties was present, but they
were never attached to the connector to allow userspace
to change them.

Add them to the connector.

Signed-off-by: Dave Stevenson 
---
 drivers/gpu/drm/vc4/vc4_vec.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/gpu/drm/vc4/vc4_vec.c b/drivers/gpu/drm/vc4/vc4_vec.c
index f9e134dd1e3b..0aed18920d18 100644
--- a/drivers/gpu/drm/vc4/vc4_vec.c
+++ b/drivers/gpu/drm/vc4/vc4_vec.c
@@ -528,6 +528,8 @@ static int vc4_vec_connector_init(struct drm_device *dev, 
struct vc4_vec *vec)
 
drm_object_attach_property(>base, prop, 
VC4_VEC_TV_MODE_NTSC);
 
+   drm_connector_attach_tv_margin_properties(connector);
+
drm_connector_attach_encoder(connector, >encoder.base);
 
return 0;
-- 
2.25.1



[PATCH 2/3] drm/vc4: Add monochrome mode to the VEC.

2024-02-16 Thread Dave Stevenson
The VEC supports not producing colour bursts for monochrome output.
It also has an option for disabling the chroma input to remove
chroma from the signal.

Now that there is a DRM_MODE_TV_MODE_MONOCHROME defined, plumb
this in.

Signed-off-by: Dave Stevenson 
---
 drivers/gpu/drm/vc4/vc4_vec.c | 28 +++-
 1 file changed, 27 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/vc4/vc4_vec.c b/drivers/gpu/drm/vc4/vc4_vec.c
index 268f18b10ee0..f9e134dd1e3b 100644
--- a/drivers/gpu/drm/vc4/vc4_vec.c
+++ b/drivers/gpu/drm/vc4/vc4_vec.c
@@ -234,6 +234,7 @@ enum vc4_vec_tv_mode_id {
VC4_VEC_TV_MODE_PAL_60,
VC4_VEC_TV_MODE_PAL_N,
VC4_VEC_TV_MODE_SECAM,
+   VC4_VEC_TV_MODE_MONOCHROME,
 };
 
 struct vc4_vec_tv_mode {
@@ -324,6 +325,22 @@ static const struct vc4_vec_tv_mode vc4_vec_tv_modes[] = {
.config1 = VEC_CONFIG1_C_CVBS_CVBS,
.custom_freq = 0x29c71c72,
},
+   {
+   /* 50Hz mono */
+   .mode = DRM_MODE_TV_MODE_MONOCHROME,
+   .expected_htotal = 864,
+   .config0 = VEC_CONFIG0_PAL_BDGHI_STD | VEC_CONFIG0_BURDIS |
+  VEC_CONFIG0_CHRDIS,
+   .config1 = VEC_CONFIG1_C_CVBS_CVBS,
+   },
+   {
+   /* 60Hz mono */
+   .mode = DRM_MODE_TV_MODE_MONOCHROME,
+   .expected_htotal = 858,
+   .config0 = VEC_CONFIG0_PAL_M_STD | VEC_CONFIG0_BURDIS |
+  VEC_CONFIG0_CHRDIS,
+   .config1 = VEC_CONFIG1_C_CVBS_CVBS,
+   },
 };
 
 static inline const struct vc4_vec_tv_mode *
@@ -351,6 +368,7 @@ static const struct drm_prop_enum_list 
legacy_tv_mode_names[] = {
{ VC4_VEC_TV_MODE_PAL_M, "PAL-M", },
{ VC4_VEC_TV_MODE_PAL_N, "PAL-N", },
{ VC4_VEC_TV_MODE_SECAM, "SECAM", },
+   { VC4_VEC_TV_MODE_MONOCHROME, "Mono", },
 };
 
 static enum drm_connector_status
@@ -406,6 +424,10 @@ vc4_vec_connector_set_property(struct drm_connector 
*connector,
state->tv.mode = DRM_MODE_TV_MODE_SECAM;
break;
 
+   case VC4_VEC_TV_MODE_MONOCHROME:
+   state->tv.mode = DRM_MODE_TV_MODE_MONOCHROME;
+   break;
+
default:
return -EINVAL;
}
@@ -453,6 +475,9 @@ vc4_vec_connector_get_property(struct drm_connector 
*connector,
*val = VC4_VEC_TV_MODE_SECAM;
break;
 
+   case DRM_MODE_TV_MODE_MONOCHROME:
+   return VC4_VEC_TV_MODE_MONOCHROME;
+
default:
return -EINVAL;
}
@@ -754,7 +779,8 @@ static int vc4_vec_bind(struct device *dev, struct device 
*master, void *data)
BIT(DRM_MODE_TV_MODE_PAL) |
BIT(DRM_MODE_TV_MODE_PAL_M) |
BIT(DRM_MODE_TV_MODE_PAL_N) |
-   BIT(DRM_MODE_TV_MODE_SECAM));
+   BIT(DRM_MODE_TV_MODE_SECAM) |
+   BIT(DRM_MODE_TV_MODE_MONOCHROME));
if (ret)
return ret;
 
-- 
2.25.1



[PATCH 1/3] drm: Add DRM_MODE_TV_MODE_MONOCHROME

2024-02-16 Thread Dave Stevenson
From: Nick Hollinghurst 

Add this as a value for enum_drm_connector_tv_mode, represented
by the string "Mono", to generate video with no colour encoding
or bursts. Define it to have no pedestal (since only NTSC-M calls
for a pedestal).

Change default mode creation to acommodate the new tv_mode value
which comprises both 525-line and 625-line formats.

Signed-off-by: Nick Hollinghurst 
Signed-off-by: Dave Stevenson 
---
 drivers/gpu/drm/drm_connector.c| 7 +++
 drivers/gpu/drm/drm_modes.c| 5 -
 drivers/gpu/drm/drm_probe_helper.c | 5 +++--
 include/drm/drm_connector.h| 7 +++
 4 files changed, 21 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
index b0516505f7ae..fe05d27f3404 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -1005,6 +1005,7 @@ static const struct drm_prop_enum_list 
drm_tv_mode_enum_list[] = {
{ DRM_MODE_TV_MODE_PAL_M, "PAL-M" },
{ DRM_MODE_TV_MODE_PAL_N, "PAL-N" },
{ DRM_MODE_TV_MODE_SECAM, "SECAM" },
+   { DRM_MODE_TV_MODE_MONOCHROME, "Mono" },
 };
 DRM_ENUM_NAME_FN(drm_get_tv_mode_name, drm_tv_mode_enum_list)
 
@@ -1697,6 +1698,12 @@ 
EXPORT_SYMBOL(drm_connector_attach_dp_subconnector_property);
  * TV Mode is CCIR System B (aka 625-lines) together with
  * the SECAM Color Encoding.
  *
+ * Mono:
+ *
+ * Use timings appropriate to the DRM mode, including
+ * equalizing pulses for a 525-line or 625-line mode,
+ * with no pedestal or color encoding.
+ *
  * Drivers can set up this property by calling
  * drm_mode_create_tv_properties().
  */
diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index c4f88c3a93b7..d274e7b00b79 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -530,7 +530,8 @@ static int fill_analog_mode(struct drm_device *dev,
  * @interlace: whether to compute an interlaced mode
  *
  * This function creates a struct drm_display_mode instance suited for
- * an analog TV output, for one of the usual analog TV mode.
+ * an analog TV output, for one of the usual analog TV modes. Where
+ * this is DRM_MODE_TV_MODE_MONOCHROME, a 625-line mode will be created.
  *
  * Note that @hdisplay is larger than the usual constraints for the PAL
  * and NTSC timings, and we'll choose to ignore most timings constraints
@@ -568,6 +569,8 @@ struct drm_display_mode *drm_analog_tv_mode(struct 
drm_device *dev,
case DRM_MODE_TV_MODE_PAL_N:
fallthrough;
case DRM_MODE_TV_MODE_SECAM:
+   fallthrough;
+   case DRM_MODE_TV_MODE_MONOCHROME:
analog = DRM_MODE_ANALOG_PAL;
break;
 
diff --git a/drivers/gpu/drm/drm_probe_helper.c 
b/drivers/gpu/drm/drm_probe_helper.c
index d1e1ade66f81..9254dc2af873 100644
--- a/drivers/gpu/drm/drm_probe_helper.c
+++ b/drivers/gpu/drm/drm_probe_helper.c
@@ -1211,8 +1211,9 @@ int drm_connector_helper_tv_get_modes(struct 
drm_connector *connector)
for (i = 0; i < tv_mode_property->num_values; i++)
supported_tv_modes |= BIT(tv_mode_property->values[i]);
 
-   if ((supported_tv_modes & ntsc_modes) &&
-   (supported_tv_modes & pal_modes)) {
+   if (((supported_tv_modes & ntsc_modes) &&
+(supported_tv_modes & pal_modes)) ||
+   (supported_tv_modes & BIT(DRM_MODE_TV_MODE_MONOCHROME))) {
uint64_t default_mode;
 
if (drm_object_property_get_default_value(>base,
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index fe88d7fc6b8f..90fd0ea0ca09 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -200,6 +200,13 @@ enum drm_connector_tv_mode {
 */
DRM_MODE_TV_MODE_SECAM,
 
+   /**
+* @DRM_MODE_TV_MODE_MONOCHROME: Use timings appropriate to
+* the DRM mode, including equalizing pulses for a 525-line
+* or 625-line mode, with no pedestal or color encoding.
+*/
+   DRM_MODE_TV_MODE_MONOCHROME,
+
/**
 * @DRM_MODE_TV_MODE_MAX: Number of analog TV output modes.
 *
-- 
2.25.1



[PATCH 0/3] vc4 VEC (analogue video) updates - margins and monochrome

2024-02-16 Thread Dave Stevenson
Hi All

A couple of patches to vc4, including adding a new "TV mode" enum for monochrome
output (yes we have some users who wish for monochrome).

Adding mono has raised a query here as to whether the the TV_MODE is meant to
describe the timing, or just the colour encoding.

The description for NTSC references "CCIR System M (aka 525-lines)", and PAL
references "CCIR System B" which is the 625 line standard.

PAL-60 is absent from the enum, but support has been added to vc4 by selecting 
DRM_MODE_TV_MODE_PAL but with the NTSC (CCIR System M) timings. Is that the
correct implementation? In which case the description for PAL should drop the
CCIR System B reference as selecting the "TV mode" doesn't dictate the timing.

Monochrome is in the same boat as it can adopt either 525 or 625 line timing,
or indeed anything else. Pi5 can support System A 405-line and the French
819-line mono modes as well.

If "TV mode" does dictate the timing as well as the colour encoding, then we
need to add PAL-60, and 2 modes for mono (extending to 4 for 405 and 819 line
modes later). If not, we ought to update the description.

Thoughts?

Thanks
  Dave

Dave Stevenson (2):
  drm/vc4: Add monochrome mode to the VEC.
  drm/vc4: vec: Add the margin properties to the connector

Nick Hollinghurst (1):
  drm: Add DRM_MODE_TV_MODE_MONOCHROME

 drivers/gpu/drm/drm_connector.c|  7 +++
 drivers/gpu/drm/drm_modes.c|  5 -
 drivers/gpu/drm/drm_probe_helper.c |  5 +++--
 drivers/gpu/drm/vc4/vc4_vec.c  | 30 +-
 include/drm/drm_connector.h|  7 +++
 5 files changed, 50 insertions(+), 4 deletions(-)

-- 
2.25.1



Re: Re: [PATCH v5 15/44] drm/connector: hdmi: Compute bpc and format automatically

2024-02-01 Thread Dave Stevenson
Hi Maxime

On Thu, 1 Feb 2024 at 12:51, Maxime Ripard  wrote:
>
> On Thu, Dec 14, 2023 at 03:10:43PM +, Dave Stevenson wrote:
> > > +static bool
> > > +sink_supports_format_bpc(const struct drm_connector *connector,
> > > +const struct drm_display_info *info,
> > > +const struct drm_display_mode *mode,
> > > +unsigned int format, unsigned int bpc)
> > > +{
> > > +   struct drm_device *dev = connector->dev;
> > > +   u8 vic = drm_match_cea_mode(mode);
> > > +
> > > +   if (vic == 1 && bpc != 8) {
> > > +   drm_dbg(dev, "VIC1 requires a bpc of 8, got %u\n", bpc);
> > > +   return false;
> > > +   }
> > > +
> > > +   if (!info->is_hdmi &&
> > > +   (format != HDMI_COLORSPACE_RGB || bpc != 8)) {
> > > +   drm_dbg(dev, "DVI Monitors require an RGB output at 8 
> > > bpc\n");
> > > +   return false;
> > > +   }
> > > +
> > > +   if (!(connector->hdmi.supported_formats & BIT(format))) {
> > > +   drm_dbg(dev, "%s format unsupported by the connector.\n",
> > > +   
> > > drm_hdmi_connector_get_output_format_name(format));
> > > +   return false;
> > > +   }
> > > +
> > > +   switch (format) {
> > > +   case HDMI_COLORSPACE_RGB:
> > > +   drm_dbg(dev, "RGB Format, checking the constraints.\n");
> > > +
> > > +   if (!(info->color_formats & DRM_COLOR_FORMAT_RGB444))
> > > +   return false;
> >
> > We've dropped this check from vc4 in our downstream kernel as it stops
> > you using the prebaked EDIDs (eg drm.edid_firmware=edid/1024x768.bin),
> > or any other EDID that is defined as an analog monitor.
> > The EDID parsing bombs out at [1], so info->color_formats gets left at 0.
>
> Right, but it only does so if the display isn't defined as a digital 
> display...
>
> > RGB is mandatory for both DVI and HDMI, so rejecting it seems overly fussy.
>
> ... which is required for both DVI and HDMI.
>
> And sure enough, if we decode that EDID:
>
> edid-decode (hex):
>
> 00 ff ff ff ff ff ff 00 31 d8 00 00 00 00 00 00
> 05 16 01 03 6d 23 1a 78 ea 5e c0 a4 59 4a 98 25
> 20 50 54 00 08 00 61 40 01 01 01 01 01 01 01 01
> 01 01 01 01 01 01 64 19 00 40 41 00 26 30 08 90
> 36 00 63 0a 11 00 00 18 00 00 00 ff 00 4c 69 6e
> 75 78 20 23 30 0a 20 20 20 20 00 00 00 fd 00 3b
> 3d 2f 31 07 00 0a 20 20 20 20 20 20 00 00 00 fc
> 00 4c 69 6e 75 78 20 58 47 41 0a 20 20 20 00 55
>
> 
>
> Block 0, Base EDID:
>   EDID Structure Version & Revision: 1.3
>   Vendor & Product Identification:
> Manufacturer: LNX
> Model: 0
> Made in: week 5 of 2012
>   Basic Display Parameters & Features:
> Analog display
> Signal Level Standard: 0.700 : 0.000 : 0.700 V p-p
> Blank level equals black level
> Sync: Separate Composite Serration
> Maximum image size: 35 cm x 26 cm
> Gamma: 2.20
> DPMS levels: Standby Suspend Off
> RGB color display
> First detailed timing is the preferred timing
>   Color Characteristics:
> Red  : 0.6416, 0.3486
> Green: 0.2919, 0.5957
> Blue : 0.1474, 0.1250
> White: 0.3125, 0.3281
>   Established Timings I & II:
> DMT 0x10:  1024x76860.003840 Hz   4:3 48.363 kHz 65.00 MHz
>   Standard Timings:
> DMT 0x10:  1024x76860.003840 Hz   4:3 48.363 kHz 65.00 MHz
>   Detailed Timing Descriptors:
> DTD 1:  1024x76860.003840 Hz   4:3 48.363 kHz 65.00 MHz 
> (355 mm x 266 mm)
>  Hfront8 Hsync 144 Hback  168 Hpol N
>  Vfront3 Vsync   6 Vback   29 Vpol N
> Display Product Serial Number: 'Linux #0'
> Display Range Limits:
>   Monitor ranges (GTF): 59-61 Hz V, 47-49 kHz H, max dotclock 70 MHz
> Display Product Name: 'Linux XGA'
> Checksum: 0x55
>
> 
>
> Warnings:
>
> Block 0, Base EDID:
>   Detailed Timing Descriptor #1: DTD is similar but not identical to DMT 0x10.
>
> EDID conformity: PASS
>
> So, if anything, it's the EDID that needs to be updated, not the code there.

So are these EDIDs only valid for VGA outputs and another set needs to
be added for HDMI monitors?

Having drm.edid_firmware=edid/1024x768.bin works on an HDMI connector
prior to this patch, so presumably drm_edid_loader needs to
automatically switch between the existing (analog) and new (digital)
EDIDs based on the connector type? Or are you requiring users to
change the strings they use?

Cheers.
  Dave


Re: drm: Stable identification of connectors?

2024-01-26 Thread Dave Stevenson
Hi Joerg

On Fri, 26 Jan 2024 at 10:45, Albert, Joerg (TT-U) 
wrote:

> Hi,
>
>
>
> I’m pretty new to DRM/DRI and wonder if there is a way to have a stable
> identification of connectors across changes in the Linux kernel and/or in
> the devicetree?
>
>
>
> Our hardware contains an iMX8QM with two displays, each one connected to a
> MIPI-DSI channel. We use kernel 6.1.38.
>
> In the output of “modetest -c” the connectors are called LVDS-1 and
> LVDS-2. These names are built in modetest.c from connector_type and
> connector_type_id.
>
>
>
> connector_type_id is set in the kernel in drivers/gpu/drm/drm_connector.c
> in __drm_connector_init():
>
>
>
>*connector* 
> ->*connector_type_id*
>   =
>
>   *ida_alloc_min* 
> (*connector_ida*
>  , 1, 
> *GFP_KERNEL* );
>
>
>
> Seems to me that this number depends on initialization order only. Is
> there any other way to identify a connector?
>
>
>
> If not, will the type_id be stable as long as we don’t change the kernel
> version and the device tree?
>

My understanding is it all depends on initialisation order, and that isn't
guaranteed.

Raspberry Pi 5 has a similar issue that it has two independent DRM driver
instances each initialising a DSI connector. Which one gets assigned DSI-1
vs DSI-2 is down to probe order, and can change between boots.
You also have the situation that a panel connected to the second connector
is referred to as DSI-1 if nothing is connected to the first, but it'll
probably bump up to DSI-2 should you later configure a panel on the first
connector. Any configuration within a window manager based on display ID is
therefore near useless if there is any change to the system.

It's the same situation if you have more than one SPI display using the
mipi-dbi-spi or tinyDRM drivers - ordering of display to SPI-x IDs is down
to probe order, so near random.

I haven't attempted to upstream this yet, but on our tree [1] I've adopted
the same approach as the I2C and SPI subsystems take where a DT alias can
be used to set the desired connector ID. Devices with no alias get assigned
IDs above the last assigned alias.

Seeing as you've raised the same issue, it'd be interesting to know the
view of the maintainers as to whether my solution is acceptable. There's no
point in trying to upstream it if it's going to be immediately shot down.

Thanks.
  Dave

[1]
https://github.com/raspberrypi/linux/commit/3aa1f2477545ea6298bc6f2d7ffae68f090af9b8
and fixup
https://github.com/raspberrypi/linux/commit/f429fc1a072d4bb35e622a1012a5a52914eba4e3


>
> Best Regards,
>
> Joerg Albert
>
>
>
>
>
>
>
>
>
>
>
>
> +491747384960
>
>
>
>
> We move the world for the better through technology and engineering.
>
> www.iav.com | Facebook  | Instagram
>  | LinkedIn
>  | Xing
>  | YouTube
> 
>
> IAV GmbH Ingenieurgesellschaft Auto und Verkehr; Sitz/Registered Office:
> Berlin; Registergericht/Registration Court: Amtsgericht Charlottenburg
> (Berlin); Registernummer/Company Registration Number: HRB 21 280 B;
> Geschäftsführer/Managing Directors: Joerg Astalosch, Martin Mahlke, Dr. Uwe
> Horn; Vorsitzender des Aufsichtsrates/Chairman of the Supervisory Board:
> Dr. Nikolai Ardey
> Datenschutzhinweise/Privacy Policy 
>
>
>


Re: [PATCH v5 08/44] drm/connector: hdmi: Add Broadcast RGB property

2024-01-12 Thread Dave Stevenson
Hi Maxime

On Fri, 12 Jan 2024 at 13:59, Maxime Ripard  wrote:
>
> Hi Dave,
>
> On Thu, Dec 14, 2023 at 02:43:37PM +, Dave Stevenson wrote:
> > On Thu, 7 Dec 2023 at 15:50, Maxime Ripard  wrote:
> > >
> > > The i915 driver has a property to force the RGB range of an HDMI output.
> > > The vc4 driver then implemented the same property with the same
> > > semantics. KWin has support for it, and a PR for mutter is also there to
> > > support it.
> > >
> > > Both drivers implementing the same property with the same semantics,
> > > plus the userspace having support for it, is proof enough that it's
> > > pretty much a de-facto standard now and we can provide helpers for it.
> > >
> > > Let's plumb it into the newly created HDMI connector.
> >
> > To have such a significant proportion of the patch being kunit tests
> > when there was no reference to such in the commit text was slightly
> > unexpected.
>
> Thanks for your review. Does that mean that you would prefer the tests
> to be in a separate patch?

If there was a need for a respin, then I think ideally yes, or at
least a mention in the commit text ("Let's plumb it into the newly
created HDMI connector*, and add appropriate unit tests*").
Overall I'm not that fussed though.

  Dave


Re: [PATCH v2 0/2] Add waveshare 7inch touchscreen panel support

2024-01-09 Thread Dave Stevenson
Hi

On Tue, 9 Jan 2024 at 11:19,  wrote:
>
> Hi,
>
> On 09/01/2024 08:09, Shengyang Chen wrote:
> > This patchset adds waveshare 7inch touchscreen panel support
> > for the StarFive JH7110 SoC.
>
> Could you precise which SKU you're referring to ? is it 19885 => 
> https://www.waveshare.com/7inch-dsi-lcd.htm ?
>
> Are you sure it requires different timings from the RPi one ? In the Waveshare
> wiki it explicitly uses the rpi setup (vc4-kms-dsi-7inch) to drive it: 
> https://www.waveshare.com/wiki/7inch_DSI_LCD

I raise the same question.

Keith Zhao earlier submitted effectively the same set of patches [1]
and the response for the updated timing was:

My platform dphy tx hardware has certain limitations.
Only supports integer multiples of 10M bitrate:
such as 160M ,170M, 180M,190M,...1G(max)

as common dphy bitrate = pixclock*bpp/lanes.
This value cannot match successfully in most cases.

so in order to match bitrate , I choose a bitrate value around
pixclock*bpp/lanes,
Prevent overflow and underflow by fine-tuning the timing parameters:-(
that will make the new timming value.


I then suggested mode_fixup should be used in the DSI host driver, and
Keith acknowledged that.

Is this new timing still because of the DSI host requirement?

  Dave

[1] https://lists.freedesktop.org/archives/dri-devel/2023-December/434150.html

> Neil
>
> >
> >
> > changes since v1:
> > - Rebased on tag v6.7.
> >
> > patch 1:
> > - Gave up original changing.
> > - Changed the commit message.
> > - Add compatible in panel-simple.yaml
> >
> > patch 2:
> > - Gave up original changing.
> > - Changed the commit message.
> > - Add new mode for the panel in panel-simple.c
> >
> > v1: 
> > https://patchwork.kernel.org/project/dri-devel/cover/20231124104451.44271-1-shengyang.c...@starfivetech.com/
> >
> > Shengyang Chen (2):
> >dt-bindings: display: panel: panel-simple: Add compatible property for
> >  waveshare 7inch touchscreen panel
> >gpu: drm: panel: panel-simple: add new display mode for waveshare
> >  7inch touchscreen panel
> >
> >   .../bindings/display/panel/panel-simple.yaml  |  2 ++
> >   drivers/gpu/drm/panel/panel-simple.c  | 28 +++
> >   2 files changed, 30 insertions(+)
> >
>


Re: [PATCH v9 09/25] drm/modes: Move named modes parsing to a separate function

2024-01-03 Thread Dave Stevenson
On Wed, 3 Jan 2024 at 14:02, Dave Stevenson
 wrote:
>
> Hi Maxime
>
> On Wed, 3 Jan 2024 at 13:33, Maxime Ripard  wrote:
> >
> > Hi Dave,
> >
> > Happy new year :)
>
> And to you.
>
> > On Tue, Jan 02, 2024 at 03:12:26PM +, Dave Stevenson wrote:
> > > Hi Maxime
> > >
> > > On Mon, 14 Nov 2022 at 13:00, Maxime Ripard  wrote:
> > > >
> > > > The current construction of the named mode parsing doesn't allow to 
> > > > extend
> > > > it easily. Let's move it to a separate function so we can add more
> > > > parameters and modes.
> > > >
> > > > In order for the tests to still pass, some extra checks are needed, so
> > > > it's not a 1:1 move.
> > > >
> > > > Reviewed-by: Noralf Trønnes 
> > > > Tested-by: Mateusz Kwiatkowski 
> > > > Signed-off-by: Maxime Ripard 
> > > >
> > > > ---
> > > > Changes in v7:
> > > > - Add Noralf Reviewed-by
> > > >
> > > > Changes in v6:
> > > > - Simplify the test for connection status extras
> > > > - Simplify the code path to call drm_mode_parse_cmdline_named_mode
> > > >
> > > > Changes in v4:
> > > > - Fold down all the named mode patches that were split into a single
> > > >   patch again to maintain bisectability
> > > > ---
> > > >  drivers/gpu/drm/drm_modes.c | 70 
> > > > +
> > > >  1 file changed, 58 insertions(+), 12 deletions(-)
> > > >
> > > > diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
> > > > index 71c050c3ee6b..37542612912b 100644
> > > > --- a/drivers/gpu/drm/drm_modes.c
> > > > +++ b/drivers/gpu/drm/drm_modes.c
> > > > @@ -2229,6 +2229,51 @@ static const char * const 
> > > > drm_named_modes_whitelist[] = {
> > > > "PAL",
> > > >  };
> > > >
> > > > +static int drm_mode_parse_cmdline_named_mode(const char *name,
> > > > +unsigned int name_end,
> > > > +struct drm_cmdline_mode 
> > > > *cmdline_mode)
> > > > +{
> > > > +   unsigned int i;
> > > > +
> > > > +   if (!name_end)
> > > > +   return 0;
> > > > +
> > > > +   /* If the name starts with a digit, it's not a named mode */
> > > > +   if (isdigit(name[0]))
> > > > +   return 0;
> > > > +
> > > > +   /*
> > > > +* If there's an equal sign in the name, the command-line
> > > > +* contains only an option and no mode.
> > > > +*/
> > > > +   if (strnchr(name, name_end, '='))
> > > > +   return 0;
> > > > +
> > > > +   /* The connection status extras can be set without a mode. */
> > > > +   if (name_end == 1 &&
> > > > +   (name[0] == 'd' || name[0] == 'D' || name[0] == 'e'))
> > > > +   return 0;
> > > > +
> > > > +   /*
> > > > +* We're sure we're a named mode at this point, iterate over the
> > > > +* list of modes we're aware of.
> > > > +*/
> > > > +   for (i = 0; i < ARRAY_SIZE(drm_named_modes_whitelist); i++) {
> > > > +   int ret;
> > > > +
> > > > +   ret = str_has_prefix(name, 
> > > > drm_named_modes_whitelist[i]);
> > > > +   if (ret != name_end)
> > > > +   continue;
> > > > +
> > > > +   strcpy(cmdline_mode->name, 
> > > > drm_named_modes_whitelist[i]);
> > > > +   cmdline_mode->specified = true;
> > > > +
> > > > +   return 1;
> > > > +   }
> > > > +
> > > > +   return -EINVAL;
> > > > +}
> > > > +
> > > >  /**
> > > >   * drm_mode_parse_command_line_for_connector - parse command line 
> > > > modeline for connector
> > > >   * @mode_option: optional per connector mode option
> > > > @@ -2265,7 +2310,7 @@ bool 
> > > > drm_mode_parse_command_line_for_connector(const char *mode_option,
> > >

Re: [PATCH v9 09/25] drm/modes: Move named modes parsing to a separate function

2024-01-03 Thread Dave Stevenson
Hi Maxime

On Wed, 3 Jan 2024 at 13:33, Maxime Ripard  wrote:
>
> Hi Dave,
>
> Happy new year :)

And to you.

> On Tue, Jan 02, 2024 at 03:12:26PM +, Dave Stevenson wrote:
> > Hi Maxime
> >
> > On Mon, 14 Nov 2022 at 13:00, Maxime Ripard  wrote:
> > >
> > > The current construction of the named mode parsing doesn't allow to extend
> > > it easily. Let's move it to a separate function so we can add more
> > > parameters and modes.
> > >
> > > In order for the tests to still pass, some extra checks are needed, so
> > > it's not a 1:1 move.
> > >
> > > Reviewed-by: Noralf Trønnes 
> > > Tested-by: Mateusz Kwiatkowski 
> > > Signed-off-by: Maxime Ripard 
> > >
> > > ---
> > > Changes in v7:
> > > - Add Noralf Reviewed-by
> > >
> > > Changes in v6:
> > > - Simplify the test for connection status extras
> > > - Simplify the code path to call drm_mode_parse_cmdline_named_mode
> > >
> > > Changes in v4:
> > > - Fold down all the named mode patches that were split into a single
> > >   patch again to maintain bisectability
> > > ---
> > >  drivers/gpu/drm/drm_modes.c | 70 
> > > +
> > >  1 file changed, 58 insertions(+), 12 deletions(-)
> > >
> > > diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
> > > index 71c050c3ee6b..37542612912b 100644
> > > --- a/drivers/gpu/drm/drm_modes.c
> > > +++ b/drivers/gpu/drm/drm_modes.c
> > > @@ -2229,6 +2229,51 @@ static const char * const 
> > > drm_named_modes_whitelist[] = {
> > > "PAL",
> > >  };
> > >
> > > +static int drm_mode_parse_cmdline_named_mode(const char *name,
> > > +unsigned int name_end,
> > > +struct drm_cmdline_mode 
> > > *cmdline_mode)
> > > +{
> > > +   unsigned int i;
> > > +
> > > +   if (!name_end)
> > > +   return 0;
> > > +
> > > +   /* If the name starts with a digit, it's not a named mode */
> > > +   if (isdigit(name[0]))
> > > +   return 0;
> > > +
> > > +   /*
> > > +* If there's an equal sign in the name, the command-line
> > > +* contains only an option and no mode.
> > > +*/
> > > +   if (strnchr(name, name_end, '='))
> > > +   return 0;
> > > +
> > > +   /* The connection status extras can be set without a mode. */
> > > +   if (name_end == 1 &&
> > > +   (name[0] == 'd' || name[0] == 'D' || name[0] == 'e'))
> > > +   return 0;
> > > +
> > > +   /*
> > > +* We're sure we're a named mode at this point, iterate over the
> > > +* list of modes we're aware of.
> > > +*/
> > > +   for (i = 0; i < ARRAY_SIZE(drm_named_modes_whitelist); i++) {
> > > +   int ret;
> > > +
> > > +   ret = str_has_prefix(name, drm_named_modes_whitelist[i]);
> > > +   if (ret != name_end)
> > > +   continue;
> > > +
> > > +   strcpy(cmdline_mode->name, drm_named_modes_whitelist[i]);
> > > +   cmdline_mode->specified = true;
> > > +
> > > +   return 1;
> > > +   }
> > > +
> > > +   return -EINVAL;
> > > +}
> > > +
> > >  /**
> > >   * drm_mode_parse_command_line_for_connector - parse command line 
> > > modeline for connector
> > >   * @mode_option: optional per connector mode option
> > > @@ -2265,7 +2310,7 @@ bool 
> > > drm_mode_parse_command_line_for_connector(const char *mode_option,
> > > const char *bpp_ptr = NULL, *refresh_ptr = NULL, *extra_ptr = 
> > > NULL;
> > > const char *options_ptr = NULL;
> > > char *bpp_end_ptr = NULL, *refresh_end_ptr = NULL;
> > > -   int i, len, ret;
> > > +   int len, ret;
> > >
> > > memset(mode, 0, sizeof(*mode));
> > > mode->panel_orientation = DRM_MODE_PANEL_ORIENTATION_UNKNOWN;
> > > @@ -2306,18 +2351,19 @@ bool 
> > > drm_mode_parse_command_line_for_connector(const char *mode_option,
> > > parse_extras = tr

Re: [PATCH v9 09/25] drm/modes: Move named modes parsing to a separate function

2024-01-02 Thread Dave Stevenson
Hi Maxime

On Mon, 14 Nov 2022 at 13:00, Maxime Ripard  wrote:
>
> The current construction of the named mode parsing doesn't allow to extend
> it easily. Let's move it to a separate function so we can add more
> parameters and modes.
>
> In order for the tests to still pass, some extra checks are needed, so
> it's not a 1:1 move.
>
> Reviewed-by: Noralf Trønnes 
> Tested-by: Mateusz Kwiatkowski 
> Signed-off-by: Maxime Ripard 
>
> ---
> Changes in v7:
> - Add Noralf Reviewed-by
>
> Changes in v6:
> - Simplify the test for connection status extras
> - Simplify the code path to call drm_mode_parse_cmdline_named_mode
>
> Changes in v4:
> - Fold down all the named mode patches that were split into a single
>   patch again to maintain bisectability
> ---
>  drivers/gpu/drm/drm_modes.c | 70 
> +
>  1 file changed, 58 insertions(+), 12 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
> index 71c050c3ee6b..37542612912b 100644
> --- a/drivers/gpu/drm/drm_modes.c
> +++ b/drivers/gpu/drm/drm_modes.c
> @@ -2229,6 +2229,51 @@ static const char * const drm_named_modes_whitelist[] 
> = {
> "PAL",
>  };
>
> +static int drm_mode_parse_cmdline_named_mode(const char *name,
> +unsigned int name_end,
> +struct drm_cmdline_mode 
> *cmdline_mode)
> +{
> +   unsigned int i;
> +
> +   if (!name_end)
> +   return 0;
> +
> +   /* If the name starts with a digit, it's not a named mode */
> +   if (isdigit(name[0]))
> +   return 0;
> +
> +   /*
> +* If there's an equal sign in the name, the command-line
> +* contains only an option and no mode.
> +*/
> +   if (strnchr(name, name_end, '='))
> +   return 0;
> +
> +   /* The connection status extras can be set without a mode. */
> +   if (name_end == 1 &&
> +   (name[0] == 'd' || name[0] == 'D' || name[0] == 'e'))
> +   return 0;
> +
> +   /*
> +* We're sure we're a named mode at this point, iterate over the
> +* list of modes we're aware of.
> +*/
> +   for (i = 0; i < ARRAY_SIZE(drm_named_modes_whitelist); i++) {
> +   int ret;
> +
> +   ret = str_has_prefix(name, drm_named_modes_whitelist[i]);
> +   if (ret != name_end)
> +   continue;
> +
> +   strcpy(cmdline_mode->name, drm_named_modes_whitelist[i]);
> +   cmdline_mode->specified = true;
> +
> +   return 1;
> +   }
> +
> +   return -EINVAL;
> +}
> +
>  /**
>   * drm_mode_parse_command_line_for_connector - parse command line modeline 
> for connector
>   * @mode_option: optional per connector mode option
> @@ -2265,7 +2310,7 @@ bool drm_mode_parse_command_line_for_connector(const 
> char *mode_option,
> const char *bpp_ptr = NULL, *refresh_ptr = NULL, *extra_ptr = NULL;
> const char *options_ptr = NULL;
> char *bpp_end_ptr = NULL, *refresh_end_ptr = NULL;
> -   int i, len, ret;
> +   int len, ret;
>
> memset(mode, 0, sizeof(*mode));
> mode->panel_orientation = DRM_MODE_PANEL_ORIENTATION_UNKNOWN;
> @@ -2306,18 +2351,19 @@ bool drm_mode_parse_command_line_for_connector(const 
> char *mode_option,
> parse_extras = true;
> }
>
> -   /* First check for a named mode */
> -   for (i = 0; i < ARRAY_SIZE(drm_named_modes_whitelist); i++) {
> -   ret = str_has_prefix(name, drm_named_modes_whitelist[i]);
> -   if (ret == mode_end) {
> -   if (refresh_ptr)
> -   return false; /* named + refresh is invalid */
> +   if (!mode_end)
> +   return false;

I'm chasing down a change in behaviour between 6.1 and 6.6, and this
patch seems to be at least part of the cause.

Since [1] we've had the emulated framebuffer on Pi being 16bpp to save
memory. All good.

It used to be possible to use "video=HDMI-A-1:-32" on the kernel
command line to set it back to 32bpp.

After this patch that is no longer possible. "mode_end = bpp_off", and
"bpp_off = bpp_ptr - name", so with bpp_ptr = name we get mode_end
being 0. That fails this conditional.
drm_mode_parse_cmdline_named_mode already aborts early but with no
error if name_end / mode_end is 0, so this "if" clause seems
redundant, and is a change in behaviour.

We do then get a second parsing failure due to the check if (bpp_ptr
|| refresh_ptr) at [2].
Prior to this patch my video= line would get mode->specified set via
"if (ret == mode_end)" removed above, as ret = mode_end = 0. We
therefore didn't evaluate the conditional that now fails.

So I guess my question is whether my command line is valid or not, and
therefore is this a regression?
If considered invalid, then presumably there is no way to update the
bpp without also having 

Re: RPI4B: what is needed for /dev/video10 to work ( v4l_m2m )

2024-01-02 Thread Dave Stevenson
On Tue, 2 Jan 2024 at 10:03, Maxime Ripard  wrote:
>
> Hi,
>
> On Wed, Dec 27, 2023 at 04:19:19PM +0100, AL13N wrote:
> > I have a RPI4B with upstream kernel 6.1 64bit and there is no /dev/video10
> > present. I thought if I waited a bit more, it would appear in the kernel,
> > but that was folly on my part.
> >
> > Currently, watching a movie is painful since the software decoding is way
> > too slow and it has very low fps on 1080p (or even 720p or even 480p)
> >
> > IIRC, someone told me something else has to be fixed before the codecs can
> > be done, but I don't remember what it was, or i didn't find it in my
> > email/the archives.
> >
> > Can someone tell me what exactly needs to be done (in kernel) so that I can
> > take a crack at it, (hopefully with some help)?
> >
> > I don't remember if this was relevant, but there was some talk of needing to
> > use opengl output with a specific texture format for it to work? or is that
> > seperate?
>
> That's something for linux-media. The hardware codec isn't part of vc4
> or v3d, it's a separate controller that requires a separate driver (in
> v4l2).
>
> That driver isn't upstream, and that would need the first thing to
> tackle.

IdeasOnBoard are working on our behalf to clean up the VCHIQ driver in
staging (hopefully unstaging it), and adding the mmal-vchiq, vcsm, and
ISP drivers. 
https://patchwork.linuxtv.org/project/linux-media/list/?series=11633
is probably the latest revision of the series, but there are a number
of supporting series around too.

The codec driver relies on the same mmal-vchiq and vcsm drivers as the
ISP, so adding that afterwards should be relatively simple.

Even though he's stepped back from being a maintainer, Stefan Wahren
is still keeping track of a number of the upstreaming tasks for the Pi
platform - see https://github.com/lategoodbye/rpi-zero/issues/43

  Dave


Re: [PATCH v5 15/44] drm/connector: hdmi: Compute bpc and format automatically

2023-12-14 Thread Dave Stevenson
Hi Maxime

On Thu, 7 Dec 2023 at 15:50, Maxime Ripard  wrote:
>
> Now that we have all the infrastructure needed, we can add some code
> that will, for a given connector state and mode, compute the best output
> format and bpc.
>
> The algorithm is the same one than the one already found in i915 and
> vc4.

We seem to have some extra words in this sentence.
"The algorithm is the same as that already found in i915 and vc4."?
Possibly "equivalent to" instead of "the same as", as i915 is slightly
different.

> Signed-off-by: Maxime Ripard 
> ---
>  drivers/gpu/drm/drm_atomic_state_helper.c  | 183 ++-
>  .../gpu/drm/tests/drm_atomic_state_helper_test.c   | 529 
> -
>  drivers/gpu/drm/tests/drm_kunit_edid.h | 160 +++
>  3 files changed, 860 insertions(+), 12 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_atomic_state_helper.c 
> b/drivers/gpu/drm/drm_atomic_state_helper.c
> index a36edda590f8..2442b5a2d94f 100644
> --- a/drivers/gpu/drm/drm_atomic_state_helper.c
> +++ b/drivers/gpu/drm/drm_atomic_state_helper.c
> @@ -682,6 +682,96 @@ static bool hdmi_is_full_range(const struct 
> drm_connector *connector,
> return drm_default_rgb_quant_range(mode) == 
> HDMI_QUANTIZATION_RANGE_FULL ? true : false;
>  }
>
> +static bool
> +sink_supports_format_bpc(const struct drm_connector *connector,
> +const struct drm_display_info *info,
> +const struct drm_display_mode *mode,
> +unsigned int format, unsigned int bpc)
> +{
> +   struct drm_device *dev = connector->dev;
> +   u8 vic = drm_match_cea_mode(mode);
> +
> +   if (vic == 1 && bpc != 8) {
> +   drm_dbg(dev, "VIC1 requires a bpc of 8, got %u\n", bpc);
> +   return false;
> +   }
> +
> +   if (!info->is_hdmi &&
> +   (format != HDMI_COLORSPACE_RGB || bpc != 8)) {
> +   drm_dbg(dev, "DVI Monitors require an RGB output at 8 bpc\n");
> +   return false;
> +   }
> +
> +   if (!(connector->hdmi.supported_formats & BIT(format))) {
> +   drm_dbg(dev, "%s format unsupported by the connector.\n",
> +   drm_hdmi_connector_get_output_format_name(format));
> +   return false;
> +   }
> +
> +   switch (format) {
> +   case HDMI_COLORSPACE_RGB:
> +   drm_dbg(dev, "RGB Format, checking the constraints.\n");
> +
> +   if (!(info->color_formats & DRM_COLOR_FORMAT_RGB444))
> +   return false;

We've dropped this check from vc4 in our downstream kernel as it stops
you using the prebaked EDIDs (eg drm.edid_firmware=edid/1024x768.bin),
or any other EDID that is defined as an analog monitor.
The EDID parsing bombs out at [1], so info->color_formats gets left at 0.

RGB is mandatory for both DVI and HDMI, so rejecting it seems overly fussy.

I don't see i915 making use of info->color_formats at all. The
equivalent function looks to be intel_hdmi_sink_bpc_possible [2] which
just accepts anything for 8bpc output.

  Dave

PS I'll have to defer looking at patch 16 for another day - it just
needs a bit more analysis than I can fit in today.

[1] 
https://elixir.free-electrons.com/linux/latest/source/drivers/gpu/drm/drm_edid.c#L6533
[2] 
https://elixir.bootlin.com/linux/latest/source/drivers/gpu/drm/i915/display/intel_hdmi.c#L1909

> +
> +   if (bpc == 10 && !(info->edid_hdmi_rgb444_dc_modes & 
> DRM_EDID_HDMI_DC_30)) {
> +   drm_dbg(dev, "10 BPC but sink doesn't support Deep 
> Color 30.\n");
> +   return false;
> +   }
> +
> +   if (bpc == 12 && !(info->edid_hdmi_rgb444_dc_modes & 
> DRM_EDID_HDMI_DC_36)) {
> +   drm_dbg(dev, "12 BPC but sink doesn't support Deep 
> Color 36.\n");
> +   return false;
> +   }
> +
> +   drm_dbg(dev, "RGB format supported in that configuration.\n");
> +
> +   return true;
> +
> +   case HDMI_COLORSPACE_YUV422:
> +   drm_dbg(dev, "YUV422 format, checking the constraints.\n");
> +
> +   if (!(info->color_formats & DRM_COLOR_FORMAT_YCBCR422)) {
> +   drm_dbg(dev, "Sink doesn't support YUV422.\n");
> +   return false;
> +   }
> +
> +   if (bpc != 12) {
> +   drm_dbg(dev, "YUV422 only supports 12 bpc.\n");
> +   return false;
> +   }
> +
> +   drm_dbg(dev, "YUV422 format supported in that 
> configuration.\n");
> +
> +   return true;
> +
> +   case HDMI_COLORSPACE_YUV444:
> +   drm_dbg(dev, "YUV444 format, checking the constraints.\n");
> +
> +   if (!(info->color_formats & DRM_COLOR_FORMAT_YCBCR444)) {
> +   drm_dbg(dev, "Sink doesn't support YUV444.\n");
> +   return false;
> 

Re: [PATCH v5 14/44] drm/connector: hdmi: Add custom hook to filter TMDS character rate

2023-12-14 Thread Dave Stevenson
On Thu, 7 Dec 2023 at 15:50, Maxime Ripard  wrote:
>
> Most of the HDMI controllers have an upper TMDS character rate limit
> they can't exceed. On "embedded"-grade display controllers, it will
> typically be lower than what high-grade monitors can provide these days,
> so drivers will filter the TMDS character rate based on the controller
> capabilities.
>
> To make that easier to handle for drivers, let's provide an optional
> hook to be implemented by drivers so they can tell the HDMI controller
> helpers if a given TMDS character rate is reachable for them or not.
>
> This will then be useful to figure out the best format and bpc count for
> a given mode.
>
> Signed-off-by: Maxime Ripard 

Reviewed-by: Dave Stevenson 

> ---
>  drivers/gpu/drm/drm_atomic_state_helper.c  |  9 +++
>  drivers/gpu/drm/drm_connector.c|  4 ++
>  .../gpu/drm/tests/drm_atomic_state_helper_test.c   | 69 
> ++
>  drivers/gpu/drm/tests/drm_connector_test.c | 15 +
>  include/drm/drm_connector.h| 30 ++
>  5 files changed, 127 insertions(+)
>
> diff --git a/drivers/gpu/drm/drm_atomic_state_helper.c 
> b/drivers/gpu/drm/drm_atomic_state_helper.c
> index 74bc3cc53c2d..a36edda590f8 100644
> --- a/drivers/gpu/drm/drm_atomic_state_helper.c
> +++ b/drivers/gpu/drm/drm_atomic_state_helper.c
> @@ -687,11 +687,20 @@ hdmi_clock_valid(const struct drm_connector *connector,
>  const struct drm_display_mode *mode,
>  unsigned long long clock)
>  {
> +   const struct drm_connector_hdmi_funcs *funcs = connector->hdmi.funcs;
> const struct drm_display_info *info = >display_info;
>
> if (info->max_tmds_clock && clock > info->max_tmds_clock * 1000)
> return MODE_CLOCK_HIGH;
>
> +   if (funcs && funcs->tmds_char_rate_valid) {
> +   enum drm_mode_status status;
> +
> +   status = funcs->tmds_char_rate_valid(connector, mode, clock);
> +   if (status != MODE_OK)
> +   return status;
> +   }
> +
> return MODE_OK;
>  }
>
> diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
> index 667326b09acc..9f314fee26ce 100644
> --- a/drivers/gpu/drm/drm_connector.c
> +++ b/drivers/gpu/drm/drm_connector.c
> @@ -457,6 +457,7 @@ EXPORT_SYMBOL(drmm_connector_init);
>   * @dev: DRM device
>   * @connector: A pointer to the HDMI connector to init
>   * @funcs: callbacks for this connector
> + * @hdmi_funcs: HDMI-related callbacks for this connector
>   * @connector_type: user visible type of the connector
>   * @ddc: optional pointer to the associated ddc adapter
>   * @supported_formats: Bitmask of @hdmi_colorspace listing supported output 
> formats
> @@ -476,6 +477,7 @@ EXPORT_SYMBOL(drmm_connector_init);
>  int drmm_connector_hdmi_init(struct drm_device *dev,
>  struct drm_connector *connector,
>  const struct drm_connector_funcs *funcs,
> +const struct drm_connector_hdmi_funcs 
> *hdmi_funcs,
>  int connector_type,
>  struct i2c_adapter *ddc,
>  unsigned long supported_formats,
> @@ -512,6 +514,8 @@ int drmm_connector_hdmi_init(struct drm_device *dev,
> if (max_bpc > 8)
> drm_connector_attach_hdr_output_metadata_property(connector);
>
> +   connector->hdmi.funcs = hdmi_funcs;
> +
> return 0;
>  }
>  EXPORT_SYMBOL(drmm_connector_hdmi_init);
> diff --git a/drivers/gpu/drm/tests/drm_atomic_state_helper_test.c 
> b/drivers/gpu/drm/tests/drm_atomic_state_helper_test.c
> index d76fafb91025..e7dbdd4a4e7f 100644
> --- a/drivers/gpu/drm/tests/drm_atomic_state_helper_test.c
> +++ b/drivers/gpu/drm/tests/drm_atomic_state_helper_test.c
> @@ -110,6 +110,21 @@ static int set_connector_edid(struct kunit *test, struct 
> drm_connector *connecto
> return 0;
>  }
>
> +static const struct drm_connector_hdmi_funcs dummy_connector_hdmi_funcs = {
> +};
> +
> +static enum drm_mode_status
> +reject_connector_tmds_char_rate_valid(const struct drm_connector *connector,
> +  const struct drm_display_mode *mode,
> +  unsigned long long tmds_rate)
> +{
> +   return MODE_BAD;
> +}
> +
> +static const struct drm_connector_hdmi_funcs reject_connector_hdmi_funcs = {
> +   .tmds_char_rate_valid   = reject_connector_tmds_char_rate_valid,
>

Re: [PATCH v5 13/44] drm/connector: hdmi: Calculate TMDS character rate

2023-12-14 Thread Dave Stevenson
On Thu, 7 Dec 2023 at 15:50, Maxime Ripard  wrote:
>
> Most HDMI drivers have some code to calculate the TMDS character rate,
> usually to adjust an internal clock to match what the mode requires.
>
> Since the TMDS character rates mostly depends on the resolution, whether
> we need to repeat pixels or not, the bpc count and the format, we can
> now derive it from the HDMI connector state that stores all those infos
> and remove the duplication from drivers.
>
> Signed-off-by: Maxime Ripard 

Reviewed-by: Dave Stevenson 

> ---
>  drivers/gpu/drm/drm_atomic.c   |   1 +
>  drivers/gpu/drm/drm_atomic_state_helper.c  |  44 +
>  .../gpu/drm/tests/drm_atomic_state_helper_test.c   | 169 
>  drivers/gpu/drm/tests/drm_kunit_edid.h | 216 
> +
>  include/drm/drm_connector.h|   5 +
>  5 files changed, 435 insertions(+)
>
> diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
> index 7aaa2a4d70d9..4f6493f91eed 100644
> --- a/drivers/gpu/drm/drm_atomic.c
> +++ b/drivers/gpu/drm/drm_atomic.c
> @@ -1150,6 +1150,7 @@ static void drm_atomic_connector_print_state(struct 
> drm_printer *p,
> drm_printf(p, "\toutput_bpc=%u\n", state->hdmi.output_bpc);
> drm_printf(p, "\toutput_format=%s\n",
>
> drm_hdmi_connector_get_output_format_name(state->hdmi.output_format));
> +   drm_printf(p, "\ttmds_char_rate=%llu\n", 
> state->hdmi.tmds_char_rate);
> }
>
> if (connector->connector_type == DRM_MODE_CONNECTOR_WRITEBACK)
> diff --git a/drivers/gpu/drm/drm_atomic_state_helper.c 
> b/drivers/gpu/drm/drm_atomic_state_helper.c
> index 92e1b087c3d0..74bc3cc53c2d 100644
> --- a/drivers/gpu/drm/drm_atomic_state_helper.c
> +++ b/drivers/gpu/drm/drm_atomic_state_helper.c
> @@ -682,6 +682,41 @@ static bool hdmi_is_full_range(const struct 
> drm_connector *connector,
> return drm_default_rgb_quant_range(mode) == 
> HDMI_QUANTIZATION_RANGE_FULL ? true : false;
>  }
>
> +static enum drm_mode_status
> +hdmi_clock_valid(const struct drm_connector *connector,
> +const struct drm_display_mode *mode,
> +unsigned long long clock)
> +{
> +   const struct drm_display_info *info = >display_info;
> +
> +   if (info->max_tmds_clock && clock > info->max_tmds_clock * 1000)
> +   return MODE_CLOCK_HIGH;
> +
> +   return MODE_OK;
> +}
> +
> +static int
> +hdmi_compute_clock(const struct drm_connector *connector,
> +  struct drm_connector_state *state,
> +  const struct drm_display_mode *mode,
> +  unsigned int bpc, enum hdmi_colorspace fmt)
> +{
> +   enum drm_mode_status status;
> +   unsigned long long clock;
> +
> +   clock = drm_connector_hdmi_compute_mode_clock(mode, bpc, fmt);
> +   if (!clock)
> +   return -EINVAL;
> +
> +   status = hdmi_clock_valid(connector, mode, clock);
> +   if (status != MODE_OK)
> +   return -EINVAL;
> +
> +   state->hdmi.tmds_char_rate = clock;
> +
> +   return 0;
> +}
> +
>  /**
>   * drm_atomic_helper_connector_hdmi_check() - Helper to check HDMI connector 
> atomic state
>   * @connector: DRM Connector
> @@ -701,9 +736,18 @@ int drm_atomic_helper_connector_hdmi_check(struct 
> drm_connector *connector,
> drm_atomic_get_old_connector_state(state, connector);
> struct drm_connector_state *new_state =
> drm_atomic_get_new_connector_state(state, connector);
> +   const struct drm_display_mode *mode =
> +   connector_state_get_mode(new_state);
> +   int ret;
>
> new_state->hdmi.is_full_range = hdmi_is_full_range(connector, 
> new_state);
>
> +   ret = hdmi_compute_clock(connector, new_state, mode,
> +new_state->hdmi.output_bpc,
> +new_state->hdmi.output_format);
> +   if (ret)
> +   return ret;
> +
> if (old_state->hdmi.broadcast_rgb != new_state->hdmi.broadcast_rgb ||
> old_state->hdmi.output_bpc != new_state->hdmi.output_bpc ||
> old_state->hdmi.output_format != new_state->hdmi.output_format) {
> diff --git a/drivers/gpu/drm/tests/drm_atomic_state_helper_test.c 
> b/drivers/gpu/drm/tests/drm_atomic_state_helper_test.c
> index 4e2ec436987b..d76fafb91025 100644
> --- a/drivers/gpu/drm/tests/drm_atomic_state_helper_test.c
> +++ b/drivers/gpu/drm/tests/drm_at

Re: [PATCH v5 12/44] drm/connector: hdmi: Add HDMI compute clock helper

2023-12-14 Thread Dave Stevenson
On Thu, 7 Dec 2023 at 15:50, Maxime Ripard  wrote:
>
> A lot of HDMI drivers have some variation of the formula to calculate
> the TMDS character rate from a mode, but few of them actually take all
> parameters into account.
>
> Let's create a helper to provide that rate taking all parameters into
> account.
>
> Signed-off-by: Maxime Ripard 
> ---
>  drivers/gpu/drm/drm_connector.c|  59 ++
>  drivers/gpu/drm/tests/drm_connector_test.c | 323 
> +
>  include/drm/drm_connector.h|   5 +
>  3 files changed, 387 insertions(+)
>
> diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
> index a72f38b6dbc8..667326b09acc 100644
> --- a/drivers/gpu/drm/drm_connector.c
> +++ b/drivers/gpu/drm/drm_connector.c
> @@ -2973,6 +2973,65 @@ void drm_connector_update_privacy_screen(const struct 
> drm_connector_state *conne
>  }
>  EXPORT_SYMBOL(drm_connector_update_privacy_screen);
>
> +/**
> + * drm_connector_hdmi_compute_mode_clock() - Computes the TMDS Character Rate
> + * @mode: Display mode to compute the clock for
> + * @bpc: Bits per character
> + * @fmt: Output Pixel Format used
> + *
> + * Returns the TMDS Character Rate for a given mode, bpc count and output 
> format.
> + *
> + * RETURNS:
> + * The TMDS Character Rate, in Hertz, or 0 on error.
> + */
> +unsigned long long
> +drm_connector_hdmi_compute_mode_clock(const struct drm_display_mode *mode,
> + unsigned int bpc,
> + enum hdmi_colorspace fmt)
> +{
> +   unsigned long long clock = mode->clock * 1000ULL;
> +   unsigned int vic = drm_match_cea_mode(mode);
> +
> +   /*
> +* CTA-861-G Spec, section 5.4 - Color Coding and Quantization
> +* mandates that VIC 1 always uses 8 bpc.
> +*/
> +   if (vic == 1 && bpc != 8)
> +   return 0;
> +
> +   /*
> +* HDMI 2.0 Spec, section 7.1 - YCbCr 4:2:0 Pixel Encoding
> +* specifies that YUV420 encoding is only available for those
> +* VICs.
> +*/
> +   if (fmt == HDMI_COLORSPACE_YUV420 &&
> +   !(vic == 96 || vic == 97 || vic == 101 ||
> + vic == 102 || vic == 106 || vic == 107))
> +   return 0;
> +
> +   /*
> +* HDMI 1.4b Spec, section 6.2.3 - Pixel Encoding Requirements
> +* specifies that YUV422 is 36-bit only.
> +*/
> +   if (fmt == HDMI_COLORSPACE_YUV422 && bpc != 12)
> +   return 0;
> +
> +   if (fmt == HDMI_COLORSPACE_YUV420)
> +   clock = clock / 2;
> +
> +   if (mode->flags & DRM_MODE_FLAG_DBLCLK)
> +   clock = clock * 2;
> +
> +   if (fmt == HDMI_COLORSPACE_YUV422)
> +   bpc = 8;

Possibly a comment on why we have these munges for 420 and 422 as they
aren't immediately obvious.

Reviewed-by: Dave Stevenson 

> +
> +   clock = clock * bpc;
> +   do_div(clock, 8);
> +
> +   return clock;
> +}
> +EXPORT_SYMBOL(drm_connector_hdmi_compute_mode_clock);
> +
>  int drm_connector_set_obj_prop(struct drm_mode_object *obj,
> struct drm_property *property,
> uint64_t value)
> diff --git a/drivers/gpu/drm/tests/drm_connector_test.c 
> b/drivers/gpu/drm/tests/drm_connector_test.c
> index fa6fe8084107..0a838924a546 100644
> --- a/drivers/gpu/drm/tests/drm_connector_test.c
> +++ b/drivers/gpu/drm/tests/drm_connector_test.c
> @@ -8,7 +8,9 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include 
> +#include 
>
>  #include 
>
> @@ -719,10 +721,331 @@ static struct kunit_suite 
> drm_connector_attach_broadcast_rgb_property_test_suite
> .test_cases = drm_connector_attach_broadcast_rgb_property_tests,
>  };
>
> +/*
> + * Test that for a given mode, with 8bpc and an RGB output the TMDS
> + * character rate is equal to the mode pixel clock.
> + */
> +static void drm_test_drm_connector_hdmi_compute_mode_clock_rgb(struct kunit 
> *test)
> +{
> +   struct drm_connector_init_priv *priv = test->priv;
> +   const struct drm_display_mode *mode;
> +   unsigned long long rate;
> +   struct drm_device *drm = >drm;
> +
> +   mode = drm_display_mode_from_cea_vic(drm, 16);
> +   KUNIT_ASSERT_NOT_NULL(test, mode);
> +
> +   KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK);
> +
> +   rate = drm_connector_hdmi_compute_mode_clock(mode, 8, 
> HDMI_COLORSPACE_RGB);
> +   KUNIT_ASSERT_GT(test, rate, 0);
> +   KUNI

Re: [PATCH v5 11/44] drm/connector: hdmi: Add support for output format

2023-12-14 Thread Dave Stevenson
On Thu, 7 Dec 2023 at 15:50, Maxime Ripard  wrote:
>
> Just like BPC, we'll add support for automatic selection of the output
> format for HDMI connectors.
>
> Let's add the needed defaults and fields for now.
>
> Signed-off-by: Maxime Ripard 

Reviewed-by: Dave Stevenson 

> ---
>  drivers/gpu/drm/drm_atomic.c   |   2 +
>  drivers/gpu/drm/drm_atomic_state_helper.c  |   3 +-
>  drivers/gpu/drm/drm_connector.c|  31 ++
>  .../gpu/drm/tests/drm_atomic_state_helper_test.c   |  90 ++---
>  drivers/gpu/drm/tests/drm_connector_test.c | 109 
> -
>  include/drm/drm_connector.h|  19 
>  6 files changed, 238 insertions(+), 16 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
> index 76c63ed04af4..7aaa2a4d70d9 100644
> --- a/drivers/gpu/drm/drm_atomic.c
> +++ b/drivers/gpu/drm/drm_atomic.c
> @@ -1148,6 +1148,8 @@ static void drm_atomic_connector_print_state(struct 
> drm_printer *p,
>
> drm_hdmi_connector_get_broadcast_rgb_name(state->hdmi.broadcast_rgb));
> drm_printf(p, "\tis_full_range=%c\n", 
> state->hdmi.is_full_range ? 'y' : 'n');
> drm_printf(p, "\toutput_bpc=%u\n", state->hdmi.output_bpc);
> +   drm_printf(p, "\toutput_format=%s\n",
> +  
> drm_hdmi_connector_get_output_format_name(state->hdmi.output_format));
> }
>
> if (connector->connector_type == DRM_MODE_CONNECTOR_WRITEBACK)
> diff --git a/drivers/gpu/drm/drm_atomic_state_helper.c 
> b/drivers/gpu/drm/drm_atomic_state_helper.c
> index 883bdc0349c0..92e1b087c3d0 100644
> --- a/drivers/gpu/drm/drm_atomic_state_helper.c
> +++ b/drivers/gpu/drm/drm_atomic_state_helper.c
> @@ -705,7 +705,8 @@ int drm_atomic_helper_connector_hdmi_check(struct 
> drm_connector *connector,
> new_state->hdmi.is_full_range = hdmi_is_full_range(connector, 
> new_state);
>
> if (old_state->hdmi.broadcast_rgb != new_state->hdmi.broadcast_rgb ||
> -   old_state->hdmi.output_bpc != new_state->hdmi.output_bpc) {
> +   old_state->hdmi.output_bpc != new_state->hdmi.output_bpc ||
> +   old_state->hdmi.output_format != new_state->hdmi.output_format) {
> struct drm_crtc *crtc = new_state->crtc;
> struct drm_crtc_state *crtc_state;
>
> diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
> index 139ac3d8160c..a72f38b6dbc8 100644
> --- a/drivers/gpu/drm/drm_connector.c
> +++ b/drivers/gpu/drm/drm_connector.c
> @@ -459,6 +459,7 @@ EXPORT_SYMBOL(drmm_connector_init);
>   * @funcs: callbacks for this connector
>   * @connector_type: user visible type of the connector
>   * @ddc: optional pointer to the associated ddc adapter
> + * @supported_formats: Bitmask of @hdmi_colorspace listing supported output 
> formats
>   * @max_bpc: Maximum bits per char the HDMI connector supports
>   *
>   * Initialises a preallocated HDMI connector. Connectors can be
> @@ -477,6 +478,7 @@ int drmm_connector_hdmi_init(struct drm_device *dev,
>  const struct drm_connector_funcs *funcs,
>  int connector_type,
>  struct i2c_adapter *ddc,
> +unsigned long supported_formats,
>  unsigned int max_bpc)
>  {
> int ret;
> @@ -485,6 +487,9 @@ int drmm_connector_hdmi_init(struct drm_device *dev,
>   connector_type == DRM_MODE_CONNECTOR_HDMIB))
> return -EINVAL;
>
> +   if (!supported_formats || !(supported_formats & 
> BIT(HDMI_COLORSPACE_RGB)))
> +   return -EINVAL;
> +
> if (!(max_bpc == 8 || max_bpc == 10 || max_bpc == 12))
> return -EINVAL;
>
> @@ -492,6 +497,8 @@ int drmm_connector_hdmi_init(struct drm_device *dev,
> if (ret)
> return ret;
>
> +   connector->hdmi.supported_formats = supported_formats;
> +
> /*
>  * drm_connector_attach_max_bpc_property() requires the
>  * connector to have a state.
> @@ -1224,6 +1231,30 @@ drm_hdmi_connector_get_broadcast_rgb_name(enum 
> drm_hdmi_broadcast_rgb broadcast_
>  }
>  EXPORT_SYMBOL(drm_hdmi_connector_get_broadcast_rgb_name);
>
> +static const char * const output_format_str[] = {
> +   [HDMI_COLORSPACE_RGB]   = "RGB",
> +   [HDMI_COLORSPACE_YUV420]= "YUV 4:2:0",
> +   [HDMI_COLORSPACE_YUV422]= "YUV 4:2:

Re: [PATCH v5 10/44] drm/connector: hdmi: Add output BPC to the connector state

2023-12-14 Thread Dave Stevenson
On Thu, 7 Dec 2023 at 15:50, Maxime Ripard  wrote:
>
> We'll add automatic selection of the output BPC in a following patch,
> but let's add it to the HDMI connector state already.
>
> Signed-off-by: Maxime Ripard 

Reviewed-by: Dave Stevenson 

> ---
>  drivers/gpu/drm/drm_atomic.c   |   1 +
>  drivers/gpu/drm/drm_atomic_state_helper.c  |   7 +-
>  drivers/gpu/drm/drm_connector.c|  20 +-
>  .../gpu/drm/tests/drm_atomic_state_helper_test.c   | 227 
> -
>  drivers/gpu/drm/tests/drm_connector_test.c | 153 +-
>  include/drm/drm_connector.h|  13 +-
>  6 files changed, 402 insertions(+), 19 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
> index e4ad53e64e07..76c63ed04af4 100644
> --- a/drivers/gpu/drm/drm_atomic.c
> +++ b/drivers/gpu/drm/drm_atomic.c
> @@ -1147,6 +1147,7 @@ static void drm_atomic_connector_print_state(struct 
> drm_printer *p,
> drm_printf(p, "\tbroadcast_rgb=%s\n",
>
> drm_hdmi_connector_get_broadcast_rgb_name(state->hdmi.broadcast_rgb));
> drm_printf(p, "\tis_full_range=%c\n", 
> state->hdmi.is_full_range ? 'y' : 'n');
> +   drm_printf(p, "\toutput_bpc=%u\n", state->hdmi.output_bpc);
> }
>
> if (connector->connector_type == DRM_MODE_CONNECTOR_WRITEBACK)
> diff --git a/drivers/gpu/drm/drm_atomic_state_helper.c 
> b/drivers/gpu/drm/drm_atomic_state_helper.c
> index 4a7114978c47..883bdc0349c0 100644
> --- a/drivers/gpu/drm/drm_atomic_state_helper.c
> +++ b/drivers/gpu/drm/drm_atomic_state_helper.c
> @@ -584,6 +584,10 @@ EXPORT_SYMBOL(drm_atomic_helper_connector_tv_reset);
>  void __drm_atomic_helper_connector_hdmi_reset(struct drm_connector 
> *connector,
>   struct drm_connector_state 
> *new_state)
>  {
> +   unsigned int max_bpc = connector->max_bpc;
> +
> +   new_state->max_bpc = max_bpc;
> +   new_state->max_requested_bpc = max_bpc;
> new_state->hdmi.broadcast_rgb = DRM_HDMI_BROADCAST_RGB_AUTO;
>  }
>  EXPORT_SYMBOL(__drm_atomic_helper_connector_hdmi_reset);
> @@ -700,7 +704,8 @@ int drm_atomic_helper_connector_hdmi_check(struct 
> drm_connector *connector,
>
> new_state->hdmi.is_full_range = hdmi_is_full_range(connector, 
> new_state);
>
> -   if (old_state->hdmi.broadcast_rgb != new_state->hdmi.broadcast_rgb) {
> +   if (old_state->hdmi.broadcast_rgb != new_state->hdmi.broadcast_rgb ||
> +   old_state->hdmi.output_bpc != new_state->hdmi.output_bpc) {
> struct drm_crtc *crtc = new_state->crtc;
> struct drm_crtc_state *crtc_state;
>
> diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
> index 929b0a911f62..139ac3d8160c 100644
> --- a/drivers/gpu/drm/drm_connector.c
> +++ b/drivers/gpu/drm/drm_connector.c
> @@ -459,6 +459,7 @@ EXPORT_SYMBOL(drmm_connector_init);
>   * @funcs: callbacks for this connector
>   * @connector_type: user visible type of the connector
>   * @ddc: optional pointer to the associated ddc adapter
> + * @max_bpc: Maximum bits per char the HDMI connector supports
>   *
>   * Initialises a preallocated HDMI connector. Connectors can be
>   * subclassed as part of driver connector objects.
> @@ -475,7 +476,8 @@ int drmm_connector_hdmi_init(struct drm_device *dev,
>  struct drm_connector *connector,
>  const struct drm_connector_funcs *funcs,
>  int connector_type,
> -struct i2c_adapter *ddc)
> +struct i2c_adapter *ddc,
> +unsigned int max_bpc)
>  {
> int ret;
>
> @@ -483,10 +485,26 @@ int drmm_connector_hdmi_init(struct drm_device *dev,
>   connector_type == DRM_MODE_CONNECTOR_HDMIB))
> return -EINVAL;
>
> +   if (!(max_bpc == 8 || max_bpc == 10 || max_bpc == 12))
> +   return -EINVAL;
> +
> ret = drmm_connector_init(dev, connector, funcs, connector_type, ddc);
> if (ret)
> return ret;
>
> +   /*
> +* drm_connector_attach_max_bpc_property() requires the
> +* connector to have a state.
> +*/
> +   if (connector->funcs->reset)
> +   connector->funcs->reset(connector);
> +
> +   drm_connector_attach_max_bpc_property(connector, 8, max_bpc);
> +   connector->max_bpc = max_bpc;
> +
> +   i

Re: [PATCH v5 09/44] drm/connector: hdmi: Add RGB Quantization Range to the connector state

2023-12-14 Thread Dave Stevenson
On Thu, 7 Dec 2023 at 15:50, Maxime Ripard  wrote:
>
> HDMI controller drivers will need to figure out the RGB range they need
> to configure based on a mode and property values. Let's expose that in
> the HDMI connector state so drivers can just use that value.

Again a mention that we're also adding unit tests wouldn't be amiss.

> Signed-off-by: Maxime Ripard 

Reviewed-by: Dave Stevenson 

> ---
>  drivers/gpu/drm/drm_atomic.c   |   4 +-
>  drivers/gpu/drm/drm_atomic_state_helper.c  |  44 +++
>  .../gpu/drm/tests/drm_atomic_state_helper_test.c   | 335 
> +
>  include/drm/drm_atomic_state_helper.h  |   1 +
>  include/drm/drm_connector.h|   6 +
>  5 files changed, 389 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
> index 1465a7f09a0b..e4ad53e64e07 100644
> --- a/drivers/gpu/drm/drm_atomic.c
> +++ b/drivers/gpu/drm/drm_atomic.c
> @@ -1143,9 +1143,11 @@ static void drm_atomic_connector_print_state(struct 
> drm_printer *p,
> drm_printf(p, "\tcolorspace=%s\n", 
> drm_get_colorspace_name(state->colorspace));
>
> if (connector->connector_type == DRM_MODE_CONNECTOR_HDMIA ||
> -   connector->connector_type == DRM_MODE_CONNECTOR_HDMIB)
> +   connector->connector_type == DRM_MODE_CONNECTOR_HDMIB) {
> drm_printf(p, "\tbroadcast_rgb=%s\n",
>
> drm_hdmi_connector_get_broadcast_rgb_name(state->hdmi.broadcast_rgb));
> +   drm_printf(p, "\tis_full_range=%c\n", 
> state->hdmi.is_full_range ? 'y' : 'n');
> +   }
>
> if (connector->connector_type == DRM_MODE_CONNECTOR_WRITEBACK)
> if (state->writeback_job && state->writeback_job->fb)
> diff --git a/drivers/gpu/drm/drm_atomic_state_helper.c 
> b/drivers/gpu/drm/drm_atomic_state_helper.c
> index 10d98620a358..4a7114978c47 100644
> --- a/drivers/gpu/drm/drm_atomic_state_helper.c
> +++ b/drivers/gpu/drm/drm_atomic_state_helper.c
> @@ -31,6 +31,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
>  #include 
> @@ -636,6 +637,47 @@ int drm_atomic_helper_connector_tv_check(struct 
> drm_connector *connector,
>  }
>  EXPORT_SYMBOL(drm_atomic_helper_connector_tv_check);
>
> +static const struct drm_display_mode *
> +connector_state_get_mode(const struct drm_connector_state *conn_state)
> +{
> +   struct drm_atomic_state *state;
> +   struct drm_crtc_state *crtc_state;
> +   struct drm_crtc *crtc;
> +
> +   state = conn_state->state;
> +   if (!state)
> +   return NULL;
> +
> +   crtc = conn_state->crtc;
> +   if (!crtc)
> +   return NULL;
> +
> +   crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
> +   if (!crtc_state)
> +   return NULL;
> +
> +   return _state->mode;
> +}
> +
> +static bool hdmi_is_full_range(const struct drm_connector *connector,
> +  const struct drm_connector_state *state)
> +{
> +   const struct drm_display_info *display = >display_info;
> +   const struct drm_display_mode *mode =
> +   connector_state_get_mode(state);
> +
> +   if (state->hdmi.broadcast_rgb == DRM_HDMI_BROADCAST_RGB_FULL)
> +   return true;
> +
> +   if (state->hdmi.broadcast_rgb == DRM_HDMI_BROADCAST_RGB_LIMITED)
> +   return false;
> +
> +   if (!display->is_hdmi)
> +   return true;
> +
> +   return drm_default_rgb_quant_range(mode) == 
> HDMI_QUANTIZATION_RANGE_FULL ? true : false;
> +}
> +
>  /**
>   * drm_atomic_helper_connector_hdmi_check() - Helper to check HDMI connector 
> atomic state
>   * @connector: DRM Connector
> @@ -656,6 +698,8 @@ int drm_atomic_helper_connector_hdmi_check(struct 
> drm_connector *connector,
> struct drm_connector_state *new_state =
> drm_atomic_get_new_connector_state(state, connector);
>
> +   new_state->hdmi.is_full_range = hdmi_is_full_range(connector, 
> new_state);
> +
> if (old_state->hdmi.broadcast_rgb != new_state->hdmi.broadcast_rgb) {
> struct drm_crtc *crtc = new_state->crtc;
> struct drm_crtc_state *crtc_state;
> diff --git a/drivers/gpu/drm/tests/drm_atomic_state_helper_test.c 
> b/drivers/gpu/drm/tests/drm_atomic_state_helper_test.c
> index 21e6f796ee13..7750c3d214a4 100644
> --- a/drivers/gpu/drm/tests/drm_atomic_state_helper_test.c
> +++ b/drivers/gpu/dr

Re: [PATCH v5 08/44] drm/connector: hdmi: Add Broadcast RGB property

2023-12-14 Thread Dave Stevenson
On Thu, 7 Dec 2023 at 15:50, Maxime Ripard  wrote:
>
> The i915 driver has a property to force the RGB range of an HDMI output.
> The vc4 driver then implemented the same property with the same
> semantics. KWin has support for it, and a PR for mutter is also there to
> support it.
>
> Both drivers implementing the same property with the same semantics,
> plus the userspace having support for it, is proof enough that it's
> pretty much a de-facto standard now and we can provide helpers for it.
>
> Let's plumb it into the newly created HDMI connector.

To have such a significant proportion of the patch being kunit tests
when there was no reference to such in the commit text was slightly
unexpected.

> Signed-off-by: Maxime Ripard 

Reviewed-by: Dave Stevenson 

> ---
>  Documentation/gpu/kms-properties.csv   |   1 -
>  drivers/gpu/drm/drm_atomic.c   |   5 +
>  drivers/gpu/drm/drm_atomic_state_helper.c  |  17 +
>  drivers/gpu/drm/drm_atomic_uapi.c  |   4 +
>  drivers/gpu/drm/drm_connector.c|  76 +
>  drivers/gpu/drm/tests/Makefile |   1 +
>  .../gpu/drm/tests/drm_atomic_state_helper_test.c   | 376 
> +
>  drivers/gpu/drm/tests/drm_connector_test.c | 117 ++-
>  drivers/gpu/drm/tests/drm_kunit_edid.h | 106 ++
>  include/drm/drm_connector.h|  36 ++
>  10 files changed, 737 insertions(+), 2 deletions(-)
>
> diff --git a/Documentation/gpu/kms-properties.csv 
> b/Documentation/gpu/kms-properties.csv
> index 0f9590834829..caef14c532d4 100644
> --- a/Documentation/gpu/kms-properties.csv
> +++ b/Documentation/gpu/kms-properties.csv
> @@ -17,7 +17,6 @@ Owner Module/Drivers,Group,Property Name,Type,Property 
> Values,Object attached,De
>  ,Virtual GPU,“suggested X”,RANGE,"Min=0, Max=0x",Connector,property 
> to suggest an X offset for a connector
>  ,,“suggested Y”,RANGE,"Min=0, Max=0x",Connector,property to suggest 
> an Y offset for a connector
>  ,Optional,"""aspect ratio""",ENUM,"{ ""None"", ""4:3"", ""16:9"" 
> }",Connector,TDB
> -i915,Generic,"""Broadcast RGB""",ENUM,"{ ""Automatic"", ""Full"", ""Limited 
> 16:235"" }",Connector,"When this property is set to Limited 16:235 and CTM is 
> set, the hardware will be programmed with the result of the multiplication of 
> CTM by the limited range matrix to ensure the pixels normally in the range 
> 0..1.0 are remapped to the range 16/255..235/255."
>  ,,“audio”,ENUM,"{ ""force-dvi"", ""off"", ""auto"", ""on"" }",Connector,TBD
>  ,SDVO-TV,“mode”,ENUM,"{ ""NTSC_M"", ""NTSC_J"", ""NTSC_443"", ""PAL_B"" } 
> etc.",Connector,TBD
>  ,,"""left_margin""",RANGE,"Min=0, Max= SDVO dependent",Connector,TBD
> diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
> index c31fc0b48c31..1465a7f09a0b 100644
> --- a/drivers/gpu/drm/drm_atomic.c
> +++ b/drivers/gpu/drm/drm_atomic.c
> @@ -1142,6 +1142,11 @@ static void drm_atomic_connector_print_state(struct 
> drm_printer *p,
> drm_printf(p, "\tmax_requested_bpc=%d\n", state->max_requested_bpc);
> drm_printf(p, "\tcolorspace=%s\n", 
> drm_get_colorspace_name(state->colorspace));
>
> +   if (connector->connector_type == DRM_MODE_CONNECTOR_HDMIA ||
> +   connector->connector_type == DRM_MODE_CONNECTOR_HDMIB)
> +   drm_printf(p, "\tbroadcast_rgb=%s\n",
> +  
> drm_hdmi_connector_get_broadcast_rgb_name(state->hdmi.broadcast_rgb));
> +
> if (connector->connector_type == DRM_MODE_CONNECTOR_WRITEBACK)
> if (state->writeback_job && state->writeback_job->fb)
> drm_printf(p, "\tfb=%d\n", 
> state->writeback_job->fb->base.id);
> diff --git a/drivers/gpu/drm/drm_atomic_state_helper.c 
> b/drivers/gpu/drm/drm_atomic_state_helper.c
> index e69c0cc1c6da..10d98620a358 100644
> --- a/drivers/gpu/drm/drm_atomic_state_helper.c
> +++ b/drivers/gpu/drm/drm_atomic_state_helper.c
> @@ -583,6 +583,7 @@ EXPORT_SYMBOL(drm_atomic_helper_connector_tv_reset);
>  void __drm_atomic_helper_connector_hdmi_reset(struct drm_connector 
> *connector,
>   struct dr

Re: [PATCH v5 07/44] drm/connector: hdmi: Create an HDMI sub-state

2023-12-14 Thread Dave Stevenson
On Thu, 7 Dec 2023 at 15:50, Maxime Ripard  wrote:
>
> The next features we will need to share across drivers will need to
> store some parameters for drivers to use, such as the selected output
> format.
>
> Let's create a new connector sub-state dedicated to HDMI controllers,
> that will eventually store everything we need.
>
> Signed-off-by: Maxime Ripard 

Reviewed-by: Dave Stevenson 

> ---
>  drivers/gpu/drm/drm_atomic_state_helper.c | 35 
> +++
>  include/drm/drm_atomic_state_helper.h |  4 
>  include/drm/drm_connector.h   |  7 +++
>  3 files changed, 46 insertions(+)
>
> diff --git a/drivers/gpu/drm/drm_atomic_state_helper.c 
> b/drivers/gpu/drm/drm_atomic_state_helper.c
> index 54975de44a0e..e69c0cc1c6da 100644
> --- a/drivers/gpu/drm/drm_atomic_state_helper.c
> +++ b/drivers/gpu/drm/drm_atomic_state_helper.c
> @@ -570,6 +570,22 @@ void drm_atomic_helper_connector_tv_reset(struct 
> drm_connector *connector)
>  }
>  EXPORT_SYMBOL(drm_atomic_helper_connector_tv_reset);
>
> +/**
> + * __drm_atomic_helper_connector_hdmi_reset() - Initializes all HDMI 
> @drm_connector_state resources
> + * @connector: DRM connector
> + * @new_state: connector state to reset
> + *
> + * Initializes all HDMI resources from a @drm_connector_state without
> + * actually allocating it. This is useful for HDMI drivers, in
> + * combination with __drm_atomic_helper_connector_reset() or
> + * drm_atomic_helper_connector_reset().
> + */
> +void __drm_atomic_helper_connector_hdmi_reset(struct drm_connector 
> *connector,
> + struct drm_connector_state 
> *new_state)
> +{
> +}
> +EXPORT_SYMBOL(__drm_atomic_helper_connector_hdmi_reset);
> +
>  /**
>   * drm_atomic_helper_connector_tv_check - Validate an analog TV connector 
> state
>   * @connector: DRM Connector
> @@ -619,6 +635,25 @@ int drm_atomic_helper_connector_tv_check(struct 
> drm_connector *connector,
>  }
>  EXPORT_SYMBOL(drm_atomic_helper_connector_tv_check);
>
> +/**
> + * drm_atomic_helper_connector_hdmi_check() - Helper to check HDMI connector 
> atomic state
> + * @connector: DRM Connector
> + * @state: the DRM State object
> + *
> + * Provides a default connector state check handler for HDMI connectors.
> + * Checks that a desired connector update is valid, and updates various
> + * fields of derived state.
> + *
> + * RETURNS:
> + * Zero on success, or an errno code otherwise.
> + */
> +int drm_atomic_helper_connector_hdmi_check(struct drm_connector *connector,
> +  struct drm_atomic_state *state)
> +{
> +   return 0;
> +}
> +EXPORT_SYMBOL(drm_atomic_helper_connector_hdmi_check);
> +
>  /**
>   * __drm_atomic_helper_connector_duplicate_state - copy atomic connector 
> state
>   * @connector: connector object
> diff --git a/include/drm/drm_atomic_state_helper.h 
> b/include/drm/drm_atomic_state_helper.h
> index b9740edb2658..d59d2b3aef9a 100644
> --- a/include/drm/drm_atomic_state_helper.h
> +++ b/include/drm/drm_atomic_state_helper.h
> @@ -71,7 +71,11 @@ void __drm_atomic_helper_connector_state_reset(struct 
> drm_connector_state *conn_
>  void __drm_atomic_helper_connector_reset(struct drm_connector *connector,
>  struct drm_connector_state 
> *conn_state);
>  void drm_atomic_helper_connector_reset(struct drm_connector *connector);
> +void __drm_atomic_helper_connector_hdmi_reset(struct drm_connector 
> *connector,
> + struct drm_connector_state 
> *new_state);
>  void drm_atomic_helper_connector_tv_reset(struct drm_connector *connector);
> +int drm_atomic_helper_connector_hdmi_check(struct drm_connector *connector,
> +  struct drm_atomic_state *state);
>  int drm_atomic_helper_connector_tv_check(struct drm_connector *connector,
>  struct drm_atomic_state *state);
>  void drm_atomic_helper_connector_tv_margins_reset(struct drm_connector 
> *connector);
> diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
> index 4491c4c2fb6e..000a2a156619 100644
> --- a/include/drm/drm_connector.h
> +++ b/include/drm/drm_connector.h
> @@ -1031,6 +1031,13 @@ struct drm_connector_state {
>  * DRM blob property for HDR output metadata
>  */
> struct drm_property_blob *hdr_output_metadata;
> +
> +   /**
> +* @hdmi: HDMI-related variable and properties. Filled by
> +* @drm_atomic_helper_connector_hdmi_check().
> +*/
> +   struct {
> +   } hdmi;
>  };
>
>  /**
>
> --
> 2.43.0
>


Re: [PATCH v5 06/44] drm/connector: Introduce an HDMI connector initialization function

2023-12-14 Thread Dave Stevenson
Hi Maxime

As requested, I'm just going through patches 6-16.
I will say that I've been less thorough in checking the kunit test
code in this series than the core code changes, and I'm trusting that
all the unit tests pass.

I get a build failure on the complete series for arm64 with the
standard defconfig
depmod: ERROR: Cycle detected: drm_display_helper -> drm_kms_helper ->
drm_display_helper
depmod: ERROR: Cycle detected: drm
depmod: ERROR: Found 2 modules in dependency cycles!

I haven't followed it through as to the reason, but obviously that
will need to be addressed.

  Dave

On Thu, 7 Dec 2023 at 15:49, Maxime Ripard  wrote:
>
> A lot of the various HDMI drivers duplicate some logic that depends on
> the HDMI spec itself and not really a particular hardware
> implementation.
>
> Output BPC or format selection, infoframe generation are good examples
> of such areas.
>
> This creates a lot of boilerplate, with a lot of variations, which makes
> it hard for userspace to rely on, and makes it difficult to get it right
> for drivers.
>
> In the next patches, we'll add a lot of infrastructure around the
> drm_connector and drm_connector_state structures, which will allow to
> abstract away the duplicated logic. This infrastructure comes with a few
> requirements though, and thus we need a new initialization function.
>
> Hopefully, this will make drivers simpler to handle, and their behaviour
> more consistent.
>
> Signed-off-by: Maxime Ripard 

Reviewed-by: Dave Stevenson 

> ---
>  drivers/gpu/drm/drm_connector.c|  39 +
>  drivers/gpu/drm/tests/drm_connector_test.c | 123 
> +
>  include/drm/drm_connector.h|   5 ++
>  3 files changed, 167 insertions(+)
>
> diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
> index b0516505f7ae..d9961cce8245 100644
> --- a/drivers/gpu/drm/drm_connector.c
> +++ b/drivers/gpu/drm/drm_connector.c
> @@ -452,6 +452,45 @@ int drmm_connector_init(struct drm_device *dev,
>  }
>  EXPORT_SYMBOL(drmm_connector_init);
>
> +/**
> + * drmm_connector_hdmi_init - Init a preallocated HDMI connector
> + * @dev: DRM device
> + * @connector: A pointer to the HDMI connector to init
> + * @funcs: callbacks for this connector
> + * @connector_type: user visible type of the connector
> + * @ddc: optional pointer to the associated ddc adapter
> + *
> + * Initialises a preallocated HDMI connector. Connectors can be
> + * subclassed as part of driver connector objects.
> + *
> + * Cleanup is automatically handled with a call to
> + * drm_connector_cleanup() in a DRM-managed action.
> + *
> + * The connector structure should be allocated with drmm_kzalloc().
> + *
> + * Returns:
> + * Zero on success, error code on failure.
> + */
> +int drmm_connector_hdmi_init(struct drm_device *dev,
> +struct drm_connector *connector,
> +const struct drm_connector_funcs *funcs,
> +int connector_type,
> +struct i2c_adapter *ddc)
> +{
> +   int ret;
> +
> +   if (!(connector_type == DRM_MODE_CONNECTOR_HDMIA ||
> + connector_type == DRM_MODE_CONNECTOR_HDMIB))
> +   return -EINVAL;
> +
> +   ret = drmm_connector_init(dev, connector, funcs, connector_type, ddc);
> +   if (ret)
> +   return ret;
> +
> +   return 0;
> +}
> +EXPORT_SYMBOL(drmm_connector_hdmi_init);
> +
>  /**
>   * drm_connector_attach_edid_property - attach edid property.
>   * @connector: the connector
> diff --git a/drivers/gpu/drm/tests/drm_connector_test.c 
> b/drivers/gpu/drm/tests/drm_connector_test.c
> index a268847be8d1..8f070cacab3b 100644
> --- a/drivers/gpu/drm/tests/drm_connector_test.c
> +++ b/drivers/gpu/drm/tests/drm_connector_test.c
> @@ -172,6 +172,128 @@ static struct kunit_suite 
> drmm_connector_init_test_suite = {
> .test_cases = drmm_connector_init_tests,
>  };
>
> +/*
> + * Test that the registration of a bog standard connector works as
> + * expected and doesn't report any error.
> + */
> +static void drm_test_connector_hdmi_init_valid(struct kunit *test)
> +{
> +   struct drm_connector_init_priv *priv = test->priv;
> +   int ret;
> +
> +   ret = drmm_connector_hdmi_init(>drm, >connector,
> +  _funcs,
> +  DRM_MODE_CONNECTOR_HDMIA,
> +  >ddc);
> +   KUNIT_EXPECT_EQ(test, ret, 0);
> +}
> +
> +/*
> + * Test that the registration of a connector without a DDC adapter
> + * doesn't report any error.
>

Re: [PATCH v5 18/44] drm/vc4: hdmi: Create destroy state implementation

2023-12-12 Thread Dave Stevenson
On Thu, 7 Dec 2023 at 15:50, Maxime Ripard  wrote:
>
> Even though we were rolling our own custom state for the vc4 HDMI
> controller driver, we were still using the generic helper to destroy
> that state.
>
> It was mostly working since the underlying state is the first member of
> our state so the pointers are probably equal in all relevant cases, but
> it's still fragile so let's fix this properly.
>
> Signed-off-by: Maxime Ripard 

Reviewed-by: Dave Stevenson 

> ---
>  drivers/gpu/drm/vc4/vc4_hdmi.c | 12 +++-
>  1 file changed, 11 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index 25c9c71256d3..f05e2c95a60d 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -672,11 +672,21 @@ vc4_hdmi_connector_duplicate_state(struct drm_connector 
> *connector)
> return _state->base;
>  }
>
> +static void vc4_hdmi_connector_destroy_state(struct drm_connector *connector,
> +struct drm_connector_state 
> *state)
> +{
> +   struct vc4_hdmi_connector_state *vc4_state =
> +   conn_state_to_vc4_hdmi_conn_state(state);
> +
> +   __drm_atomic_helper_connector_destroy_state(state);
> +   kfree(vc4_state);
> +}
> +
>  static const struct drm_connector_funcs vc4_hdmi_connector_funcs = {
> .fill_modes = drm_helper_probe_single_connector_modes,
> .reset = vc4_hdmi_connector_reset,
> .atomic_duplicate_state = vc4_hdmi_connector_duplicate_state,
> -   .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
> +   .atomic_destroy_state = vc4_hdmi_connector_destroy_state,
> .atomic_get_property = vc4_hdmi_connector_get_property,
> .atomic_set_property = vc4_hdmi_connector_set_property,
>  };
>
> --
> 2.43.0
>


Re: [PATCH v1 0/2] Add waveshare 7inch touchscreen panel support

2023-12-06 Thread Dave Stevenson
Hi Keith

On Wed, 6 Dec 2023 at 08:55, Keith Zhao  wrote:
>
>
>
> On 2023/11/25 0:04, Dave Stevenson wrote:
> > On Fri, 24 Nov 2023 at 15:00, Stefan Wahren  wrote:
> >>
> >> Hi Shengyang,
> >>
> >> [fix address of Emma]
> >
> > Not merged to master yet, but Emma has stepped back from maintenance.
> > https://lists.freedesktop.org/archives/dri-devel/2023-October/428829.html
> > Dropped from the cc.
> >
> >> Am 24.11.23 um 11:44 schrieb Shengyang Chen:
> >> > This patchset adds waveshare 7inch touchscreen panel support
> >> > for the StarFive JH7110 SoC.
> >> >
> >> > Patch 1 add new compatible for the raspberrypi panel driver and its 
> >> > dt-binding.
> >> > Patch 2 add new display mode and new probing process for raspberrypi 
> >> > panel driver.
> >> >
> >> > Waveshare 7inch touchscreen panel is a kind of raspberrypi panel
> >> > which can be drived by raspberrypi panel driver.
> >> >
> >> > The series has been tested on the VisionFive 2 board.
> >> surprisingly i was recently working on the official Raspberry Pi
> >> touchscreen and was able to get it running the new way.
> >>
> >> What do i mean with the new way. There is almost nothing special to the
> >> Raspberry Pi touchscreen, so we should try to use/extend existing
> >> components like:
> >>
> >> CONFIG_DRM_PANEL_SIMPLE
> >> CONFIG_TOUCHSCREEN_EDT_FT5X06
> >> CONFIG_DRM_TOSHIBA_TC358762
> >>
> >> The only special part is the Attiny on the connector PCB which requires:
> >>
> >> CONFIG_REGULATOR_RASPBERRYPI_TOUCHSCREEN_ATTINY
> >>
> >> So the whole point is to avoid writing monolitic drivers for simple
> >> panel like that.
> >>
> >> There is a WIP branch based on top of Linux 6.7-rcX, which should
> >> demonstrate this approach [1]. Unfortunately it is not ready for
> >> upstreaming, but it has been tested on a Raspberry Pi 3 B Plus. Maybe
> >> this is helpful for your case.
> >>
> >> Actually i consider panel-raspberrypi-touchscreen.c as a dead end, which
> >> shouldn't be extended.
> >
> > Agreed.
> >
> > The panel control being bound in with the Atmel control has no hook
> > for the EDT5x06 touch driver to hook in and keep the power to the
> > touch controller active. When the panel disable gets called, bye bye
> > touch overlay :-(
> >
> > And I'm reading the driver change as more of a hack to get it to work
> > on your platform, not as adding support for the Waveshare panel
> > variant.
> > Waveshare deliberately cloned the behaviour of the Pi 7" panel in
> > order to make it work with the old Pi firmware drivers, so it
> > shouldn't need any significant changes. Where did the new timings come
> > from?
> >
> >   Dave
> hi Dave :
> that's means the panel driver split into 3 sub-modules:
> panel + panel_bridge + regulator.

Correct.

You'll have a fourth device in edt_ft5x06 for the touch overlay too,
which will link to the regulator driver for power control.

> I have a question: in the
> static int rpi_touchscreen_probe(struct i2c_client *i2c)
> {
> ..
>
> ver = rpi_touchscreen_i2c_read(ts, REG_ID);
> if (ver < 0) {
> dev_err(dev, "Atmel I2C read failed: %d\n", ver);
> return -ENODEV;
> }
>
> switch (ver) {
> case 0xde: /* ver 1 */
> case 0xc3: /* ver 2 */
> break;
> default:
> dev_err(dev, "Unknown Atmel firmware revision: 0x%02x\n", 
> ver);
> return -ENODEV;
> }
>
> ..
> }
> i think this "I2C read" can use to detect whether the panel is connected to 
> dsi controller.
>
> and when split the panel driver into 3 sub-modules, it seems the default way 
> is connected.
> if I drop the panel , run modetest to check the connector status , result 
> connected.
> Is there any way to detect the connection in this case?
> Thanks

I am not aware of any DSI drivers that support hotplugging, therefore
the connector state will always be connected if the device probes.

On vc4 the relevant DSI host controller has to have been enabled in
device tree and will be a required component for binding. The DSI host
controller will be waiting on the DSI peripheral driver to call
mipi_dsi_attach, which then calls component_add. If the panel or panel
regulator isn't present, then that never happens if 

Re: [PATCH v4 02/10] drm/bridge: Fix a use case in the bridge disable logic

2023-12-05 Thread Dave Stevenson
Hi Dario

On Tue, 5 Dec 2023 at 10:54, Dario Binacchi
 wrote:
>
> The patch fixes the code for finding the next bridge with the
> "pre_enable_prev_first" flag set to false. In case this condition is
> not verified, i. e. there is no subsequent bridge with the flag set to
> false, the whole bridge list is traversed, invalidating the "next"
> variable.
>
> The use of a new iteration variable (i. e. "iter") ensures that the value
> of the "next" variable is not invalidated.

We already have https://patchwork.freedesktop.org/patch/529288/ that
has been reviewed (but not applied) to resolve this. What does this
version do differently and why?

  Dave

> Fixes: 4fb912e5e190 ("drm/bridge: Introduce pre_enable_prev_first to alter 
> bridge init order")
> Co-developed-by: Michael Trimarchi 
> Signed-off-by: Michael Trimarchi 
> Signed-off-by: Dario Binacchi 
> ---
>
> (no changes since v1)
>
>  drivers/gpu/drm/drm_bridge.c | 9 +
>  1 file changed, 5 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
> index f66bf4925dd8..2e5781bf192e 100644
> --- a/drivers/gpu/drm/drm_bridge.c
> +++ b/drivers/gpu/drm/drm_bridge.c
> @@ -662,7 +662,7 @@ void drm_atomic_bridge_chain_post_disable(struct 
> drm_bridge *bridge,
>   struct drm_atomic_state *old_state)
>  {
> struct drm_encoder *encoder;
> -   struct drm_bridge *next, *limit;
> +   struct drm_bridge *iter, *next, *limit;
>
> if (!bridge)
> return;
> @@ -680,14 +680,15 @@ void drm_atomic_bridge_chain_post_disable(struct 
> drm_bridge *bridge,
>  * was enabled first, so disabled last
>  */
> limit = next;
> +   iter = next;
>
> /* Find the next bridge that has NOT requested
>  * prev to be enabled first / disabled last
>  */
> -   list_for_each_entry_from(next, 
> >bridge_chain,
> +   list_for_each_entry_from(iter, 
> >bridge_chain,
>  chain_node) {
> -   if (!next->pre_enable_prev_first) {
> -   next = list_prev_entry(next, 
> chain_node);
> +   if (!iter->pre_enable_prev_first) {
> +   next = list_prev_entry(iter, 
> chain_node);
> limit = next;
> break;
> }
> --
> 2.43.0
>


Re: [PATCH v1 0/2] Add waveshare 7inch touchscreen panel support

2023-11-24 Thread Dave Stevenson
On Fri, 24 Nov 2023 at 15:00, Stefan Wahren  wrote:
>
> Hi Shengyang,
>
> [fix address of Emma]

Not merged to master yet, but Emma has stepped back from maintenance.
https://lists.freedesktop.org/archives/dri-devel/2023-October/428829.html
Dropped from the cc.

> Am 24.11.23 um 11:44 schrieb Shengyang Chen:
> > This patchset adds waveshare 7inch touchscreen panel support
> > for the StarFive JH7110 SoC.
> >
> > Patch 1 add new compatible for the raspberrypi panel driver and its 
> > dt-binding.
> > Patch 2 add new display mode and new probing process for raspberrypi panel 
> > driver.
> >
> > Waveshare 7inch touchscreen panel is a kind of raspberrypi panel
> > which can be drived by raspberrypi panel driver.
> >
> > The series has been tested on the VisionFive 2 board.
> surprisingly i was recently working on the official Raspberry Pi
> touchscreen and was able to get it running the new way.
>
> What do i mean with the new way. There is almost nothing special to the
> Raspberry Pi touchscreen, so we should try to use/extend existing
> components like:
>
> CONFIG_DRM_PANEL_SIMPLE
> CONFIG_TOUCHSCREEN_EDT_FT5X06
> CONFIG_DRM_TOSHIBA_TC358762
>
> The only special part is the Attiny on the connector PCB which requires:
>
> CONFIG_REGULATOR_RASPBERRYPI_TOUCHSCREEN_ATTINY
>
> So the whole point is to avoid writing monolitic drivers for simple
> panel like that.
>
> There is a WIP branch based on top of Linux 6.7-rcX, which should
> demonstrate this approach [1]. Unfortunately it is not ready for
> upstreaming, but it has been tested on a Raspberry Pi 3 B Plus. Maybe
> this is helpful for your case.
>
> Actually i consider panel-raspberrypi-touchscreen.c as a dead end, which
> shouldn't be extended.

Agreed.

The panel control being bound in with the Atmel control has no hook
for the EDT5x06 touch driver to hook in and keep the power to the
touch controller active. When the panel disable gets called, bye bye
touch overlay :-(

And I'm reading the driver change as more of a hack to get it to work
on your platform, not as adding support for the Waveshare panel
variant.
Waveshare deliberately cloned the behaviour of the Pi 7" panel in
order to make it work with the old Pi firmware drivers, so it
shouldn't need any significant changes. Where did the new timings come
from?

  Dave

> Btw there are already DT overlays in mainline which seems to use the
> Raspberry Pi 7inch panel (without touch function yet) [2].
>
> [1] - https://github.com/lategoodbye/rpi-zero/commits/v6.7-7inch-ts
> [2] -
> https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx-0x-rpidsi.dtso?h=v6.6.2=6b4da1354fd81adace0cda448c77d8f2a47d8474
>
> >
> > Shengyang Chen (2):
> >dt-bindings: display: panel: raspberrypi: Add compatible property for
> >  waveshare 7inch touchscreen panel
> >gpu: drm: panel: raspberrypi: add new display mode and new probing
> >  process
> >
> >   .../panel/raspberrypi,7inch-touchscreen.yaml  |  4 +-
> >   .../drm/panel/panel-raspberrypi-touchscreen.c | 99 ---
> >   2 files changed, 91 insertions(+), 12 deletions(-)
> >
>


Re: [RFC PATCH 2/2] vc4: introduce DMA-BUF heap

2023-11-09 Thread Dave Stevenson
Hi Simon

On Thu, 9 Nov 2023 at 17:46, Simon Ser  wrote:
>
> On Thursday, November 9th, 2023 at 16:42, Dave Stevenson 
>  wrote:
>
> > > > - What would be a good name for the heap? "vc4" is maybe a bit naive and
> > > >   not precise enough. Something with "cma"? Do we need to plan a naming
> > > >   scheme to accomodate for multiple vc4 devices?
> > >
> > > That's a general issue though that happens with pretty much all devices
> > > with a separate node for modesetting and rendering, so I don't think
> > > addressing it only for vc4 make sense, we should make it generic.
> > >
> > > So maybe something like "scanout"?
> > >
> > > One thing we need to consider too is that the Pi5 will have multiple
> > > display nodes (4(?) iirc) with different capabilities, vc4 being only
> > > one of them. This will impact that solution too.
> >
> > It does need to scale.
> >
> > Pi5 adds 4 additional DRM devices (2xDSI, 1xDPI, and 1xComposite
> > Video), and just this last week I've been running Wayfire with TinyDRM
> > drivers for SPI displays and UDL (DisplayLink) outputs as well.
> > Presumably all of those drivers need to have appropriate hooks added
> > so they each expose a dma-heap to enable scanout buffers to be
> > allocated.
>
> I'm not sure this makes sense necessarily for all of these devices. For vc4 
> and
> the 4 additional RPi 5 DRM devices, probably. For the rest, e.g. UDL, I'm not
> sure it makes sense to expose scanout memory allocation via DMA heaps: AFAIK
> UDL needs CPU access to the buffers, it can't "scanout", and thus directly
> rendering via v3d to a "scanout-capable" buffer doesn't make sense. There will
> be a copy (CPU download) either way, and allocating via v3d wouldn't make a
> difference.

You as a developer may know that UDL is going to need CPU access, but
how does a generic userspace app know? Is it a case of falling back to
allocating via the renderer if there is no suitably named heap?

> > Can we add another function pointer to the struct drm_driver (or
> > similar) to do the allocation, and move the actual dmabuf handling
> > code into the core?
>
> Do you mean that the new logic introduced in this patch should be in DRM core
> to allow other drivers to more easily re-use it? Or do you mean something 
> else?

Yes, make it easy to reuse between drivers.

> Indeed, there is nothing vc4-specific in this patch, the only requirement is
> that the driver uses drm_gem_dma_helper. So this code could be moved into (or
> alongside) that helper in DRM core. However, maybe it would be best to wait to
> have a second user for this infrastructure before we move into core.

Upstreaming of the DSI / DPI / composite drivers for Pi5 should only
be a few months away, and they can all directly scanout.

I expect the Rockchip platforms to also fall into the same category as
the Pi, with Mali as the 3D IP, and the VOP block as the scanout
engine. Have I missed some detail that means that they aren't a second
user for this?

> > > > - Need to add !vc5 support.
> > >
> > > If by !vc5 you mean RPi0-3, then it's probably not needed there at all
> > > since it has a single node for both modesetting and rendering?
> >
> > That is true, but potentially vc4 could be rendering for scanout via UDL or 
> > SPI.
> > Is it easier to always have the dma-heap allocator for every DRM card
> > rather than making userspace mix and match depending on whether it is
> > all in one vs split?
>
> I don't think it's realistic to try to always make DMA heaps available for 
> each
> and every driver which might need it from day one. It's too big of a task. And
> it's an even bigger task to try to design a fully generic heap compatibility
> uAPI from day one. I'd much rather add the heaps one by one, if and when we
> figure that it makes sense, and incrementally work our way through.

Is it really that massive a task? We have the dma heap UAPI for
handling the allocations, so what new UAPI is required?

If it's a new function pointer in struct drm_driver, then the heap is
only created by the core if that function is defined using the driver
name. The function returns a struct dma_buf *.
Any driver using drm_gem_dma_helper can use the new helper function
that is basically your vc4_dma_heap_allocate. The "if
(WARN_ON_ONCE(!vc4->is_vc5))" could be handled by not setting the
function pointer on those platforms.

Sorry, I feel I must be missing some critical piece of information here.

  Dave


Re: [RFC PATCH 2/2] vc4: introduce DMA-BUF heap

2023-11-09 Thread Dave Stevenson
Hi Simon and Maxime

On Thu, 9 Nov 2023 at 09:12, Maxime Ripard  wrote:
>
> Hi Simon,
>
> On Thu, Nov 09, 2023 at 07:45:58AM +, Simon Ser wrote:
> > User-space sometimes needs to allocate scanout-capable memory for
> > GPU rendering purposes. On a vc4/v3d split render/display SoC, this
> > is achieved via DRM dumb buffers: the v3d user-space driver opens
> > the primary vc4 node, allocates a DRM dumb buffer there, exports it
> > as a DMA-BUF, imports it into the v3d render node, and renders to it.
> >
> > However, DRM dumb buffers are only meant for CPU rendering, they are
> > not intended to be used for GPU rendering. Primary nodes should only
> > be used for mode-setting purposes, other programs should not attempt
> > to open it. Moreover, opening the primary node is already broken on
> > some setups: systemd grants permission to open primary nodes to
> > physically logged in users, but this breaks when the user is not
> > physically logged in (e.g. headless setup) and when the distribution
> > is using a different init (e.g. Alpine Linux uses openrc).
> >
> > We need an alternate way for v3d to allocate scanout-capable memory.
> > Leverage DMA heaps for this purpose: expose a CMA heap to user-space.
> > Preliminary testing has been done with wlroots [1].
> >
> > This is still an RFC. Open questions:
> >
> > - Does this approach make sense to y'all in general?
>
> Makes sense to me :)
>
> > - What would be a good name for the heap? "vc4" is maybe a bit naive and
> >   not precise enough. Something with "cma"? Do we need to plan a naming
> >   scheme to accomodate for multiple vc4 devices?
>
> That's a general issue though that happens with pretty much all devices
> with a separate node for modesetting and rendering, so I don't think
> addressing it only for vc4 make sense, we should make it generic.
>
> So maybe something like "scanout"?
>
> One thing we need to consider too is that the Pi5 will have multiple
> display nodes (4(?) iirc) with different capabilities, vc4 being only
> one of them. This will impact that solution too.

It does need to scale.

Pi5 adds 4 additional DRM devices (2xDSI, 1xDPI, and 1xComposite
Video), and just this last week I've been running Wayfire with TinyDRM
drivers for SPI displays and UDL (DisplayLink) outputs as well.
Presumably all of those drivers need to have appropriate hooks added
so they each expose a dma-heap to enable scanout buffers to be
allocated.

Can we add another function pointer to the struct drm_driver (or
similar) to do the allocation, and move the actual dmabuf handling
code into the core?

> > - Right now root privileges are necessary to open the heap. Should we
> >   allow everybody to open the heap by default (after all, user-space can
> >   already allocate arbitrary amounts of GPU memory)? Should we leave it
> >   up to user-space to solve this issue (via logind/seatd or a Wayland
> >   protocol or something else)?
>
> I would have expected a udev rule to handle that?
>
> > TODO:
> >
> > - Need to add !vc5 support.
>
> If by !vc5 you mean RPi0-3, then it's probably not needed there at all
> since it has a single node for both modesetting and rendering?

That is true, but potentially vc4 could be rendering for scanout via UDL or SPI.
Is it easier to always have the dma-heap allocator for every DRM card
rather than making userspace mix and match depending on whether it is
all in one vs split?

  Dave


Re: [PATCH] drm/vc4: fix typo

2023-10-23 Thread Dave Stevenson
Hi Dario

Thanks for the patch.

On Mon, 23 Oct 2023 at 09:59, Dario Binacchi
 wrote:
>
> Replace 'pack' with 'back'.
>
> Fixes: c8b75bca92cb ("drm/vc4: Add KMS support for Raspberry Pi.")
> Signed-off-by: Dario Binacchi 

Reviewed-by: Dave Stevenson 

> ---
>
>  drivers/gpu/drm/vc4/vc4_regs.h | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h
> index f3763bd600f6..8ac9515554f8 100644
> --- a/drivers/gpu/drm/vc4/vc4_regs.h
> +++ b/drivers/gpu/drm/vc4/vc4_regs.h
> @@ -588,7 +588,7 @@ enum {
>  # define VC4_HDMI_HORZA_HAP_MASK   VC4_MASK(12, 0)
>  # define VC4_HDMI_HORZA_HAP_SHIFT  0
>
> -/* Horizontal pack porch (htotal - hsync_end). */
> +/* Horizontal back porch (htotal - hsync_end). */
>  # define VC4_HDMI_HORZB_HBP_MASK   VC4_MASK(29, 20)
>  # define VC4_HDMI_HORZB_HBP_SHIFT  20
>  /* Horizontal sync pulse (hsync_end - hsync_start). */
> --
> 2.42.0
>


Re: DRM FB emulation initialisation leaving the display disabled

2023-10-13 Thread Dave Stevenson
Hi Thomas

Thanks for the response.

On Thu, 12 Oct 2023 at 08:03, Thomas Zimmermann  wrote:
>
> Hi Dave
>
> Am 11.10.23 um 17:52 schrieb Dave Stevenson:
> > Hi Thomas (and everyone else)
> >
> > Maxime has suggested you're the person for DRM framebuffer emulation.
> >
> > I'm getting some unexpected behaviour when there are multiple DRM
> > drivers in play. In this case it happens to be vc4 and the tiny
> > hx8357d SPI display driver, but this affects most of the tiny DRM
> > drivers and also the DSI and DPI outputs on the Pi5.
> > We get different behaviour depending on whether vc4 or hx8357d
> > initialises first.
> >
> > If hx8357d loads first and registers as /dev/fb0 through the fb
> > emulation, then we get fbcon enabling the display and putting the
> > emulated framebuffer on it. vc4 then loads, registers /dev/fb1, and
> > through the hotplug handler it enables the display
> > (drm_fb_helper_hotplug_event calls, drm_fb_helper_set_par, which calls
> > __drm_fb_helper_restore_fbdev_mode_unlocked).
> >
> > If vc4 loads first and claims /dev/fb0, fbcon initalises and enables
> > the display. hx8357d then loads and registers as /dev/fb1. fbcon is
> > not configured for that fb, and there is no subsequent hotplug event
> > (SPI displays aren't hotpluggable), so we have a fully configured
> > framebuffer exposed to userspace but the display itself isn't enabled
> > so we don't see anything :-(
> > Open and close /dev/dri/card1 and the lastclose hook calls
> > drm_fb_helper_restore_fbdev_mode_unlocked and we get the display
> > enabled.
>
> What you're describing sounds like the recent bug report at
>
>https://gitlab.freedesktop.org/drm/amd/-/issues/2649
>
> which had similar symptoms with amdgpu. IIRC the console didn't
> initialize if the DRM hotplugging event happened before fbdev emulation
> was ready. DRM's fbdev code would then not see the hotplugged connector.
>
> Do you have commit 27655b9bb9f0 ("drm/client: Send hotplug event after
> registering a client") in your tree? (It's been ported into various
> stable branches as well.)

I was about to switch from my 6.1.55 build to the latest just to
ensure it hadn't been fixed, but that commit hit the 6.1 stable branch
in 6.1.43, so I do have it.

Other priorities have overtaken my investigation of this, but at least
knowing that it should enable the outputs (and nominally through the
hotplug hook) I can have another look at what is actually going on.

Thanks again
  Dave

> Best regard
> Thomas
>
> >
> > Is it intentional that we're left in this limbo state with the display
> > not enabled if fbcon isn't enabled on a framebuffer?
> >
> > We're trying to get people to transition from the fbdev drivers to DRM
> > equivalents, but this seems to be a backwards step if there is an
> > extra step required to get the display enabled. Many users are still
> > just using the framebuffer.
> >
> > Any input is much appreciated.
> >
> > Thanks,
> >Dave
>
> --
> Thomas Zimmermann
> Graphics Driver Developer
> SUSE Software Solutions Germany GmbH
> Frankenstrasse 146, 90461 Nuernberg, Germany
> GF: Ivo Totev, Andrew Myers, Andrew McDonald, Boudien Moerman
> HRB 36809 (AG Nuernberg)


DRM FB emulation initialisation leaving the display disabled

2023-10-11 Thread Dave Stevenson
Hi Thomas (and everyone else)

Maxime has suggested you're the person for DRM framebuffer emulation.

I'm getting some unexpected behaviour when there are multiple DRM
drivers in play. In this case it happens to be vc4 and the tiny
hx8357d SPI display driver, but this affects most of the tiny DRM
drivers and also the DSI and DPI outputs on the Pi5.
We get different behaviour depending on whether vc4 or hx8357d
initialises first.

If hx8357d loads first and registers as /dev/fb0 through the fb
emulation, then we get fbcon enabling the display and putting the
emulated framebuffer on it. vc4 then loads, registers /dev/fb1, and
through the hotplug handler it enables the display
(drm_fb_helper_hotplug_event calls, drm_fb_helper_set_par, which calls
__drm_fb_helper_restore_fbdev_mode_unlocked).

If vc4 loads first and claims /dev/fb0, fbcon initalises and enables
the display. hx8357d then loads and registers as /dev/fb1. fbcon is
not configured for that fb, and there is no subsequent hotplug event
(SPI displays aren't hotpluggable), so we have a fully configured
framebuffer exposed to userspace but the display itself isn't enabled
so we don't see anything :-(
Open and close /dev/dri/card1 and the lastclose hook calls
drm_fb_helper_restore_fbdev_mode_unlocked and we get the display
enabled.

Is it intentional that we're left in this limbo state with the display
not enabled if fbcon isn't enabled on a framebuffer?

We're trying to get people to transition from the fbdev drivers to DRM
equivalents, but this seems to be a backwards step if there is an
extra step required to get the display enabled. Many users are still
just using the framebuffer.

Any input is much appreciated.

Thanks,
  Dave


Re: [PATCH] drm/panel: Add prepare_prev_first flag to Visionox VTDR6130

2023-08-29 Thread Dave Stevenson
Hi Neil

On Mon, 28 Aug 2023 at 09:49,  wrote:
>
> Hi Jessica,
>
> On 25/08/2023 20:37, Jessica Zhang wrote:
> >
> >
> > On 8/21/2023 3:01 AM, neil.armstr...@linaro.org wrote:
> >> Hi Maxime,
> >>
> >> On 21/08/2023 10:17, Maxime Ripard wrote:
> >>> Hi,
> >>>
> >>> On Fri, Aug 18, 2023 at 10:25:48AM +0200, neil.armstr...@linaro.org wrote:
>  On 17/08/2023 20:35, Dmitry Baryshkov wrote:
> > On 16/08/2023 10:51, neil.armstr...@linaro.org wrote:
> >> Sending HS commands will always work on any controller, it's all
> >> about LP commands. The Samsung panels you listed only send HS
> >> commands so they can use prepare_prev_first and work on any
> >> controllers.
> >
> > I think there is some misunderstanding there, supported by the
> > description of the flag.
> >
> > If I remember correctly, some hosts (sunxi) can not send DCS
> > commands after enabling video stream and switching to HS mode, see
> > [1]. Thus, as you know, most of the drivers have all DSI panel setup
> > commands in drm_panel_funcs::prepare() /
> > drm_bridge_funcs::pre_enable() callbacks, not paying attention
> > whether these commands are to be sent in LP or in HS mode.
> >
> > Previously DSI source drivers could power on the DSI link either in
> > mode_set() or in pre_enable() callbacks, with mode_set() being the
> > hack to make panel/bridge drivers to be able to send commands from
> > their prepare() / pre_enable() callbacks.
> >
> > With the prev_first flags being introduced, we have established that
> > DSI link should be enabled in DSI host's pre_enable() callback and
> > switched to HS mode (be it command or video) in the enable()
> > callback.
> >
> > So far so good.
> 
>  It seems coherent, I would like first to have a state of all DSI host
>  drivers and make this would actually work first before adding the
>  prev_first flag to all the required panels.
> >>>
> >>> This is definitely what we should do in an ideal world, but at least for
> >>> sunxi there's no easy way for it at the moment. There's no documentation
> >>> for it and the driver provided doesn't allow this to happen.
> >>>
> >>> Note that I'm not trying to discourage you or something here, I'm simply
> >>> pointing out that this will be something that we will have to take into
> >>> account. And it's possible that other drivers are in a similar
> >>> situation.
> >>>
> > Unfortunately this change is not fully backwards-compatible. This
> > requires that all DSI panels sending commands from prepare() should
> > have the prepare_prev_first flag. In some sense, all such patches
> > might have Fixes: 5ea6b1702781 ("drm/panel: Add prepare_prev_first
> > flag to drm_panel").
> 
>  This kind of migration should be done *before* any possible
>  regression, not the other way round.
> 
>  If all panels sending commands from prepare() should have the
>  prepare_prev_first flag, then it should be first, check for
>  regressions then continue.
> 
>  
> 
> >>
> >> I understand, but this patch doesn't qualify as a fix for
> >> 9e15123eca79 and is too late to be merged in drm-misc-next for
> >> v6.6, and since 9e15123eca79 actually breaks some support it
> >> should be reverted (+ deps) since we are late in the rc cycles.
> >
> > If we go this way, we can never reapply these patches. There will be
> > no guarantee that all panel drivers are completely converted. We
> > already have a story without an observable end -
> > DRM_BRIDGE_ATTACH_NO_CONNECTOR.
> 
>  I don't understand this point, who would block re-applying the patches ?
> 
>  The migration to DRM_BRIDGE_ATTACH_NO_CONNECTOR was done over multiple
>  Linux version and went smoothly because we reverted regressing patches
>  and restarted when needed, I don't understand why we can't do this
>  here aswell.
> 
> > I'd consider that the DSI driver is correct here and it is about the
> > panel drivers that require fixes patches. If you care about the
> > particular Fixes tag, I have provided one several lines above.
> 
>  Unfortunately it should be done in the other way round, prepare for
>  migration, then migrate,
> 
>  I mean if it's a required migration, then it should be done and I'll
>  support it from both bridge and panel PoV.
> 
>  So, first this patch has the wrong Fixes tag, and I would like a
>  better explanation on the commit message in any case. Then I would
>  like to have an ack from some drm-misc maintainers before applying it
>  because it fixes a patch that was sent via the msm tree thus per the
>  drm-misc rules I cannot apply it via the drm-misc-next-fixes tree.
> >>>
> >>> Sorry, it's not clear to me what you'd like our feedback on exactly?
> >>
> >> So let me resume the situation:
> >>
> >> 

Re: [PATCH] drm/panel/panel-sitronix-st7701: Move init sequence from prepare() to enable()

2023-08-29 Thread Dave Stevenson
Hi Marek & Mimoja

On Sat, 26 Aug 2023 at 22:02, Marek Vasut  wrote:
>
> On 8/26/23 20:33, Mimoja wrote:
>
> Hi,
>
> +CC Dave , he might be able to help with the last part.
>
> > I appreciate you taking the time to respond!
> >
> > On 26.08.23 17:18, Marek Vasut wrote:
> >> On 8/26/23 11:55, Mimoja wrote:
> >>> "The .prepare() function is typically called before the display
> >>> controller
> >>> starts to transmit video data."
> >>> and
> >>> "After the display controller has started transmitting video data,
> >>> it's safe
> >>>   to call the .enable() function."
> >>
> >> DSI commands are not DSI video, so this should be OK ?
> >
> > You are correct, my commit message is mixing things up here. I wanted to
> > emphasize roughly the thought of
> > "when enable() is called the dsi core is expected to have its clock
> > initialized". Will take note to clarify this if I succeed to
> > make a case for this patch below :)
>
> I vaguely recall there was this flag in include/drm/drm_bridge.h which
> might be related:
>
> 748 /**
> 749  * @pre_enable_prev_first: The bridge requires that the prev
> 750  * bridge @pre_enable function is called before its @pre_enable,
> 751  * and conversely for post_disable. This is most frequently a
> 752  * requirement for DSI devices which need the host to be initialised
> 753  * before the peripheral.
> 754  */
> 755 bool pre_enable_prev_first;
>
> Could it be, this is what you need ?

drm_panel has prepare_prev_first, which maps to drm_bridge's
pre_enable_prev_first, but same concept.
Most likely this is what you're after, but only got added in 6.3.

> >>> While generally fine this can lead to a fillup of the transmission
> >>> queue before
> >>> the transmission is set up on certain dsi bridges.
> >>> This issue can also be seen on downstream imx8m* kernels.
> >>
> >> Can you reproduce this with current mainline Linux or linux-next tree ?
> >> I recall the display pipeline in the NXP downstream stuff is very
> >> different from mainline .
> >
> > You are very much correct. The NXP downstream kernel is completely
> > different from the upstream one
> > and is really a great example to show the issue (code cleaned up for
> > readability):
> >
> > https://github.com/varigit/linux-imx/blob/5.15-2.0.x-imx_var01/drivers/gpu/drm/bridge/sec-dsim.c#L1368
> > ```
> >  ret = drm_panel_prepare(dsim->panel);
> >  if (unlikely(ret)) [...]
> >
> >  /* config esc clock, byte clock and etc */
> >  sec_mipi_dsim_config_clkctrl(dsim);
> >
> >  ret = drm_panel_enable(dsim->panel);
> >  if (unlikely(ret)) [...]
> >
> > ```

That DSI host driver looks very strange, or perhaps just outdated. It
implements atomic_enable and atomic_disable, but not atomic_pre_enable
or atomic_post_disable. Any attached panel or bridge drivers therefore
don't get called in the expected way by the bridge chain.
You are on 5.15 which may predate some of the reworking, but should
still support panel_bridge so that calling one of the of_get_bridge
functions gives you a bridge irregardless of whether it is a bridge or
panel. I'd question why the DSI host driver is making calls down the
bridge chain for itself - either it results in calling functions
multiple times, or you break the bridge chain (as vc4 used to do) but
mess up atomic states as the core can't add the state of the removed
nodes.

> >
> >> Which SoC does have this problem ?
> > Sadly I don't have any SoCs available which would work perfectly with
> > linux-next, let alone are confirmed affected :/
> >
> > I were able to make my Kingway Panel work (Custom one and so far
> > unsupported by the st7701 driver) with this
> > patch on downstream 5.4 and 5.15 imx8mn as well as on a raspberry pi CM4
> > with 6.1. However raspberrypi/linux brings
> > SPI support to the st7701 driver which should not affect this but I
> > would just like to document it here.

DPI video with SPI for configuration was added to the Pi kernel to
support the Pimoroni HyperPixel 2 round display[1].

If you have the panel attached to a CM4, and prepare_prev_first is
set, then I would expect it to work on the Pi.
The docs[2] state that transfer can be called in any state, however I
know that is an issue in vc4 that I need to address at some point. If
fixed, then no change should be required.

[1] https://shop.pimoroni.com/products/hyperpixel-round?variant=39381081882707
[2] 
https://github.com/torvalds/linux/blob/master/include/drm/drm_mipi_dsi.h#L84-L87

> > I could not find any success story with st7701 and the rpi on 6.1 online
> > after a short search (and only one
> > reference with 5.10 which seems to me a bit different in a short
> > comparison)  but again I can only offer
> > circumstantial evidence. Sorry :/
>
> Maybe Dave can help with this part .

I don't recall having had an ST7701 panel using DSI, so I'm afraid I
can't really help there.

  Dave


Re: [PATCH] drm/panel: Add prepare_prev_first flag to Visionox VTDR6130

2023-08-21 Thread Dave Stevenson
Hi Dmitry

On Fri, 18 Aug 2023 at 11:27, Dmitry Baryshkov
 wrote:
>
> On 18/08/2023 11:25, neil.armstr...@linaro.org wrote:
> > Hi Dmitry,
> >
> > On 17/08/2023 20:35, Dmitry Baryshkov wrote:
> >> On 16/08/2023 10:51, neil.armstr...@linaro.org wrote:
> >>> Hi Abhinav,
> >>>
> >>> On 14/08/2023 20:02, Abhinav Kumar wrote:
> >
> > 
> >
> >>>
> >>> Sending HS commands will always work on any controller, it's all
> >>> about LP commands.
> >>> The Samsung panels you listed only send HS commands so they can use
> >>> prepare_prev_first
> >>> and work on any controllers.
> >>
> >> I think there is some misunderstanding there, supported by the
> >> description of the flag.
> >>
> >> If I remember correctly, some hosts (sunxi) can not send DCS commands
> >> after enabling video stream and switching to HS mode, see [1]. Thus,
> >> as you know, most of the drivers have all DSI panel setup commands in
> >> drm_panel_funcs::prepare() / drm_bridge_funcs::pre_enable() callbacks,
> >> not paying attention whether these commands are to be sent in LP or in
> >> HS mode.
> >>
> >> Previously DSI source drivers could power on the DSI link either in
> >> mode_set() or in pre_enable() callbacks, with mode_set() being the
> >> hack to make panel/bridge drivers to be able to send commands from
> >> their prepare() / pre_enable() callbacks.
> >>
> >> With the prev_first flags being introduced, we have established that
> >> DSI link should be enabled in DSI host's pre_enable() callback and
> >> switched to HS mode (be it command or video) in the enable() callback.
> >>
> >> So far so good.
> >
> > It seems coherent, I would like first to have a state of all DSI host
> > drivers and make this would actually work first before adding the
> > prev_first flag to all the required panels.
> >
> >>
> >> Unfortunately this change is not fully backwards-compatible. This
> >> requires that all DSI panels sending commands from prepare() should
> >> have the prepare_prev_first flag. In some sense, all such patches
> >> might have Fixes: 5ea6b1702781 ("drm/panel: Add prepare_prev_first
> >> flag to drm_panel").
> >
> > This kind of migration should be done *before* any possible regression,
> > not the other way round.
> >
> > If all panels sending commands from prepare() should have the
> > prepare_prev_first flag, then it should be first, check for regressions
> > then continue.
> >
> > 
> >
> >>>
> >>> I understand, but this patch doesn't qualify as a fix for
> >>> 9e15123eca79 and is too late to be merged in drm-misc-next for v6.6,
> >>> and since 9e15123eca79 actually breaks some support it should be
> >>> reverted (+ deps) since we are late in the rc cycles.
> >>
> >> If we go this way, we can never reapply these patches. There will be
> >> no guarantee that all panel drivers are completely converted. We
> >> already have a story without an observable end -
> >> DRM_BRIDGE_ATTACH_NO_CONNECTOR.
> >
> > I don't understand this point, who would block re-applying the patches ?
>
> Consider us reverting 9e15123eca79 now and then reapplying it next
> cycle. Then another panel / bridge that was not converted to use
> pre_enable_prev_first pops up. And suddently we have to revert them again.
>
> > The migration to DRM_BRIDGE_ATTACH_NO_CONNECTOR was done over multiple
> > Linux version and went smoothly because we reverted
> > regressing patches and restarted when needed, I don't understand why we
> > can't do this here aswell.
>
> With DRM_BRIDGE_ATTACH_NO_CONNECTOR both host and peripheral drivers
> were involved. This way they share knowledge about the migration state.
>
> With prev_first we do not have such shared knowledge. Host assumes that
> it can work according to the documentation: turn DSI link to LP-11 in
> pre_enable(), switch to HS in enable(). It can not check whether the
> next bridge did not set pre_enable_prev_first because of it not being
> required (like for the Parade bridge) or because next bridge is not
> converted yet (and thus DSI host should power up the link in
> atomic_mode_set).
>
> Granted that there is no way for the DSI host driver to attune itself to
> the DSI peripheral driver requirements, I can only consider
> corresponding (requiring prev_first) panel drivers broken since
> 5ea6b1702781 ("drm/panel: Add prepare_prev_first flag to drm_panel") and
> all bridge drivers with this issue broken since 4fb912e5e190
> ("drm/bridge: Introduce pre_enable_prev_first to alter bridge init order").

Can I point out that even prior to 5ea6b1702781 the docs stated [1]

"Also note that those callbacks can be called no matter the state the
host is in. Drivers that need the underlying device to be powered to
perform these operations will first need to make sure it’s been
properly enabled."

added in bacbab58f09dc. So your DSI host driver isn't working in the
documented manner prior to 5ea6b1702781, therefore 5ea6b1702781
doesn't cause a regression in itself, and there was no direct
requirement for 5ea6b1702781 to add the flag to 

Re: [PATCH RFC 10/13] drm/connector: hdmi: Add Infoframes generation

2023-08-15 Thread Dave Stevenson
Hi Maxime

On Mon, 14 Aug 2023 at 14:56, Maxime Ripard  wrote:
>
> Infoframes in KMS is usually handled by a bunch of low-level helpers
> that require quite some boilerplate for drivers. This leads to
> discrepancies with how drivers generate them, and which are actually
> sent.
>
> Now that we have everything needed to generate them in the HDMI
> connector state, we can generate them in our common logic so that
> drivers can simply reuse what we precomputed.
>
> Signed-off-by: Maxime Ripard 
> ---
>  drivers/gpu/drm/drm_hdmi_connector.c | 287 
> +++
>  include/drm/drm_connector.h  | 100 
>  2 files changed, 387 insertions(+)
>
> diff --git a/drivers/gpu/drm/drm_hdmi_connector.c 
> b/drivers/gpu/drm/drm_hdmi_connector.c
> index 22c49906dfb5..46cafb17def7 100644
> --- a/drivers/gpu/drm/drm_hdmi_connector.c
> +++ b/drivers/gpu/drm/drm_hdmi_connector.c
> @@ -5,8 +5,10 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
> +#include 
>
>  #include 
>
> @@ -499,6 +501,131 @@ drm_hdmi_connector_compute_config(const struct 
> drm_hdmi_connector *hdmi_connecto
> return -EINVAL;
>  }
>
> +static int
> +drm_hdmi_connector_generate_avi_infoframe(const struct drm_hdmi_connector 
> *hdmi_connector,
> + struct drm_hdmi_connector_state 
> *hdmi_state)
> +{
> +   const struct drm_connector *connector = _connector->base;
> +   const struct drm_connector_state *state = _state->base;
> +   const struct drm_display_mode *mode =
> +   connector_state_get_adjusted_mode(state);
> +   struct hdmi_avi_infoframe *frame = _state->infoframes.avi;
> +   bool is_lim_range =
> +   drm_atomic_helper_hdmi_connector_is_full_range(hdmi_connector,
> +  hdmi_state);
> +   enum hdmi_quantization_range rgb_quant_range =
> +   is_lim_range ? HDMI_QUANTIZATION_RANGE_FULL : 
> HDMI_QUANTIZATION_RANGE_LIMITED;
> +   int ret;
> +
> +   ret = drm_hdmi_avi_infoframe_from_display_mode(frame, connector, 
> mode);
> +   if (ret)
> +   return ret;
> +
> +   frame->colorspace = hdmi_state->output_format;
> +
> +   drm_hdmi_avi_infoframe_quant_range(frame, connector, mode, 
> rgb_quant_range);
> +   drm_hdmi_avi_infoframe_colorimetry(frame, state);
> +   drm_hdmi_avi_infoframe_bars(frame, state);
> +
> +   return 0;
> +}
> +
> +static int
> +drm_hdmi_connector_generate_spd_infoframe(const struct drm_hdmi_connector 
> *hdmi_connector,
> + struct drm_hdmi_connector_state 
> *hdmi_state)
> +{
> +   struct hdmi_spd_infoframe *frame = _state->infoframes.spd;
> +   int ret;
> +
> +   ret = hdmi_spd_infoframe_init(frame,
> + hdmi_connector->vendor,
> + hdmi_connector->product);
> +   if (ret)
> +   return ret;
> +
> +   frame->sdi = HDMI_SPD_SDI_PC;
> +
> +   return 0;
> +}
> +
> +static int
> +drm_hdmi_connector_generate_hdr_infoframe(const struct drm_hdmi_connector 
> *hdmi_connector,
> + struct drm_hdmi_connector_state 
> *hdmi_state)
> +{
> +   const struct drm_connector_state *state = _state->base;
> +   struct hdmi_drm_infoframe *frame = _state->infoframes.drm;
> +   int ret;
> +
> +   if (hdmi_connector->max_bpc < 10)
> +   return 0;
> +
> +   if (!state->hdr_output_metadata)
> +   return 0;

Minor issue here I think.

If bpc < 10 or hdr_output_metadata isn't defined then the infoframe
will be left at all 0's due to the state's kzalloc. However we will
still call update_infoframe and therefore write_infoframe asking for
the infoframe to be sent, but frame->any.type = 0. It is true that
frame type 0 isn't defined, but what is the driver expected to make of
that?

If frame->any.type is initialised appropriately (or type is passed
directly), then a length of 0 could be reasonably used to signal that
the infoframe should not be sent. Otherwise I don't think we have a
path which can stop sending the HDR infoframe if it has ever been
sent.

On vc4 I think it's also going to trip up as it has a buffer slot per
type, and slot 0 is used for the GCP.

Thanks
  Dave

> +
> +   ret = drm_hdmi_infoframe_set_hdr_metadata(frame, state);
> +   if (ret)
> +   return ret;
> +
> +   return 0;
> +}
> +
> +static int
> +drm_hdmi_connector_generate_vendor_infoframe(const struct drm_hdmi_connector 
> *hdmi_connector,
> +struct drm_hdmi_connector_state 
> *hdmi_state)
> +{
> +   const struct drm_connector *connector = _connector->base;
> +   const struct drm_connector_state *state = _state->base;
> +   const struct drm_display_mode *mode =
> +   

Re: [PATCH v3 02/10] drm/panel: Check for already prepared/enabled in drm_panel

2023-08-02 Thread Dave Stevenson
On Wed, 2 Aug 2023 at 18:26, Chris Morgan  wrote:
>
> * Spam *
> On Mon, Jul 31, 2023 at 07:03:07PM +0200, Maxime Ripard wrote:
> > Hi,
> >
> > On Mon, Jul 31, 2023 at 11:33:22AM -0500, Chris Morgan wrote:
> > > In my case a few different panel drivers disable the regulators in the
> > > unprepare/disable routines.
> >
> > And that's totally fine.
> >
> > > For at least the Rockchip DSI implementations for some reason the
> > > panel gets unprepared more than once, which triggers an unbalanced
> > > regulator disable.
> >
> > "For some reason" being that DW-DSI apparently finds it ok to bypass any
> > kind of abstraction and randomly calling panel functions by itself:
> >
> > https://elixir.bootlin.com/linux/v6.4.7/source/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c#L868
> >
> > It looks like it's fixed it current drm-misc-next though.
>
> Good, when I get a chance I will test it out with the existing panels
> I have at my disposal and submit some patches to clean them up.
>
> >
> > > Obviously though the correct course of action is to fix the reason why
> > > the panel is disabled more than once, but that's at least the root
> > > cause of this behavior on the few panels I've worked with.
> >
> > Like I said we already have a commit on the way to fix that, so it
> > shouldn't be an issue anymore.
> >
> > I stand by what I was saying earlier though, I think it's mostly
> > cargo-cult or drivers being very wrong. If anything, the DW-DSI stuff
> > made me even more convinced that we shouldn't even entertain that idea
> > :)

DW-DSI is hacking around the fact that DSI panels may want to send DCS
commands in unprepare, however the DSI host driver shuts down the
controller in the DSI bridge post_disable which gets called first.

That ordering can now be reversed with pre_enable_prev_first flag in
struct drm_bridge, or prepare_prev_first in drm_panel, hence no need
for the DSI controller to jump around the bridge chain.

  Dave

> > Maxime
>
> Thank you, and yes if a driver is doing something it shouldn't we
> shouldn't be patching around that, we should be fixing things. Thanks
> for providing me with the additional info.
>
> Chris
>


Re: [PATCH v2 2/2] drm/bridge: Document bridge init order with pre_enable_prev_first

2023-08-01 Thread Dave Stevenson
On Tue, 28 Mar 2023 at 18:08, Jagan Teki  wrote:
>
> In order to satisfy the MIPI DSI initialization sequence the bridge
> init order has been altered with the help of pre_enable_prev_first
> in pre_enable and post_disable bridge operations.
>
> Document the affected bridge init order with an example on the
> bridge operations helpers.
>
> Signed-off-by: Jagan Teki 

Reviewed-by: Dave Stevenson 

> ---
> Changes for v2:
> - add missing dri-devel in CC
> - prefix @ for bridge helper names
>
>  drivers/gpu/drm/drm_bridge.c | 14 ++
>  1 file changed, 14 insertions(+)
>
> diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
> index 052a8e6c9961..caf0f341e524 100644
> --- a/drivers/gpu/drm/drm_bridge.c
> +++ b/drivers/gpu/drm/drm_bridge.c
> @@ -654,6 +654,13 @@ static void drm_atomic_bridge_call_post_disable(struct 
> drm_bridge *bridge,
>   * bridge will be called before the previous one to reverse the @pre_enable
>   * calling direction.
>   *
> + * Example:
> + * Bridge A ---> Bridge B ---> Bridge C ---> Bridge D ---> Bridge E
> + *
> + * With pre_enable_prev_first flag enable in Bridge B, D, E then the 
> resulting
> + * @post_disable order would be,
> + * Bridge B, Bridge A, Bridge E, Bridge D, Bridge C.
> + *
>   * Note: the bridge passed should be the one closest to the encoder
>   */
>  void drm_atomic_bridge_chain_post_disable(struct drm_bridge *bridge,
> @@ -750,6 +757,13 @@ static void drm_atomic_bridge_call_pre_enable(struct 
> drm_bridge *bridge,
>   * If a bridge sets @pre_enable_prev_first, then the pre_enable for the
>   * prev bridge will be called before pre_enable of this bridge.
>   *
> + * Example:
> + * Bridge A ---> Bridge B ---> Bridge C ---> Bridge D ---> Bridge E
> + *
> + * With pre_enable_prev_first flag enable in Bridge B, D, E then the 
> resulting
> + * @pre_enable order would be,
> + * Bridge C, Bridge D, Bridge E, Bridge A, Bridge B.
> + *
>   * Note: the bridge passed should be the one closest to the encoder
>   */
>  void drm_atomic_bridge_chain_pre_enable(struct drm_bridge *bridge,
> --
> 2.25.1
>


Re: [PATCH v2 1/2] drm/bridge: Fix improper bridge init order with pre_enable_prev_first

2023-08-01 Thread Dave Stevenson
Hi Jagan

My apologies for dropping the ball on this one, and thanks to Frieder
for the nudge.

On Wed, 12 Apr 2023 at 07:25, Jagan Teki  wrote:
>
> Hi Dave,
>
> Added Maxime, Laurent [which I thought I added before]
>
> On Tue, Mar 28, 2023 at 10:38 PM Jagan Teki  
> wrote:
> >
> > For a given bridge pipeline if any bridge sets pre_enable_prev_first
> > flag then the pre_enable for the previous bridge will be called before
> > pre_enable of this bridge and opposite is done for post_disable.
> >
> > These are the potential bridge flags to alter bridge init order in order
> > to satisfy the MIPI DSI host and downstream panel or bridge to function.
> > However the existing pre_enable_prev_first logic with associated bridge
> > ordering has broken for both pre_enable and post_disable calls.
> >
> > [pre_enable]
> >
> > The altered bridge ordering has failed if two consecutive bridges on a
> > given pipeline enables the pre_enable_prev_first flag.
> >
> > Example:
> > - Panel
> > - Bridge 1
> > - Bridge 2 pre_enable_prev_first
> > - Bridge 3
> > - Bridge 4 pre_enable_prev_first
> > - Bridge 5 pre_enable_prev_first
> > - Bridge 6
> > - Encoder
> >
> > In this example, Bridge 4 and Bridge 5 have pre_enable_prev_first.
> >
> > The logic looks for a bridge which enabled pre_enable_prev_first flag
> > on each iteration and assigned the previou bridge to limit pointer
> > if the bridge doesn't enable pre_enable_prev_first flags.
> >
> > If control found Bridge 2 is pre_enable_prev_first then the iteration
> > looks for Bridge 3 and found it is not pre_enable_prev_first and assigns
> > it's previous Bridge 4 to limit pointer and calls pre_enable of Bridge 3
> > and Bridge 2 and assign iter pointer with limit which is Bridge 4.
> >
> > Here is the actual problem, for the next iteration control look for
> > Bridge 5 instead of Bridge 4 has iter pointer in previous iteration
> > moved to Bridge 4 so this iteration skips the Bridge 4. The iteration
> > found Bridge 6 doesn't pre_enable_prev_first flags so the limit assigned
> > to Encoder. From next iteration Encoder skips as it is the last bridge
> > for reverse order pipeline.
> >
> > So, the resulting pre_enable bridge order would be,
> > - Panel, Bridge 1, Bridge 3, Bridge 2, Bridge 6, Bridge 5.
> >
> > This patch fixes this by assigning limit to next pointer instead of
> > previous bridge since the iteration always looks for bridge that does
> > NOT request prev so assigning next makes sure the last bridge on a
> > given iteration what exactly the limit bridge is.
> >
> > So, the resulting pre_enable bridge order with fix would be,
> > - Panel, Bridge 1, Bridge 3, Bridge 2, Bridge 6, Bridge 5, Bridge 4,
> >   Encoder.
> >
> > [post_disable]
> >
> > The altered bridge ordering has failed if two consecutive bridges on a
> > given pipeline enables the pre_enable_prev_first flag.
> >
> > Example:
> > - Panel
> > - Bridge 1
> > - Bridge 2 pre_enable_prev_first
> > - Bridge 3
> > - Bridge 4 pre_enable_prev_first
> > - Bridge 5 pre_enable_prev_first
> > - Bridge 6
> > - Encoder
> >
> > In this example Bridge 5 and Bridge 4 have pre_enable_prev_first.
> >
> > The logic looks for a bridge which enabled pre_enable_prev_first flags
> > on each iteration and assigned the previou bridge to next and next to
> > limit pointer if the bridge does enable pre_enable_prev_first flag.
> >
> > If control starts from Bridge 6 then it found next Bridge 5 is
> > pre_enable_prev_first and immediately the next assigned to previous
> > Bridge 6 and limit assignments to next Bridge 6 and call post_enable
> > of Bridge 6 even though the next consecutive Bridge 5 is enabled with
> > pre_enable_prev_first. This clearly misses the logic to find the state
> > of next conducive bridge as everytime the next and limit assigns
> > previous bridge if given bridge enabled pre_enable_prev_first.
> >
> > So, the resulting post_disable bridge order would be,
> > - Encoder, Bridge 6, Bridge 5, Bridge 4, Bridge 3, Bridge 2, Bridge 1,
> >   Panel.
> >
> > This patch fixes this by assigning next with previou bridge only if the
> > bridge doesn't enable pre_enable_prev_first flag and the next further
> > assign it to limit. This way we can find the bridge that NOT requested
> > prev to disable last.
> >
> > So, the resulting pre_enable bridge order with fix would be,
> > - Encoder, Bridge 4, Bridge 5, Bridge 6, Bridge 2, Bridge 3, Bridge 1,
> >   Panel.
> >
> > Validated the bridge init ordering by incorporating dummy bridges in
> > the sun6i-mipi-dsi pipeline
> >
> > Fixes: 4fb912e5e190 ("drm/bridge: Introduce pre_enable_prev_first to
> > alter bridge init order")
> > Signed-off-by: Jagan Teki 

Thanks for investigating and sorting this.

Reviewed-by: Dave Stevenson 

> > ---
> > Changes for v2:
> > - add missing dri-devel in CC
>
> Would you please look into this issue?
>
> Thanks,
> Jagan.


Re: [PATCH 1/1] drm/bridge: Fix handling of bridges with pre_enable_prev_first flag

2023-07-14 Thread Dave Stevenson
Hi Frieder

On Mon, 10 Jul 2023 at 08:46, Frieder Schrempf
 wrote:
>
> On 07.07.23 21:00, Vladimir Lypak wrote:
> > [Sie erhalten nicht häufig E-Mails von vladimir.ly...@gmail.com. Weitere 
> > Informationen, warum dies wichtig ist, finden Sie unter 
> > https://aka.ms/LearnAboutSenderIdentification ]
> >
> > In function drm_atomic_bridge_chain_post_disable handling of
> > pre_enable_prev_first flag is broken because "next" variable will always
> > end up set to value of "bridge". This breaks loop which should disable
> > bridges in reverse:
> >
> >  next = list_next_entry(bridge, chain_node);
> >
> >  if (next->pre_enable_prev_first) {
> > /* next bridge had requested that prev
> >  * was enabled first, so disabled last
> >  */
> > limit = next;
> >
> > /* Find the next bridge that has NOT requested
> >  * prev to be enabled first / disabled last
> >  */
> > list_for_each_entry_from(next, >bridge_chain,
> >  chain_node) {
> > // Next condition is always true. It is likely meant to be inversed
> > // according to comment above. But doing this uncovers another problem:
> > // it won't work if there are few bridges with this flag set at the end.
> > if (next->pre_enable_prev_first) {
> > next = list_prev_entry(next, chain_node);
> > limit = next;
> > // Here we always set next = limit = branch at first iteration.
> > break;
> > }
> > }
> >
> > /* Call these bridges in reverse order */
> > list_for_each_entry_from_reverse(next, >bridge_chain,
> >  chain_node) {
> > // This loop never executes past this branch.
> > if (next == bridge)
> > break;
> >
> > drm_atomic_bridge_call_post_disable(next, old_state);
> >
> > In this patch logic for handling the flag is simplified. Temporary
> > "iter" variable is introduced instead of "next" which is used only
> > inside inner loops.
> >
> > Fixes: 4fb912e5e190 ("drm/bridge: Introduce pre_enable_prev_first to alter 
> > bridge init order")
> > Signed-off-by: Vladimir Lypak 
>
> I haven't had a chance to look at this, but I still want to reference
> another patch by Jagan that intends to fix some bug in this area:
>
> https://patchwork.kernel.org/project/dri-devel/patch/20230328170752.1102347-1-ja...@amarulasolutions.com/
>
> +Cc: Jagan
>
> Dave, as you introduced this feature, did you have a chance to look at
> Jagan's and Vladimir's patches?

Sorry, they'd fallen off my radar.
I'm having a look at the moment, but will probably need to carry it
over to Monday.

  Dave


Re: [PATCH v2] dt-bindings: display: panel: add panel-mipi-dsi-bringup

2023-05-17 Thread Dave Stevenson
Hi Paulo

On Tue, 16 May 2023 at 14:09, Paulo Pavačić  wrote:
>
> Add dt-bindings documentation for panel-mipi-dsi-bringup which currently
> supports fannal,c3004 panel. Also added fannal to vendor-prefixes.
>
> v2 changelog:
>   - revised driver title, now describes purpose
>   - revised description, now describes hw
>   - revised maintainers, now has only 1 mail
>   - removed diacritics from commit/commit author
>   - properties/compatible is now enum
>   - compatible using only lowercase
>   - revised dts example
>   - modified MAINTAINERS in this commit (instead of driver commit)
>   - dt_bindings_check checked yml
>   - checkpatch warning fixed
>
> Signed-off-by: Paulo Pavacic 
> ---
>  .../display/panel/panel-mipi-dsi-bringup.yaml | 54 +++
>  .../devicetree/bindings/vendor-prefixes.yaml  |  2 +
>  MAINTAINERS   |  6 +++
>  3 files changed, 62 insertions(+)
>  create mode 100644
> Documentation/devicetree/bindings/display/panel/panel-mipi-dsi-bringup.yaml
>
> diff --git 
> a/Documentation/devicetree/bindings/display/panel/panel-mipi-dsi-bringup.yaml
> b/Documentation/devicetree/bindings/display/panel/panel-mipi-dsi-bringup.yaml
> new file mode 100644
> index ..c9e2b545657e
> --- /dev/null
> +++ 
> b/Documentation/devicetree/bindings/display/panel/panel-mipi-dsi-bringup.yaml
> @@ -0,0 +1,54 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/display/panel/panel-mipi-dsi-bringup.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: MIPI DSI Bringup Panel Porting Bindings
> +
> +description: |
> +  MIPI DSI Bringup Panel porting bindings to be used for a collection of 
> panels
> +  from different manufacturers which don't require backlight control from the
> +  driver and have a single reset pin which is required to be passed as an
> +  argument.

Don't we already have support for DSI displays that only need a single
reset pin via panel-simple? [1]

The bit that confuses me is that the driver patch [2] is using DSI DCS
commands to configure the panel - that differs from this dt binding
description of the panel only needing a reset pin.

Potentially there is gain in having a template DSI panel driver
available for reference, but this driver/binding appears to be trying
to act as a generic thing.

  Dave

[1] 
https://elixir.bootlin.com/linux/v6.3.2/source/drivers/gpu/drm/panel/panel-simple.c#L4605
[2] https://lists.freedesktop.org/archives/dri-devel/2023-May/404775.html


> +
> +maintainers:
> +  - Paulo Pavacic 
> +
> +allOf:
> +  - $ref: panel-common.yaml#
> +
> +properties:
> +
> +  compatible:
> +enum:
> +  # compatible must be listed in alphabetical order, ordered by 
> compatible.
> +  # The description in the comment is mandatory for each compatible.
> +
> +# Fannal 480x800 panel
> +  - fannal,c3004
> +
> +  reg: true
> +  reset-gpios: true
> +
> +required:
> +  - compatible
> +  - reg
> +  - reset-gpios
> +
> +additionalProperties: false
> +
> +examples:
> +  - |
> +#include 
> +//example on IMX8MM where GPIO pin 9 is used as a reset pin
> +mipi_dsi@32e1 {
> +panel@0 {
> +compatible = "fannal,c3004";
> +reg = <0>;
> +pinctrl-0 = <_mipi_dsi_rst>;
> +pinctrl-names = "default";
> +reset-gpios = < 9 GPIO_ACTIVE_LOW>;
> +};
> +};
> +...
> diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml
> b/Documentation/devicetree/bindings/vendor-prefixes.yaml
> index 82d39ab0231b..f962750f630a 100644
> --- a/Documentation/devicetree/bindings/vendor-prefixes.yaml
> +++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml
> @@ -462,6 +462,8 @@ patternProperties:
>  description: Facebook
>"^fairphone,.*":
>  description: Fairphone B.V.
> +  "^fannal,.*":
> +description: Fannal Electronics Co., Ltd
>"^faraday,.*":
>  description: Faraday Technology Corporation
>"^fastrax,.*":
> diff --git a/MAINTAINERS b/MAINTAINERS
> index e0ad886d3163..46f988ee60bd 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -6566,6 +6566,12 @@ T:git git://anongit.freedesktop.org/drm/drm-misc
>  F:Documentation/devicetree/bindings/display/panel/panel-mipi-dbi-spi.yaml
>  F:drivers/gpu/drm/tiny/panel-mipi-dbi.c
>
> +DRM DRIVER FOR MIPI DSI BRINGUP
> +M:Paulo Pavacic 
> +S:Maintained
> +C:mipi-dsi-bringup:matrix.org
> +F:
> Documentation/devicetree/bindings/display/panel/panel-mipi-dsi-bringup.yaml
> +
>  DRM DRIVER FOR MSM ADRENO GPU
>  M:Rob Clark 
>  M:Abhinav Kumar 
> --
> 2.40.1
>


Re: [PATCH 52/53] drm/vc4: Convert to platform remove callback returning void

2023-05-09 Thread Dave Stevenson
On Sun, 7 May 2023 at 17:27, Uwe Kleine-König
 wrote:
>
> The .remove() callback for a platform driver returns an int which makes
> many driver authors wrongly assume it's possible to do error handling by
> returning an error code. However the value returned is (mostly) ignored
> and this typically results in resource leaks. To improve here there is a
> quest to make the remove callback return void. In the first step of this
> quest all drivers are converted to .remove_new() which already returns
> void.
>
> Trivially convert the vc4 drm drivers from always returning zero in the
> remove callback to the void returning variant.
>
> Signed-off-by: Uwe Kleine-König 

Thanks for the patch - looks good.

Reviewed-by: Dave Stevenson 

> ---
>  drivers/gpu/drm/vc4/vc4_crtc.c | 5 ++---
>  drivers/gpu/drm/vc4/vc4_dpi.c  | 5 ++---
>  drivers/gpu/drm/vc4/vc4_drv.c  | 6 ++
>  drivers/gpu/drm/vc4/vc4_dsi.c  | 6 ++
>  drivers/gpu/drm/vc4/vc4_hdmi.c | 5 ++---
>  drivers/gpu/drm/vc4/vc4_hvs.c  | 5 ++---
>  drivers/gpu/drm/vc4/vc4_txp.c  | 5 ++---
>  drivers/gpu/drm/vc4/vc4_v3d.c  | 5 ++---
>  drivers/gpu/drm/vc4/vc4_vec.c  | 5 ++---
>  9 files changed, 18 insertions(+), 29 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
> index bef9d45ef1df..7610e841ef3c 100644
> --- a/drivers/gpu/drm/vc4/vc4_crtc.c
> +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
> @@ -1450,15 +1450,14 @@ static int vc4_crtc_dev_probe(struct platform_device 
> *pdev)
> return component_add(>dev, _crtc_ops);
>  }
>
> -static int vc4_crtc_dev_remove(struct platform_device *pdev)
> +static void vc4_crtc_dev_remove(struct platform_device *pdev)
>  {
> component_del(>dev, _crtc_ops);
> -   return 0;
>  }
>
>  struct platform_driver vc4_crtc_driver = {
> .probe = vc4_crtc_dev_probe,
> -   .remove = vc4_crtc_dev_remove,
> +   .remove_new = vc4_crtc_dev_remove,
> .driver = {
> .name = "vc4_crtc",
> .of_match_table = vc4_crtc_dt_match,
> diff --git a/drivers/gpu/drm/vc4/vc4_dpi.c b/drivers/gpu/drm/vc4/vc4_dpi.c
> index f518d6e59ed6..e67856ae9d75 100644
> --- a/drivers/gpu/drm/vc4/vc4_dpi.c
> +++ b/drivers/gpu/drm/vc4/vc4_dpi.c
> @@ -391,15 +391,14 @@ static int vc4_dpi_dev_probe(struct platform_device 
> *pdev)
> return component_add(>dev, _dpi_ops);
>  }
>
> -static int vc4_dpi_dev_remove(struct platform_device *pdev)
> +static void vc4_dpi_dev_remove(struct platform_device *pdev)
>  {
> component_del(>dev, _dpi_ops);
> -   return 0;
>  }
>
>  struct platform_driver vc4_dpi_driver = {
> .probe = vc4_dpi_dev_probe,
> -   .remove = vc4_dpi_dev_remove,
> +   .remove_new = vc4_dpi_dev_remove,
> .driver = {
> .name = "vc4_dpi",
> .of_match_table = vc4_dpi_dt_match,
> diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c
> index 0ccaee57fe9a..cee41e318bf9 100644
> --- a/drivers/gpu/drm/vc4/vc4_drv.c
> +++ b/drivers/gpu/drm/vc4/vc4_drv.c
> @@ -439,11 +439,9 @@ static int vc4_platform_drm_probe(struct platform_device 
> *pdev)
> return component_master_add_with_match(dev, _drm_ops, match);
>  }
>
> -static int vc4_platform_drm_remove(struct platform_device *pdev)
> +static void vc4_platform_drm_remove(struct platform_device *pdev)
>  {
> component_master_del(>dev, _drm_ops);
> -
> -   return 0;
>  }
>
>  static const struct of_device_id vc4_of_match[] = {
> @@ -456,7 +454,7 @@ MODULE_DEVICE_TABLE(of, vc4_of_match);
>
>  static struct platform_driver vc4_platform_driver = {
> .probe  = vc4_platform_drm_probe,
> -   .remove = vc4_platform_drm_remove,
> +   .remove_new = vc4_platform_drm_remove,
> .driver = {
> .name   = "vc4-drm",
> .of_match_table = vc4_of_match,
> diff --git a/drivers/gpu/drm/vc4/vc4_dsi.c b/drivers/gpu/drm/vc4/vc4_dsi.c
> index a5c075f802e4..839d7d682842 100644
> --- a/drivers/gpu/drm/vc4/vc4_dsi.c
> +++ b/drivers/gpu/drm/vc4/vc4_dsi.c
> @@ -1830,20 +1830,18 @@ static int vc4_dsi_dev_probe(struct platform_device 
> *pdev)
> return 0;
>  }
>
> -static int vc4_dsi_dev_remove(struct platform_device *pdev)
> +static void vc4_dsi_dev_remove(struct platform_device *pdev)
>  {
> struct device *dev = >dev;
> struct vc4_dsi *dsi = dev_get_drvdata(dev);
>
> mipi_dsi_host_unregister(>dsi_host);
> vc4_dsi_put(dsi);
> -
> -   return 0;
>  }
>
>  struct platform_driver vc4_dsi_driver = {
>   

Re: [PATCH v2 2/3] DRM: Create new Content Protection connector property

2023-04-24 Thread Dave Stevenson
Hi Mark (and Dmitry)

On Fri, 21 Apr 2023 at 18:07, Dmitry Baryshkov
 wrote:
>
> On 21/04/2023 19:27, Mark Yacoub wrote:
> > From: Mark Yacoub 
>
> Nit: is there a reason for this header? My first impression is that it
> matches your outgoing name & email address and as such is not necessary.
>
> Nit#2: subject should mention 'Key', as you are creating a property for
> the key.
>
> >
> > [Why]
> > To enable Protected Content, some drivers require a key to be injected
> > from user space to enable HDCP on the connector.
> >
> > [How]
> > Create new "Content Protection Property" of type "Blob"
>
> Generic observation is that the ability to inject HDCP keys manually
> seems to be quite unique to your hardware. As such, I think the debugfs
> or sysfs suits better in comparison to the DRM property.

I was about to reply to v1 with a very similar comment over the
requirement to keep HDCP keys secret.

v2 has added WRITE_ONLY blobs so at least another process can't just
read the blob back out again, but it feels like there are still
numerous ways to grab those keys. For an unsecured userspace to have
the keys in the first place seems like a bad move, and IMHO they
should only be held in either a secure environment, or only held in
hardware (passed direct from OTP to HDCP block).


There's also the DRM uAPI requirement for having reviewed patches for
an open source project to go alongside any uAPI change. Do such
patches exist? 
https://docs.kernel.org/gpu/drm-uapi.html#open-source-userspace-requirements

  Dave

> >
> > Signed-off-by: Mark Yacoub 
> > ---
> >   drivers/gpu/drm/drm_atomic_uapi.c | 9 +
> >   include/drm/drm_connector.h   | 6 ++
> >   include/drm/drm_mode_config.h | 6 ++
> >   3 files changed, 21 insertions(+)
> >
> > diff --git a/drivers/gpu/drm/drm_atomic_uapi.c 
> > b/drivers/gpu/drm/drm_atomic_uapi.c
> > index d867e7f9f2cd5..e20bc57cdb05c 100644
> > --- a/drivers/gpu/drm/drm_atomic_uapi.c
> > +++ b/drivers/gpu/drm/drm_atomic_uapi.c
> > @@ -749,6 +749,11 @@ static int drm_atomic_connector_set_property(struct 
> > drm_connector *connector,
> >   state->content_protection = val;
> >   } else if (property == config->hdcp_content_type_property) {
> >   state->hdcp_content_type = val;
> > + } else if (property == config->content_protection_key_property) {
> > + ret = drm_atomic_replace_property_blob_from_id(
> > + dev, >content_protection_key, val, -1, -1,
> > + );
> > + return ret;
> >   } else if (property == connector->colorspace_property) {
> >   state->colorspace = val;
> >   } else if (property == config->writeback_fb_id_property) {
> > @@ -843,6 +848,10 @@ drm_atomic_connector_get_property(struct drm_connector 
> > *connector,
> >   *val = state->content_protection;
> >   } else if (property == config->hdcp_content_type_property) {
> >   *val = state->hdcp_content_type;
> > + } else if (property == config->content_protection_key_property) {
> > + *val = state->content_protection_key ?
> > +state->content_protection_key->base.id :
> > +0;
> >   } else if (property == config->writeback_fb_id_property) {
> >   /* Writeback framebuffer is one-shot, write and forget */
> >   *val = 0;
> > diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
> > index 7b5048516185c..2fbe51272bfeb 100644
> > --- a/include/drm/drm_connector.h
> > +++ b/include/drm/drm_connector.h
> > @@ -896,6 +896,12 @@ struct drm_connector_state {
> >*/
> >   unsigned int content_protection;
> >
> > + /**
> > +  * @content_protection_key: DRM blob property for holding the Content
> > +  * Protection Key injected from user space.
> > +  */
> > + struct drm_property_blob *content_protection_key;
> > +
> >   /**
> >* @colorspace: State variable for Connector property to request
> >* colorspace change on Sink. This is most commonly used to switch
> > diff --git a/include/drm/drm_mode_config.h b/include/drm/drm_mode_config.h
> > index e5b053001d22e..615d1e5f57562 100644
> > --- a/include/drm/drm_mode_config.h
> > +++ b/include/drm/drm_mode_config.h
> > @@ -887,6 +887,12 @@ struct drm_mode_config {
> >*/
> >   struct drm_property *hdcp_content_type_property;
> >
> > + /**
> > +  * @content_protection_key_property: DRM blob property that receives 
> > the
> > +  * content protection key from user space to be injected into the 
> > kernel.
> > +  */
> > + struct drm_property *content_protection_key_property;
> > +
> >   /* dumb ioctl parameters */
> >   uint32_t preferred_depth, prefer_shadow;
> >
>
> --
> With best wishes
> Dmitry
>


Re: [PATCH v7 10/12] drm/bridge: Implement enable_next_first to alter bridge init order

2023-03-30 Thread Dave Stevenson
Hi Jagan

On Thu, 30 Mar 2023 at 07:56, Jagan Teki  wrote:
>
> On Wed, Mar 29, 2023 at 10:16 PM Maxime Ripard  wrote:
> >
> > On Wed, Mar 29, 2023 at 05:28:28PM +0100, Dave Stevenson wrote:
> > > On Wed, 29 Mar 2023 at 14:19, Jagan Teki  
> > > wrote:
> > > >
> > > > DSI sink devices typically send the MIPI-DCS commands to the DSI host
> > > > via general MIPI_DSI_DCS read and write API.
> > > >
> > > > The classical DSI sequence mentioned that the DSI host receives MIPI-DCS
> > > > commands from the DSI sink first in order to switch HS mode properly.
> > > > Once the DSI host switches to HS mode any MIPI-DCS commands from the
> > > > DSI sink are unfunctional.
> > >
> > > That statement contradicts the spec.
> > > The DSI spec section 8.11.1 Transmission Packet Sequences says that
> > > during any BLLP (Blanking or Low Power) period the host can do any of:
> > > - remain in LP-11
> > > - transmit one or more non-video packets from host to peripheral in 
> > > escape mode
> > > - transmit one or more non-video packets from host to peripheral in
> > > using HS mode
> > > - receive one or more packets from peripheral to host using escape mode
> > > - transmit data on a different virtual channel.
> > >
> > > Indeed if the sink doesn't set MIPI_DSI_MODE_LPM /
> > > MIPI_DSI_MSG_USE_LPM, then the expectation is that any data transfer
> > > will be in HS mode.
> > >
> > > That makes me confused as to the need for this patch.
> >
> > Yeah, and it looks like that would break the expectation that, in
> > enable, a bridge can expect its controller to be in HS mode.
> >
> > I think that was Jagan is trying to do is to work around an issue with
> > the Allwinner DSI driver:
> > https://elixir.bootlin.com/linux/v6.3-rc4/source/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c#L775
>
> Correct and I can see it seems to be a classic DSI sequence observed
> in dw-mipi-dsi as well - based on Neil's comments.
> https://lore.kernel.org/all/9aa3d19d-4378-aaf3-6857-c40be5d25...@baylibre.com/

Neil's comments are from 2021, and his response would appear to be
with regard the PHY power up sequence issues that
pre_enable_prev_first should solve. The DSI host pre_enable can now be
called before the sink's pre_enable, therefore allowing the PHY to be
configured in pre_enable. Hacking the PHY init into mode_set is
therefore not required.

I don't see any restriction in dw-mipi-dsi over when transfer can be
called (as long as it is between pre_enable and post_disable), and it
supports MIPI_DSI_MSG_USE_LPM for requesting the command be sent in
either LP or HS mode.

> In fact, I did follow and initialize the command-mode mode_set which
> set low-speed DCS and switch back to video-mode @enable and switch to
> HS but could see the same issue as the host cannot accept DCS as
> before (I might implement improper sequence, but not sure due to lack
> of documentation). But this sequence has issues with calling
> post_disable twice even on dw-mipi-dsi.

Calling up/down the bridge chain from within other bridge elements is
going to have issues and shouldn't be necessary.

The comment in dw-mipi-dsi post_disable[1]
* TODO Only way found to call panel-bridge post_disable &
* panel unprepare before the dsi "final" disable...
* This needs to be fixed in the drm_bridge framework and the API
* needs to be updated to manage our own call chains...

It has now been fixed up with pre_enable_prev_first.

I seem to recall seeing a patchset for one of the DSI hosts (other
than vc4) that was moving the init from mode_set to pre_enable - I
think it is probably [2] for msm.

Cheers
  Dave

[1] 
https://github.com/torvalds/linux/blob/master/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c#L862-L867
[2] 
https://github.com/torvalds/linux/commit/ec7981e6c614254937b37ce0af9eac09901c05c5

> May be Neill, can comment here?
>
> Thanks,
> Jagan.


Re: [PATCH v7 10/12] drm/bridge: Implement enable_next_first to alter bridge init order

2023-03-29 Thread Dave Stevenson
Hi Maxime

On Wed, 29 Mar 2023 at 17:46, Maxime Ripard  wrote:
>
> On Wed, Mar 29, 2023 at 05:28:28PM +0100, Dave Stevenson wrote:
> > On Wed, 29 Mar 2023 at 14:19, Jagan Teki  wrote:
> > >
> > > DSI sink devices typically send the MIPI-DCS commands to the DSI host
> > > via general MIPI_DSI_DCS read and write API.
> > >
> > > The classical DSI sequence mentioned that the DSI host receives MIPI-DCS
> > > commands from the DSI sink first in order to switch HS mode properly.
> > > Once the DSI host switches to HS mode any MIPI-DCS commands from the
> > > DSI sink are unfunctional.
> >
> > That statement contradicts the spec.
> > The DSI spec section 8.11.1 Transmission Packet Sequences says that
> > during any BLLP (Blanking or Low Power) period the host can do any of:
> > - remain in LP-11
> > - transmit one or more non-video packets from host to peripheral in escape 
> > mode
> > - transmit one or more non-video packets from host to peripheral in
> > using HS mode
> > - receive one or more packets from peripheral to host using escape mode
> > - transmit data on a different virtual channel.
> >
> > Indeed if the sink doesn't set MIPI_DSI_MODE_LPM /
> > MIPI_DSI_MSG_USE_LPM, then the expectation is that any data transfer
> > will be in HS mode.
> >
> > That makes me confused as to the need for this patch.
>
> Yeah, and it looks like that would break the expectation that, in
> enable, a bridge can expect its controller to be in HS mode.
>
> I think that was Jagan is trying to do is to work around an issue with
> the Allwinner DSI driver:
> https://elixir.bootlin.com/linux/v6.3-rc4/source/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c#L775
>
> This is working mostly fine since we only have panel support and can
> control that, but with bridge support added in the latest patch, then it
> probably doesn't work anymore.
>
> The proper way to fix this isn't to put more logic into the framework,
> it's to make the DSI driver behave as expected by KMS.
>
> Unfortunately, that controller is not documented, so it's not clear to
> me how we can fix it.
>
> IIRC, it's basically a state machine where you would encode the
> transitions between one DSI state and the next depending on what your
> expectations are.
>
> I think there's two problem with the driver that need to be addressed:
>
>   - First the driver will drop back to LP11 mode to submit commands. I
> don't think it's needed and could even be hurtful to the video
> stream if it was to happen during HS mode:
> 
> https://elixir.bootlin.com/linux/v6.3-rc4/source/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c#L877
>
>   - And then, it looks like, in HSD mode, we never get to go to the
> state LPTX is in (LPDT). It would be interesting to test whether
> adding a transition to that state makes it work or not.

Ooh, not fun.
I'll agree with your assessment - it looks like sunxi driver has
significant limitations on the modes of operation it supports. If
there is no information on sending HS commands, I wonder if it's
possible to note the video state in transfer and stop video, send the
command, and resume video again. Ugly as heck, but possibly the only
real option without documentation. It does raise the question of do
other blocks (eg crtc) need to be stopped as well, or does stopping
the PHY and/or DSI block stop the pixel data getting clocked out.

I can only guess at the meaning of the enum sun6i_dsi_start_inst and
enum sun6i_dsi_inst_id states. LPTX and LPRX are largely obvious, but
HSC(ommand) and HSD(ata) perhaps?
I thought on initial reading that the setup in sun6i_dsi_start made
sense as a sequence of commands, but looking closer at the bitmasking
and shifting I'm not so convinced. Are the DSI_INST_ID_xxx defines
shifts or the bitmask values to or in, as they get used for both.

  Dave


Re: [PATCH v7 10/12] drm/bridge: Implement enable_next_first to alter bridge init order

2023-03-29 Thread Dave Stevenson
Hi Jagan

On Wed, 29 Mar 2023 at 14:19, Jagan Teki  wrote:
>
> DSI sink devices typically send the MIPI-DCS commands to the DSI host
> via general MIPI_DSI_DCS read and write API.
>
> The classical DSI sequence mentioned that the DSI host receives MIPI-DCS
> commands from the DSI sink first in order to switch HS mode properly.
> Once the DSI host switches to HS mode any MIPI-DCS commands from the
> DSI sink are unfunctional.

That statement contradicts the spec.
The DSI spec section 8.11.1 Transmission Packet Sequences says that
during any BLLP (Blanking or Low Power) period the host can do any of:
- remain in LP-11
- transmit one or more non-video packets from host to peripheral in escape mode
- transmit one or more non-video packets from host to peripheral in
using HS mode
- receive one or more packets from peripheral to host using escape mode
- transmit data on a different virtual channel.

Indeed if the sink doesn't set MIPI_DSI_MODE_LPM /
MIPI_DSI_MSG_USE_LPM, then the expectation is that any data transfer
will be in HS mode.

That makes me confused as to the need for this patch.

  Dave

> DSI sink uses the @enable function to send the MIPI-DCS commands. In a
> typical DSI host, sink pipeline the @enable call chain start with the
> DSI host, and then the DSI sink which is the "wrong" order as DSI host
> @enable is called and switched to HS mode before DSI sink @enable.
>
> If the DSI host enables with the @enable_next_first flag then the
> @enable for the DSI sink will be called first before the @enable of
> the DSI host. This alter bridge init order makes sure that the MIPI-DCS
> commands send first and then switch to the HS mode properly by DSI host.
>
> This new flag @enable_next_first that any bridg can set to swap the
> order of @enable (and #disable) for that and the immediately next bridge.
>
> [enable]
> If a bridge sets @enable_next_first, then the @enable for the next bridge
> will be called first before enable of this bridge.
>
> [disable]
> If a bridge sets @enable_next_first, then the @disable for the next bridge
> will be called first before @disable of this bridge to reverse the @enable
> calling direction.
>
> eg:
> - Panel
> - Bridge 1
> - Bridge 2 enable_next_first
> - Bridge 3
> - Bridge 4 enable_next_first
> - Bridge 5 enable_next_first
> - Bridge 6
> - Encoder
>
> Would result in enable's being called as Encoder, Bridge 6, Bridge 3,
> Bridge 4, Bridge 5, Bridge 1, Bridge 2, Panel.
>
> and the result in disable's being called as Panel, Bridge 2, Bridge 1,
> Bridge 5, Bridge 4, Bridge 3, Bridge 6, Encoder.
>
> Signed-off-by: Jagan Teki 
> ---
> Changes for v7:
> - new patch
>
>  drivers/gpu/drm/drm_bridge.c | 171 ++-
>  include/drm/drm_bridge.h |   8 ++
>  2 files changed, 154 insertions(+), 25 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
> index caf0f341e524..cdc2669b3512 100644
> --- a/drivers/gpu/drm/drm_bridge.c
> +++ b/drivers/gpu/drm/drm_bridge.c
> @@ -577,6 +577,24 @@ void drm_bridge_chain_mode_set(struct drm_bridge *bridge,
>  }
>  EXPORT_SYMBOL(drm_bridge_chain_mode_set);
>
> +static void drm_atomic_bridge_call_disable(struct drm_bridge *bridge,
> +  struct drm_atomic_state *old_state)
> +{
> +   if (old_state && bridge->funcs->atomic_disable) {
> +   struct drm_bridge_state *old_bridge_state;
> +
> +   old_bridge_state =
> +   drm_atomic_get_old_bridge_state(old_state,
> +   bridge);
> +   if (WARN_ON(!old_bridge_state))
> +   return;
> +
> +   bridge->funcs->atomic_disable(bridge, old_bridge_state);
> +   } else if (bridge->funcs->disable) {
> +   bridge->funcs->disable(bridge);
> +   }
> +}
> +
>  /**
>   * drm_atomic_bridge_chain_disable - disables all bridges in the encoder 
> chain
>   * @bridge: bridge control structure
> @@ -587,33 +605,73 @@ EXPORT_SYMBOL(drm_bridge_chain_mode_set);
>   * starting from the last bridge to the first. These are called before 
> calling
>   * _encoder_helper_funcs.atomic_disable
>   *
> + * If a bridge sets @enable_next_first, then the @disable for the next bridge
> + * will be called first before @disable of this bridge to reverse the @enable
> + * calling direction.
> + *
> + * Example:
> + * Bridge A ---> Bridge B ---> Bridge C ---> Bridge D ---> Bridge E
> + *
> + * With enable_next_first flag enable in Bridge A, C, D then the resulting
> + * @disable order would be,
> + * Bridge C, Bridge D, Bridge E, Bridge A, Bridge B.
> + *
>   * Note: the bridge passed should be the one closest to the encoder
>   */
>  void drm_atomic_bridge_chain_disable(struct drm_bridge *bridge,
>  struct drm_atomic_state *old_state)
>  {
> struct drm_encoder *encoder;
> -   struct drm_bridge *iter;
> +   struct drm_bridge 

Re: [regression] RPI4B drm vc4: no crtc or sizes since 5.17 (works in 5.16; and still broken in at least 6.1)

2023-03-10 Thread Dave Stevenson
On Fri, 10 Mar 2023 at 12:59, AL13N  wrote:
>
>
> I donno if this is related or not, but since 6.1 has v3d, i'm assuming
> the opengl compositor will be faster and not draw too much cpu?
>
> I did try youtube video, but that on 1080p fullscreen, takes all the CPU
> and seems to have dropped frames still?

Does your browser actually use sensible EGL calls to pass dmabufs
around the system? Chromium with Ozone sort of does, but that's about
it.
It's another thing that is implemented in Raspberry Pi OS.

> does rpi4B actually have video decoding hardware?

I've already referred you to https://github.com/lategoodbye/rpi-zero/issues/43
> VCHIQ codecs - Unknown

It is present in our vendor kernel, but not upstreamed. You've chosen
to run mainline.

> and is this related to
> drm? because netflix did not work at all, which requires drm, but is
> this a different a different drm than this driver?

Digital Rights Management != Direct Rendering Manager.

Netflix on an unsecured platform will only work through something like
Widevine for software decode.

  Dave


Re: [regression] RPI4B drm vc4: no crtc or sizes since 5.17 (works in 5.16; and still broken in at least 6.1)

2023-03-10 Thread Dave Stevenson
On Fri, 10 Mar 2023 at 09:10, AL13N  wrote:
>
> Dave Stevenson schreef op 2023-03-09 13:59:
> > On Wed, 8 Mar 2023 at 22:46, AL13N  wrote:
> >>
> >> AL13N schreef op 2023-03-08 22:16:
> >> > Maxime Ripard schreef op 2023-03-08 13:35:
> >> >> Hi,
> >> >>
> >> >> On Tue, Mar 07, 2023 at 05:10:16PM +, Dave Stevenson wrote:
> >> >>> On Tue, 7 Mar 2023 at 16:25, AL13N  wrote:
> >> >>> > AL13N schreef op 2023-03-06 17:34:
> >> >>> > > I have a RPI4B connected on 2nd HDMI port (furthest away from 
> >> >>> > > power)
> >> >>> > > to a 4K TV, which works until 5.16, from 5.17 there is no X (or
> >> >>> > > plymouth), the cause of no X is that EDID gives nothing, and in the
> >> >>> > > journal; there is "Cannot find any crct or sizes". Only the kernel 
> >> >>> > > is
> >> >>> > > changed for this.
> >> >>> > >

> >>
> >> a bit puzzling why it does EDID block twice and it's twice checksum
> >> invalid?
> >> I also see forcing connector on.
> >>
> >> earlier, i did try to make an edid file from a modeline that worked on
> >> 5.16 and pass it using drm_kms_helper.edid_firmware= ; but that didn't
> >> work, there only was some kind of warning that i should use something
> >> else...
> >
> > It always helps to actually quote warnings or errors.
> > Almost certainly "drm_kms_helper.edid_firmware is deprecated, please
> > use drm.edid_firmware instead.", in which case do as it tells you and
> > use "drm.edid_firmware=".
>
> oh, i interpreted this as "it works for now, but will be removed later"
> ? are you saying it really doesn't work and i should retest with
> "drm.edid_firmware=" ?

Reporting that you got a warning or error message which you then
ignored doesn't help the debug process.
Seeing it's been deprecated since 5.4 in 2017, it would be a fair
candidate to disappear.

> >> reading through all your messages, does this mean, that i should be
> >> able
> >> to boot if we were to "fix" this edid file? and pass it? or is this
> >> something that needs change in kernel?
> >
> > At present you have 2 issues
> > - the monitor or cable doesn't handle the hotplug line correctly
> > - the monitor doesn't provide a valid EDID.
> >
> > The first you can workaround with "video=HDMI-A-2:D".
>
> I thought the video= had to be turned off for drm.edid_firmware= to work
> well?

No - they do 2 different jobs.
video=HDMI-A-2:D will force the connector to report connected, and
therefore trigger a read of the EDID.
drm.edid_firmware means that the EDID used will be read from that file
rather than over the DDC link.

> rpi4 config.txt has a disable_fw_kms_setup=1 that disables the video
> tags that are auto-added to cmdline (this option is commented atm)
> there is also a hdmi_force_hotplug=1 option that is turned on atm

hdmi_force_hotplug=1 only affects the firmware, not the vc4 kernel driver.

> > The second you can work around by capturing the EDID, fixing it, and
> > then using "drm.edid_firmware=".
> > The first fix is to just fixup the checksum (edid-decode even tells
> > you the correct value as 0xEB). That doesn't solve the fact that the
> > EDID contains other rubbish like being an analog display which may
> > cause further issues. The simplest fix for reporting as an analog
> > display is to change byte 20 from 0x00 to 0x80, and then correct the
> > checksum again.
> >
> > The EDID advertises 4k60, 1080p60, and GTF 2288x1432 @ 61Hz.
> > In order to support 4k60 it needs to support HDMI2.0 and enabling
> > scrambling via SCDC. That should also be signalled in the EDID Sink
> > Capability Data Structure block but isn't, so 4k60 support may be
> > compromised.
>
> the rpi4 also has in config.txt a hdmi_enable_4kp60=1, which i have not
> turned on atm; i don't know if that has any impact here...

Without that then any mode that requires a pixel clock above the
340MHz limit of HDMI 1.4 will be filtered out. 4k60 will therefore not
be available to you on your system.

> > Sorry, all of this comes back to the monitor vendor shipping rubbish.
> > None of this is the fault of the vc4 driver, and it only worked under
> > 5.16 by chance.
>
> do the config.txt directives on the rpi4 have any impact here? I always
> figured these options only changed the cmdline video= parameters, it
> can't really have an

Re: [regression] RPI4B drm vc4: no crtc or sizes since 5.17 (works in 5.16; and still broken in at least 6.1)

2023-03-09 Thread Dave Stevenson
On Wed, 8 Mar 2023 at 22:46, AL13N  wrote:
>
> AL13N schreef op 2023-03-08 22:16:
> > Maxime Ripard schreef op 2023-03-08 13:35:
> >> Hi,
> >>
> >> On Tue, Mar 07, 2023 at 05:10:16PM +, Dave Stevenson wrote:
> >>> On Tue, 7 Mar 2023 at 16:25, AL13N  wrote:
> >>> > AL13N schreef op 2023-03-06 17:34:
> >>> > > I have a RPI4B connected on 2nd HDMI port (furthest away from power)
> >>> > > to a 4K TV, which works until 5.16, from 5.17 there is no X (or
> >>> > > plymouth), the cause of no X is that EDID gives nothing, and in the
> >>> > > journal; there is "Cannot find any crct or sizes". Only the kernel is
> >>> > > changed for this.
> >>> > >
> >>> > > In 5.16 instead of this message there is a bunch of hex lines prefixed
> >>> > > with BAD.
> >>> > >
> >>> > > It is still broken in 6.1 at the very least.
> >>> > >
> >>> > > I donno if this is related to this part, but I wanted to try a newer
> >>> > > kernel, because the RPI4 seems to do all the video decoding in
> >>> > > software and cannot seem to handle it.
> >>> > >
> >>> > >
> >>> > > logs:
> >>> > > vc4-drm gpu: bound fef05700.hdmi (ops vc4_hdmi_ops [vc4])
> >>> > > vc4-drm gpu: bound fe004000.txp (ops vc4_txp_ops [vc4])
> >>> > > vc4-drm gpu: bound fe206000.pixelvalve (ops vc4_crtc_ops [vc4])
> >>> > > vc4-drm gpu: bound fe207000.pixelvalve (ops vc4_crtc_ops [vc4])
> >>> > > vc4-drm gpu: bound fe20a000.pixelvalve (ops vc4_crtc_ops [vc4])
> >>> > > vc4-drm gpu: bound fe216000.pixelvalve (ops vc4_crtc_ops [vc4])
> >>> > > vc4-drm gpu: bound fec12000.pixelvalve (ops vc4_crtc_ops [vc4])
> >>> > > checking generic (3ea81000 12c000) vs hw (0 )
> >>> > > fb0: switching to vc4 from simple
> >>> > > Console: switching to colour dummy device 80x25
> >>> > > [drm] Initialized vc4 0.0.0 20140616 for gpu on minor 0
> >>> > > vc4-drm gpu: [drm] Cannot find any crtc or sizes
> >>> >
> >>> > 5.16 log has:
> >>> >
> >>> > vc4-drm gpu: bound fef05700.hdmi (ops vc4_hdmi_ops [vc4])
> >>> > vc4-drm gpu: bound fe004000.txp (ops vc4_txp_ops [vc4])
> >>> > vc4-drm gpu: bound fe206000.pixelvalve (ops vc4_crtc_ops [vc4])
> >>> > vc4-drm gpu: bound fe207000.pixelvalve (ops vc4_crtc_ops [vc4])
> >>> > vc4-drm gpu: bound fe20a000.pixelvalve (ops vc4_crtc_ops [vc4])
> >>> > vc4-drm gpu: bound fe216000.pixelvalve (ops vc4_crtc_ops [vc4])
> >>> > vc4-drm gpu: bound fec12000.pixelvalve (ops vc4_crtc_ops [vc4])
> >>> > [drm] Initialized vc4 0.0.0 20140616 for gpu on minor 0
> >>> > [00] BAD  00 ff ff ff ff ff ff 00 36 74 00 00 00 00 00 00
> >>> > [00] BAD  0b 1f 01 03 00 23 01 78 0a cf 74 a3 57 4c b0 23
> >>> > [00] BAD  09 48 4c 00 00 00 01 01 01 ff 01 ff ff 01 01 01
> >>> > [00] BAD  01 01 01 01 01 20 08 e8 00 30 f2 70 5a 80 b0 58
> >>> > [00] BAD  8a 00 c4 8e 21 00 00 1e 02 3a 80 18 71 38 2d 40
> >>> > [00] BAD  58 2c 45 00 c4 8e 21 00 00 1e 00 00 00 fc 00 53
> >>> > [00] BAD  41 4c 4f 52 41 0a 20 20 20 20 20 20 00 00 00 fd
> >>> > [00] BAD  00 3b 46 1f 8c 3c 00 0a 20 20 20 20 20 20 01 aa
> >>> > Console: switching to colour frame buffer device 240x67
> >>> > vc4-drm gpu: [drm] fb0: vc4drmfb frame buffer device
> >>> >
> >>> >
> >>> > i donno what this bad is, but it doesn't happen in 5.17... maybe these
> >>> > BAD got filtered out, but they did end up working for me? or something?
> >>> > i donno...
> >>>
> >>> Run it through edid-decode - the checksum is wrong.
> >>>
> >>> Block 0, Base EDID:
> >>>   EDID Structure Version & Revision: 1.3
> >>>   Vendor & Product Identification:
> >>> Manufacturer: MST
> >>> Model: 0
> >>> Made in: week 11 of 2021
> >>>   Basic Display Parameters & Features:
> >>> Analog display
> >>> Input voltage level: 0.7/0.3 V
> >>> Blank level equals black level
> >>> Maximum image size: 35 cm x 

Re: [regression] RPI4B drm vc4: no crtc or sizes since 5.17 (works in 5.16; and still broken in at least 6.1)

2023-03-09 Thread Dave Stevenson
On Thu, 9 Mar 2023 at 11:26, AL13N  wrote:
>
> Dave Stevenson schreef op 2023-03-07 18:10:
> > Hi Maarten
> >
> > On Tue, 7 Mar 2023 at 16:25, AL13N  wrote:
> >>
> >> AL13N schreef op 2023-03-06 17:34:
> >> > Hi,
> >> >
> >> > I have a RPI4B connected on 2nd HDMI port (furthest away from power)
> >> > to a 4K TV, which works until 5.16, from 5.17 there is no X (or
> >> > plymouth), the cause of no X is that EDID gives nothing, and in the
> >> > journal; there is "Cannot find any crct or sizes". Only the kernel is
> >> > changed for this.
> >> >
> >> > In 5.16 instead of this message there is a bunch of hex lines prefixed
> >> > with BAD.
> >> >
> >> > It is still broken in 6.1 at the very least.
> >> >
> >> > I donno if this is related to this part, but I wanted to try a newer
> >> > kernel, because the RPI4 seems to do all the video decoding in
> >> > software and cannot seem to handle it.
> >> >
> >> >
> >> > logs:
> >> > vc4-drm gpu: bound fef05700.hdmi (ops vc4_hdmi_ops [vc4])
> >> > vc4-drm gpu: bound fe004000.txp (ops vc4_txp_ops [vc4])
> >> > vc4-drm gpu: bound fe206000.pixelvalve (ops vc4_crtc_ops [vc4])
> >> > vc4-drm gpu: bound fe207000.pixelvalve (ops vc4_crtc_ops [vc4])
> >> > vc4-drm gpu: bound fe20a000.pixelvalve (ops vc4_crtc_ops [vc4])
> >> > vc4-drm gpu: bound fe216000.pixelvalve (ops vc4_crtc_ops [vc4])
> >> > vc4-drm gpu: bound fec12000.pixelvalve (ops vc4_crtc_ops [vc4])
> >> > checking generic (3ea81000 12c000) vs hw (0 )
> >> > fb0: switching to vc4 from simple
> >> > Console: switching to colour dummy device 80x25
> >> > [drm] Initialized vc4 0.0.0 20140616 for gpu on minor 0
> >> > vc4-drm gpu: [drm] Cannot find any crtc or sizes
> >>
> >> 5.16 log has:
> >>
> >> vc4-drm gpu: bound fef05700.hdmi (ops vc4_hdmi_ops [vc4])
> >> vc4-drm gpu: bound fe004000.txp (ops vc4_txp_ops [vc4])
> >> vc4-drm gpu: bound fe206000.pixelvalve (ops vc4_crtc_ops [vc4])
> >> vc4-drm gpu: bound fe207000.pixelvalve (ops vc4_crtc_ops [vc4])
> >> vc4-drm gpu: bound fe20a000.pixelvalve (ops vc4_crtc_ops [vc4])
> >> vc4-drm gpu: bound fe216000.pixelvalve (ops vc4_crtc_ops [vc4])
> >> vc4-drm gpu: bound fec12000.pixelvalve (ops vc4_crtc_ops [vc4])
> >> [drm] Initialized vc4 0.0.0 20140616 for gpu on minor 0
> >> [00] BAD  00 ff ff ff ff ff ff 00 36 74 00 00 00 00 00 00
> >> [00] BAD  0b 1f 01 03 00 23 01 78 0a cf 74 a3 57 4c b0 23
> >> [00] BAD  09 48 4c 00 00 00 01 01 01 ff 01 ff ff 01 01 01
> >> [00] BAD  01 01 01 01 01 20 08 e8 00 30 f2 70 5a 80 b0 58
> >> [00] BAD  8a 00 c4 8e 21 00 00 1e 02 3a 80 18 71 38 2d 40
> >> [00] BAD  58 2c 45 00 c4 8e 21 00 00 1e 00 00 00 fc 00 53
> >> [00] BAD  41 4c 4f 52 41 0a 20 20 20 20 20 20 00 00 00 fd
> >> [00] BAD  00 3b 46 1f 8c 3c 00 0a 20 20 20 20 20 20 01 aa
> >> Console: switching to colour frame buffer device 240x67
> >> vc4-drm gpu: [drm] fb0: vc4drmfb frame buffer device
> >>
> >>
> >> i donno what this bad is, but it doesn't happen in 5.17... maybe these
> >> BAD got filtered out, but they did end up working for me? or
> >> something?
> >> i donno...
> >
> > Run it through edid-decode - the checksum is wrong.
> >
> > Block 0, Base EDID:
> >   EDID Structure Version & Revision: 1.3
> >   Vendor & Product Identification:
> > Manufacturer: MST
> > Model: 0
> > Made in: week 11 of 2021
> >   Basic Display Parameters & Features:
> > Analog display
> > Input voltage level: 0.7/0.3 V
> > Blank level equals black level
> > Maximum image size: 35 cm x 1 cm
> > Gamma: 2.20
> > RGB color display
> > First detailed timing is the preferred timing
> >   Color Characteristics:
> > Red  : 0.6396, 0.3398
> > Green: 0.2998, 0.6904
> > Blue : 0.1376, 0.0380
> > White: 0.2822, 0.2968
> >   Established Timings I & II: none
> >   Standard Timings:
> > GTF :  2288x1432   61.000 Hz  16:10   90.463 kHz 282.245 MHz
> >   Detailed Timing Descriptors:
> > DTD 1:  3840x2160   60.000 Hz  16:9   135.000 kHz 594.000 MHz (708
> > mm x 398 mm)
> >  Hfront  176 Hsync  88 Hback 296 Hpol P
&

Re: [regression] RPI4B drm vc4: no crtc or sizes since 5.17 (works in 5.16; and still broken in at least 6.1)

2023-03-07 Thread Dave Stevenson
Hi Maarten

On Tue, 7 Mar 2023 at 16:25, AL13N  wrote:
>
> AL13N schreef op 2023-03-06 17:34:
> > Hi,
> >
> > I have a RPI4B connected on 2nd HDMI port (furthest away from power)
> > to a 4K TV, which works until 5.16, from 5.17 there is no X (or
> > plymouth), the cause of no X is that EDID gives nothing, and in the
> > journal; there is "Cannot find any crct or sizes". Only the kernel is
> > changed for this.
> >
> > In 5.16 instead of this message there is a bunch of hex lines prefixed
> > with BAD.
> >
> > It is still broken in 6.1 at the very least.
> >
> > I donno if this is related to this part, but I wanted to try a newer
> > kernel, because the RPI4 seems to do all the video decoding in
> > software and cannot seem to handle it.
> >
> >
> > logs:
> > vc4-drm gpu: bound fef05700.hdmi (ops vc4_hdmi_ops [vc4])
> > vc4-drm gpu: bound fe004000.txp (ops vc4_txp_ops [vc4])
> > vc4-drm gpu: bound fe206000.pixelvalve (ops vc4_crtc_ops [vc4])
> > vc4-drm gpu: bound fe207000.pixelvalve (ops vc4_crtc_ops [vc4])
> > vc4-drm gpu: bound fe20a000.pixelvalve (ops vc4_crtc_ops [vc4])
> > vc4-drm gpu: bound fe216000.pixelvalve (ops vc4_crtc_ops [vc4])
> > vc4-drm gpu: bound fec12000.pixelvalve (ops vc4_crtc_ops [vc4])
> > checking generic (3ea81000 12c000) vs hw (0 )
> > fb0: switching to vc4 from simple
> > Console: switching to colour dummy device 80x25
> > [drm] Initialized vc4 0.0.0 20140616 for gpu on minor 0
> > vc4-drm gpu: [drm] Cannot find any crtc or sizes
>
> 5.16 log has:
>
> vc4-drm gpu: bound fef05700.hdmi (ops vc4_hdmi_ops [vc4])
> vc4-drm gpu: bound fe004000.txp (ops vc4_txp_ops [vc4])
> vc4-drm gpu: bound fe206000.pixelvalve (ops vc4_crtc_ops [vc4])
> vc4-drm gpu: bound fe207000.pixelvalve (ops vc4_crtc_ops [vc4])
> vc4-drm gpu: bound fe20a000.pixelvalve (ops vc4_crtc_ops [vc4])
> vc4-drm gpu: bound fe216000.pixelvalve (ops vc4_crtc_ops [vc4])
> vc4-drm gpu: bound fec12000.pixelvalve (ops vc4_crtc_ops [vc4])
> [drm] Initialized vc4 0.0.0 20140616 for gpu on minor 0
> [00] BAD  00 ff ff ff ff ff ff 00 36 74 00 00 00 00 00 00
> [00] BAD  0b 1f 01 03 00 23 01 78 0a cf 74 a3 57 4c b0 23
> [00] BAD  09 48 4c 00 00 00 01 01 01 ff 01 ff ff 01 01 01
> [00] BAD  01 01 01 01 01 20 08 e8 00 30 f2 70 5a 80 b0 58
> [00] BAD  8a 00 c4 8e 21 00 00 1e 02 3a 80 18 71 38 2d 40
> [00] BAD  58 2c 45 00 c4 8e 21 00 00 1e 00 00 00 fc 00 53
> [00] BAD  41 4c 4f 52 41 0a 20 20 20 20 20 20 00 00 00 fd
> [00] BAD  00 3b 46 1f 8c 3c 00 0a 20 20 20 20 20 20 01 aa
> Console: switching to colour frame buffer device 240x67
> vc4-drm gpu: [drm] fb0: vc4drmfb frame buffer device
>
>
> i donno what this bad is, but it doesn't happen in 5.17... maybe these
> BAD got filtered out, but they did end up working for me? or something?
> i donno...

Run it through edid-decode - the checksum is wrong.

Block 0, Base EDID:
  EDID Structure Version & Revision: 1.3
  Vendor & Product Identification:
Manufacturer: MST
Model: 0
Made in: week 11 of 2021
  Basic Display Parameters & Features:
Analog display
Input voltage level: 0.7/0.3 V
Blank level equals black level
Maximum image size: 35 cm x 1 cm
Gamma: 2.20
RGB color display
First detailed timing is the preferred timing
  Color Characteristics:
Red  : 0.6396, 0.3398
Green: 0.2998, 0.6904
Blue : 0.1376, 0.0380
White: 0.2822, 0.2968
  Established Timings I & II: none
  Standard Timings:
GTF :  2288x1432   61.000 Hz  16:10   90.463 kHz 282.245 MHz
  Detailed Timing Descriptors:
DTD 1:  3840x2160   60.000 Hz  16:9   135.000 kHz 594.000 MHz (708
mm x 398 mm)
 Hfront  176 Hsync  88 Hback 296 Hpol P
 Vfront8 Vsync  10 Vback  72 Vpol P
DTD 2:  1920x1080   60.000 Hz  16:967.500 kHz 148.500 MHz (708
mm x 398 mm)
 Hfront   88 Hsync  44 Hback 148 Hpol P
 Vfront4 Vsync   5 Vback  36 Vpol P
Display Product Name: 'SALORA'
  Display Range Limits:
Monitor ranges (GTF): 59-70 Hz V, 31-140 kHz H, max dotclock 600 MHz
  Extension blocks: 1
Checksum: 0xaa (should be 0xeb)

Weird that it also says that it's an analog display when it's
connected over HDMI. Something rather bizarre there, and I think it'll
hit problems in drm_edid at [1] as we end up with a connector having
no color_formats defined. I was discussing this with Maxime only last
week, but in relation to VGA monitors connected through HDMI to VGA
adapters without rewriting the EDID.


If you have an issue between 5.16 and 5.17, then I'd guess at [2] and
your monitor not asserting hotplug correctly. The raw hotplug status
is reported in /sys/kernel/debug/dri/N/hdmi0_regs (N will be either 0
or 1 depending on the probe order of the vc4 and v3d drivers). Grep
for HDMI_HOTPLUG.

Incorrect hotplug behaviour causes grief when combined with HDMI2.0
and scrambling. If you don' t know the other end has been
disconnected, then you 

Re: [PATCH] drm: document TV margin properties

2023-02-28 Thread Dave Stevenson
On Tue, 28 Feb 2023 at 11:45, Ville Syrjälä
 wrote:
>
> On Tue, Feb 28, 2023 at 11:37:38AM +, Dave Stevenson wrote:
> > Hi Pekka
> >
> > On Tue, 28 Feb 2023 at 10:12, Pekka Paalanen  wrote:
> > >
> > > On Tue, 28 Feb 2023 09:53:47 +
> > > Simon Ser  wrote:
> > >
> > > > On Tuesday, February 28th, 2023 at 09:46, Pekka Paalanen 
> > > >  wrote:
> > > >
> > > > > can these be negative as well, to achieve overscan and not just
> > > > > underscan? Did I get overscan and underscan right... these are related
> > > > > to under/overscan, aren't they?
> > > > >
> > > > > Hmm, no, I guess that doesn't make sense, there is no room in the
> > > > > signal to have negative margins, it would result in clipping the
> > > > > framebuffer while scaling up. So this can only be used to scale
> > > > > framebuffer down, add borders, and the TV then scales it back up
> > > > > again?
> > > >
> > > > Correct.
> > > >
> > > > > Looks like neither my Intel nor AMD cards support these, I don't see
> > > > > the properties. More things to the list of KMS properties Weston needs
> > > > > to explicitly control. Oh, it seems vc4 exclusive for now.
> >
> > I've started a discussion with Simon with regard overscan handling [1].
> > There would be nothing stopping Weston ignoring the DRM properties if
> > Weston/userspace provides a way to reduce the destintation rectangle
> > on the display device. Using that would also be renderer agnostic.
> >
> > [1] https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/3597
> >
> > > > i915 does support it but for TV connectors only 
> > > > (i915/display/intel_tv.c).
> > > > gud also supports it.
> > > >
> > > > > Where does this text appear in the HTML kernel docs? I tried to look 
> > > > > at
> > > > > drm_connector.c but I cannot find the spot where this patch applies.
> > > >
> > > > Here:
> > > > https://dri.freedesktop.org/docs/drm/gpu/drm-kms.html#analog-tv-specific-connector-properties
> > >
> > > Analog TV properties? So this does not apply to e.g. HDMI?
> > >
> > > I believe HDMI TVs do have the problems that margins could mitigate.
> >
> > Correct. Particularly on TVs instead of monitors, it's not uncommon to
> > find the HDMI output gets overscanned.
> >
> > > > > Is this actually a connector property? How does that work, should this
> > > > > not be a CRTC property?
> > > >
> > > > Yeah, it's a connector property for some reason.
> > > >
> > > > > Is this instead not scaling anything but simply sending metadata
> > > > > through the connector?
> > > >
> > > > No metadata is sent. This is purely equivalent to setting up CRTC_*
> > > > properties to scale the planes.
> > >
> > > Oh! That would be really good to mention in the doc. Maybe even prefer
> > > plane props over this? Or is this for analog TV, and plane props for
> > > digital TV?
> > >
> > >
> > > The above are the important comments. All below is just musings you can
> > > ignore if you wish.
> > >
> > > > > Or are there underlying requirements that this connector property is
> > > > > actually affecting the CRTC, which means that it is fundamentally
> > > > > impossible to use multiple connectors with different values on the 
> > > > > same
> > > > > CRTC? And drivers will reject any attempt, so there is no need to
> > > > > define what conflicting settings will do?
> > > >
> > > > I don't think any driver above supports cloning CRTCs for these
> > > > connector types. i915 sets clonable = false for these connectors.
> > > > vc4 picks the first connector's TV margins, always.
> > >
> > > Sounds like i915 does it right, and vc4 does not, assuming vc4 does not
> > > prevent cloning.
> >
> > The cloneable flag is in struct intel_encoder, not core.
>
> It gets converted into the core thing by intel_encoder_possible_clones().

Thanks Ville.
vc4 never adds additional possible_clones, therefore I believe it is
still doing the right thing.

  Dave


Re: [PATCH] drm: document TV margin properties

2023-02-28 Thread Dave Stevenson
Hi Pekka

On Tue, 28 Feb 2023 at 10:12, Pekka Paalanen  wrote:
>
> On Tue, 28 Feb 2023 09:53:47 +
> Simon Ser  wrote:
>
> > On Tuesday, February 28th, 2023 at 09:46, Pekka Paalanen 
> >  wrote:
> >
> > > can these be negative as well, to achieve overscan and not just
> > > underscan? Did I get overscan and underscan right... these are related
> > > to under/overscan, aren't they?
> > >
> > > Hmm, no, I guess that doesn't make sense, there is no room in the
> > > signal to have negative margins, it would result in clipping the
> > > framebuffer while scaling up. So this can only be used to scale
> > > framebuffer down, add borders, and the TV then scales it back up
> > > again?
> >
> > Correct.
> >
> > > Looks like neither my Intel nor AMD cards support these, I don't see
> > > the properties. More things to the list of KMS properties Weston needs
> > > to explicitly control. Oh, it seems vc4 exclusive for now.

I've started a discussion with Simon with regard overscan handling [1].
There would be nothing stopping Weston ignoring the DRM properties if
Weston/userspace provides a way to reduce the destintation rectangle
on the display device. Using that would also be renderer agnostic.

[1] https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/3597

> > i915 does support it but for TV connectors only (i915/display/intel_tv.c).
> > gud also supports it.
> >
> > > Where does this text appear in the HTML kernel docs? I tried to look at
> > > drm_connector.c but I cannot find the spot where this patch applies.
> >
> > Here:
> > https://dri.freedesktop.org/docs/drm/gpu/drm-kms.html#analog-tv-specific-connector-properties
>
> Analog TV properties? So this does not apply to e.g. HDMI?
>
> I believe HDMI TVs do have the problems that margins could mitigate.

Correct. Particularly on TVs instead of monitors, it's not uncommon to
find the HDMI output gets overscanned.

> > > Is this actually a connector property? How does that work, should this
> > > not be a CRTC property?
> >
> > Yeah, it's a connector property for some reason.
> >
> > > Is this instead not scaling anything but simply sending metadata
> > > through the connector?
> >
> > No metadata is sent. This is purely equivalent to setting up CRTC_*
> > properties to scale the planes.
>
> Oh! That would be really good to mention in the doc. Maybe even prefer
> plane props over this? Or is this for analog TV, and plane props for
> digital TV?
>
>
> The above are the important comments. All below is just musings you can
> ignore if you wish.
>
> > > Or are there underlying requirements that this connector property is
> > > actually affecting the CRTC, which means that it is fundamentally
> > > impossible to use multiple connectors with different values on the same
> > > CRTC? And drivers will reject any attempt, so there is no need to
> > > define what conflicting settings will do?
> >
> > I don't think any driver above supports cloning CRTCs for these
> > connector types. i915 sets clonable = false for these connectors.
> > vc4 picks the first connector's TV margins, always.
>
> Sounds like i915 does it right, and vc4 does not, assuming vc4 does not
> prevent cloning.

The cloneable flag is in struct intel_encoder, not core.

vc4 doesn't support cloning of a single CRTC to multiple connectors at
all, and I believe sets up the possible_crtc bitmasks correctly to
denote that.

  Dave

> >
> > > IOW, does simply the existence of these properties on a connector
> > > guarantee that the connector must be the only one on a CRTC?
> >
> > I suppose that there could exist some hardware capable of applying
> > margins post-CRTC? Such driver could support cloning CRTCs and still
> > applying the connector margins correctly.
>
> Yeah, theoretically. But in the KMS object model, is there the idea
> that connectors do not do image manipulation, they can only convert the
> signal type at most and send metadata?
>
>
> Thanks,
> pq


Re: [PATCH] drm: document TV margin properties

2023-02-27 Thread Dave Stevenson
On Mon, 27 Feb 2023 at 12:21, Simon Ser  wrote:
>
> Add docs for "{left,right,top,bottom} margin" properties.
>
> Signed-off-by: Simon Ser 
> Cc: Maxime Ripard 
> Cc: Daniel Vetter 
> Cc: Pekka Paalanen 
> Cc: Noralf Trønnes 
> Cc: Mateusz Kwiatkowski 

This certainly matches my understanding of the properties. Thanks.

Reviewed-by: Dave Stevenson 

> ---
>  drivers/gpu/drm/drm_connector.c | 14 ++
>  1 file changed, 10 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
> index 9d0250c28e9b..65a586680940 100644
> --- a/drivers/gpu/drm/drm_connector.c
> +++ b/drivers/gpu/drm/drm_connector.c
> @@ -1590,10 +1590,6 @@ 
> EXPORT_SYMBOL(drm_connector_attach_dp_subconnector_property);
>
>  /*
>   * TODO: Document the properties:
> - *   - left margin
> - *   - right margin
> - *   - top margin
> - *   - bottom margin
>   *   - brightness
>   *   - contrast
>   *   - flicker reduction
> @@ -1651,6 +1647,16 @@ 
> EXPORT_SYMBOL(drm_connector_attach_dp_subconnector_property);
>   *
>   * Drivers can set up this property by calling
>   * drm_mode_create_tv_properties().
> + *
> + * left margin, right margin, top margin, bottom margin:
> + * Add margins to the connector's viewport.
> + *
> + * The value is the size in pixels of the black border which will be
> + * added. The attached CRTC's content will be scaled to fill the whole
> + * area inside the margin.
> + *
> + * Drivers can set up these properties by calling
> + * drm_mode_create_tv_margin_properties().
>   */
>
>  /**
> --
> 2.39.2
>
>


Re: [PATCH 1/2] drm: document DRM_IOCTL_PRIME_HANDLE_TO_FD and PRIME_FD_TO_HANDLE

2023-02-20 Thread Dave Stevenson
On Mon, 20 Feb 2023 at 15:57, Simon Ser  wrote:
>
> On Monday, February 20th, 2023 at 16:49, Dave Stevenson 
>  wrote:
>
> > > + * User-space sets _prime_handle.fd with a DMA-BUF file descriptor to
> > > + * import, and gets back a GEM handle in _prime_handle.handle.
> > > + * _prime_handle.flags is unused.
> >
> > Is it worth explicitly stating that the handle would be released via
> > DRM_IOCTL_GEM_CLOSE? I've had userspace developers query how to
> > release imported handles in the past.
>
> v2 spells this out I think.

It does - thanks.
I was reading back through my emails from Friday and the weekend, and
hadn't noticed v2 :-/ Sorry for the noise.

  Dave


Re: [PATCH 1/2] drm: document DRM_IOCTL_PRIME_HANDLE_TO_FD and PRIME_FD_TO_HANDLE

2023-02-20 Thread Dave Stevenson
Hi Simon

On Thu, 16 Feb 2023 at 13:09, Simon Ser  wrote:
>
> Signed-off-by: Simon Ser 
> Cc: Daniel Vetter 
> Cc: Pekka Paalanen 
> Cc: Daniel Stone 
> ---
>  include/uapi/drm/drm.h | 17 +
>  1 file changed, 17 insertions(+)
>
> diff --git a/include/uapi/drm/drm.h b/include/uapi/drm/drm.h
> index 4cb956a52aee..54b2313c8332 100644
> --- a/include/uapi/drm/drm.h
> +++ b/include/uapi/drm/drm.h
> @@ -1012,7 +1012,24 @@ extern "C" {
>  #define DRM_IOCTL_UNLOCK   DRM_IOW( 0x2b, struct drm_lock)
>  #define DRM_IOCTL_FINISH   DRM_IOW( 0x2c, struct drm_lock)
>
> +/**
> + * DRM_IOCTL_PRIME_HANDLE_TO_FD - Convert a GEM handle to a DMA-BUF FD.
> + *
> + * User-space sets _prime_handle.handle with the GEM handle to export and
> + * _prime_handle.flags, and gets back a DMA-BUF file descriptor in
> + * _prime_handle.fd.
> + */
>  #define DRM_IOCTL_PRIME_HANDLE_TO_FDDRM_IOWR(0x2d, struct 
> drm_prime_handle)
> +/**
> + * DRM_IOCTL_PRIME_FD_TO_HANDLE - Convert a DMA-BUF FD to a GEM handle.
> + *
> + * User-space sets _prime_handle.fd with a DMA-BUF file descriptor to
> + * import, and gets back a GEM handle in _prime_handle.handle.
> + * _prime_handle.flags is unused.

Is it worth explicitly stating that the handle would be released via
DRM_IOCTL_GEM_CLOSE? I've had userspace developers query how to
release imported handles in the past.

  Dave

> + *
> + * If an existing GEM handle refers to the memory object backing the DMA-BUF,
> + * that GEM handle is returned.
> + */
>  #define DRM_IOCTL_PRIME_FD_TO_HANDLEDRM_IOWR(0x2e, struct 
> drm_prime_handle)
>
>  #define DRM_IOCTL_AGP_ACQUIRE  DRM_IO(  0x30)
> --
> 2.39.1
>
>


Re: [PATCH v2 3/9] drm/vc4: hdmi: Add Broadcast RGB property to allow override of RGB range

2023-02-20 Thread Dave Stevenson
Hi Hans

On Sat, 18 Feb 2023 at 11:33, Hans Verkuil  wrote:
>
> Hi Maxime, Dave,
>
> On 26/01/2023 14:46, Maxime Ripard wrote:
> > From: Dave Stevenson 
> >
> > Copy Intel's "Broadcast RGB" property semantics to add manual override
> > of the HDMI pixel range for monitors that don't abide by the content
> > of the AVI Infoframe.
>
> Do we have to copy that property as-is?

Firstly I'll agree with your later comment that having this control
allows testing of a range of output modes, and working around HDMI
sinks that have dodgy implementations.
(In our vendor kernel we now also have a property to override the
kernel chosen output format to enable testing of YCbCr4:4:4 and 4:2:2
output).

The DRM subsystem has the requirement for an open-source userspace
project to be using any new property before it will be merged [1].
This property already exists for i915 and gma-500, therefore avoids
that requirement.

There are objections to the UAPI for Broadcast RGB [2], but if it's
good enough for the existing implementations then there can be no
objection to it being implemented in the same way for other drivers.
Otherwise it is a missing feature of the DRM API, and the linked
discussion is realistically at least a year away from being resolved.
Why bury our heads in the sand for that period?

[1] 
https://dri.freedesktop.org/docs/drm/gpu/drm-uapi.html#open-source-userspace-requirements
[2] https://lists.freedesktop.org/archives/dri-devel/2023-February/391061.html

> First of all, I think this should really be a drm-level property, rather than
> a driver property: RGB Quantization Range mismatches are the bane of my life,
> and I think a way to override this would help everyone.

Linked to above, if it were the preferred method for controlling this
then I would expect it to become a drm-level property.

> Secondly, I hate the name they came up with: 'Broadcast RGB' is pretty 
> meaningless.
> Can't we stick to something closer to what the CTA-861/HDMI specs use, which 
> is
> 'RGB Quantization Range'? So either use that, or just 'RGB Range'.
>
> In addition, 'Limited 16:235' should just be 'Limited' since the actual range
> depends on the bits-per-color-component.

It's documented UAPI with those names[3], therefore any change would
be a change to user-space's expectation and a regression. At least by
sticking with the same names then any user space implementation that
exists for i915 or gma-500 will also work in the same way on vc4.

[3] 
https://www.kernel.org/doc/html/latest/gpu/drm-kms.html#existing-kms-properties

> >
> > Signed-off-by: Dave Stevenson 
> > Signed-off-by: Maxime Ripard 
> > ---
> >  drivers/gpu/drm/vc4/vc4_hdmi.c | 97 
> > --
> >  drivers/gpu/drm/vc4/vc4_hdmi.h |  9 
> >  2 files changed, 102 insertions(+), 4 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> > index 4b3bf77bb5cd..78749c6fa837 100644
> > --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> > +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> > @@ -150,10 +150,16 @@ static bool vc4_hdmi_mode_needs_scrambling(const 
> > struct drm_display_mode *mode,
> >  }
> >
> >  static bool vc4_hdmi_is_full_range_rgb(struct vc4_hdmi *vc4_hdmi,
> > -const struct drm_display_mode *mode)
> > +struct vc4_hdmi_connector_state 
> > *vc4_state)
> >  {
> > + const struct drm_display_mode *mode = _hdmi->saved_adjusted_mode;
> >   struct drm_display_info *display = _hdmi->connector.display_info;
> >
> > + if (vc4_state->broadcast_rgb == VC4_HDMI_BROADCAST_RGB_LIMITED)
> > + return false;
> > + else if (vc4_state->broadcast_rgb == VC4_HDMI_BROADCAST_RGB_FULL)
> > + return true;
> > +
> >   return !display->is_hdmi ||
> >   drm_default_rgb_quant_range(mode) == 
> > HDMI_QUANTIZATION_RANGE_FULL;
> >  }
> > @@ -524,8 +530,12 @@ static int vc4_hdmi_connector_atomic_check(struct 
> > drm_connector *connector,
> >  {
> >   struct drm_connector_state *old_state =
> >   drm_atomic_get_old_connector_state(state, connector);
> > + struct vc4_hdmi_connector_state *old_vc4_state =
> > + conn_state_to_vc4_hdmi_conn_state(old_state);
> >   struct drm_connector_state *new_state =
> >   drm_atomic_get_new_connector_state(state, connector);
> > + struct vc4_hdmi_connector_state *new_vc4_state =
> > + conn_state_to_vc4_hdmi_conn_state(new_state);
> >   struct drm_crtc *crtc = new_state->crtc;
> >
> >   if (!crtc)
&g

Re: [RFT PATCH v2 1/3] drm/bridge: tc358762: Set pre_enable_prev_first

2023-02-01 Thread Dave Stevenson
On Tue, 31 Jan 2023 at 22:22, Douglas Anderson  wrote:
>
> Set the "pre_enable_prev_first" as provided by commit 4fb912e5e190
> ("drm/bridge: Introduce pre_enable_prev_first to alter bridge init
> order"). This should allow us to revert commit ec7981e6c614
> ("drm/msm/dsi: don't powerup at modeset time for parade-ps8640") and
> commit 7d8e9a90509f ("drm/msm/dsi: move DSI host powerup to modeset
> time").

I see no reference in the TC358762 datasheet to requiring the DSI
interface to be in any particular state.
However, setting this flag does mean that the DSI host doesn't need to
power up and down for each host_transfer request from
tc358762_pre_enable/tc358762_init, so on that basis I'm good with it.

Reviewed-by: Dave Stevenson 

> Cc: Dave Stevenson 
> Cc: Dmitry Baryshkov 
> Cc: Abhinav Kumar 
> Signed-off-by: Douglas Anderson 
> ---
>
> (no changes since v1)
>
>  drivers/gpu/drm/bridge/tc358762.c | 1 +
>  1 file changed, 1 insertion(+)
>
> diff --git a/drivers/gpu/drm/bridge/tc358762.c 
> b/drivers/gpu/drm/bridge/tc358762.c
> index 0b6a28436885..77f7f7f54757 100644
> --- a/drivers/gpu/drm/bridge/tc358762.c
> +++ b/drivers/gpu/drm/bridge/tc358762.c
> @@ -229,6 +229,7 @@ static int tc358762_probe(struct mipi_dsi_device *dsi)
> ctx->bridge.funcs = _bridge_funcs;
> ctx->bridge.type = DRM_MODE_CONNECTOR_DPI;
> ctx->bridge.of_node = dev->of_node;
> +   ctx->bridge.pre_enable_prev_first = true;
>
> drm_bridge_add(>bridge);
>
> --
> 2.39.1.456.gfc5497dd1b-goog
>


Re: [PATCH v11 3/3] drm: exynos: dsi: Restore proper bridge chain order

2023-01-20 Thread Dave Stevenson
Hi Jagan

On Fri, 20 Jan 2023 at 19:10, Jagan Teki  wrote:
>
> Hi Dave,
>
> On Sat, Jan 21, 2023 at 12:26 AM Dave Stevenson
>  wrote:
> >
> > Hi Jagan
> >
> > Responding due to Marek's comment on the "Add Samsung MIPI DSIM
> > bridge" series, although I know very little about the Exynos
> > specifics, and may well be missing context of what you're trying to
> > achieve.
> >
> > On Mon, 12 Dec 2022 at 18:29, Jagan Teki  wrote:
> > >
> > > Restore the proper bridge chain by finding the previous bridge
> > > in the chain instead of passing NULL.
> > >
> > > This establishes a proper bridge chain while attaching downstream
> > > bridges.
> > >
> > > Reviewed-by: Marek Vasut 
> > > Signed-off-by: Marek Szyprowski 
> > > Signed-off-by: Jagan Teki 
> > > ---
> > > Changes for v11:
> > > - add bridge.pre_enable_prev_first
> > > Changes for v10:
> > > - collect Marek review tag
> > >
> > >  drivers/gpu/drm/exynos/exynos_drm_dsi.c | 9 +++--
> > >  1 file changed, 7 insertions(+), 2 deletions(-)
> > >
> > > diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c 
> > > b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
> > > index ec673223d6b7..9d10a89d28f1 100644
> > > --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
> > > +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
> > > @@ -1428,7 +1428,8 @@ static int exynos_dsi_attach(struct drm_bridge 
> > > *bridge,
> > >  {
> > > struct exynos_dsi *dsi = bridge_to_dsi(bridge);
> > >
> > > -   return drm_bridge_attach(bridge->encoder, dsi->out_bridge, NULL, 
> > > flags);
> > > +   return drm_bridge_attach(bridge->encoder, dsi->out_bridge, bridge,
> > > +flags);
> >
> > Agreed on this change.
> >
> > >  }
> > >
> > >  static const struct drm_bridge_funcs exynos_dsi_bridge_funcs = {
> > > @@ -1474,7 +1475,10 @@ static int exynos_dsi_host_attach(struct 
> > > mipi_dsi_host *host,
> > >
> > > drm_bridge_add(>bridge);
> > >
> > > -   drm_bridge_attach(encoder, >bridge, NULL, 0);
> > > +   drm_bridge_attach(encoder, >bridge,
> > > + list_first_entry_or_null(>bridge_chain,
> > > +  struct drm_bridge,
> > > +  chain_node), 0);
> >
> > What bridge are you expecting between the encoder and this bridge?
> > The encoder is the drm_simple_encoder_init encoder that you've created
> > in exynos_dsi_bind, so separating that from the bridge you're also
> > creating here seems weird.
> >
> > >
> > > /*
> > >  * This is a temporary solution and should be made by more 
> > > generic way.
> > > @@ -1709,6 +1713,7 @@ static int exynos_dsi_probe(struct platform_device 
> > > *pdev)
> > > dsi->bridge.funcs = _dsi_bridge_funcs;
> > > dsi->bridge.of_node = dev->of_node;
> > > dsi->bridge.type = DRM_MODE_CONNECTOR_DSI;
> > > +   dsi->bridge.pre_enable_prev_first = true;
> >
> > Setting dsi->bridge.pre_enable_prev_first on what is presumably the
> > DSI host controller seems a little odd.
> > Same question again - what bridge are you expecting to be upstream of
> > the DSI host that needs to be preenabled before it? Whilst it's
> > possible that there's another bridge, I'd have expected that to be the
> > first link from your encoder as they appear to both belong to the same
> > bit of driver.
>
> Let me answer all together here. I can explain a bit about one of the
> pipelines used in Exynos. Exynos DSI DRM drivers have some strict host
> initialization which is not the same as what we used in i.MX8M even
> though it uses the same DSIM IP.
>
> Exynos5433 Decon -> Exynos MIC -> Exynos DSI -> s6e3ha2 DSI panel
>
> Here MIC is the bridge, Exynos DSI is the bridge and the requirement
> is to expect the upstream bridge to pre_enable first from DSI which
> means the MIC.

That makes sense for the pre_enable_prev_first flag.

The drm_bridge_attach(... list_first_entry_or_null) still seems a
little weird. I think you are making the assumption that there is only
ever going to be the zero or one bridge (the MIC) between encoder and
DSI bridge - the DSI bridge is linking itself to the first entry off
the encoder bridge_chain (or NULL to link to the encoder). Is that
reasonable? I've no idea!

I must confess to not having looked at the attaching sequence
recently, and I'm about to head home for the weekend.
I have no real knowledge of how Exynos is working, and am aware that
you're having to rejuggle stuff to try and support i.MX8M and Exynos,
so leave that one up to you.

Cheers
  Dave


Re: [PATCH v10 00/18] drm: Add Samsung MIPI DSIM bridge

2023-01-20 Thread Dave Stevenson
Hi Marek & Jagan

On Fri, 20 Jan 2023 at 15:06, Marek Vasut  wrote:
>
> On 1/20/23 15:41, Jagan Teki wrote:
> > Hi Fabio,
>
> Hello all,
>
> > On Fri, Jan 20, 2023 at 5:36 PM Fabio Estevam  wrote:
> >>
> >> Hi Jagan,
> >>
> >> On Thu, Jan 19, 2023 at 2:59 PM Jagan Teki  
> >> wrote:
> >>
> >>> There are two patch series prior to this need to apply.
> >>>
> >>> https://patchwork.kernel.org/project/dri-devel/patch/20221212145745.15387-1-ja...@amarulasolutions.com/
> >>> https://patchwork.kernel.org/project/dri-devel/cover/20221212182923.29155-1-ja...@amarulasolutions.com/
> >>
> >> Would it make sense to re-submit these two patches as part of your series?
> >
> > The previous version's comment was to separate them from the DSIM series.
>
> Hm, seems like those first two patches got stuck. I fixed up the
> malformed Fixes: line (it was split across two lines and had angular
> brackets around it) and picked the first series via drm-misc-next .
>
> Can you send a subsequent patch to convert the DSIM_* macros to BIT()
> macro , since checkpatch --strict complains about it ?
>
> For the second series, you likely want a RB from Maxime Ripard and Dave
> Stevenson first about the probe order handling.

Not sure what I can add for "Enable prepare_prev_first flag for
samsung-s6e panels" and "tc358764: Enable pre_enable_prev_first flag"
as I have no datasheet for those devices.
On the basis that they are wanting the DSI host to be in LP-11 before
prepare/pre_enable, then setting the flag is the right thing. More
than happy to say
Acked-by: Dave Stevenson 
to those two (I can't find them quickly in my mail to respond directly).

I have just sent a separate response on the third patch.

  Dave


Re: [PATCH v11 3/3] drm: exynos: dsi: Restore proper bridge chain order

2023-01-20 Thread Dave Stevenson
Hi Jagan

Responding due to Marek's comment on the "Add Samsung MIPI DSIM
bridge" series, although I know very little about the Exynos
specifics, and may well be missing context of what you're trying to
achieve.

On Mon, 12 Dec 2022 at 18:29, Jagan Teki  wrote:
>
> Restore the proper bridge chain by finding the previous bridge
> in the chain instead of passing NULL.
>
> This establishes a proper bridge chain while attaching downstream
> bridges.
>
> Reviewed-by: Marek Vasut 
> Signed-off-by: Marek Szyprowski 
> Signed-off-by: Jagan Teki 
> ---
> Changes for v11:
> - add bridge.pre_enable_prev_first
> Changes for v10:
> - collect Marek review tag
>
>  drivers/gpu/drm/exynos/exynos_drm_dsi.c | 9 +++--
>  1 file changed, 7 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c 
> b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
> index ec673223d6b7..9d10a89d28f1 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
> @@ -1428,7 +1428,8 @@ static int exynos_dsi_attach(struct drm_bridge *bridge,
>  {
> struct exynos_dsi *dsi = bridge_to_dsi(bridge);
>
> -   return drm_bridge_attach(bridge->encoder, dsi->out_bridge, NULL, 
> flags);
> +   return drm_bridge_attach(bridge->encoder, dsi->out_bridge, bridge,
> +flags);

Agreed on this change.

>  }
>
>  static const struct drm_bridge_funcs exynos_dsi_bridge_funcs = {
> @@ -1474,7 +1475,10 @@ static int exynos_dsi_host_attach(struct mipi_dsi_host 
> *host,
>
> drm_bridge_add(>bridge);
>
> -   drm_bridge_attach(encoder, >bridge, NULL, 0);
> +   drm_bridge_attach(encoder, >bridge,
> + list_first_entry_or_null(>bridge_chain,
> +  struct drm_bridge,
> +  chain_node), 0);

What bridge are you expecting between the encoder and this bridge?
The encoder is the drm_simple_encoder_init encoder that you've created
in exynos_dsi_bind, so separating that from the bridge you're also
creating here seems weird.

>
> /*
>  * This is a temporary solution and should be made by more generic 
> way.
> @@ -1709,6 +1713,7 @@ static int exynos_dsi_probe(struct platform_device 
> *pdev)
> dsi->bridge.funcs = _dsi_bridge_funcs;
> dsi->bridge.of_node = dev->of_node;
> dsi->bridge.type = DRM_MODE_CONNECTOR_DSI;
> +   dsi->bridge.pre_enable_prev_first = true;

Setting dsi->bridge.pre_enable_prev_first on what is presumably the
DSI host controller seems a little odd.
Same question again - what bridge are you expecting to be upstream of
the DSI host that needs to be preenabled before it? Whilst it's
possible that there's another bridge, I'd have expected that to be the
first link from your encoder as they appear to both belong to the same
bit of driver.

  Dave

> ret = component_add(dev, _dsi_component_ops);
> if (ret)
> --
> 2.25.1
>


Re: [PATCH] drm/panel: boe-tv101wum-nl6: Ensure DSI writes succeed during disable

2023-01-16 Thread Dave Stevenson
Hi Stephen

On Fri, 13 Jan 2023 at 21:12, Stephen Boyd  wrote:
>
> Quoting Dave Stevenson (2023-01-13 08:27:29)
> > Hi Stephen
> >
> > On Fri, 6 Jan 2023 at 03:01, Stephen Boyd  wrote:
> > >
> > > The unprepare sequence has started to fail after moving to panel bridge
> > > code in the msm drm driver (commit 007ac0262b0d ("drm/msm/dsi: switch to
> > > DRM_PANEL_BRIDGE")). You'll see messages like this in the kernel logs:
> > >
> > >panel-boe-tv101wum-nl6 ae94000.dsi.0: failed to set panel off: -22
> > >
> > > This is because boe_panel_enter_sleep_mode() needs an operating DSI link
> > > to set the panel into sleep mode. Performing those writes in the
> > > unprepare phase of bridge ops is too late, because the link has already
> > > been torn down by the DSI controller in post_disable, i.e. the PHY has
> > > been disabled, etc. See dsi_mgr_bridge_post_disable() for more details
> > > on the DSI .
> > >
> > > Split the unprepare function into a disable part and an unprepare part.
> > > For now, just the DSI writes to enter sleep mode are put in the disable
> > > function. This fixes the panel off routine and keeps the panel happy.
> >
> > It is documented that the mipi_dsi_host_ops transfer function should
> > be called with the host in any state [1], so the host driver is
> > failing there.
>
> Thanks for the info! It says "Drivers that need the underlying device to
> be powered to perform these operations will first need to make sure it’s
> been properly enabled." Does that mean the panel driver needs to make
> sure the underlying dsi host device is powered? The sentence is too
> ambiguous for me to understand what 'drivers' and 'underlying device'
> are.

The DSI host driver (ie in your case something under
drivers/gpu/drm/msm/dsi) should ensure that a transfer can be made,
regardless of state.

I must say that this has been documented as the case, but doesn't
necessarily reflect reality in a number of drivers.

> >
> > This sounds like the same issue I was addressing in adding the
> > prepare_prev_first flag to drm_panel, and pre_enable_prev_first to
> > drm_bridge via [2].
> > Defining prepare_prev_first for your panel would result in the host
> > pre_enable being called before the panel prepare, and therefore the
> > transfer calls from boe_panel_init_dcs_cmd boe_panel_prepare won't be
> > relying on the DSI host powering up early. It will also call the panel
> > unprepare before the DSI host bridge post_disable is called, and
> > therefore the DSI host will still be powered up and the transfer won't
> > fail.
> >
> > Actually I've just noted the comment at [3]. [2] is that framework fix
> > that means that the magic workaround isn't required, but it will
> > require this panel to opt in to the ordering change.
>
> Cool. Glad that we can clean that up with your series.
>
> Is it wrong to split unprepare to a disable and unprepare phase? I'm not
> super keen on fixing 6.1 stable kernels by opting this driver into the
> ordering change. Splitting the phase into two is small and simple and
> works. I suspect changing the ordering may uncover more bugs, or be a
> larger task. I'd be glad to test that series[2] from you to get rid of
> [3].

Ah, I hadn't realised it was a regression in a released kernel :(

Splitting into a disable and unprepare is totally fine. Normally
disable would normally disable the panel and backlight (probably by
drm_panel before the panel disable call), with unprepare disabling
power and clocks

Do note that AIUI you will be telling the panel to enter sleep mode
whilst video is still being transmitted. That should be safe as the
panel has to still be partially active to handle an exit sleep mode
command, but actually powering hardware down at that point could cause
DSI bus arbitration errors as clock or data lanes could be pulled down
when the host is trying to adopt HS or LP11.

  Dave

> >
> >
> > [1] 
> > https://www.kernel.org/doc/html/latest/gpu/drm-kms-helpers.html#c.mipi_dsi_host_ops
> > [2] https://patchwork.freedesktop.org/series/100252/
> > [3] 
> > https://github.com/torvalds/linux/blob/master/drivers/gpu/drm/msm/dsi/dsi_manager.c#L47
> >


Re: [PATCH] drm/panel: boe-tv101wum-nl6: Ensure DSI writes succeed during disable

2023-01-13 Thread Dave Stevenson
Hi Stephen

On Fri, 6 Jan 2023 at 03:01, Stephen Boyd  wrote:
>
> The unprepare sequence has started to fail after moving to panel bridge
> code in the msm drm driver (commit 007ac0262b0d ("drm/msm/dsi: switch to
> DRM_PANEL_BRIDGE")). You'll see messages like this in the kernel logs:
>
>panel-boe-tv101wum-nl6 ae94000.dsi.0: failed to set panel off: -22
>
> This is because boe_panel_enter_sleep_mode() needs an operating DSI link
> to set the panel into sleep mode. Performing those writes in the
> unprepare phase of bridge ops is too late, because the link has already
> been torn down by the DSI controller in post_disable, i.e. the PHY has
> been disabled, etc. See dsi_mgr_bridge_post_disable() for more details
> on the DSI .
>
> Split the unprepare function into a disable part and an unprepare part.
> For now, just the DSI writes to enter sleep mode are put in the disable
> function. This fixes the panel off routine and keeps the panel happy.

It is documented that the mipi_dsi_host_ops transfer function should
be called with the host in any state [1], so the host driver is
failing there.

This sounds like the same issue I was addressing in adding the
prepare_prev_first flag to drm_panel, and pre_enable_prev_first to
drm_bridge via [2].
Defining prepare_prev_first for your panel would result in the host
pre_enable being called before the panel prepare, and therefore the
transfer calls from boe_panel_init_dcs_cmd boe_panel_prepare won't be
relying on the DSI host powering up early. It will also call the panel
unprepare before the DSI host bridge post_disable is called, and
therefore the DSI host will still be powered up and the transfer won't
fail.

Actually I've just noted the comment at [3]. [2] is that framework fix
that means that the magic workaround isn't required, but it will
require this panel to opt in to the ordering change.

Cheers.
  Dave

[1] 
https://www.kernel.org/doc/html/latest/gpu/drm-kms-helpers.html#c.mipi_dsi_host_ops
[2] https://patchwork.freedesktop.org/series/100252/
[3] 
https://github.com/torvalds/linux/blob/master/drivers/gpu/drm/msm/dsi/dsi_manager.c#L47

> My Wormdingler has an integrated touchscreen that stops responding to
> touch if the panel is only half disabled too. This patch fixes it. And
> finally, this saves power when the screen is off because without this
> fix the regulators for the panel are left enabled when nothing is being
> displayed on the screen.
>
> Fixes: 007ac0262b0d ("drm/msm/dsi: switch to DRM_PANEL_BRIDGE")
> Fixes: a869b9db7adf ("drm/panel: support for boe tv101wum-nl6 wuxga dsi video 
> mode panel")
> Cc: yangcong 
> Cc: Douglas Anderson 
> Cc: Jitao Shi 
> Cc: Sam Ravnborg 
> Cc: Rob Clark 
> Cc: Dmitry Baryshkov 
> Signed-off-by: Stephen Boyd 
> ---
>  drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c | 16 
>  1 file changed, 12 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c 
> b/drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c
> index 857a2f0420d7..c924f1124ebc 100644
> --- a/drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c
> +++ b/drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c
> @@ -1193,14 +1193,11 @@ static int boe_panel_enter_sleep_mode(struct 
> boe_panel *boe)
> return 0;
>  }
>
> -static int boe_panel_unprepare(struct drm_panel *panel)
> +static int boe_panel_disable(struct drm_panel *panel)
>  {
> struct boe_panel *boe = to_boe_panel(panel);
> int ret;
>
> -   if (!boe->prepared)
> -   return 0;
> -
> ret = boe_panel_enter_sleep_mode(boe);
> if (ret < 0) {
> dev_err(panel->dev, "failed to set panel off: %d\n", ret);
> @@ -1209,6 +1206,16 @@ static int boe_panel_unprepare(struct drm_panel *panel)
>
> msleep(150);
>
> +   return 0;
> +}
> +
> +static int boe_panel_unprepare(struct drm_panel *panel)
> +{
> +   struct boe_panel *boe = to_boe_panel(panel);
> +
> +   if (!boe->prepared)
> +   return 0;
> +
> if (boe->desc->discharge_on_disable) {
> regulator_disable(boe->avee);
> regulator_disable(boe->avdd);
> @@ -1528,6 +1535,7 @@ static enum drm_panel_orientation 
> boe_panel_get_orientation(struct drm_panel *pa
>  }
>
>  static const struct drm_panel_funcs boe_panel_funcs = {
> +   .disable = boe_panel_disable,
> .unprepare = boe_panel_unprepare,
> .prepare = boe_panel_prepare,
> .enable = boe_panel_enable,
>
> base-commit: 1b929c02afd37871d5afb9d498426f83432e71c2
> --
> https://chromeos.dev
>


Re: [PATCH 5/9] drm/vc4: hdmi: Rework the CSC matrices organization

2023-01-11 Thread Dave Stevenson
Hi Thomas

Thanks for the review

On Wed, 11 Jan 2023 at 15:03, Thomas Zimmermann  wrote:
>
> Hi
>
> Am 07.12.22 um 17:07 schrieb Maxime Ripard:
> > From: Dave Stevenson 
> >
> > The CSC matrices were stored as separate matrix for each colorspace, and
> > if we wanted a limited or full RGB output.
> >
> > This created some gaps in our support and we would not always pick the
> > relevant matrix.
> >
> > Let's rework our data structure to store one per colorspace, and then a
> > matrix for limited range and one for full range. This makes us add a new
> > matrix to support full range BT709 YUV output, and drops the redundant
> > (but somehow different) BT709 YUV444 vs YUV422 matrix.
>
> The final sentence is confusing and I didn't understand how two
> different matrices can now be just one.

Two changes to accommodate the hardware requirements:

Firstly the driver was only defining
vc5_hdmi_csc_full_rgb_to_limited_yuv444_bt709 and
vc5_hdmi_csc_full_rgb_to_limited_yuv422_bt709. There was no matrix for
full_rgb_to_full_yuv_bt709, so that had to be added.

Secondly, for some reason when in 444 mode the hardware wants the
matrix rows in a different order. That is why
vc5_hdmi_csc_full_rgb_to_limited_yuv444_bt709 differed from
vc5_hdmi_csc_full_rgb_to_limited_yuv422_bt709 - it was a simple
reordering of the rows.

This patch dropped the special handling for 444, and in the process
programmed the wrong coefficients into the hardware :-(
Patch 6/9 then reintroduces this reordering, so really should be
squashed into the one patch.

Looking at my more recent work, it looks like I messed up on 6/9 too.
One of the patches on [1] corrects that row swapping for yuv444 - I
was obviously having a bad day.

Maxime: Are you OK to fix that up?

Thanks

  Dave

[1] https://github.com/raspberrypi/linux/pull/5249/commits

> Best regards
> Thomas
>
> >
> > Signed-off-by: Dave Stevenson 
> > Signed-off-by: Maxime Ripard 
> > ---
> >   drivers/gpu/drm/vc4/vc4_hdmi.c | 124 
> > +
> >   1 file changed, 63 insertions(+), 61 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> > index 51469939a8b4..299a8fe7a2ae 100644
> > --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> > +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> > @@ -1178,68 +1178,72 @@ static void vc4_hdmi_csc_setup(struct vc4_hdmi 
> > *vc4_hdmi,
> >   }
> >
> >   /*
> > - * If we need to output Full Range RGB, then use the unity matrix
> > + * Matrices for (internal) RGB to RGB output.
> >*
> > - * [ 1  0  0  0]
> > - * [ 0  1  0  0]
> > - * [ 0  0  1  0]
> > - *
> > - * Matrix is signed 2p13 fixed point, with signed 9p6 offsets
> > - */
> > -static const u16 vc5_hdmi_csc_full_rgb_unity[3][4] = {
> > - { 0x2000, 0x, 0x, 0x },
> > - { 0x, 0x2000, 0x, 0x },
> > - { 0x, 0x, 0x2000, 0x },
> > -};
> > -
> > -/*
> > - * CEA VICs other than #1 require limited range RGB output unless
> > - * overridden by an AVI infoframe. Apply a colorspace conversion to
> > - * squash 0-255 down to 16-235. The matrix here is:
> > - *
> > - * [ 0.8594 0  0  16]
> > - * [ 0  0.8594 0  16]
> > - * [ 0  0  0.8594 16]
> > - *
> > - * Matrix is signed 2p13 fixed point, with signed 9p6 offsets
> > + * Matrices are signed 2p13 fixed point, with signed 9p6 offsets
> >*/
> > -static const u16 vc5_hdmi_csc_full_rgb_to_limited_rgb[3][4] = {
> > - { 0x1b80, 0x, 0x, 0x0400 },
> > - { 0x, 0x1b80, 0x, 0x0400 },
> > - { 0x, 0x, 0x1b80, 0x0400 },
> > +static const u16 vc5_hdmi_csc_full_rgb_to_rgb[2][3][4] = {
> > + {
> > + /*
> > +  * Full range - unity
> > +  *
> > +  * [ 1  0  0  0]
> > +  * [ 0  1  0  0]
> > +  * [ 0  0  1  0]
> > +  */
> > + { 0x2000, 0x, 0x, 0x },
> > + { 0x, 0x2000, 0x, 0x },
> > + { 0x, 0x, 0x2000, 0x },
> > + },
> > + {
> > + /*
> > +  * Limited range
> > +  *
> > +  * CEA VICs other than #1 require limited range RGB
> > +  * output unless overridden by an AVI infoframe. Apply a
> > +  * colorspace conversion to squash 0-255 down to 16-235.
> > +  * The matrix here is:
> > +  

Re: [PATCH 08/15] drm/vc4: hvs: Ignore atomic_flush if we're disabled

2023-01-09 Thread Dave Stevenson
Hi Maxime

On Wed, 7 Dec 2022 at 11:55, Maxime Ripard  wrote:
>
> atomic_flush will be called for each CRTC even if they aren't enabled.
>
> The whole code we have there will thus run without a properly affected
> channel, which can then result in all sorts of weird behaviour.
>
> Signed-off-by: Maxime Ripard 

Reviewed-by: Dave Stevenson 

> ---
>  drivers/gpu/drm/vc4/vc4_hvs.c | 3 +++
>  1 file changed, 3 insertions(+)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c
> index 3582ede1a0aa..5fadbf219542 100644
> --- a/drivers/gpu/drm/vc4/vc4_hvs.c
> +++ b/drivers/gpu/drm/vc4/vc4_hvs.c
> @@ -579,6 +579,9 @@ void vc4_hvs_atomic_flush(struct drm_crtc *crtc,
> return;
> }
>
> +   if (vc4_state->assigned_channel == VC4_HVS_CHANNEL_DISABLED)
> +   return;
> +
> if (debug_dump_regs) {
> DRM_INFO("CRTC %d HVS before:\n", drm_crtc_index(crtc));
> vc4_hvs_dump_state(hvs);
>
> --
> 2.38.1


[PATCH] drm/bridge: panel: Set pre_enable_prev_first from drmm_panel_bridge_add

2022-12-22 Thread Dave Stevenson
Commit 5ea6b1702781 ("drm/panel: Add prepare_prev_first flag to drm_panel")
added code to copy prepare_prev_first from drm_panel to pre_enable_prev_first
in drm_bridge when called through devm_panel_bridge_add, but
missed drmm_panel_bridge_add.

Add the same code to drmm_panel_bridge_add.

Fixes: 5ea6b1702781 ("drm/panel: Add prepare_prev_first flag to drm_panel")
Signed-off-by: Dave Stevenson 
---
 drivers/gpu/drm/bridge/panel.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/gpu/drm/bridge/panel.c b/drivers/gpu/drm/bridge/panel.c
index 03c3274dc3d9..1708098fba6d 100644
--- a/drivers/gpu/drm/bridge/panel.c
+++ b/drivers/gpu/drm/bridge/panel.c
@@ -404,6 +404,8 @@ struct drm_bridge *drmm_panel_bridge_add(struct drm_device 
*drm,
if (ret)
return ERR_PTR(ret);
 
+   bridge->pre_enable_prev_first = panel->prepare_prev_first;
+
return bridge;
 }
 EXPORT_SYMBOL(drmm_panel_bridge_add);
-- 
2.34.1



[PATCH v4 2/6] drm/mediatek: dp: Replace usage of drm_bridge_chain_ functions

2022-12-05 Thread Dave Stevenson
Commit f70ac097a2cf ("drm/mediatek: Add MT8195 Embedded DisplayPort
driver") added usage of the drm_bridge_chain_ functions which are
to be deprecated.

Replace with the drm_atomic_bridge_chain_ variants using the
current state.

Signed-off-by: Dave Stevenson 
---
 drivers/gpu/drm/mediatek/mtk_dp.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/mediatek/mtk_dp.c 
b/drivers/gpu/drm/mediatek/mtk_dp.c
index 9d085c05c49c..b4feaabdb6a7 100644
--- a/drivers/gpu/drm/mediatek/mtk_dp.c
+++ b/drivers/gpu/drm/mediatek/mtk_dp.c
@@ -1981,7 +1981,7 @@ static struct edid *mtk_dp_get_edid(struct drm_bridge 
*bridge,
struct cea_sad *sads;
 
if (!enabled) {
-   drm_bridge_chain_pre_enable(bridge);
+   drm_atomic_bridge_chain_pre_enable(bridge, 
connector->state->state);
 
/* power on aux */
mtk_dp_update_bits(mtk_dp, MTK_DP_TOP_PWR_STATE,
@@ -2019,7 +2019,7 @@ static struct edid *mtk_dp_get_edid(struct drm_bridge 
*bridge,
   DP_PWR_STATE_BANDGAP_TPLL,
   DP_PWR_STATE_MASK);
 
-   drm_bridge_chain_post_disable(bridge);
+   drm_atomic_bridge_chain_post_disable(bridge, 
connector->state->state);
}
 
return new_edid;
-- 
2.34.1



[PATCH v4 3/6] drm/bridge: Drop unused drm_bridge_chain functions

2022-12-05 Thread Dave Stevenson
From: Sam Ravnborg 

The drm_bridge_chain_{pre_enable,enable,disable,post_disable} has no
users left and we have atomic variants that should be used.
Drop them so they do not gain new users.

Adjust a few comments to avoid references to the dropped functions.

Signed-off-by: Sam Ravnborg 
Reviewed-by: Maxime Ripard 
Reviewed-by: Laurent Pinchart 
Cc: Laurent Pinchart 
Cc: Maarten Lankhorst 
Cc: Maxime Ripard 
Cc: Thomas Zimmermann 
Cc: Andrzej Hajda 
Cc: Neil Armstrong 
Cc: Robert Foss 
Cc: Daniel Vetter 
Signed-off-by: Dave Stevenson 
---
 drivers/gpu/drm/drm_bridge.c | 110 ---
 include/drm/drm_bridge.h |  28 -
 2 files changed, 138 deletions(-)

diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
index 1545c50fd1c8..bb7fc09267af 100644
--- a/drivers/gpu/drm/drm_bridge.c
+++ b/drivers/gpu/drm/drm_bridge.c
@@ -509,61 +509,6 @@ drm_bridge_chain_mode_valid(struct drm_bridge *bridge,
 }
 EXPORT_SYMBOL(drm_bridge_chain_mode_valid);
 
-/**
- * drm_bridge_chain_disable - disables all bridges in the encoder chain
- * @bridge: bridge control structure
- *
- * Calls _bridge_funcs.disable op for all the bridges in the encoder
- * chain, starting from the last bridge to the first. These are called before
- * calling the encoder's prepare op.
- *
- * Note: the bridge passed should be the one closest to the encoder
- */
-void drm_bridge_chain_disable(struct drm_bridge *bridge)
-{
-   struct drm_encoder *encoder;
-   struct drm_bridge *iter;
-
-   if (!bridge)
-   return;
-
-   encoder = bridge->encoder;
-   list_for_each_entry_reverse(iter, >bridge_chain, chain_node) {
-   if (iter->funcs->disable)
-   iter->funcs->disable(iter);
-
-   if (iter == bridge)
-   break;
-   }
-}
-EXPORT_SYMBOL(drm_bridge_chain_disable);
-
-/**
- * drm_bridge_chain_post_disable - cleans up after disabling all bridges in the
- *encoder chain
- * @bridge: bridge control structure
- *
- * Calls _bridge_funcs.post_disable op for all the bridges in the
- * encoder chain, starting from the first bridge to the last. These are called
- * after completing the encoder's prepare op.
- *
- * Note: the bridge passed should be the one closest to the encoder
- */
-void drm_bridge_chain_post_disable(struct drm_bridge *bridge)
-{
-   struct drm_encoder *encoder;
-
-   if (!bridge)
-   return;
-
-   encoder = bridge->encoder;
-   list_for_each_entry_from(bridge, >bridge_chain, chain_node) {
-   if (bridge->funcs->post_disable)
-   bridge->funcs->post_disable(bridge);
-   }
-}
-EXPORT_SYMBOL(drm_bridge_chain_post_disable);
-
 /**
  * drm_bridge_chain_mode_set - set proposed mode for all bridges in the
  *encoder chain
@@ -593,61 +538,6 @@ void drm_bridge_chain_mode_set(struct drm_bridge *bridge,
 }
 EXPORT_SYMBOL(drm_bridge_chain_mode_set);
 
-/**
- * drm_bridge_chain_pre_enable - prepares for enabling all bridges in the
- *  encoder chain
- * @bridge: bridge control structure
- *
- * Calls _bridge_funcs.pre_enable op for all the bridges in the encoder
- * chain, starting from the last bridge to the first. These are called
- * before calling the encoder's commit op.
- *
- * Note: the bridge passed should be the one closest to the encoder
- */
-void drm_bridge_chain_pre_enable(struct drm_bridge *bridge)
-{
-   struct drm_encoder *encoder;
-   struct drm_bridge *iter;
-
-   if (!bridge)
-   return;
-
-   encoder = bridge->encoder;
-   list_for_each_entry_reverse(iter, >bridge_chain, chain_node) {
-   if (iter->funcs->pre_enable)
-   iter->funcs->pre_enable(iter);
-
-   if (iter == bridge)
-   break;
-   }
-}
-EXPORT_SYMBOL(drm_bridge_chain_pre_enable);
-
-/**
- * drm_bridge_chain_enable - enables all bridges in the encoder chain
- * @bridge: bridge control structure
- *
- * Calls _bridge_funcs.enable op for all the bridges in the encoder
- * chain, starting from the first bridge to the last. These are called
- * after completing the encoder's commit op.
- *
- * Note that the bridge passed should be the one closest to the encoder
- */
-void drm_bridge_chain_enable(struct drm_bridge *bridge)
-{
-   struct drm_encoder *encoder;
-
-   if (!bridge)
-   return;
-
-   encoder = bridge->encoder;
-   list_for_each_entry_from(bridge, >bridge_chain, chain_node) {
-   if (bridge->funcs->enable)
-   bridge->funcs->enable(bridge);
-   }
-}
-EXPORT_SYMBOL(drm_bridge_chain_enable);
-
 /**
  * drm_atomic_bridge_chain_disable - disables all bridges in the encoder chain
  * @bridge: bridge control structure
diff --git a/include/drm/

[PATCH v4 4/6] drm/bridge: Introduce pre_enable_prev_first to alter bridge init order

2022-12-05 Thread Dave Stevenson
DSI sink devices typically want the DSI host powered up and configured
before they are powered up. pre_enable is the place this would normally
happen, but they are called in reverse order from panel/connector towards
the encoder, which is the "wrong" order.

Add a new flag pre_enable_prev_first that any bridge can set
to swap the order of pre_enable (and post_disable) for that and the
immediately previous bridge.
Should the immediately previous bridge also set the
pre_enable_prev_first flag, the previous bridge to that will be called
before either of those which requested pre_enable_prev_first.

eg:
- Panel
- Bridge 1
- Bridge 2 pre_enable_prev_first
- Bridge 3
- Bridge 4 pre_enable_prev_first
- Bridge 5 pre_enable_prev_first
- Bridge 6
- Encoder
Would result in pre_enable's being called as Panel, Bridge 1, Bridge 3,
Bridge 2, Bridge 6, Bridge 5, Bridge 4, Encoder.

Signed-off-by: Dave Stevenson 
Tested-by: Frieder Schrempf 
Reviewed-by: Frieder Schrempf 
---
 drivers/gpu/drm/drm_bridge.c | 145 +--
 include/drm/drm_bridge.h |   8 ++
 2 files changed, 129 insertions(+), 24 deletions(-)

diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
index bb7fc09267af..5f40c83b1b42 100644
--- a/drivers/gpu/drm/drm_bridge.c
+++ b/drivers/gpu/drm/drm_bridge.c
@@ -581,6 +581,25 @@ void drm_atomic_bridge_chain_disable(struct drm_bridge 
*bridge,
 }
 EXPORT_SYMBOL(drm_atomic_bridge_chain_disable);
 
+static void drm_atomic_bridge_call_post_disable(struct drm_bridge *bridge,
+   struct drm_atomic_state 
*old_state)
+{
+   if (old_state && bridge->funcs->atomic_post_disable) {
+   struct drm_bridge_state *old_bridge_state;
+
+   old_bridge_state =
+   drm_atomic_get_old_bridge_state(old_state,
+   bridge);
+   if (WARN_ON(!old_bridge_state))
+   return;
+
+   bridge->funcs->atomic_post_disable(bridge,
+  old_bridge_state);
+   } else if (bridge->funcs->post_disable) {
+   bridge->funcs->post_disable(bridge);
+   }
+}
+
 /**
  * drm_atomic_bridge_chain_post_disable - cleans up after disabling all bridges
  *   in the encoder chain
@@ -592,36 +611,86 @@ EXPORT_SYMBOL(drm_atomic_bridge_chain_disable);
  * starting from the first bridge to the last. These are called after 
completing
  * _encoder_helper_funcs.atomic_disable
  *
+ * If a bridge sets @pre_enable_prev_first, then the @post_disable for that
+ * bridge will be called before the previous one to reverse the @pre_enable
+ * calling direction.
+ *
  * Note: the bridge passed should be the one closest to the encoder
  */
 void drm_atomic_bridge_chain_post_disable(struct drm_bridge *bridge,
  struct drm_atomic_state *old_state)
 {
struct drm_encoder *encoder;
+   struct drm_bridge *next, *limit;
 
if (!bridge)
return;
 
encoder = bridge->encoder;
+
list_for_each_entry_from(bridge, >bridge_chain, chain_node) {
-   if (bridge->funcs->atomic_post_disable) {
-   struct drm_bridge_state *old_bridge_state;
+   limit = NULL;
+
+   if (!list_is_last(>chain_node, >bridge_chain)) 
{
+   next = list_next_entry(bridge, chain_node);
+
+   if (next->pre_enable_prev_first) {
+   /* next bridge had requested that prev
+* was enabled first, so disabled last
+*/
+   limit = next;
+
+   /* Find the next bridge that has NOT requested
+* prev to be enabled first / disabled last
+*/
+   list_for_each_entry_from(next, 
>bridge_chain,
+chain_node) {
+   if (next->pre_enable_prev_first) {
+   next = list_prev_entry(next, 
chain_node);
+   limit = next;
+   break;
+   }
+   }
+
+   /* Call these bridges in reverse order */
+   list_for_each_entry_from_reverse(next, 
>bridge_chain,
+chain_node) {
+   if (next == bridge)
+   break;
+
+

[PATCH v4 6/6] drm/bridge: Document the expected behaviour of DSI host controllers

2022-12-05 Thread Dave Stevenson
The exact behaviour of DSI host controllers is not specified,
therefore define it.

Signed-off-by: Dave Stevenson 
Reviewed-by: Laurent Pinchart 
---
 Documentation/gpu/drm-kms-helpers.rst |  7 +
 drivers/gpu/drm/drm_bridge.c  | 39 +++
 2 files changed, 46 insertions(+)

diff --git a/Documentation/gpu/drm-kms-helpers.rst 
b/Documentation/gpu/drm-kms-helpers.rst
index a4860ffd6e86..b8ab05e42dbb 100644
--- a/Documentation/gpu/drm-kms-helpers.rst
+++ b/Documentation/gpu/drm-kms-helpers.rst
@@ -188,6 +188,13 @@ Bridge Helper Reference
 .. kernel-doc:: drivers/gpu/drm/drm_bridge.c
:export:
 
+MIPI-DSI bridge operation
+-
+
+.. kernel-doc:: drivers/gpu/drm/drm_bridge.c
+   :doc: dsi bridge operations
+
+
 Bridge Connector Helper Reference
 -
 
diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
index 5f40c83b1b42..c3d69af02e79 100644
--- a/drivers/gpu/drm/drm_bridge.c
+++ b/drivers/gpu/drm/drm_bridge.c
@@ -153,6 +153,45 @@
  * situation when probing.
  */
 
+/**
+ * DOC: dsi bridge operations
+ *
+ * DSI host interfaces are expected to be implemented as bridges rather than
+ * encoders, however there are a few aspects of their operation that need to
+ * be defined in order to provide a consistent interface.
+ *
+ * A DSI host should keep the PHY powered down until the pre_enable operation 
is
+ * called. All lanes are in an undefined idle state up to this point, and it
+ * must not be assumed that it is LP-11.
+ * pre_enable should initialise the PHY, set the data lanes to LP-11, and the
+ * clock lane to either LP-11 or HS depending on the mode_flag
+ * %MIPI_DSI_CLOCK_NON_CONTINUOUS.
+ *
+ * Ordinarily the downstream bridge DSI peripheral pre_enable will have been
+ * called before the DSI host. If the DSI peripheral requires LP-11 and/or
+ * the clock lane to be in HS mode prior to pre_enable, then it can set the
+ * _enable_prev_first flag to request the pre_enable (and
+ * post_disable) order to be altered to enable the DSI host first.
+ *
+ * Either the CRTC being enabled, or the DSI host enable operation should 
switch
+ * the host to actively transmitting video on the data lanes.
+ *
+ * The reverse also applies. The DSI host disable operation or stopping the 
CRTC
+ * should stop transmitting video, and the data lanes should return to the 
LP-11
+ * state. The DSI host _disable operation should disable the PHY.
+ * If the _enable_prev_first flag is set, then the DSI peripheral's
+ * bridge _disable will be called before the DSI host's post_disable.
+ *
+ * Whilst it is valid to call _transfer prior to pre_enable or after
+ * post_disable, the exact state of the lanes is undefined at this point. The
+ * DSI host should initialise the interface, transmit the data, and then 
disable
+ * the interface again.
+ *
+ * Ultra Low Power State (ULPS) is not explicitly supported by DRM. If
+ * implemented, it therefore needs to be handled entirely within the DSI Host
+ * driver.
+ */
+
 static DEFINE_MUTEX(bridge_lock);
 static LIST_HEAD(bridge_list);
 
-- 
2.34.1



[PATCH v4 5/6] drm/panel: Add prepare_prev_first flag to drm_panel

2022-12-05 Thread Dave Stevenson
Mapping to the drm_bridge flag pre_enable_prev_first,
add a new flag prepare_prev_first to drm_panel to allow
the panel driver to request that the upstream bridge should
be pre_enabled before the panel prepare.

Signed-off-by: Dave Stevenson 
Reviewed-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/bridge/panel.c |  2 ++
 include/drm/drm_panel.h| 10 ++
 2 files changed, 12 insertions(+)

diff --git a/drivers/gpu/drm/bridge/panel.c b/drivers/gpu/drm/bridge/panel.c
index 216af76d0042..03c3274dc3d9 100644
--- a/drivers/gpu/drm/bridge/panel.c
+++ b/drivers/gpu/drm/bridge/panel.c
@@ -364,6 +364,8 @@ struct drm_bridge *devm_drm_panel_bridge_add_typed(struct 
device *dev,
devres_free(ptr);
}
 
+   bridge->pre_enable_prev_first = panel->prepare_prev_first;
+
return bridge;
 }
 EXPORT_SYMBOL(devm_drm_panel_bridge_add_typed);
diff --git a/include/drm/drm_panel.h b/include/drm/drm_panel.h
index 994bfcdd84c5..432fab2347eb 100644
--- a/include/drm/drm_panel.h
+++ b/include/drm/drm_panel.h
@@ -188,6 +188,16 @@ struct drm_panel {
 * Panel entry in registry.
 */
struct list_head list;
+
+   /**
+* @prepare_prev_first:
+*
+* The previous controller should be prepared first, before the prepare
+* for the panel is called. This is largely required for DSI panels
+* where the DSI host controller should be initialised to LP-11 before
+* the panel is powered up.
+*/
+   bool prepare_prev_first;
 };
 
 void drm_panel_init(struct drm_panel *panel, struct device *dev,
-- 
2.34.1



[PATCH v4 1/6] drm/bridge: ps8640: Use atomic variants of drm_bridge_funcs

2022-12-05 Thread Dave Stevenson
From: Sam Ravnborg 

The atomic variants of enable/disable in drm_bridge_funcs are the
preferred operations - introduce these.

The ps8640 driver used the non-atomic variants of the 
drm_bridge_chain_pre_enable/
drm_bridge_chain_post_disable - convert these to the atomic variants.

v2:
  - Init state operations in drm_bridge_funcs (Laurent)

Signed-off-by: Sam Ravnborg 
Reviewed-by: Maxime Ripard 
Cc: Jitao Shi 
Cc: Philip Chen 
Cc: Neil Armstrong 
Cc: Robert Foss 
Cc: Laurent Pinchart 
Cc: Jonas Karlman 
Cc: Jernej Skrabec 
Reviewed-by: Laurent Pinchart 
Signed-off-by: Dave Stevenson 
---
 drivers/gpu/drm/bridge/parade-ps8640.c | 18 --
 1 file changed, 12 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/bridge/parade-ps8640.c 
b/drivers/gpu/drm/bridge/parade-ps8640.c
index f74090a9cc9e..4b361d7d5e44 100644
--- a/drivers/gpu/drm/bridge/parade-ps8640.c
+++ b/drivers/gpu/drm/bridge/parade-ps8640.c
@@ -15,6 +15,7 @@
 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -442,7 +443,8 @@ static const struct dev_pm_ops ps8640_pm_ops = {
pm_runtime_force_resume)
 };
 
-static void ps8640_pre_enable(struct drm_bridge *bridge)
+static void ps8640_atomic_pre_enable(struct drm_bridge *bridge,
+struct drm_bridge_state *old_bridge_state)
 {
struct ps8640 *ps_bridge = bridge_to_ps8640(bridge);
struct regmap *map = ps_bridge->regmap[PAGE2_TOP_CNTL];
@@ -476,7 +478,8 @@ static void ps8640_pre_enable(struct drm_bridge *bridge)
ps_bridge->pre_enabled = true;
 }
 
-static void ps8640_post_disable(struct drm_bridge *bridge)
+static void ps8640_atomic_post_disable(struct drm_bridge *bridge,
+  struct drm_bridge_state 
*old_bridge_state)
 {
struct ps8640 *ps_bridge = bridge_to_ps8640(bridge);
 
@@ -554,7 +557,7 @@ static struct edid *ps8640_bridge_get_edid(struct 
drm_bridge *bridge,
 * EDID, for this chip, we need to do a full poweron, otherwise it will
 * fail.
 */
-   drm_bridge_chain_pre_enable(bridge);
+   drm_atomic_bridge_chain_pre_enable(bridge, connector->state->state);
 
edid = drm_get_edid(connector,
ps_bridge->page[PAGE0_DP_CNTL]->adapter);
@@ -564,7 +567,7 @@ static struct edid *ps8640_bridge_get_edid(struct 
drm_bridge *bridge,
 * before, return the chip to its original power state.
 */
if (poweroff)
-   drm_bridge_chain_post_disable(bridge);
+   drm_atomic_bridge_chain_post_disable(bridge, 
connector->state->state);
 
return edid;
 }
@@ -579,8 +582,11 @@ static const struct drm_bridge_funcs ps8640_bridge_funcs = 
{
.attach = ps8640_bridge_attach,
.detach = ps8640_bridge_detach,
.get_edid = ps8640_bridge_get_edid,
-   .post_disable = ps8640_post_disable,
-   .pre_enable = ps8640_pre_enable,
+   .atomic_post_disable = ps8640_atomic_post_disable,
+   .atomic_pre_enable = ps8640_atomic_pre_enable,
+   .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
+   .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
+   .atomic_reset = drm_atomic_helper_bridge_reset,
 };
 
 static int ps8640_bridge_get_dsi_resources(struct device *dev, struct ps8640 
*ps_bridge)
-- 
2.34.1



[PATCH v4 0/6] DSI host and peripheral initialisation ordering

2022-12-05 Thread Dave Stevenson
github.com/6by9/linux/tree/drm-misc-next-vc4_dsi
[8] https://github.com/6by9/linux/tree/rpi-5.15.y-sn65dsi83
My branches are going to be out of date by now - sorry.

Dave Stevenson (4):
  drm/mediatek: dp: Replace usage of drm_bridge_chain_ functions
  drm/bridge: Introduce pre_enable_prev_first to alter bridge init order
  drm/panel: Add prepare_prev_first flag to drm_panel
  drm/bridge: Document the expected behaviour of DSI host controllers

Sam Ravnborg (2):
  drm/bridge: ps8640: Use atomic variants of drm_bridge_funcs
  drm/bridge: Drop unused drm_bridge_chain functions

 Documentation/gpu/drm-kms-helpers.rst  |   7 +
 drivers/gpu/drm/bridge/panel.c |   2 +
 drivers/gpu/drm/bridge/parade-ps8640.c |  18 +-
 drivers/gpu/drm/drm_bridge.c   | 294 ++---
 drivers/gpu/drm/mediatek/mtk_dp.c  |   4 +-
 include/drm/drm_bridge.h   |  36 +--
 include/drm/drm_panel.h|  10 +
 7 files changed, 201 insertions(+), 170 deletions(-)

-- 
2.34.1



Re: [PATCH v8 06/14] drm: bridge: samsung-dsim: Handle proper DSI host initialization

2022-12-05 Thread Dave Stevenson
Hi Frieder

On Mon, 5 Dec 2022 at 07:30, Frieder Schrempf
 wrote:
>
> On 02.12.22 15:55, Dave Stevenson wrote:
> > Hi Marek
> >
> > On Fri, 2 Dec 2022 at 12:21, Marek Vasut  wrote:
> >>
> >> On 12/2/22 11:52, Marek Szyprowski wrote:
> >>> Hi,
> >>>
> >>> Sorry for delay, I was on a sick leave last 2 weeks.
> >>>
> >>> On 28.11.2022 15:43, Jagan Teki wrote:
> >>>> ,On Sat, Nov 26, 2022 at 3:44 AM Marek Vasut  wrote:
> >>>>> On 11/23/22 21:09, Jagan Teki wrote:
> >>>>>> On Sat, Nov 19, 2022 at 7:45 PM Marek Vasut  wrote:
> >>>>>>> On 11/17/22 14:04, Marek Szyprowski wrote:
> >>>>>>>> On 17.11.2022 05:58, Marek Vasut wrote:
> >>>>>>>>> On 11/10/22 19:38, Jagan Teki wrote:
> >>>>>>>>>> DSI host initialization handling in previous exynos dsi driver has
> >>>>>>>>>> some pitfalls. It initializes the host during host transfer() hook
> >>>>>>>>>> that is indeed not the desired call flow for I2C and any other DSI
> >>>>>>>>>> configured downstream bridges.
> >>>>>>>>>>
> >>>>>>>>>> Host transfer() is usually triggered for downstream DSI panels or
> >>>>>>>>>> bridges and I2C-configured-DSI bridges miss these host 
> >>>>>>>>>> initialization
> >>>>>>>>>> as these downstream bridges use bridge operations hooks like 
> >>>>>>>>>> pre_enable,
> >>>>>>>>>> and enable in order to initialize or set up the host.
> >>>>>>>>>>
> >>>>>>>>>> This patch is trying to handle the host init handler to satisfy all
> >>>>>>>>>> downstream panels and bridges. Added the DSIM_STATE_REINITIALIZED 
> >>>>>>>>>> state
> >>>>>>>>>> flag to ensure that host init is also done on first cmd transfer, 
> >>>>>>>>>> this
> >>>>>>>>>> helps existing DSI panels work on exynos platform (form Marek
> >>>>>>>>>> Szyprowski).
> >>>>>>>>>>
> >>>>>>>>>> v8, v7, v6, v5:
> >>>>>>>>>> * none
> >>>>>>>>>>
> >>>>>>>>>> v4:
> >>>>>>>>>> * update init handling to ensure host init done on first cmd 
> >>>>>>>>>> transfer
> >>>>>>>>>>
> >>>>>>>>>> v3:
> >>>>>>>>>> * none
> >>>>>>>>>>
> >>>>>>>>>> v2:
> >>>>>>>>>> * check initialized state in samsung_dsim_init
> >>>>>>>>>>
> >>>>>>>>>> v1:
> >>>>>>>>>> * keep DSI init in host transfer
> >>>>>>>>>>
> >>>>>>>>>> Signed-off-by: Marek Szyprowski 
> >>>>>>>>>> Signed-off-by: Jagan Teki 
> >>>>>>>>>> ---
> >>>>>>>>>>   drivers/gpu/drm/bridge/samsung-dsim.c | 25 
> >>>>>>>>>> +
> >>>>>>>>>>   include/drm/bridge/samsung-dsim.h |  5 +++--
> >>>>>>>>>>   2 files changed, 20 insertions(+), 10 deletions(-)
> >>>>>>>>>>
> >>>>>>>>>> diff --git a/drivers/gpu/drm/bridge/samsung-dsim.c
> >>>>>>>>>> b/drivers/gpu/drm/bridge/samsung-dsim.c
> >>>>>>>>>> index bb1f45fd5a88..ec7e01ae02ea 100644
> >>>>>>>>>> --- a/drivers/gpu/drm/bridge/samsung-dsim.c
> >>>>>>>>>> +++ b/drivers/gpu/drm/bridge/samsung-dsim.c
> >>>>>>>>>> @@ -1234,12 +1234,17 @@ static void samsung_dsim_disable_irq(struct
> >>>>>>>>>> samsung_dsim *dsi)
> >>>>>>>>>>   disable_irq(dsi->irq);
> >>>>>>>>>>   }
> >>>>>>>&g

Re: [PATCH v8 06/14] drm: bridge: samsung-dsim: Handle proper DSI host initialization

2022-12-02 Thread Dave Stevenson
Hi Marek

On Fri, 2 Dec 2022 at 12:21, Marek Vasut  wrote:
>
> On 12/2/22 11:52, Marek Szyprowski wrote:
> > Hi,
> >
> > Sorry for delay, I was on a sick leave last 2 weeks.
> >
> > On 28.11.2022 15:43, Jagan Teki wrote:
> >> ,On Sat, Nov 26, 2022 at 3:44 AM Marek Vasut  wrote:
> >>> On 11/23/22 21:09, Jagan Teki wrote:
>  On Sat, Nov 19, 2022 at 7:45 PM Marek Vasut  wrote:
> > On 11/17/22 14:04, Marek Szyprowski wrote:
> >> On 17.11.2022 05:58, Marek Vasut wrote:
> >>> On 11/10/22 19:38, Jagan Teki wrote:
>  DSI host initialization handling in previous exynos dsi driver has
>  some pitfalls. It initializes the host during host transfer() hook
>  that is indeed not the desired call flow for I2C and any other DSI
>  configured downstream bridges.
> 
>  Host transfer() is usually triggered for downstream DSI panels or
>  bridges and I2C-configured-DSI bridges miss these host initialization
>  as these downstream bridges use bridge operations hooks like 
>  pre_enable,
>  and enable in order to initialize or set up the host.
> 
>  This patch is trying to handle the host init handler to satisfy all
>  downstream panels and bridges. Added the DSIM_STATE_REINITIALIZED 
>  state
>  flag to ensure that host init is also done on first cmd transfer, 
>  this
>  helps existing DSI panels work on exynos platform (form Marek
>  Szyprowski).
> 
>  v8, v7, v6, v5:
>  * none
> 
>  v4:
>  * update init handling to ensure host init done on first cmd transfer
> 
>  v3:
>  * none
> 
>  v2:
>  * check initialized state in samsung_dsim_init
> 
>  v1:
>  * keep DSI init in host transfer
> 
>  Signed-off-by: Marek Szyprowski 
>  Signed-off-by: Jagan Teki 
>  ---
>    drivers/gpu/drm/bridge/samsung-dsim.c | 25 
>  +
>    include/drm/bridge/samsung-dsim.h |  5 +++--
>    2 files changed, 20 insertions(+), 10 deletions(-)
> 
>  diff --git a/drivers/gpu/drm/bridge/samsung-dsim.c
>  b/drivers/gpu/drm/bridge/samsung-dsim.c
>  index bb1f45fd5a88..ec7e01ae02ea 100644
>  --- a/drivers/gpu/drm/bridge/samsung-dsim.c
>  +++ b/drivers/gpu/drm/bridge/samsung-dsim.c
>  @@ -1234,12 +1234,17 @@ static void samsung_dsim_disable_irq(struct
>  samsung_dsim *dsi)
>    disable_irq(dsi->irq);
>    }
>    -static int samsung_dsim_init(struct samsung_dsim *dsi)
>  +static int samsung_dsim_init(struct samsung_dsim *dsi, unsigned int
>  flag)
>    {
>    const struct samsung_dsim_driver_data *driver_data =
>  dsi->driver_data;
>    +if (dsi->state & flag)
>  +return 0;
>  +
>    samsung_dsim_reset(dsi);
>  -samsung_dsim_enable_irq(dsi);
>  +
>  +if (!(dsi->state & DSIM_STATE_INITIALIZED))
>  +samsung_dsim_enable_irq(dsi);
>  if (driver_data->reg_values[RESET_TYPE] == DSIM_FUNCRST)
>    samsung_dsim_enable_lane(dsi, BIT(dsi->lanes) - 1);
>  @@ -1250,6 +1255,8 @@ static int samsung_dsim_init(struct
>  samsung_dsim *dsi)
>    samsung_dsim_set_phy_ctrl(dsi);
>    samsung_dsim_init_link(dsi);
>    +dsi->state |= flag;
>  +
>    return 0;
>    }
>    @@ -1269,6 +1276,10 @@ static void
>  samsung_dsim_atomic_pre_enable(struct drm_bridge *bridge,
>    }
>  dsi->state |= DSIM_STATE_ENABLED;
>  +
>  +ret = samsung_dsim_init(dsi, DSIM_STATE_INITIALIZED);
>  +if (ret)
>  +return;
>    }
>  static void samsung_dsim_atomic_enable(struct drm_bridge 
>  *bridge,
>  @@ -1458,12 +1469,9 @@ static ssize_t
>  samsung_dsim_host_transfer(struct mipi_dsi_host *host,
>    if (!(dsi->state & DSIM_STATE_ENABLED))
>    return -EINVAL;
>    -if (!(dsi->state & DSIM_STATE_INITIALIZED)) {
>  -ret = samsung_dsim_init(dsi);
>  -if (ret)
>  -return ret;
>  -dsi->state |= DSIM_STATE_INITIALIZED;
>  -}
>  +ret = samsung_dsim_init(dsi, DSIM_STATE_REINITIALIZED);
> >>> This triggers full controller reset and reprogramming upon first
> >>> command transfer, is such heavy handed reload really necessary ?
> >> Yes it is, otherwise the proper DSI panels doesn't work with Exynos DRM
> >> DSI. If this is a real issue 

[PATCH v3 1/5] drm/bridge: ps8640: Use atomic variants of drm_bridge_funcs

2022-12-02 Thread Dave Stevenson
From: Sam Ravnborg 

The atomic variants of enable/disable in drm_bridge_funcs are the
preferred operations - introduce these.

The ps8640 driver used the non-atomic variants of the 
drm_bridge_chain_pre_enable/
drm_bridge_chain_post_disable - convert these to the atomic variants.

v2:
  - Init state operations in drm_bridge_funcs (Laurent)

Signed-off-by: Sam Ravnborg 
Reviewed-by: Maxime Ripard 
Cc: Jitao Shi 
Cc: Enric Balletbo i Serra 
Cc: Philip Chen 
Cc: Andrzej Hajda 
Cc: Neil Armstrong 
Cc: Robert Foss 
Cc: Laurent Pinchart 
Cc: Jonas Karlman 
Cc: Jernej Skrabec 
Reviewed-by: Laurent Pinchart 
Signed-off-by: Dave Stevenson 
---
 drivers/gpu/drm/bridge/parade-ps8640.c | 18 --
 1 file changed, 12 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/bridge/parade-ps8640.c 
b/drivers/gpu/drm/bridge/parade-ps8640.c
index f74090a9cc9e..4b361d7d5e44 100644
--- a/drivers/gpu/drm/bridge/parade-ps8640.c
+++ b/drivers/gpu/drm/bridge/parade-ps8640.c
@@ -15,6 +15,7 @@
 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -442,7 +443,8 @@ static const struct dev_pm_ops ps8640_pm_ops = {
pm_runtime_force_resume)
 };
 
-static void ps8640_pre_enable(struct drm_bridge *bridge)
+static void ps8640_atomic_pre_enable(struct drm_bridge *bridge,
+struct drm_bridge_state *old_bridge_state)
 {
struct ps8640 *ps_bridge = bridge_to_ps8640(bridge);
struct regmap *map = ps_bridge->regmap[PAGE2_TOP_CNTL];
@@ -476,7 +478,8 @@ static void ps8640_pre_enable(struct drm_bridge *bridge)
ps_bridge->pre_enabled = true;
 }
 
-static void ps8640_post_disable(struct drm_bridge *bridge)
+static void ps8640_atomic_post_disable(struct drm_bridge *bridge,
+  struct drm_bridge_state 
*old_bridge_state)
 {
struct ps8640 *ps_bridge = bridge_to_ps8640(bridge);
 
@@ -554,7 +557,7 @@ static struct edid *ps8640_bridge_get_edid(struct 
drm_bridge *bridge,
 * EDID, for this chip, we need to do a full poweron, otherwise it will
 * fail.
 */
-   drm_bridge_chain_pre_enable(bridge);
+   drm_atomic_bridge_chain_pre_enable(bridge, connector->state->state);
 
edid = drm_get_edid(connector,
ps_bridge->page[PAGE0_DP_CNTL]->adapter);
@@ -564,7 +567,7 @@ static struct edid *ps8640_bridge_get_edid(struct 
drm_bridge *bridge,
 * before, return the chip to its original power state.
 */
if (poweroff)
-   drm_bridge_chain_post_disable(bridge);
+   drm_atomic_bridge_chain_post_disable(bridge, 
connector->state->state);
 
return edid;
 }
@@ -579,8 +582,11 @@ static const struct drm_bridge_funcs ps8640_bridge_funcs = 
{
.attach = ps8640_bridge_attach,
.detach = ps8640_bridge_detach,
.get_edid = ps8640_bridge_get_edid,
-   .post_disable = ps8640_post_disable,
-   .pre_enable = ps8640_pre_enable,
+   .atomic_post_disable = ps8640_atomic_post_disable,
+   .atomic_pre_enable = ps8640_atomic_pre_enable,
+   .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
+   .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
+   .atomic_reset = drm_atomic_helper_bridge_reset,
 };
 
 static int ps8640_bridge_get_dsi_resources(struct device *dev, struct ps8640 
*ps_bridge)
-- 
2.34.1



[PATCH v3 5/5] drm/bridge: Document the expected behaviour of DSI host controllers

2022-12-02 Thread Dave Stevenson
The exact behaviour of DSI host controllers is not specified,
therefore define it.

Signed-off-by: Dave Stevenson 
Reviewed-by: Laurent Pinchart 
---
 Documentation/gpu/drm-kms-helpers.rst |  7 +
 drivers/gpu/drm/drm_bridge.c  | 39 +++
 2 files changed, 46 insertions(+)

diff --git a/Documentation/gpu/drm-kms-helpers.rst 
b/Documentation/gpu/drm-kms-helpers.rst
index a4860ffd6e86..b8ab05e42dbb 100644
--- a/Documentation/gpu/drm-kms-helpers.rst
+++ b/Documentation/gpu/drm-kms-helpers.rst
@@ -188,6 +188,13 @@ Bridge Helper Reference
 .. kernel-doc:: drivers/gpu/drm/drm_bridge.c
:export:
 
+MIPI-DSI bridge operation
+-
+
+.. kernel-doc:: drivers/gpu/drm/drm_bridge.c
+   :doc: dsi bridge operations
+
+
 Bridge Connector Helper Reference
 -
 
diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
index 41051869d6bf..bd73d32f29c0 100644
--- a/drivers/gpu/drm/drm_bridge.c
+++ b/drivers/gpu/drm/drm_bridge.c
@@ -153,6 +153,45 @@
  * situation when probing.
  */
 
+/**
+ * DOC: dsi bridge operations
+ *
+ * DSI host interfaces are expected to be implemented as bridges rather than
+ * encoders, however there are a few aspects of their operation that need to
+ * be defined in order to provide a consistent interface.
+ *
+ * A DSI host should keep the PHY powered down until the pre_enable operation 
is
+ * called. All lanes are in an undefined idle state up to this point, and it
+ * must not be assumed that it is LP-11.
+ * pre_enable should initialise the PHY, set the data lanes to LP-11, and the
+ * clock lane to either LP-11 or HS depending on the mode_flag
+ * %MIPI_DSI_CLOCK_NON_CONTINUOUS.
+ *
+ * Ordinarily the downstream bridge DSI peripheral pre_enable will have been
+ * called before the DSI host. If the DSI peripheral requires LP-11 and/or
+ * the clock lane to be in HS mode prior to pre_enable, then it can set the
+ * _enable_prev_first flag to request the pre_enable (and
+ * post_disable) order to be altered to enable the DSI host first.
+ *
+ * Either the CRTC being enabled, or the DSI host enable operation should 
switch
+ * the host to actively transmitting video on the data lanes.
+ *
+ * The reverse also applies. The DSI host disable operation or stopping the 
CRTC
+ * should stop transmitting video, and the data lanes should return to the 
LP-11
+ * state. The DSI host _disable operation should disable the PHY.
+ * If the _enable_prev_first flag is set, then the DSI peripheral's
+ * bridge _disable will be called before the DSI host's post_disable.
+ *
+ * Whilst it is valid to call _transfer prior to pre_enable or after
+ * post_disable, the exact state of the lanes is undefined at this point. The
+ * DSI host should initialise the interface, transmit the data, and then 
disable
+ * the interface again.
+ *
+ * Ultra Low Power State (ULPS) is not explicitly supported by DRM. If
+ * implemented, it therefore needs to be handled entirely within the DSI Host
+ * driver.
+ */
+
 static DEFINE_MUTEX(bridge_lock);
 static LIST_HEAD(bridge_list);
 
-- 
2.34.1



[PATCH v3 4/5] drm/panel: Add prepare_prev_first flag to drm_panel

2022-12-02 Thread Dave Stevenson
Mapping to the drm_bridge flag pre_enable_prev_first,
add a new flag prepare_prev_first to drm_panel to allow
the panel driver to request that the upstream bridge should
be pre_enabled before the panel prepare.

Signed-off-by: Dave Stevenson 
Reviewed-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/bridge/panel.c |  2 ++
 include/drm/drm_panel.h| 10 ++
 2 files changed, 12 insertions(+)

diff --git a/drivers/gpu/drm/bridge/panel.c b/drivers/gpu/drm/bridge/panel.c
index 216af76d0042..03c3274dc3d9 100644
--- a/drivers/gpu/drm/bridge/panel.c
+++ b/drivers/gpu/drm/bridge/panel.c
@@ -364,6 +364,8 @@ struct drm_bridge *devm_drm_panel_bridge_add_typed(struct 
device *dev,
devres_free(ptr);
}
 
+   bridge->pre_enable_prev_first = panel->prepare_prev_first;
+
return bridge;
 }
 EXPORT_SYMBOL(devm_drm_panel_bridge_add_typed);
diff --git a/include/drm/drm_panel.h b/include/drm/drm_panel.h
index 994bfcdd84c5..432fab2347eb 100644
--- a/include/drm/drm_panel.h
+++ b/include/drm/drm_panel.h
@@ -188,6 +188,16 @@ struct drm_panel {
 * Panel entry in registry.
 */
struct list_head list;
+
+   /**
+* @prepare_prev_first:
+*
+* The previous controller should be prepared first, before the prepare
+* for the panel is called. This is largely required for DSI panels
+* where the DSI host controller should be initialised to LP-11 before
+* the panel is powered up.
+*/
+   bool prepare_prev_first;
 };
 
 void drm_panel_init(struct drm_panel *panel, struct device *dev,
-- 
2.34.1



[PATCH v3 2/5] drm/bridge: Drop unused drm_bridge_chain functions

2022-12-02 Thread Dave Stevenson
From: Sam Ravnborg 

The drm_bridge_chain_{pre_enable,enable,disable,post_disable} has no
users left and we have atomic variants that should be used.
Drop them so they do not gain new users.

Adjust a few comments to avoid references to the dropped functions.

Signed-off-by: Sam Ravnborg 
Reviewed-by: Maxime Ripard 
Reviewed-by: Laurent Pinchart 
Cc: Laurent Pinchart 
Cc: Maarten Lankhorst 
Cc: Maxime Ripard 
Cc: Thomas Zimmermann 
Cc: Andrzej Hajda 
Cc: Neil Armstrong 
Cc: Robert Foss 
Cc: Daniel Vetter 
Signed-off-by: Dave Stevenson 
---
 drivers/gpu/drm/drm_bridge.c | 110 ---
 include/drm/drm_bridge.h |  28 -
 2 files changed, 138 deletions(-)

diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
index 1545c50fd1c8..bb7fc09267af 100644
--- a/drivers/gpu/drm/drm_bridge.c
+++ b/drivers/gpu/drm/drm_bridge.c
@@ -509,61 +509,6 @@ drm_bridge_chain_mode_valid(struct drm_bridge *bridge,
 }
 EXPORT_SYMBOL(drm_bridge_chain_mode_valid);
 
-/**
- * drm_bridge_chain_disable - disables all bridges in the encoder chain
- * @bridge: bridge control structure
- *
- * Calls _bridge_funcs.disable op for all the bridges in the encoder
- * chain, starting from the last bridge to the first. These are called before
- * calling the encoder's prepare op.
- *
- * Note: the bridge passed should be the one closest to the encoder
- */
-void drm_bridge_chain_disable(struct drm_bridge *bridge)
-{
-   struct drm_encoder *encoder;
-   struct drm_bridge *iter;
-
-   if (!bridge)
-   return;
-
-   encoder = bridge->encoder;
-   list_for_each_entry_reverse(iter, >bridge_chain, chain_node) {
-   if (iter->funcs->disable)
-   iter->funcs->disable(iter);
-
-   if (iter == bridge)
-   break;
-   }
-}
-EXPORT_SYMBOL(drm_bridge_chain_disable);
-
-/**
- * drm_bridge_chain_post_disable - cleans up after disabling all bridges in the
- *encoder chain
- * @bridge: bridge control structure
- *
- * Calls _bridge_funcs.post_disable op for all the bridges in the
- * encoder chain, starting from the first bridge to the last. These are called
- * after completing the encoder's prepare op.
- *
- * Note: the bridge passed should be the one closest to the encoder
- */
-void drm_bridge_chain_post_disable(struct drm_bridge *bridge)
-{
-   struct drm_encoder *encoder;
-
-   if (!bridge)
-   return;
-
-   encoder = bridge->encoder;
-   list_for_each_entry_from(bridge, >bridge_chain, chain_node) {
-   if (bridge->funcs->post_disable)
-   bridge->funcs->post_disable(bridge);
-   }
-}
-EXPORT_SYMBOL(drm_bridge_chain_post_disable);
-
 /**
  * drm_bridge_chain_mode_set - set proposed mode for all bridges in the
  *encoder chain
@@ -593,61 +538,6 @@ void drm_bridge_chain_mode_set(struct drm_bridge *bridge,
 }
 EXPORT_SYMBOL(drm_bridge_chain_mode_set);
 
-/**
- * drm_bridge_chain_pre_enable - prepares for enabling all bridges in the
- *  encoder chain
- * @bridge: bridge control structure
- *
- * Calls _bridge_funcs.pre_enable op for all the bridges in the encoder
- * chain, starting from the last bridge to the first. These are called
- * before calling the encoder's commit op.
- *
- * Note: the bridge passed should be the one closest to the encoder
- */
-void drm_bridge_chain_pre_enable(struct drm_bridge *bridge)
-{
-   struct drm_encoder *encoder;
-   struct drm_bridge *iter;
-
-   if (!bridge)
-   return;
-
-   encoder = bridge->encoder;
-   list_for_each_entry_reverse(iter, >bridge_chain, chain_node) {
-   if (iter->funcs->pre_enable)
-   iter->funcs->pre_enable(iter);
-
-   if (iter == bridge)
-   break;
-   }
-}
-EXPORT_SYMBOL(drm_bridge_chain_pre_enable);
-
-/**
- * drm_bridge_chain_enable - enables all bridges in the encoder chain
- * @bridge: bridge control structure
- *
- * Calls _bridge_funcs.enable op for all the bridges in the encoder
- * chain, starting from the first bridge to the last. These are called
- * after completing the encoder's commit op.
- *
- * Note that the bridge passed should be the one closest to the encoder
- */
-void drm_bridge_chain_enable(struct drm_bridge *bridge)
-{
-   struct drm_encoder *encoder;
-
-   if (!bridge)
-   return;
-
-   encoder = bridge->encoder;
-   list_for_each_entry_from(bridge, >bridge_chain, chain_node) {
-   if (bridge->funcs->enable)
-   bridge->funcs->enable(bridge);
-   }
-}
-EXPORT_SYMBOL(drm_bridge_chain_enable);
-
 /**
  * drm_atomic_bridge_chain_disable - disables all bridges in the encoder chain
  * @bridge: bridge control structure
diff --git a/include/drm/

[PATCH v3 3/5] drm/bridge: Introduce pre_enable_prev_first to alter bridge init order

2022-12-02 Thread Dave Stevenson
DSI sink devices typically want the DSI host powered up and configured
before they are powered up. pre_enable is the place this would normally
happen, but they are called in reverse order from panel/connector towards
the encoder, which is the "wrong" order.

Add a new flag pre_enable_prev_first that any bridge can set
to swap the order of pre_enable (and post_disable) for that and the
immediately previous bridge.
Should the immediately previous bridge also set the
pre_enable_prev_first flag, the previous bridge to that will be called
before either of those which requested pre_enable_prev_first.

eg:
- Panel
- Bridge 1
- Bridge 2 pre_enable_prev_first
- Bridge 3
- Bridge 4 pre_enable_prev_first
- Bridge 5 pre_enable_prev_first
- Bridge 6
- Encoder
Would result in pre_enable's being called as Panel, Bridge 1, Bridge 3,
Bridge 2, Bridge 6, Bridge 5, Bridge 4, Encoder.

Signed-off-by: Dave Stevenson 
---
 drivers/gpu/drm/drm_bridge.c | 144 +--
 include/drm/drm_bridge.h |   8 ++
 2 files changed, 128 insertions(+), 24 deletions(-)

diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
index bb7fc09267af..41051869d6bf 100644
--- a/drivers/gpu/drm/drm_bridge.c
+++ b/drivers/gpu/drm/drm_bridge.c
@@ -581,6 +581,25 @@ void drm_atomic_bridge_chain_disable(struct drm_bridge 
*bridge,
 }
 EXPORT_SYMBOL(drm_atomic_bridge_chain_disable);
 
+static void drm_atomic_bridge_call_post_disable(struct drm_bridge *bridge,
+   struct drm_atomic_state 
*old_state)
+{
+   if (old_state && bridge->funcs->atomic_post_disable) {
+   struct drm_bridge_state *old_bridge_state;
+
+   old_bridge_state =
+   drm_atomic_get_old_bridge_state(old_state,
+   bridge);
+   if (WARN_ON(!old_bridge_state))
+   return;
+
+   bridge->funcs->atomic_post_disable(bridge,
+  old_bridge_state);
+   } else if (bridge->funcs->post_disable) {
+   bridge->funcs->post_disable(bridge);
+   }
+}
+
 /**
  * drm_atomic_bridge_chain_post_disable - cleans up after disabling all bridges
  *   in the encoder chain
@@ -592,36 +611,85 @@ EXPORT_SYMBOL(drm_atomic_bridge_chain_disable);
  * starting from the first bridge to the last. These are called after 
completing
  * _encoder_helper_funcs.atomic_disable
  *
+ * If a bridge sets @pre_enable_prev_first, then the @post_disable for that
+ * bridge will be called before the previous one to reverse the @pre_enable
+ * calling direction.
+ *
  * Note: the bridge passed should be the one closest to the encoder
  */
 void drm_atomic_bridge_chain_post_disable(struct drm_bridge *bridge,
  struct drm_atomic_state *old_state)
 {
struct drm_encoder *encoder;
+   struct drm_bridge *next, *limit;
 
if (!bridge)
return;
 
encoder = bridge->encoder;
+
list_for_each_entry_from(bridge, >bridge_chain, chain_node) {
-   if (bridge->funcs->atomic_post_disable) {
-   struct drm_bridge_state *old_bridge_state;
+   limit = NULL;
+
+   if (!list_is_last(>chain_node, >bridge_chain)) 
{
+   next = list_next_entry(bridge, chain_node);
+
+   if (next->pre_enable_prev_first) {
+   /* next bridge had requested that prev
+* was enabled first, so disabled last
+*/
+   limit = next;
+
+   /* Find the next bridge that has NOT requested
+* prev to be enabled first / disabled last
+*/
+   list_for_each_entry_from(next, 
>bridge_chain,
+chain_node) {
+   if (next->pre_enable_prev_first) {
+   next = list_prev_entry(next, 
chain_node);
+   limit = next;
+   break;
+   }
+   }
+
+   /* Call these bridges in reverse order */
+   list_for_each_entry_from_reverse(next, 
>bridge_chain,
+chain_node) {
+   if (next == bridge)
+   break;
+
+   
drm_atomic_bridge_call_post_disable(next,
+ 

[PATCH v3 0/5] DSI host and peripheral initialisation ordering

2022-12-02 Thread Dave Stevenson
Hi All

Changes from v2 (sorry it's taken me a while to get around to these):
- Added Sam's patches to drop drm_bridge_chain functions
- Renamed upstream to previously (Sam)
- Moved copying of panel->prepare_prev_first to bridge->pre_enable_prev_first
  from drm_panel_bridge_add_typed to devm_drm_panel_bridge_add_typed (Jagan)

Changes from v1:
- New patch to refactor drm_bridge_chain_post_disable and 
drm_bridge_chain_pre_enable
  to reuse drm_atomic_bridge_chain_post_disable / 
drm_atomic_bridge_chain_pre_enable
  but with a NULL state.
- New patch that adds a pre_enable_upstream_first to drm_panel.
- changed from an OPS flag to a bool "pre_enable_upstream_first" in drm_bridge.
- Followed Andrzej's suggestion of using continue in the main loop to avoid
  needing 2 additional loops (one forward to find the last bridge wanting
  upstream first, and the second backwards again).
- Actioned Laurent's review comments on docs patch.

Original cover letter:

Hopefully I've cc'ed all those that have bashed this problem around previously,
or are otherwise linked to DRM bridges.

There have been numerous discussions around how DSI support is currently broken
as it doesn't support initialising the PHY to LP-11 and potentially the clock
lane to HS prior to configuring the DSI peripheral. There is no op where the
interface is initialised but HS video isn't also being sent.
Currently you have:
- peripheral pre_enable (host not initialised yet)
- host pre_enable
- encoder enable
- host enable
- peripheral enable (video already running)

vc4 and exynos currently implement the DSI host as an encoder, and split the
bridge_chain. This fails if you want to switch to being a bridge and/or use
atomic calls as the state of all the elements split off are not added by
drm_atomic_add_encoder_bridges.

dw-mipi-dsi[1] and now msm[2] use the mode_set hook to initialise the PHY, so
the bridge/panel pre_enable can send commands. In their post_disable they then
call the downstream bridge/panel post_disable op manually so that shutdown
commands can be sent before shutting down the PHY. Nothing handles that fact,
so the framework then continues down the bridge chain and calls the post_disable
again, so we get unbalanced panel prepare/unprepare calls being reported [3].

There have been patches[4] proposing reversing the entire direction of
pre_enable and post_disable, but that risks driving voltage into devices that
have yet to be powered up.
There have been discussions about adding either a pre_pre_enable, or adding a
DSI host_op to initialise the host[5]. Both require significant reworking to all
existing drivers in moving initialisation phases.
We have patches that look like they may well be addressing race conditions in
starting up a DSI peripheral[6].

This patch takes a hybrid of the two: an optional reversing of the order for
specific links within the bridge chain within pre_enable and post_disable done
within the drm_bridge framework.
I'm more than happy to move where the flag exists in structures (currently as
DRM_BRIDGE_OP_UPSTREAM_FIRST in drm_bridge_ops, but it isn't an op), but does
this solve the problem posed? If not, then can you describe the actual scenario
it doesn't cover?
A DSI peripheral can set the flag to get the DSI host initialised first, and
therefore it has a stable LP-11 state before pre_enable. Likewise the peripheral
can still send shutdown commands prior to the DSI host being shut down in
post_disable. It also handles the case where there are multiple devices in the
chain that all want their upstream bridge enabled first, so should there be a
DSI mux between host and peripheral, then it can still get the host to the
correct state.

An example tree is at [7] which is drm-misc-next with these patches and then a
conversion of vc4_dsi to use the atomic bridge functions (will be upstreamed
once we're over this hurdle). It is working happily with the Toshiba TC358762 on
a Raspberry Pi 7" panel.
The same approach but on our vendor 5.15 tree[8] has also been tested
successfully on a TI SN65DSI83 and LVDS panel.

Whilst here, I've also documented the expected behaviour of DSI hosts and
peripherals to aid those who come along after.

Thanks
  Dave

[1] 
https://github.com/torvalds/linux/blob/master/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c#L940
[2] https://lists.freedesktop.org/archives/dri-devel/2022-January/337769.html
[3] https://lists.freedesktop.org/archives/dri-devel/2021-December/333908.html
[4] https://lists.freedesktop.org/archives/dri-devel/2021-October/328476.html
[5] https://lists.freedesktop.org/archives/dri-devel/2021-October/325853.html
[6] https://lists.freedesktop.org/archives/dri-devel/2022-February/341852.html
[7] https://github.com/6by9/linux/tree/drm-misc-next-vc4_dsi
[8] https://github.com/6by9/linux/tree/rpi-5.15.y-sn65dsi83

Dave Stevenson (3):
  drm/bridge: Introduce pre_enable_prev_first to alter bridge init order
  drm/panel: Add prepare_prev_first flag to d

Re: [PATCH v2 01/11] pwm: Make .get_state() callback return an error code

2022-12-01 Thread Dave Stevenson
channel = >channels[pwm->hwpwm];
> channel_data = _pwm_per_channel_data[pwm->hwpwm];
> @@ -357,6 +357,8 @@ static void meson_pwm_get_state(struct pwm_chip *chip, 
> struct pwm_device *pwm,
> state->period = 0;
> state->duty_cycle = 0;
> }
> +
> +   return 0;
>  }
>
>  static const struct pwm_ops meson_pwm_ops = {
> diff --git a/drivers/pwm/pwm-mtk-disp.c b/drivers/pwm/pwm-mtk-disp.c
> index c605013e4114..9a6bb334a31b 100644
> --- a/drivers/pwm/pwm-mtk-disp.c
> +++ b/drivers/pwm/pwm-mtk-disp.c
> @@ -172,9 +172,9 @@ static int mtk_disp_pwm_apply(struct pwm_chip *chip, 
> struct pwm_device *pwm,
> return 0;
>  }
>
> -static void mtk_disp_pwm_get_state(struct pwm_chip *chip,
> -  struct pwm_device *pwm,
> -  struct pwm_state *state)
> +static int mtk_disp_pwm_get_state(struct pwm_chip *chip,
> + struct pwm_device *pwm,
> + struct pwm_state *state)
>  {
> struct mtk_disp_pwm *mdp = to_mtk_disp_pwm(chip);
> u64 rate, period, high_width;
> @@ -184,14 +184,14 @@ static void mtk_disp_pwm_get_state(struct pwm_chip 
> *chip,
> err = clk_prepare_enable(mdp->clk_main);
> if (err < 0) {
> dev_err(chip->dev, "Can't enable mdp->clk_main: %pe\n", 
> ERR_PTR(err));
> -   return;
> +   return 0;
> }
>
> err = clk_prepare_enable(mdp->clk_mm);
> if (err < 0) {
> dev_err(chip->dev, "Can't enable mdp->clk_mm: %pe\n", 
> ERR_PTR(err));
> clk_disable_unprepare(mdp->clk_main);
> -   return;
> +   return 0;
> }
>
> rate = clk_get_rate(mdp->clk_main);
> @@ -211,6 +211,8 @@ static void mtk_disp_pwm_get_state(struct pwm_chip *chip,
> state->polarity = PWM_POLARITY_NORMAL;
> clk_disable_unprepare(mdp->clk_mm);
> clk_disable_unprepare(mdp->clk_main);
> +
> +   return 0;
>  }
>
>  static const struct pwm_ops mtk_disp_pwm_ops = {
> diff --git a/drivers/pwm/pwm-pca9685.c b/drivers/pwm/pwm-pca9685.c
> index f230c10d28bb..41be244e7dd3 100644
> --- a/drivers/pwm/pwm-pca9685.c
> +++ b/drivers/pwm/pwm-pca9685.c
> @@ -431,8 +431,8 @@ static int pca9685_pwm_apply(struct pwm_chip *chip, 
> struct pwm_device *pwm,
> return ret;
>  }
>
> -static void pca9685_pwm_get_state(struct pwm_chip *chip, struct pwm_device 
> *pwm,
> - struct pwm_state *state)
> +static int pca9685_pwm_get_state(struct pwm_chip *chip, struct pwm_device 
> *pwm,
> +struct pwm_state *state)
>  {
> struct pca9685 *pca = to_pca(chip);
> unsigned long long duty;
> @@ -458,12 +458,14 @@ static void pca9685_pwm_get_state(struct pwm_chip 
> *chip, struct pwm_device *pwm,
>  */
> state->duty_cycle = 0;
> state->enabled = false;
> -   return;
> +   return 0;
> }
>
> state->enabled = true;
> duty = pca9685_pwm_get_duty(pca, pwm->hwpwm);
> state->duty_cycle = DIV_ROUND_DOWN_ULL(duty * state->period, 
> PCA9685_COUNTER_RANGE);
> +
> +   return 0;
>  }
>
>  static int pca9685_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
> diff --git a/drivers/pwm/pwm-raspberrypi-poe.c 
> b/drivers/pwm/pwm-raspberrypi-poe.c
> index 6ff73029f367..2939b71a7ba7 100644
> --- a/drivers/pwm/pwm-raspberrypi-poe.c
> +++ b/drivers/pwm/pwm-raspberrypi-poe.c
> @@ -82,9 +82,9 @@ static int raspberrypi_pwm_get_property(struct rpi_firmware 
> *firmware,
> return 0;
>  }
>
> -static void raspberrypi_pwm_get_state(struct pwm_chip *chip,
> - struct pwm_device *pwm,
> - struct pwm_state *state)
> +static int raspberrypi_pwm_get_state(struct pwm_chip *chip,
> +struct pwm_device *pwm,
> +struct pwm_state *state)
>  {
> struct raspberrypi_pwm *rpipwm = raspberrypi_pwm_from_chip(chip);
>
> @@ -93,6 +93,8 @@ static void raspberrypi_pwm_get_state(struct pwm_chip *chip,
>  RPI_PWM_MAX_DUTY);
> state->enabled = !!(rpipwm->duty_cycle);
> state->polarity = PWM_POLARITY_NORMAL;
> +
> +   return 0;
>  }
>
>  static int raspberrypi_pwm_apply(struct pwm_chip *chip, struct pwm_device 

Re: [PATCH] drm/vc4: Fix NULL pointer access in vc4_platform_drm_probe()

2022-11-21 Thread Dave Stevenson
Hi Lino

On Sun, 20 Nov 2022 at 15:26, Lino Sanfilippo  wrote:
>
> From: Lino Sanfilippo 
>
> In vc4_platform_drm_probe() function vc4_match_add_drivers() is called to
> find component matches for the component drivers. If no such match is found
> the passed variable "match" is still NULL after the function returns.

This would imply a very strange device tree that has bothered to add
the drm device but none of the devices that are required to run the
DRM pipeline, but avoiding a NULL deref is certainly preferable.

> Do not pass "match" to component_master_add_with_match() in this case since
> this results in a NULL pointer access as soon as match->num is used to
> allocate a component_match array. Instead return with -ENODEV from the
> drivers probe function.
>
> Fixes: c8b75bca92cb ("drm/vc4: Add KMS support for Raspberry Pi.")
> Cc: sta...@vger.kernel.org
> Signed-off-by: Lino Sanfilippo 

Acked-by: Dave Stevenson 

> ---
>  drivers/gpu/drm/vc4/vc4_drv.c | 3 +++
>  1 file changed, 3 insertions(+)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c
> index 2027063fdc30..2e53d7f8ad44 100644
> --- a/drivers/gpu/drm/vc4/vc4_drv.c
> +++ b/drivers/gpu/drm/vc4/vc4_drv.c
> @@ -437,6 +437,9 @@ static int vc4_platform_drm_probe(struct platform_device 
> *pdev)
> vc4_match_add_drivers(dev, ,
>   component_drivers, 
> ARRAY_SIZE(component_drivers));
>
> +   if (!match)
> +   return -ENODEV;
> +
> return component_master_add_with_match(dev, _drm_ops, match);
>  }
>
>
> base-commit: 30a0b95b1335e12efef89dd78518ed3e4a71a763
> --
> 2.36.1
>


Re: The state of Quantization Range handling

2022-11-18 Thread Dave Stevenson
Hi Pekka

On Fri, 18 Nov 2022 at 10:15, Pekka Paalanen  wrote:
>
> On Thu, 17 Nov 2022 22:13:26 +0100
> Sebastian Wick  wrote:
>
> > Hi Dave,
> >
> > I noticed that I didn't get the Broadcast RGB property thanks to you
> > (more below)
> >
> > On Tue, Nov 15, 2022 at 2:16 PM Dave Stevenson
> >  wrote:
> > >
> > > Hi Sebastian
> > >
> > > Thanks for starting the conversation - it's stalled a number of times
> > > previously.
> > >
> > > On Mon, 14 Nov 2022 at 23:12, Sebastian Wick  
> > > wrote:
> > > >
> > > > There are still regular bug reports about monitors (sinks) and sources
> > > > disagreeing about the quantization range of the pixel data. In
> > > > particular sources sending full range data when the sink expects
> > > > limited range. From a user space perspective, this is all hidden in
> > > > the kernel. We send full range data to the kernel and then hope it
> > > > does the right thing but as the bug reports show: some combinations of
> > > > displays and drivers result in problems.
> > >
> > > I'll agree that we as Raspberry Pi also get a number of bug reports
> > > where sinks don't always look at the infoframes and misinterpret the
> > > data.
> > >
> > > > In general the whole handling of the quantization range on linux is
> > > > not defined or documented at all. User space sends full range data
> > > > because that's what seems to work most of the time but technically
> > > > this is all undefined and user space can not fix those issues. Some
> > > > compositors have resorted to giving users the option to choose the
> > > > quantization range but this really should only be necessary for
> > > > straight up broken hardware.
> > >
> > > Wowsers! Making userspace worry about limited range data would be a
> > > very weird decision in my view, so compositors should always deal in
> > > full range data.
> >
> > Making this a user space problem is IMO the ideal way to deal with it
> > but that's a bit harder to do (I'll answer that in the reply to
> > Pekka). So let's just assume we all agree that user space only deals
> > with full range data.
>
> Limited range was invented for some reason, so it must have some use
> somewhere, at least in the past. Maybe it was needed to calibrate mixed
> digital/analog video processing chains with test images that needed to
> contain sub-blacks and super-whites, to make sure that sub-blacks come
> out as the nominal black etc. Just because desktop computers do not
> seem to have any need for limited range, I personally wouldn't be as
> arrogant as to say it's never useful. Maybe there are professional
> video/broadcasting needs that currently can only be realized with
> proprietary OS/hardware, because Linux just can't do it today?
>
> Why would TVs support limited range, if it was never useful? Why would
> video sources produce limited range if it was always strictly inferior
> to full range?
>
> Even digital image processing algorithms might make use of
> out-of-unit-range values, not just analog circuitry for overshoot.
>
> But no, I can't give a real example, just speculation. Hence it's fine
> by me to discard limited range processing for now. Still, what I
> explain below would allow limited range processing without any extra
> complexity by making the KMS color pipeline better defined and less
> limiting for userspace.

AIUI limited range comes from the analogue world, or possibly creative
(film/TV) world, hence being used on Consumer devices rather than IT
ones (CTA and CEA modes vs VESA and DMT modes).

YCbCr output from video codecs typically uses a range of 16-235,
therefore a media player wanting to pass the decoded video out to the
display exactly as-is needs to be able to signal that to the display
for it to be interpreted correctly.
HDMI extended DVI. I believe both YCbCr support and range control were
added to the HDMI spec at the same time, presumably to allow for this
use case. Limited range RGB seems to be a bit of a quirk though.

Just to be annoying, JPEG uses full range YCbCr.

> > > How would composition of multiple DRM planes work if some are limited
> > > range and some are full but you want limited range output? Your
> > > hardware needs to have CSC matrices to convert full range down to
> > > limited range, and know that you want to use them to effectively
> > > compose to limited range.
> > > In fact you can't currently tell DRM that an RGB plane is limited
> > > range - the values in enum dr

Re: [PATCH V2 0/3] DSI host and peripheral initialisation ordering

2022-11-15 Thread Dave Stevenson
Hi Dmitry

On Tue, 15 Nov 2022 at 14:21, Dmitry Baryshkov
 wrote:
>
> On 15/11/2022 17:14, Dave Stevenson wrote:
> > Hi Dmitry
> >
> > On Sun, 13 Nov 2022 at 13:06, Dmitry Baryshkov
> >  wrote:
> >>
> >> Hi Dave,
> >>
> >> On 19/07/2022 16:45, Dave Stevenson wrote:
> >>> Hi Sam
> >>>
> >>> On Mon, 18 Jul 2022 at 21:52, Sam Ravnborg  wrote:
> >>>>
> >>>> Hi Dave,
> >>>>
> >>>> a long overdue reply on this series.
> >>>>
> >>>> On Fri, Mar 04, 2022 at 03:17:55PM +, Dave Stevenson wrote:
> >>>>> Hi All
> >>>>>
> >>>>> Changes from v1:
> >>>>> - New patch to refactor drm_bridge_chain_post_disable and 
> >>>>> drm_bridge_chain_pre_enable
> >>>>> to reuse drm_atomic_bridge_chain_post_disable / 
> >>>>> drm_atomic_bridge_chain_pre_enable
> >>>>> but with a NULL state.
> >>>>> - New patch that adds a pre_enable_upstream_first to drm_panel.
> >>>>> - changed from an OPS flag to a bool "pre_enable_upstream_first" in 
> >>>>> drm_bridge.
> >>>>> - Followed Andrzej's suggestion of using continue in the main loop to 
> >>>>> avoid
> >>>>> needing 2 additional loops (one forward to find the last bridge 
> >>>>> wanting
> >>>>> upstream first, and the second backwards again).
> >>>>> - Actioned Laurent's review comments on docs patch.
> >>>>>
> >>>>> Original cover letter:
> >>>>>
> >>>>> Hopefully I've cc'ed all those that have bashed this problem around 
> >>>>> previously,
> >>>>> or are otherwise linked to DRM bridges.
> >>>>>
> >>>>> There have been numerous discussions around how DSI support is 
> >>>>> currently broken
> >>>>> as it doesn't support initialising the PHY to LP-11 and potentially the 
> >>>>> clock
> >>>>> lane to HS prior to configuring the DSI peripheral. There is no op 
> >>>>> where the
> >>>>> interface is initialised but HS video isn't also being sent.
> >>>>> Currently you have:
> >>>>> - peripheral pre_enable (host not initialised yet)
> >>>>> - host pre_enable
> >>>>> - encoder enable
> >>>>> - host enable
> >>>>> - peripheral enable (video already running)
> >>>>>
> >>>>> vc4 and exynos currently implement the DSI host as an encoder, and 
> >>>>> split the
> >>>>> bridge_chain. This fails if you want to switch to being a bridge and/or 
> >>>>> use
> >>>>> atomic calls as the state of all the elements split off are not added by
> >>>>> drm_atomic_add_encoder_bridges.
> >>>>
> >>>> A typically chain looks like this:
> >>>>
> >>>> CRTC => Encoder => Bridge A => Bridge B
> >>>>
> >>>> We have in DRM bridges established what is the "next" bridge - indicated
> >>>> with the direction of the arrows in the drawing.
> >>>>
> >>>> This set of patches introduces the concept of "upstream" bridges.
> >>>>
> >>>> pre_enable_prev_bridge_first would be easier to understand as it uses
> >>>> the current terminology.
> >>>> I get that "upstream" is used in the DSI specification - but we are
> >>>> dealing with bridges that happens to support DSI and more, and mixing
> >>>> the two terminologies is not good.
> >>>>
> >>>> Note: Upstream is also used in a bridge doc section - here it should
> >>>> most likely be updated too.
> >>>
> >>> Sure, I have no issues with switching to prev/next from 
> >>> upstream/downstream.
> >>> To the outsider it can be confusing - in pre_enable and disable, the
> >>> next bridge to be called is the previous one. At least it is
> >>> documented.
> >>>
> >>>> The current approach set a flag that magically makes the core do 
> >>>> something
> >>>> else. Have you considered a much more explicit approach?
> >>>>
> >>>> 

Re: [PATCH V2 0/3] DSI host and peripheral initialisation ordering

2022-11-15 Thread Dave Stevenson
Hi Dmitry

On Sun, 13 Nov 2022 at 13:06, Dmitry Baryshkov
 wrote:
>
> Hi Dave,
>
> On 19/07/2022 16:45, Dave Stevenson wrote:
> > Hi Sam
> >
> > On Mon, 18 Jul 2022 at 21:52, Sam Ravnborg  wrote:
> >>
> >> Hi Dave,
> >>
> >> a long overdue reply on this series.
> >>
> >> On Fri, Mar 04, 2022 at 03:17:55PM +, Dave Stevenson wrote:
> >>> Hi All
> >>>
> >>> Changes from v1:
> >>> - New patch to refactor drm_bridge_chain_post_disable and 
> >>> drm_bridge_chain_pre_enable
> >>>to reuse drm_atomic_bridge_chain_post_disable / 
> >>> drm_atomic_bridge_chain_pre_enable
> >>>but with a NULL state.
> >>> - New patch that adds a pre_enable_upstream_first to drm_panel.
> >>> - changed from an OPS flag to a bool "pre_enable_upstream_first" in 
> >>> drm_bridge.
> >>> - Followed Andrzej's suggestion of using continue in the main loop to 
> >>> avoid
> >>>needing 2 additional loops (one forward to find the last bridge wanting
> >>>upstream first, and the second backwards again).
> >>> - Actioned Laurent's review comments on docs patch.
> >>>
> >>> Original cover letter:
> >>>
> >>> Hopefully I've cc'ed all those that have bashed this problem around 
> >>> previously,
> >>> or are otherwise linked to DRM bridges.
> >>>
> >>> There have been numerous discussions around how DSI support is currently 
> >>> broken
> >>> as it doesn't support initialising the PHY to LP-11 and potentially the 
> >>> clock
> >>> lane to HS prior to configuring the DSI peripheral. There is no op where 
> >>> the
> >>> interface is initialised but HS video isn't also being sent.
> >>> Currently you have:
> >>> - peripheral pre_enable (host not initialised yet)
> >>> - host pre_enable
> >>> - encoder enable
> >>> - host enable
> >>> - peripheral enable (video already running)
> >>>
> >>> vc4 and exynos currently implement the DSI host as an encoder, and split 
> >>> the
> >>> bridge_chain. This fails if you want to switch to being a bridge and/or 
> >>> use
> >>> atomic calls as the state of all the elements split off are not added by
> >>> drm_atomic_add_encoder_bridges.
> >>
> >> A typically chain looks like this:
> >>
> >> CRTC => Encoder => Bridge A => Bridge B
> >>
> >> We have in DRM bridges established what is the "next" bridge - indicated
> >> with the direction of the arrows in the drawing.
> >>
> >> This set of patches introduces the concept of "upstream" bridges.
> >>
> >> pre_enable_prev_bridge_first would be easier to understand as it uses
> >> the current terminology.
> >> I get that "upstream" is used in the DSI specification - but we are
> >> dealing with bridges that happens to support DSI and more, and mixing
> >> the two terminologies is not good.
> >>
> >> Note: Upstream is also used in a bridge doc section - here it should
> >>most likely be updated too.
> >
> > Sure, I have no issues with switching to prev/next from upstream/downstream.
> > To the outsider it can be confusing - in pre_enable and disable, the
> > next bridge to be called is the previous one. At least it is
> > documented.
> >
> >> The current approach set a flag that magically makes the core do something
> >> else. Have you considered a much more explicit approach?
> >>
> >> A few helpers like:
> >>
> >>  drm_bridge_pre_enable_prev_bridge()
> >>  drm_bridge_enable_prev_bridge()
> >>  drm_bridge_disable_prev_bridge()
> >>  drm_bridge_post_disable_prev_bridge()
> >
> > No point in drm_bridge_enable_prev_bridge() and
> > drm_bridge_post_disable_prev_bridge() as the call order down the chain
> > will mean that they have already been called.
> > drm_bridge_enable_next_bridge() and
> > drm_bridge_post_disable_next_bridge() possibly.
> >
> >> And then update the core so the relevant function is only called once
> >> for a bridge.
> >> Then the need for DSI lanes in LP-11 can be archived by a call to
> >>
> >>  drm_bridge_pre_enable_prev_bridge()
> >
> > Unfortunately it gets ugly with post_

Re: The state of Quantization Range handling

2022-11-15 Thread Dave Stevenson
Hi Sebastian

Thanks for starting the conversation - it's stalled a number of times
previously.

On Mon, 14 Nov 2022 at 23:12, Sebastian Wick  wrote:
>
> There are still regular bug reports about monitors (sinks) and sources
> disagreeing about the quantization range of the pixel data. In
> particular sources sending full range data when the sink expects
> limited range. From a user space perspective, this is all hidden in
> the kernel. We send full range data to the kernel and then hope it
> does the right thing but as the bug reports show: some combinations of
> displays and drivers result in problems.

I'll agree that we as Raspberry Pi also get a number of bug reports
where sinks don't always look at the infoframes and misinterpret the
data.

> In general the whole handling of the quantization range on linux is
> not defined or documented at all. User space sends full range data
> because that's what seems to work most of the time but technically
> this is all undefined and user space can not fix those issues. Some
> compositors have resorted to giving users the option to choose the
> quantization range but this really should only be necessary for
> straight up broken hardware.

Wowsers! Making userspace worry about limited range data would be a
very weird decision in my view, so compositors should always deal in
full range data.

How would composition of multiple DRM planes work if some are limited
range and some are full but you want limited range output? Your
hardware needs to have CSC matrices to convert full range down to
limited range, and know that you want to use them to effectively
compose to limited range.
In fact you can't currently tell DRM that an RGB plane is limited
range - the values in enum drm_color_range are
DRM_COLOR_YCBCR_LIMITED_RANGE and DRM_COLOR_YCBCR_FULL_RANGE [1].

> Quantization Range can be explicitly controlled by AVI InfoFrame or
> HDMI General Control Packets. This is the ideal case and when the
> source uses them there is not a lot that can go wrong. Not all
> displays support those explicit controls in which case the chosen
> video format (IT, CE, SD; details in CTA-861-H 5.1) influences which
> quantization range the sink expects.
>
> This means that we have to expect that sometimes we have to send
> limited and sometimes full range content. The big question however
> that is not answered in the docs: who is responsible for making sure
> the data is in the correct range? Is it the kernel or user space?
>
> If it's the kernel: does user space supply full range or limited range
> content? Each of those has a disadvantage. If we send full range
> content and the driver scales it down to limited range, we can't use
> the out-of-range bits to transfer information. If we send limited
> range content and the driver scales it up we lose information.

How often have you encountered the out-of-range bits being used?
Personally I've never come across it. Is it really that common?
If trying to pass non-video data from the client then you need to pray
there is no scaling or filtering during composition as it could
legitimately be corrupted.

> Either way, this must be documented. My suggestion is to say that the
> kernel always expects full range data as input and is responsible for
> scaling it to limited range data if the sink expects limited range
> data.

AIUI That is the current situation. It certainly fits the way that all
our hardware works.

> Another problem is that some displays do not behave correctly. It must
> be possible to override the kernel when the user detects such a
> situation. This override then controls if the driver converts the full
> range data coming from the client or not (Default, Force Limited,
> Force Full). It does not try to control what range the sink expects.

Sorry, I'm not clear from the description. Is this a plane, crtc, or
connector property?

"Data coming from the client" would imply a plane property only -
effectively extending enum drm_color_range for RGB formats.

If it is a connector property then what do you mean by not controlling
the range? It doesn't change the AVI Infoframe or GCP and leaves the
sink thinking it is the default? If so, doesn't that mean this control
can now make a compliant sink incorrectly render the data? Assuming
the driver is using drm_hdmi_avi_infoframe_quant_range [2], then the
sink is likely to be told explicitly that it is one value which is
then actually wrong.


Or is this a flag to tell the crtc to compose all planes to a limited
range output, thereby updating all the CSC matrices used for RGB and
YCbCr planes? There's still no guarantee that the composition won't
clip the video to the specified output range thereby losing the out of
range values you carefully crafted.

> Let's call this the Quantization Range Override property which should
> be implemented by all drivers.
>
> All drivers should make sure their behavior is correct:
>
> * check that drivers choose the correct default quantization range 

Re: [PATCH] drm/panel/raspberrypi-touchscreen: Fix error handling in rpi_touchscreen_init()

2022-11-14 Thread Dave Stevenson
Hi Yuan

On Mon, 14 Nov 2022 at 08:21, Yuan Can  wrote:
>
> A problem about modprobe panel-raspberrypi-touchscreen is triggered with
> the following log given:
>
>  [  542.980748] Error: Driver 'rpi-ts-dsi' is already registered, aborting...
>
> And with this log printed, the panel_raspberrypi_touchscreen is listed by
> lsmod, rmmod on it can trigger the WARN of "Unexpected driver unregister".
>
> The reason is that the return value of mipi_dsi_driver_register() and
> i2c_add_driver() is not checked in rpi_touchscreen_init(), if
> i2c_add_driver() failed, the rpi_touchscreen_dsi_driver is never
> unregistered, and next time when install this module, the
> mipi_dsi_driver_register() is failed but rpi_touchscreen_init() returns 0,
> leading to the panel_raspberrypi_touchscreen listed by lsmod.
>
> Call graph of modprobe panel-raspberrypi-touchscreen at the first time:
>  rpi_touchscreen_init()
>mipi_dsi_driver_register() # register rpi_touchscreen_dsi_driver
>i2c_add_driver()
>  driver_register()
>bus_add_driver()
>  priv = kzalloc(...) # OOM happened
>  # return without unregister rpi_touchscreen_dsi_driver
>
> Call graph of retrying modprobe panel-raspberrypi-touchscreen:
>  rpi_touchscreen_init()
>mipi_dsi_driver_register() # Error message printed, register failed!
>i2c_add_driver() # succeed and return
>
> Fix by checking the return value of both functions and unregister
> rpi_touchscreen_dsi_driver if i2c_add_driver() failed.
>
> Fixes: 2f733d6194bd ("drm/panel: Add support for the Raspberry Pi 7" 
> Touchscreen.")
> Signed-off-by: Yuan Can 

Acked-by: Dave Stevenson 

I would strongly recommend that you look at switching to the tc358762
bridge, panel-simple, and the rpi-panel-attiny-regulator regulator
driver, rather than this driver.

The raspberrypi-touchscreen driver has no suitable hooks for the
edt-ft5x06 touch driver to register for regulator control. If the
display sleeps then the power is killed to the touch controller but
the touch driver has no knowledge of this. This issue should have been
solved with rpi-panel-attiny / tc358762 / panel-simple.

  Dave

> ---
>  .../gpu/drm/panel/panel-raspberrypi-touchscreen.c   | 13 +++--
>  1 file changed, 11 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/panel/panel-raspberrypi-touchscreen.c 
> b/drivers/gpu/drm/panel/panel-raspberrypi-touchscreen.c
> index 79f852465a84..9f3d0fedc3f2 100644
> --- a/drivers/gpu/drm/panel/panel-raspberrypi-touchscreen.c
> +++ b/drivers/gpu/drm/panel/panel-raspberrypi-touchscreen.c
> @@ -497,8 +497,17 @@ static struct i2c_driver rpi_touchscreen_driver = {
>
>  static int __init rpi_touchscreen_init(void)
>  {
> -   mipi_dsi_driver_register(_touchscreen_dsi_driver);
> -   return i2c_add_driver(_touchscreen_driver);
> +   int ret;
> +
> +   ret = mipi_dsi_driver_register(_touchscreen_dsi_driver);
> +   if (ret)
> +   return ret;
> +
> +   ret = i2c_add_driver(_touchscreen_driver);
> +   if (ret)
> +   mipi_dsi_driver_unregister(_touchscreen_dsi_driver);
> +
> +   return ret;
>  }
>  module_init(rpi_touchscreen_init);
>
> --
> 2.17.1
>


Re: [PATCH] drm/bridge: sii9234: Remove the unused function sii9234_mode_valid()

2022-11-08 Thread Dave Stevenson
On Fri, 4 Nov 2022 at 06:37, Jiapeng Chong
 wrote:
>
> The function sii9234_mode_valid() is defined in the sii9234.c file, but
> not called elsewhere, so remove this unused function.

Did you mean bridge_to_sii9234() rather than sii9234_mode_valid() here?

sii9234_mode_valid() is referenced in sii9234_bridge_funcs, and it's
bridge_to_sii9234 that you've actually removed.

  Dave

> drivers/gpu/drm/bridge/sii9234.c:870:31: warning: unused function 
> 'bridge_to_sii9234'.
>
> Link: https://bugzilla.openanolis.cn/show_bug.cgi?id=2735
> Reported-by: Abaci Robot 
> Signed-off-by: Jiapeng Chong 
> ---
>  drivers/gpu/drm/bridge/sii9234.c | 5 -
>  1 file changed, 5 deletions(-)
>
> diff --git a/drivers/gpu/drm/bridge/sii9234.c 
> b/drivers/gpu/drm/bridge/sii9234.c
> index 5b3061d4b5c3..62b6bc8ca7af 100644
> --- a/drivers/gpu/drm/bridge/sii9234.c
> +++ b/drivers/gpu/drm/bridge/sii9234.c
> @@ -867,11 +867,6 @@ static int sii9234_init_resources(struct sii9234 *ctx,
> return 0;
>  }
>
> -static inline struct sii9234 *bridge_to_sii9234(struct drm_bridge *bridge)
> -{
> -   return container_of(bridge, struct sii9234, bridge);
> -}
> -
>  static enum drm_mode_status sii9234_mode_valid(struct drm_bridge *bridge,
>  const struct drm_display_info *info,
>  const struct drm_display_mode *mode)
> --
> 2.20.1.7.g153144c
>


Re: [PATCH v5 5/7] drm/vc4: hdmi: Rework hdmi_enable_4kp60 detection code

2022-10-27 Thread Dave Stevenson
On Thu, 27 Oct 2022 at 13:53, Maxime Ripard  wrote:
>
> In order to support higher HDMI frequencies, users have to set the
> hdmi_enable_4kp60 parameter in their config.txt file.
>
> This will have the side-effect of raising the maximum of the core clock,
> tied to the HVS, and managed by the HVS driver.
>
> However, we are querying this in the HDMI driver by poking into the HVS
> structure to get our struct clk handle.
>
> Let's make this part of the HVS bind implementation to have all the core
> clock related setup in the same place.
>
> Signed-off-by: Maxime Ripard 

Thanks for the rename of the variable - pulling scrambling into it
made it confusing.

Reviewed-by: Dave Stevenson 

> ---
>  drivers/gpu/drm/vc4/vc4_drv.h  | 10 ++
>  drivers/gpu/drm/vc4/vc4_hdmi.c | 15 ---
>  drivers/gpu/drm/vc4/vc4_hdmi.h |  8 
>  drivers/gpu/drm/vc4/vc4_hvs.c  | 23 +++
>  4 files changed, 37 insertions(+), 19 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
> index 418a8242691f..8da2b80fdbd3 100644
> --- a/drivers/gpu/drm/vc4/vc4_drv.h
> +++ b/drivers/gpu/drm/vc4/vc4_drv.h
> @@ -326,6 +326,8 @@ struct vc4_hvs {
>
> struct clk *core_clk;
>
> +   unsigned long max_core_rate;
> +
> /* Memory manager for CRTCs to allocate space in the display
>  * list.  Units are dwords.
>  */
> @@ -337,6 +339,14 @@ struct vc4_hvs {
> struct drm_mm_node mitchell_netravali_filter;
>
> struct debugfs_regset32 regset;
> +
> +   /*
> +* Even if HDMI0 on the RPi4 can output modes requiring a pixel
> +* rate higher than 297MHz, it needs some adjustments in the
> +* config.txt file to be able to do so and thus won't always be
> +* available.
> +*/
> +   bool vc5_hdmi_enable_hdmi_20;
>  };
>
>  struct vc4_plane {
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index 3acc1858c55f..98a6643821bb 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -46,7 +46,6 @@
>  #include 
>  #include 
>  #include 
> -#include 
>  #include 
>  #include 
>  #include 
> @@ -460,6 +459,7 @@ static int vc4_hdmi_connector_detect_ctx(struct 
> drm_connector *connector,
>  static int vc4_hdmi_connector_get_modes(struct drm_connector *connector)
>  {
> struct vc4_hdmi *vc4_hdmi = connector_to_vc4_hdmi(connector);
> +   struct vc4_dev *vc4 = to_vc4_dev(connector->dev);
> int ret = 0;
> struct edid *edid;
>
> @@ -483,7 +483,7 @@ static int vc4_hdmi_connector_get_modes(struct 
> drm_connector *connector)
> ret = drm_add_edid_modes(connector, edid);
> kfree(edid);
>
> -   if (vc4_hdmi->disable_4kp60) {
> +   if (!vc4->hvs->vc5_hdmi_enable_hdmi_20) {
> struct drm_device *drm = connector->dev;
> const struct drm_display_mode *mode;
>
> @@ -1757,11 +1757,12 @@ vc4_hdmi_encoder_clock_valid(const struct vc4_hdmi 
> *vc4_hdmi,
>  {
> const struct drm_connector *connector = _hdmi->connector;
> const struct drm_display_info *info = >display_info;
> +   struct vc4_dev *vc4 = to_vc4_dev(connector->dev);
>
> if (clock > vc4_hdmi->variant->max_pixel_clock)
> return MODE_CLOCK_HIGH;
>
> -   if (vc4_hdmi->disable_4kp60 && clock > HDMI_14_MAX_TMDS_CLK)
> +   if (!vc4->hvs->vc5_hdmi_enable_hdmi_20 && clock > 
> HDMI_14_MAX_TMDS_CLK)
> return MODE_CLOCK_HIGH;
>
> if (info->max_tmds_clock && clock > (info->max_tmds_clock * 1000))
> @@ -3428,14 +3429,6 @@ static int vc4_hdmi_bind(struct device *dev, struct 
> device *master, void *data)
> vc4_hdmi->disable_wifi_frequencies =
> of_property_read_bool(dev->of_node, 
> "wifi-2.4ghz-coexistence");
>
> -   if (variant->max_pixel_clock == 6) {
> -   struct vc4_dev *vc4 = to_vc4_dev(drm);
> -   unsigned int max_rate = 
> rpi_firmware_clk_get_max_rate(vc4->hvs->core_clk);
> -
> -   if (max_rate < 55000)
> -   vc4_hdmi->disable_4kp60 = true;
> -   }
> -
> ret = devm_pm_runtime_enable(dev);
> if (ret)
> return ret;
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
> index db823efb2563..e3619836ca17 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.h
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
> @@ -156,14 +156,6 @@ struct vc4_hdmi {
&

Re: [PATCH v4 7/7] drm/vc4: Make sure we don't end up with a core clock too high

2022-10-26 Thread Dave Stevenson
On Thu, 20 Oct 2022 at 10:14,  wrote:
>
> Following the clock rate range improvements to the clock framework,
> trying to set a disjoint range on a clock will now result in an error.
>
> Thus, we can't set a minimum rate higher than the maximum reported by
> the firmware, or clk_set_min_rate() will fail.
>
> Thus we need to clamp the rate we are about to ask for to the maximum
> rate possible on that clock.
>
> Signed-off-by: Maxime Ripard 

Thanks Maxime.

Reviewed-by: Dave Stevenson 

> ---
>  drivers/gpu/drm/vc4/vc4_kms.c | 13 -
>  1 file changed, 8 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c
> index 4419e810103d..5c97642ed66a 100644
> --- a/drivers/gpu/drm/vc4/vc4_kms.c
> +++ b/drivers/gpu/drm/vc4/vc4_kms.c
> @@ -396,8 +396,8 @@ static void vc4_atomic_commit_tail(struct 
> drm_atomic_state *state)
> if (vc4->is_vc5) {
> unsigned long state_rate = max(old_hvs_state->core_clock_rate,
>
> new_hvs_state->core_clock_rate);
> -   unsigned long core_rate = max_t(unsigned long,
> -   5, state_rate);
> +   unsigned long core_rate = clamp_t(unsigned long, state_rate,
> + 5, 
> hvs->max_core_rate);
>
> drm_dbg(dev, "Raising the core clock at %lu Hz\n", core_rate);
>
> @@ -431,14 +431,17 @@ static void vc4_atomic_commit_tail(struct 
> drm_atomic_state *state)
> drm_atomic_helper_cleanup_planes(dev, state);
>
> if (vc4->is_vc5) {
> -   drm_dbg(dev, "Running the core clock at %lu Hz\n",
> -   new_hvs_state->core_clock_rate);
> +   unsigned long core_rate = min_t(unsigned long,
> +   hvs->max_core_rate,
> +   
> new_hvs_state->core_clock_rate);
> +
> +   drm_dbg(dev, "Running the core clock at %lu Hz\n", core_rate);
>
> /*
>  * Request a clock rate based on the current HVS
>  * requirements.
>  */
> -   WARN_ON(clk_set_min_rate(hvs->core_clk, 
> new_hvs_state->core_clock_rate));
> +   WARN_ON(clk_set_min_rate(hvs->core_clk, core_rate));
>
> drm_dbg(dev, "Core clock actual rate: %lu Hz\n",
> clk_get_rate(hvs->core_clk));
>
> --
> b4 0.10.1


Re: [PATCH v4 6/7] drm/vc4: hdmi: Add more checks for 4k resolutions

2022-10-26 Thread Dave Stevenson
On Thu, 20 Oct 2022 at 10:14,  wrote:
>
> From: Dom Cobley 
>
> At least the 4096x2160@60Hz mode requires some overclocking that isn't
> available by default, even if hdmi_enable_4kp60 is enabled.
>
> Let's add some logic to detect whether we can satisfy the core clock
> requirements for that mode, and prevent it from being used otherwise.
>
> Signed-off-by: Dom Cobley 
> Signed-off-by: Maxime Ripard 

Reviewed-by: Dave Stevenson 

> ---
>  drivers/gpu/drm/vc4/vc4_drv.h  |  6 ++
>  drivers/gpu/drm/vc4/vc4_hdmi.c | 11 +--
>  drivers/gpu/drm/vc4/vc4_hvs.c  |  3 +++
>  3 files changed, 18 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
> index 8b2b1af565f9..72a6b7151d23 100644
> --- a/drivers/gpu/drm/vc4/vc4_drv.h
> +++ b/drivers/gpu/drm/vc4/vc4_drv.h
> @@ -347,6 +347,12 @@ struct vc4_hvs {
>  * available.
>  */
> bool vc5_hdmi_enable_scrambling;
> +
> +   /*
> +* 4096x2160@60 requires a core overclock to work, so register
> +* whether that is sufficient.
> +*/
> +   bool vc5_hdmi_enable_4096by2160;
>  };
>
>  struct vc4_plane {
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index afe3daa2173e..fd3730ea976f 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -1753,6 +1753,7 @@ vc4_hdmi_sink_supports_format_bpc(const struct vc4_hdmi 
> *vc4_hdmi,
>
>  static enum drm_mode_status
>  vc4_hdmi_encoder_clock_valid(const struct vc4_hdmi *vc4_hdmi,
> +const struct drm_display_mode *mode,
>  unsigned long long clock)
>  {
> const struct drm_connector *connector = _hdmi->connector;
> @@ -1765,6 +1766,12 @@ vc4_hdmi_encoder_clock_valid(const struct vc4_hdmi 
> *vc4_hdmi,
> if (!vc4->hvs->vc5_hdmi_enable_scrambling && clock > 
> HDMI_14_MAX_TMDS_CLK)
> return MODE_CLOCK_HIGH;
>
> +   /* 4096x2160@60 is not reliable without overclocking core */
> +   if (!vc4->hvs->vc5_hdmi_enable_4096by2160 &&
> +   mode->hdisplay > 3840 && mode->vdisplay >= 2160 &&
> +   drm_mode_vrefresh(mode) >= 50)
> +   return MODE_CLOCK_HIGH;
> +
> if (info->max_tmds_clock && clock > (info->max_tmds_clock * 1000))
> return MODE_CLOCK_HIGH;
>
> @@ -1799,7 +1806,7 @@ vc4_hdmi_encoder_compute_clock(const struct vc4_hdmi 
> *vc4_hdmi,
> unsigned long long clock;
>
> clock = vc4_hdmi_encoder_compute_mode_clock(mode, bpc, fmt);
> -   if (vc4_hdmi_encoder_clock_valid(vc4_hdmi, clock) != MODE_OK)
> +   if (vc4_hdmi_encoder_clock_valid(vc4_hdmi, mode, clock) != MODE_OK)
> return -EINVAL;
>
> vc4_state->tmds_char_rate = clock;
> @@ -1962,7 +1969,7 @@ vc4_hdmi_encoder_mode_valid(struct drm_encoder *encoder,
>  (mode->hsync_end % 2) || (mode->htotal % 2)))
> return MODE_H_ILLEGAL;
>
> -   return vc4_hdmi_encoder_clock_valid(vc4_hdmi, mode->clock * 1000);
> +   return vc4_hdmi_encoder_clock_valid(vc4_hdmi, mode, mode->clock * 
> 1000);
>  }
>
>  static const struct drm_encoder_helper_funcs vc4_hdmi_encoder_helper_funcs = 
> {
> diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c
> index 300ac0b57571..a68913f76687 100644
> --- a/drivers/gpu/drm/vc4/vc4_hvs.c
> +++ b/drivers/gpu/drm/vc4/vc4_hvs.c
> @@ -818,6 +818,9 @@ static int vc4_hvs_bind(struct device *dev, struct device 
> *master, void *data)
> if (max_rate >= 55000)
> hvs->vc5_hdmi_enable_scrambling = true;
>
> +   if (max_rate >= 6)
> +   hvs->vc5_hdmi_enable_4096by2160 = true;
> +
> hvs->max_core_rate = max_rate;
>
> ret = clk_prepare_enable(hvs->core_clk);
>
> --
> b4 0.10.1


Re: [PATCH v4 5/7] drm/vc4: hdmi: Rework hdmi_enable_4kp60 detection code

2022-10-26 Thread Dave Stevenson
I knew there was something else

On Wed, 26 Oct 2022 at 17:00, Dave Stevenson
 wrote:
>
> Hi Maxime
>
> On Thu, 20 Oct 2022 at 10:14,  wrote:
> >
> > In order to support higher HDMI frequencies, users have to set the
> > hdmi_enable_4kp60 parameter in their config.txt file.
> >
> > This will have the side-effect of raising the maximum of the core clock,
> > tied to the HVS, and managed by the HVS driver.
> >
> > However, we are querying this in the HDMI driver by poking into the HVS
> > structure to get our struct clk handle.
> >
> > Let's make this part of the HVS bind implementation to have all the core
> > clock related setup in the same place.
> >
> > Signed-off-by: Maxime Ripard 
> > ---
> >  drivers/gpu/drm/vc4/vc4_drv.h  | 10 ++
> >  drivers/gpu/drm/vc4/vc4_hdmi.c | 15 ---
> >  drivers/gpu/drm/vc4/vc4_hdmi.h |  8 
> >  drivers/gpu/drm/vc4/vc4_hvs.c  | 23 +++
> >  4 files changed, 37 insertions(+), 19 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
> > index 418a8242691f..8b2b1af565f9 100644
> > --- a/drivers/gpu/drm/vc4/vc4_drv.h
> > +++ b/drivers/gpu/drm/vc4/vc4_drv.h
> > @@ -326,6 +326,8 @@ struct vc4_hvs {
> >
> > struct clk *core_clk;
> >
> > +   unsigned long max_core_rate;
> > +
> > /* Memory manager for CRTCs to allocate space in the display
> >  * list.  Units are dwords.
> >  */
> > @@ -337,6 +339,14 @@ struct vc4_hvs {
> > struct drm_mm_node mitchell_netravali_filter;
> >
> > struct debugfs_regset32 regset;
> > +
> > +   /*
> > +* Even if HDMI0 on the RPi4 can output modes requiring a pixel
> > +* rate higher than 297MHz, it needs some adjustments in the
> > +* config.txt file to be able to do so and thus won't always be
> > +* available.
> > +*/
> > +   bool vc5_hdmi_enable_scrambling;

Name only. This flag isn't to do with scrambling, it's whether we can
achieve pixel rates greater than those defined by HDMI 1.4.

We do have code related to enabling scrambling, which is part of HDMI
2.0, so this currently could cause confusion.

  Dave

> >  };
> >
> >  struct vc4_plane {
> > diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> > index 87961d4de5aa..afe3daa2173e 100644
> > --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> > +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> > @@ -46,7 +46,6 @@
> >  #include 
> >  #include 
> >  #include 
> > -#include 
> >  #include 
> >  #include 
> >  #include 
> > @@ -460,6 +459,7 @@ static int vc4_hdmi_connector_detect_ctx(struct 
> > drm_connector *connector,
> >  static int vc4_hdmi_connector_get_modes(struct drm_connector *connector)
> >  {
> > struct vc4_hdmi *vc4_hdmi = connector_to_vc4_hdmi(connector);
> > +   struct vc4_dev *vc4 = to_vc4_dev(connector->dev);
> > int ret = 0;
> > struct edid *edid;
> >
> > @@ -483,7 +483,7 @@ static int vc4_hdmi_connector_get_modes(struct 
> > drm_connector *connector)
> > ret = drm_add_edid_modes(connector, edid);
> > kfree(edid);
> >
> > -   if (vc4_hdmi->disable_4kp60) {
> > +   if (!vc4->hvs->vc5_hdmi_enable_scrambling) {
> > struct drm_device *drm = connector->dev;
> > const struct drm_display_mode *mode;
> >
> > @@ -1757,11 +1757,12 @@ vc4_hdmi_encoder_clock_valid(const struct vc4_hdmi 
> > *vc4_hdmi,
> >  {
> > const struct drm_connector *connector = _hdmi->connector;
> > const struct drm_display_info *info = >display_info;
> > +   struct vc4_dev *vc4 = to_vc4_dev(connector->dev);
> >
> > if (clock > vc4_hdmi->variant->max_pixel_clock)
> > return MODE_CLOCK_HIGH;
> >
> > -   if (vc4_hdmi->disable_4kp60 && clock > HDMI_14_MAX_TMDS_CLK)
> > +   if (!vc4->hvs->vc5_hdmi_enable_scrambling && clock > 
> > HDMI_14_MAX_TMDS_CLK)
> > return MODE_CLOCK_HIGH;
> >
> > if (info->max_tmds_clock && clock > (info->max_tmds_clock * 1000))
> > @@ -3428,14 +3429,6 @@ static int vc4_hdmi_bind(struct device *dev, struct 
> > device *master, void *data)
> > vc4_hdmi->disable_wifi_frequencies =
> > of_property_read_bool(dev->of_node, 
> > "wifi-2.4

Re: [PATCH v4 5/7] drm/vc4: hdmi: Rework hdmi_enable_4kp60 detection code

2022-10-26 Thread Dave Stevenson
Hi Maxime

On Thu, 20 Oct 2022 at 10:14,  wrote:
>
> In order to support higher HDMI frequencies, users have to set the
> hdmi_enable_4kp60 parameter in their config.txt file.
>
> This will have the side-effect of raising the maximum of the core clock,
> tied to the HVS, and managed by the HVS driver.
>
> However, we are querying this in the HDMI driver by poking into the HVS
> structure to get our struct clk handle.
>
> Let's make this part of the HVS bind implementation to have all the core
> clock related setup in the same place.
>
> Signed-off-by: Maxime Ripard 
> ---
>  drivers/gpu/drm/vc4/vc4_drv.h  | 10 ++
>  drivers/gpu/drm/vc4/vc4_hdmi.c | 15 ---
>  drivers/gpu/drm/vc4/vc4_hdmi.h |  8 
>  drivers/gpu/drm/vc4/vc4_hvs.c  | 23 +++
>  4 files changed, 37 insertions(+), 19 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
> index 418a8242691f..8b2b1af565f9 100644
> --- a/drivers/gpu/drm/vc4/vc4_drv.h
> +++ b/drivers/gpu/drm/vc4/vc4_drv.h
> @@ -326,6 +326,8 @@ struct vc4_hvs {
>
> struct clk *core_clk;
>
> +   unsigned long max_core_rate;
> +
> /* Memory manager for CRTCs to allocate space in the display
>  * list.  Units are dwords.
>  */
> @@ -337,6 +339,14 @@ struct vc4_hvs {
> struct drm_mm_node mitchell_netravali_filter;
>
> struct debugfs_regset32 regset;
> +
> +   /*
> +* Even if HDMI0 on the RPi4 can output modes requiring a pixel
> +* rate higher than 297MHz, it needs some adjustments in the
> +* config.txt file to be able to do so and thus won't always be
> +* available.
> +*/
> +   bool vc5_hdmi_enable_scrambling;
>  };
>
>  struct vc4_plane {
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index 87961d4de5aa..afe3daa2173e 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -46,7 +46,6 @@
>  #include 
>  #include 
>  #include 
> -#include 
>  #include 
>  #include 
>  #include 
> @@ -460,6 +459,7 @@ static int vc4_hdmi_connector_detect_ctx(struct 
> drm_connector *connector,
>  static int vc4_hdmi_connector_get_modes(struct drm_connector *connector)
>  {
> struct vc4_hdmi *vc4_hdmi = connector_to_vc4_hdmi(connector);
> +   struct vc4_dev *vc4 = to_vc4_dev(connector->dev);
> int ret = 0;
> struct edid *edid;
>
> @@ -483,7 +483,7 @@ static int vc4_hdmi_connector_get_modes(struct 
> drm_connector *connector)
> ret = drm_add_edid_modes(connector, edid);
> kfree(edid);
>
> -   if (vc4_hdmi->disable_4kp60) {
> +   if (!vc4->hvs->vc5_hdmi_enable_scrambling) {
> struct drm_device *drm = connector->dev;
> const struct drm_display_mode *mode;
>
> @@ -1757,11 +1757,12 @@ vc4_hdmi_encoder_clock_valid(const struct vc4_hdmi 
> *vc4_hdmi,
>  {
> const struct drm_connector *connector = _hdmi->connector;
> const struct drm_display_info *info = >display_info;
> +   struct vc4_dev *vc4 = to_vc4_dev(connector->dev);
>
> if (clock > vc4_hdmi->variant->max_pixel_clock)
> return MODE_CLOCK_HIGH;
>
> -   if (vc4_hdmi->disable_4kp60 && clock > HDMI_14_MAX_TMDS_CLK)
> +   if (!vc4->hvs->vc5_hdmi_enable_scrambling && clock > 
> HDMI_14_MAX_TMDS_CLK)
> return MODE_CLOCK_HIGH;
>
> if (info->max_tmds_clock && clock > (info->max_tmds_clock * 1000))
> @@ -3428,14 +3429,6 @@ static int vc4_hdmi_bind(struct device *dev, struct 
> device *master, void *data)
> vc4_hdmi->disable_wifi_frequencies =
> of_property_read_bool(dev->of_node, 
> "wifi-2.4ghz-coexistence");
>
> -   if (variant->max_pixel_clock == 6) {
> -   struct vc4_dev *vc4 = to_vc4_dev(drm);
> -   unsigned long max_rate = 
> rpi_firmware_clk_get_max_rate(vc4->hvs->core_clk);
> -
> -   if (max_rate < 55000)
> -   vc4_hdmi->disable_4kp60 = true;
> -   }
> -
> ret = devm_pm_runtime_enable(dev);
> if (ret)
> return ret;
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
> index db823efb2563..e3619836ca17 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.h
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
> @@ -156,14 +156,6 @@ struct vc4_hdmi {
>  */
> bool disable_wifi_frequencies;
>
> -   /*
> -* Even if HDMI0 on the RPi4 can output modes requiring a pixel
> -* rate higher than 297MHz, it needs some adjustments in the
> -* config.txt file to be able to do so and thus won't always be
> -* available.
> -*/
> -   bool disable_4kp60;
> -
> struct cec_adapter *cec_adap;
> struct cec_msg cec_rx_msg;
> bool cec_tx_ok;
> diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c
> index 4ac9f5a2d5f9..300ac0b57571 100644

Re: [PATCH v4 4/7] drm/vc4: hdmi: Fix hdmi_enable_4kp60 detection

2022-10-26 Thread Dave Stevenson
On Wed, 26 Oct 2022 at 16:27, Dave Stevenson
 wrote:
>
> On Thu, 20 Oct 2022 at 10:14,  wrote:
> >
> > In order to support higher HDMI frequencies, users have to set the
> > hdmi_enable_4kp60 parameter in their config.txt file.
> >
> > We were detecting this so far by calling clk_round_rate() on the core
> > clock with the frequency we're supposed to run at when one of those
> > modes is enabled. Whether or not the parameter was enabled could then be
> > inferred by the returned rate since the maximum clock rate reported by
> > the firmware was one of the side effect of setting that parameter.
> >
> > However, the recent clock rework we did changed what clk_round_rate()
> > was returning to always return the minimum allowed, and thus this test
> > wasn't reliable anymore.
> >
> > Let's use the new clk_get_max_rate() function to reliably determine the
> > maximum rate allowed on that clock and fix the 4k@60Hz output.
> >
> > Fixes: e9d6cea2af1c ("clk: bcm: rpi: Run some clocks at the minimum rate 
> > allowed")
> > Signed-off-by: Maxime Ripard 
>
> Reviewed-by: Dave Stevenson 
>
> > ---
> >  drivers/gpu/drm/vc4/vc4_hdmi.c | 3 ++-
> >  1 file changed, 2 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> > index 64f9feabf43e..87961d4de5aa 100644
> > --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> > +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> > @@ -46,6 +46,7 @@
> >  #include 
> >  #include 
> >  #include 
> > +#include 
> >  #include 
> >  #include 
> >  #include 
> > @@ -3429,7 +3430,7 @@ static int vc4_hdmi_bind(struct device *dev, struct 
> > device *master, void *data)
> >
> > if (variant->max_pixel_clock == 6) {
> > struct vc4_dev *vc4 = to_vc4_dev(drm);
> > -   long max_rate = clk_round_rate(vc4->hvs->core_clk, 
> > 55000);
> > +   unsigned long max_rate = 
> > rpi_firmware_clk_get_max_rate(vc4->hvs->core_clk);

Actually minor nit:
rpi_firmware_clk_get_max_rate returns an unsigned int.
AFAICT we don't need the range of unsigned long in any subsequent
code, so I think it could just be unsigned int here.

clk_round_rate returned a long, and therefore previously it did have to be that.

  Dave

> > if (max_rate < 55000)
> > vc4_hdmi->disable_4kp60 = true;
> >
> > --
> > b4 0.10.1


Re: [PATCH v4 4/7] drm/vc4: hdmi: Fix hdmi_enable_4kp60 detection

2022-10-26 Thread Dave Stevenson
On Thu, 20 Oct 2022 at 10:14,  wrote:
>
> In order to support higher HDMI frequencies, users have to set the
> hdmi_enable_4kp60 parameter in their config.txt file.
>
> We were detecting this so far by calling clk_round_rate() on the core
> clock with the frequency we're supposed to run at when one of those
> modes is enabled. Whether or not the parameter was enabled could then be
> inferred by the returned rate since the maximum clock rate reported by
> the firmware was one of the side effect of setting that parameter.
>
> However, the recent clock rework we did changed what clk_round_rate()
> was returning to always return the minimum allowed, and thus this test
> wasn't reliable anymore.
>
> Let's use the new clk_get_max_rate() function to reliably determine the
> maximum rate allowed on that clock and fix the 4k@60Hz output.
>
> Fixes: e9d6cea2af1c ("clk: bcm: rpi: Run some clocks at the minimum rate 
> allowed")
> Signed-off-by: Maxime Ripard 

Reviewed-by: Dave Stevenson 

> ---
>  drivers/gpu/drm/vc4/vc4_hdmi.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index 64f9feabf43e..87961d4de5aa 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -46,6 +46,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
>  #include 
> @@ -3429,7 +3430,7 @@ static int vc4_hdmi_bind(struct device *dev, struct 
> device *master, void *data)
>
> if (variant->max_pixel_clock == 6) {
> struct vc4_dev *vc4 = to_vc4_dev(drm);
> -   long max_rate = clk_round_rate(vc4->hvs->core_clk, 55000);
> +   unsigned long max_rate = 
> rpi_firmware_clk_get_max_rate(vc4->hvs->core_clk);
>
> if (max_rate < 55000)
> vc4_hdmi->disable_4kp60 = true;
>
> --
> b4 0.10.1


Re: [PATCH v3 2/4] dt-bindings: display: add new bus-format property for panel-dpi

2022-10-19 Thread Dave Stevenson
Hi Laurent

On Sun, 16 Oct 2022 at 02:33, Laurent Pinchart
 wrote:
>
> Hello,
>
> On Fri, Oct 14, 2022 at 03:08:49PM +0100, Dave Stevenson wrote:
> > On Thu, 13 Oct 2022 at 13:58, Francesco Dolcini wrote:
> > > On Tue, Jun 28, 2022 at 08:18:36PM +0200, Max Krummenacher wrote:
> > > > From: Max Krummenacher 
> > > >
> > > > The property is used to set the enum bus_format and infer the bpc
> > > > for a panel defined by 'panel-dpi'.
> > > > This specifies how the panel is connected to the display interface.
> > > >
> > > > Signed-off-by: Max Krummenacher 
> > > >
> > >
> > > 
> > >
> > > > diff --git 
> > > > a/Documentation/devicetree/bindings/display/panel/panel-dpi.yaml 
> > > > b/Documentation/devicetree/bindings/display/panel/panel-dpi.yaml
> > > > index dae0676b5c6e..52f5db03b6a8 100644
> > > > --- a/Documentation/devicetree/bindings/display/panel/panel-dpi.yaml
> > > > +++ b/Documentation/devicetree/bindings/display/panel/panel-dpi.yaml
> > > > @@ -26,7 +26,28 @@ properties:
> > > >height-mm: true
> > > >label: true
> > > >panel-timing: true
> > > > -  port: true
> > > > +
> > > > +  port:
> > > > +$ref: /schemas/graph.yaml#/$defs/port-base
> > > > +description:
> > > > +  Input port node, receives the panel data.
> > > > +
> > > > +properties:
> > > > +  endpoint:
> > > > +$ref: /schemas/graph.yaml#/$defs/endpoint-base
> > > > +
> > > > +properties:
> > > > +  bus-format:
> > > > +$ref: /schemas/types.yaml#/definitions/uint32
> > > > +minimum: 0x1001
> > > > +maximum: 0x1fff
> > > > +description: |
> > > > +  Describes how the display panel is connected to the 
> > > > display interface.
> > > > +  Valid values are defined in 
> > > > .
> > > > +  The mapping between the color/significance of the panel 
> > > > lines to the
> > > > +  parallel data lines are defined in:
> > > > +  
> > > > https://www.kernel.org/doc/html/v5.17/userspace-api/media/v4l/subdev-formats.html#packed-rgb-formats
> > > > +
> > >
> > > Last month I had the chance to talk in person about this topic with
> > > Dave, Marek and Max in Dublin.
> > >
> > > My understanding is that this change is addressing a general need, Dave
> > > confirmed me they have a downstream patch for raspberrypi [1].
> > >
> > > From what I could tell the only concern is about the actual encoding of
> > > this `bus-format` property.
> > >
> > > I am personally convinced that a simple enum is the way to go, I think
> > > that Marek proposal is adding complexity and not flexibility (from my
> > > understanding Dave is on the same page, just correct me if I
> > > misunderstood you).
> >
> > Yes I agree with you here.
> >
> > This binding is for the panel, and currently the only path to pass the
> > panel mode to the DPI transmitter is one or more MEDIA_BUS_FMT_* enums
> > in struct drm_display_info *bus_formats.
> >
> > Looking at Marek's comment over DSI and data-lanes, yes both source
> > and sink could advertise a data-lanes property to cover the condition
> > where they aren't wired up in a 1:1 fashion. Reality is that most
> > drivers don't support reordering the lanes - looking at the bindings,
> > only one (msm) documents the use of data-lanes on the host side.
> > rcar_mipi_dsi looks at the number of lanes specified only, and then
> > checks that the number requested by the device is <= the number
> > configured.
> >
> > As I see it, the comparison here is that this "bus-format" property is
> > the equivalent of the data-lanes on the sink, and is the desired
> > number of lanes value passed from sink to source (one integer, not a
> > mapping).
> > If the source can reorder the lanes, then that is a property of the
> > source. This binding is for the sink, and so isn't a reasonable
> > comparison. It also doesn't have to be called "bus-format" on the
> > source, and can take a totally different form.
> > I'll admit that I know data-lane configuration more from CSI2, but
> > within V4L2 it i

Re: [PATCH V2 3/4] drm/panel: Add prepare_upstream_first flag to drm_panel

2022-10-18 Thread Dave Stevenson
Hi Jagan

On Mon, 17 Oct 2022 at 03:44, Jagan Teki  wrote:
>
> Hi Dave,
>
> On Fri, Oct 7, 2022 at 6:26 PM Dave Stevenson
>  wrote:
> >
> > Hi Jagan
> >
> > On Thu, 6 Oct 2022 at 15:25, Jagan Teki  wrote:
> > >
> > > On Fri, Mar 4, 2022 at 8:48 PM Dave Stevenson
> > >  wrote:
> > > >
> > > > Mapping to the drm_bridge flag pre_enable_upstream_first,
> > > > add a new flag prepare_upstream_first to drm_panel to allow
> > > > the panel driver to request that the upstream bridge should
> > > > be pre_enabled before the panel prepare.
> > > >
> > > > Signed-off-by: Dave Stevenson 
> > > > ---
> > > >  drivers/gpu/drm/bridge/panel.c |  3 +++
> > > >  include/drm/drm_panel.h| 10 ++
> > > >  2 files changed, 13 insertions(+)
> > > >
> > > > diff --git a/drivers/gpu/drm/bridge/panel.c 
> > > > b/drivers/gpu/drm/bridge/panel.c
> > > > index 5be057575183..2ea08b3ba326 100644
> > > > --- a/drivers/gpu/drm/bridge/panel.c
> > > > +++ b/drivers/gpu/drm/bridge/panel.c
> > > > @@ -234,6 +234,9 @@ struct drm_bridge 
> > > > *drm_panel_bridge_add_typed(struct drm_panel *panel,
> > > > panel_bridge->bridge.ops = DRM_BRIDGE_OP_MODES;
> > > > panel_bridge->bridge.type = connector_type;
> > > >
> > > > +   panel_bridge->bridge.pre_enable_upstream_first =
> > > > +   
> > > > panel->prepare_upstream_first;
> > > > +
> > >
> > > panel_bridge is common for bridge users who used panel and those who
> > > might not need upstream first, so better to handle per bridge user
> > > whoever needs this.
> >
> > Sorry, I don't follow you.
>
> panel_bridge driver is a common bridge for drm_panel_bridge_add
> registered bridges. If we enable pre_enable_upstream_first globally in
> panel_bridge driver then it affects panes that don't require
> pre_enable first for that bridge chain. Hope you understand.

No, sorry, I'm still not getting your point.

It is not enabled globally.
If (and only if) the specific panel driver has set
prepare_upstream_first in the struct drm_panel passed to
drm_panel_add(), then that setting is replicated in the associated
struct drm_bridge pre_enable_upstream_first.

Can you give an example of where you see this being an issue?

You proposed handling this on a per bridge user basis? What exactly
are you calling a bridge user in that case? The DSI host (or
equivalent) source to the panel? Because the panel driver has no idea
it is being wrapped into a drm_bridge.
However that source device can't alter the bridge chain call order
(breaking the chain as Exynos and vc4 do does not work with the atomic
API in "entertaining" ways), and it has no knowledge of the behaviour
the attached panel wants, nor does it know that it's going through
panel_bridge.

As per my previous email, devm_drm_of_get_bridge is the only other
place in the callstack that has both the drm_panel and drm_bridge
handles. Does putting the assignment from drm_panel to drm_bridge in
there solve your concern?

Thanks.
  Dave


Re: [PATCH 5/7] drm/vc4: dpi: Support BGR666 formats

2022-10-17 Thread Dave Stevenson
Hi Laurent

Thanks for the review.

On Sat, 15 Oct 2022 at 18:31, Laurent Pinchart
 wrote:
>
> On Sat, Oct 15, 2022 at 08:26:48PM +0300, Laurent Pinchart wrote:
> > Hi Maxime and Joerg,
> >
> > Thank you for the patch.
> >
> > On Thu, Oct 13, 2022 at 11:56:49AM +0200, Maxime Ripard wrote:
> > > From: Joerg Quinten 
> > >
> > > The VC4 DPI output can support multiple BGR666 variants, but they were
> > > never added to the driver. Let's add the the support for those formats.
> > >
> > > Signed-off-by: Joerg Quinten 
> > > Signed-off-by: Maxime Ripard 
> >
> > Reviewed-by: Laurent Pinchart 
> >
> > > ---
> > >  drivers/gpu/drm/vc4/vc4_dpi.c | 6 ++
> > >  1 file changed, 6 insertions(+)
> > >
> > > diff --git a/drivers/gpu/drm/vc4/vc4_dpi.c b/drivers/gpu/drm/vc4/vc4_dpi.c
> > > index 7da3dd1db50e..ecbe4cd87036 100644
> > > --- a/drivers/gpu/drm/vc4/vc4_dpi.c
> > > +++ b/drivers/gpu/drm/vc4/vc4_dpi.c
> > > @@ -170,10 +170,16 @@ static void vc4_dpi_encoder_enable(struct 
> > > drm_encoder *encoder)
> > > dpi_c |= VC4_SET_FIELD(DPI_ORDER_BGR,
> > >DPI_ORDER);
> > > break;
> > > +   case MEDIA_BUS_FMT_BGR666_1X24_CPADHI:
> > > +   dpi_c |= VC4_SET_FIELD(DPI_ORDER_BGR, 
> > > DPI_ORDER);
> > > +   fallthrough;
>
> Upon closer inspection of the code, I think you also need
>
> -   dpi_c &= ~DPI_FORMAT_MASK;
> +   dpi_c &= ~(DPI_ORDER_MASK | DPI_FORMAT_MASK);
>
> a few lines above.

Hmm, curious as there appears to be a difference between our vendor
tree and mainline in the contents of a patch with almost the same
commit text.

https://github.com/torvalds/linux/commit/7a70b0b97889a89f397913c971cadfc6db9b310a
vs 
https://github.com/raspberrypi/linux/commit/9d9dc236a9ee9021363b8601b6188e7be86d1971

Our tree leaves dpi_c effectively clear, and selects the default at
the end. Mainline sets the default first.


Even so, dpi_c gets initialised with
dpi_c = DPI_ENABLE;
dpi_c |= VC4_SET_FIELD(DPI_FORMAT_24BIT_888_RGB, DPI_FORMAT);
dpi_c &= ~DPI_FORMAT_MASK;
so at this point in the switch, the DPI_ORDER bits haven't changed
from the default of 0.

  Dave

> > > case MEDIA_BUS_FMT_RGB666_1X24_CPADHI:
> > > dpi_c |= 
> > > VC4_SET_FIELD(DPI_FORMAT_18BIT_666_RGB_2,
> > >DPI_FORMAT);
> > > break;
> > > +   case MEDIA_BUS_FMT_BGR666_1X18:
> > > +   dpi_c |= VC4_SET_FIELD(DPI_ORDER_BGR, 
> > > DPI_ORDER);
> > > +   fallthrough;
> > > case MEDIA_BUS_FMT_RGB666_1X18:
> > > dpi_c |= 
> > > VC4_SET_FIELD(DPI_FORMAT_18BIT_666_RGB_1,
> > >DPI_FORMAT);
> > >
>
> --
> Regards,
>
> Laurent Pinchart


  1   2   3   4   >