2022-10-27 13:09:29

by Maxime Ripard

[permalink] [raw]
Subject: [PATCH v5 0/7] drm/vc4: Fix the core clock behaviour

Hi,

Those patches used to be part of a larger clock fixes series:
https://lore.kernel.org/linux-clk/[email protected]/

However, that series doesn't seem to be getting anywhere, so I've split out
these patches that fix a regression that has been there since 5.18 and that
prevents the 4k output from working on the RaspberryPi4.

Hopefully, we will be able to merge those patches through the DRM tree to avoid
any further disruption.

Let me know what you think,
Maxime

To: Florian Fainelli <[email protected]>
To: Broadcom internal kernel review list <[email protected]>
To: Ray Jui <[email protected]>
To: Scott Branden <[email protected]>
To: Michael Turquette <[email protected]>
To: Stephen Boyd <[email protected]>
To: Emma Anholt <[email protected]>
To: Maxime Ripard <[email protected]>
To: David Airlie <[email protected]>
To: Daniel Vetter <[email protected]>
Cc: Stefan Wahren <[email protected]>
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
Cc: Dom Cobley <[email protected]>
Signed-off-by: Maxime Ripard <[email protected]>

---
Changes in v5:
- Changed the bool name
- Change type of variable storing the max rate to unsigned int
- Link to v4: https://lore.kernel.org/r/[email protected]

Changes in v4:
- Move the rpi_firmware_of_match to avoid confusion
- Link to v3: https://lore.kernel.org/r/[email protected]

Changes in v3:
- Return UINT_MAX when the firmware call fails in the _get_max_rate function
- Link to v2: https://lore.kernel.org/r/[email protected]

Changes in v2:
- Dropped the clock patches, made an ad-hoc function in the firmware driver
- Link to v1: https://lore.kernel.org/r/[email protected]

---
Dom Cobley (1):
drm/vc4: hdmi: Add more checks for 4k resolutions

Maxime Ripard (6):
firmware: raspberrypi: Introduce rpi_firmware_find_node()
firmware: raspberrypi: Move the clock IDs to the firmware header
firmware: raspberrypi: Provide a helper to query a clock max rate
drm/vc4: hdmi: Fix hdmi_enable_4kp60 detection
drm/vc4: hdmi: Rework hdmi_enable_4kp60 detection code
drm/vc4: Make sure we don't end up with a core clock too high

drivers/clk/bcm/clk-raspberrypi.c | 19 -----------
drivers/firmware/raspberrypi.c | 38 ++++++++++++++++++----
drivers/gpu/drm/vc4/vc4_drv.h | 16 +++++++++
drivers/gpu/drm/vc4/vc4_hdmi.c | 25 +++++++-------
drivers/gpu/drm/vc4/vc4_hdmi.h | 8 -----
drivers/gpu/drm/vc4/vc4_hvs.c | 26 +++++++++++++++
drivers/gpu/drm/vc4/vc4_kms.c | 13 +++++---
include/soc/bcm2835/raspberrypi-firmware.h | 52 ++++++++++++++++++++++++++++++
8 files changed, 147 insertions(+), 50 deletions(-)
---
base-commit: 9abf2313adc1ca1b6180c508c25f22f9395cc780
change-id: 20220815-rpi-fix-4k-60-17273650429d

Best regards,
--
Maxime Ripard <[email protected]>


2022-10-27 13:50:26

by Maxime Ripard

[permalink] [raw]
Subject: [PATCH v5 5/7] drm/vc4: hdmi: Rework hdmi_enable_4kp60 detection code

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 <[email protected]>
---
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 <linux/pm_runtime.h>
#include <linux/rational.h>
#include <linux/reset.h>
-#include <soc/bcm2835/raspberrypi-clocks.h>
#include <sound/dmaengine_pcm.h>
#include <sound/hdmi-codec.h>
#include <sound/pcm_drm_eld.h>
@@ -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 = &vc4_hdmi->connector;
const struct drm_display_info *info = &connector->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 == 600000000) {
- 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 < 550000000)
- 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..fc4b7310bf63 100644
--- a/drivers/gpu/drm/vc4/vc4_hvs.c
+++ b/drivers/gpu/drm/vc4/vc4_hvs.c
@@ -28,6 +28,8 @@
#include <drm/drm_drv.h>
#include <drm/drm_vblank.h>

+#include <soc/bcm2835/raspberrypi-firmware.h>
+
#include "vc4_drv.h"
#include "vc4_regs.h"

@@ -791,12 +793,33 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data)
hvs->regset.nregs = ARRAY_SIZE(hvs_regs);

if (vc4->is_vc5) {
+ struct rpi_firmware *firmware;
+ struct device_node *node;
+ unsigned int max_rate;
+
+ node = rpi_firmware_find_node();
+ if (!node)
+ return -EINVAL;
+
+ firmware = rpi_firmware_get(node);
+ of_node_put(node);
+ if (!firmware)
+ return -EPROBE_DEFER;
+
hvs->core_clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(hvs->core_clk)) {
dev_err(&pdev->dev, "Couldn't get core clock\n");
return PTR_ERR(hvs->core_clk);
}

+ max_rate = rpi_firmware_clk_get_max_rate(firmware,
+ RPI_FIRMWARE_CORE_CLK_ID);
+ rpi_firmware_put(firmware);
+ if (max_rate >= 550000000)
+ hvs->vc5_hdmi_enable_hdmi_20 = true;
+
+ hvs->max_core_rate = max_rate;
+
ret = clk_prepare_enable(hvs->core_clk);
if (ret) {
dev_err(&pdev->dev, "Couldn't enable the core clock\n");

--
b4 0.11.0-dev-99e3a

2022-10-27 13:57:22

by Maxime Ripard

[permalink] [raw]
Subject: [PATCH v5 1/7] firmware: raspberrypi: Introduce rpi_firmware_find_node()

A significant number of RaspberryPi drivers using the firmware don't
have a phandle to it, so end up scanning the device tree to find a node
with the firmware compatible.

That code is duplicated everywhere, so let's introduce a helper instead.

Acked-by: Florian Fainelli <[email protected]>
Signed-off-by: Maxime Ripard <[email protected]>
---
drivers/firmware/raspberrypi.c | 18 ++++++++++++------
include/soc/bcm2835/raspberrypi-firmware.h | 7 +++++++
2 files changed, 19 insertions(+), 6 deletions(-)

diff --git a/drivers/firmware/raspberrypi.c b/drivers/firmware/raspberrypi.c
index 4b8978b254f9..932a8bef22fb 100644
--- a/drivers/firmware/raspberrypi.c
+++ b/drivers/firmware/raspberrypi.c
@@ -311,6 +311,18 @@ static int rpi_firmware_remove(struct platform_device *pdev)
return 0;
}

+static const struct of_device_id rpi_firmware_of_match[] = {
+ { .compatible = "raspberrypi,bcm2835-firmware", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, rpi_firmware_of_match);
+
+struct device_node *rpi_firmware_find_node(void)
+{
+ return of_find_matching_node(NULL, rpi_firmware_of_match);
+}
+EXPORT_SYMBOL_GPL(rpi_firmware_find_node);
+
/**
* rpi_firmware_get - Get pointer to rpi_firmware structure.
* @firmware_node: Pointer to the firmware Device Tree node.
@@ -366,12 +378,6 @@ struct rpi_firmware *devm_rpi_firmware_get(struct device *dev,
}
EXPORT_SYMBOL_GPL(devm_rpi_firmware_get);

-static const struct of_device_id rpi_firmware_of_match[] = {
- { .compatible = "raspberrypi,bcm2835-firmware", },
- {},
-};
-MODULE_DEVICE_TABLE(of, rpi_firmware_of_match);
-
static struct platform_driver rpi_firmware_driver = {
.driver = {
.name = "raspberrypi-firmware",
diff --git a/include/soc/bcm2835/raspberrypi-firmware.h b/include/soc/bcm2835/raspberrypi-firmware.h
index 811ea668c4a1..63426082bcb9 100644
--- a/include/soc/bcm2835/raspberrypi-firmware.h
+++ b/include/soc/bcm2835/raspberrypi-firmware.h
@@ -142,6 +142,7 @@ int rpi_firmware_property(struct rpi_firmware *fw,
int rpi_firmware_property_list(struct rpi_firmware *fw,
void *data, size_t tag_size);
void rpi_firmware_put(struct rpi_firmware *fw);
+struct device_node *rpi_firmware_find_node(void);
struct rpi_firmware *rpi_firmware_get(struct device_node *firmware_node);
struct rpi_firmware *devm_rpi_firmware_get(struct device *dev,
struct device_node *firmware_node);
@@ -159,6 +160,12 @@ static inline int rpi_firmware_property_list(struct rpi_firmware *fw,
}

static inline void rpi_firmware_put(struct rpi_firmware *fw) { }
+
+static inline struct device_node *rpi_firmware_find_node(void)
+{
+ return NULL;
+}
+
static inline struct rpi_firmware *rpi_firmware_get(struct device_node *firmware_node)
{
return NULL;

--
b4 0.11.0-dev-99e3a

2022-10-27 14:00:43

by Maxime Ripard

[permalink] [raw]
Subject: [PATCH v5 4/7] drm/vc4: hdmi: Fix hdmi_enable_4kp60 detection

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")
Reviewed-by: Dave Stevenson <[email protected]>
Signed-off-by: Maxime Ripard <[email protected]>
---
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..3acc1858c55f 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -46,6 +46,7 @@
#include <linux/pm_runtime.h>
#include <linux/rational.h>
#include <linux/reset.h>
+#include <soc/bcm2835/raspberrypi-clocks.h>
#include <sound/dmaengine_pcm.h>
#include <sound/hdmi-codec.h>
#include <sound/pcm_drm_eld.h>
@@ -3429,7 +3430,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)

if (variant->max_pixel_clock == 600000000) {
struct vc4_dev *vc4 = to_vc4_dev(drm);
- long max_rate = clk_round_rate(vc4->hvs->core_clk, 550000000);
+ unsigned int max_rate = rpi_firmware_clk_get_max_rate(vc4->hvs->core_clk);

if (max_rate < 550000000)
vc4_hdmi->disable_4kp60 = true;

--
b4 0.11.0-dev-99e3a

2022-10-27 14:01:04

by Maxime Ripard

[permalink] [raw]
Subject: [PATCH v5 6/7] drm/vc4: hdmi: Add more checks for 4k resolutions

From: Dom Cobley <[email protected]>

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 <[email protected]>
Reviewed-by: Dave Stevenson <[email protected]>
Signed-off-by: Maxime Ripard <[email protected]>
---
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 8da2b80fdbd3..515228682e8e 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_hdmi_20;
+
+ /*
+ * 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 98a6643821bb..1b201df2d4f9 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 = &vc4_hdmi->connector;
@@ -1765,6 +1766,12 @@ vc4_hdmi_encoder_clock_valid(const struct vc4_hdmi *vc4_hdmi,
if (!vc4->hvs->vc5_hdmi_enable_hdmi_20 && 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 fc4b7310bf63..c4453a5ae163 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 >= 550000000)
hvs->vc5_hdmi_enable_hdmi_20 = true;

+ if (max_rate >= 600000000)
+ hvs->vc5_hdmi_enable_4096by2160 = true;
+
hvs->max_core_rate = max_rate;

ret = clk_prepare_enable(hvs->core_clk);

--
b4 0.11.0-dev-99e3a

2022-10-27 14:03:12

by Maxime Ripard

[permalink] [raw]
Subject: [PATCH v5 3/7] firmware: raspberrypi: Provide a helper to query a clock max rate

The firmware allows to query for its clocks the operating range of a
given clock. We'll need this for some drivers (KMS, in particular) to
infer the state of some configuration options, so let's create a
function to do so.

Acked-by: Stephen Boyd <[email protected]>
Reviewed-by: Florian Fainelli <[email protected]>
Signed-off-by: Maxime Ripard <[email protected]>
---
drivers/firmware/raspberrypi.c | 20 ++++++++++++++++++++
include/soc/bcm2835/raspberrypi-firmware.h | 26 ++++++++++++++++++++++++++
2 files changed, 46 insertions(+)

diff --git a/drivers/firmware/raspberrypi.c b/drivers/firmware/raspberrypi.c
index 932a8bef22fb..b15aa6fce0e9 100644
--- a/drivers/firmware/raspberrypi.c
+++ b/drivers/firmware/raspberrypi.c
@@ -228,6 +228,26 @@ static void rpi_register_clk_driver(struct device *dev)
-1, NULL, 0);
}

+unsigned int rpi_firmware_clk_get_max_rate(struct rpi_firmware *fw, unsigned int id)
+{
+ struct rpi_firmware_clk_rate_request msg =
+ RPI_FIRMWARE_CLK_RATE_REQUEST(id);
+ int ret;
+
+ ret = rpi_firmware_property(fw, RPI_FIRMWARE_GET_MAX_CLOCK_RATE,
+ &msg, sizeof(msg));
+ if (ret)
+ /*
+ * If our firmware doesn't support that operation, or fails, we
+ * assume the maximum clock rate is absolute maximum we can
+ * store over our type.
+ */
+ return UINT_MAX;
+
+ return le32_to_cpu(msg.rate);
+}
+EXPORT_SYMBOL_GPL(rpi_firmware_clk_get_max_rate);
+
static void rpi_firmware_delete(struct kref *kref)
{
struct rpi_firmware *fw = container_of(kref, struct rpi_firmware,
diff --git a/include/soc/bcm2835/raspberrypi-firmware.h b/include/soc/bcm2835/raspberrypi-firmware.h
index 9b1db12d013f..ab955591cb72 100644
--- a/include/soc/bcm2835/raspberrypi-firmware.h
+++ b/include/soc/bcm2835/raspberrypi-firmware.h
@@ -155,12 +155,32 @@ enum rpi_firmware_clk_id {
RPI_FIRMWARE_NUM_CLK_ID,
};

+/**
+ * struct rpi_firmware_clk_rate_request - Firmware Request for a rate
+ * @id: ID of the clock being queried
+ * @rate: Rate in Hertz. Set by the firmware.
+ *
+ * Used by @RPI_FIRMWARE_GET_CLOCK_RATE, @RPI_FIRMWARE_GET_CLOCK_MEASURED,
+ * @RPI_FIRMWARE_GET_MAX_CLOCK_RATE and @RPI_FIRMWARE_GET_MIN_CLOCK_RATE.
+ */
+struct rpi_firmware_clk_rate_request {
+ __le32 id;
+ __le32 rate;
+} __packed;
+
+#define RPI_FIRMWARE_CLK_RATE_REQUEST(_id) \
+ { \
+ .id = _id, \
+ }
+
#if IS_ENABLED(CONFIG_RASPBERRYPI_FIRMWARE)
int rpi_firmware_property(struct rpi_firmware *fw,
u32 tag, void *data, size_t len);
int rpi_firmware_property_list(struct rpi_firmware *fw,
void *data, size_t tag_size);
void rpi_firmware_put(struct rpi_firmware *fw);
+unsigned int rpi_firmware_clk_get_max_rate(struct rpi_firmware *fw,
+ unsigned int id);
struct device_node *rpi_firmware_find_node(void);
struct rpi_firmware *rpi_firmware_get(struct device_node *firmware_node);
struct rpi_firmware *devm_rpi_firmware_get(struct device *dev,
@@ -180,6 +200,12 @@ static inline int rpi_firmware_property_list(struct rpi_firmware *fw,

static inline void rpi_firmware_put(struct rpi_firmware *fw) { }

+static inline unsigned int rpi_firmware_clk_get_max_rate(struct rpi_firmware *fw,
+ unsigned int id)
+{
+ return UINT_MAX;
+}
+
static inline struct device_node *rpi_firmware_find_node(void)
{
return NULL;

--
b4 0.11.0-dev-99e3a

2022-10-27 14:09:40

by Dave Stevenson

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

On Thu, 27 Oct 2022 at 13:53, Maxime Ripard <[email protected]> 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 <[email protected]>

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

Reviewed-by: Dave Stevenson <[email protected]>

> ---
> 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 <linux/pm_runtime.h>
> #include <linux/rational.h>
> #include <linux/reset.h>
> -#include <soc/bcm2835/raspberrypi-clocks.h>
> #include <sound/dmaengine_pcm.h>
> #include <sound/hdmi-codec.h>
> #include <sound/pcm_drm_eld.h>
> @@ -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 = &vc4_hdmi->connector;
> const struct drm_display_info *info = &connector->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 == 600000000) {
> - 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 < 550000000)
> - 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..fc4b7310bf63 100644
> --- a/drivers/gpu/drm/vc4/vc4_hvs.c
> +++ b/drivers/gpu/drm/vc4/vc4_hvs.c
> @@ -28,6 +28,8 @@
> #include <drm/drm_drv.h>
> #include <drm/drm_vblank.h>
>
> +#include <soc/bcm2835/raspberrypi-firmware.h>
> +
> #include "vc4_drv.h"
> #include "vc4_regs.h"
>
> @@ -791,12 +793,33 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data)
> hvs->regset.nregs = ARRAY_SIZE(hvs_regs);
>
> if (vc4->is_vc5) {
> + struct rpi_firmware *firmware;
> + struct device_node *node;
> + unsigned int max_rate;
> +
> + node = rpi_firmware_find_node();
> + if (!node)
> + return -EINVAL;
> +
> + firmware = rpi_firmware_get(node);
> + of_node_put(node);
> + if (!firmware)
> + return -EPROBE_DEFER;
> +
> hvs->core_clk = devm_clk_get(&pdev->dev, NULL);
> if (IS_ERR(hvs->core_clk)) {
> dev_err(&pdev->dev, "Couldn't get core clock\n");
> return PTR_ERR(hvs->core_clk);
> }
>
> + max_rate = rpi_firmware_clk_get_max_rate(firmware,
> + RPI_FIRMWARE_CORE_CLK_ID);
> + rpi_firmware_put(firmware);
> + if (max_rate >= 550000000)
> + hvs->vc5_hdmi_enable_hdmi_20 = true;
> +
> + hvs->max_core_rate = max_rate;
> +
> ret = clk_prepare_enable(hvs->core_clk);
> if (ret) {
> dev_err(&pdev->dev, "Couldn't enable the core clock\n");
>
> --
> b4 0.11.0-dev-99e3a

2022-10-27 15:07:51

by Maxime Ripard

[permalink] [raw]
Subject: Re: [PATCH v5 0/7] drm/vc4: Fix the core clock behaviour

Hi Florian,

On Thu, Oct 27, 2022 at 02:52:40PM +0200, Maxime Ripard wrote:
> Hi,
>
> Those patches used to be part of a larger clock fixes series:
> https://lore.kernel.org/linux-clk/[email protected]/
>
> However, that series doesn't seem to be getting anywhere, so I've split out
> these patches that fix a regression that has been there since 5.18 and that
> prevents the 4k output from working on the RaspberryPi4.
>
> Hopefully, we will be able to merge those patches through the DRM tree to avoid
> any further disruption.

I intend to get this through drm-misc, but you just gave your
Reviewed-by on all the firmware patches but the first. Are you ok with
this? If so, can I add your Acked-by?

Thanks!
Maxime


Attachments:
(No filename) (767.00 B)
signature.asc (235.00 B)
Download all attachments

2022-10-27 16:20:19

by Florian Fainelli

[permalink] [raw]
Subject: Re: [PATCH v5 0/7] drm/vc4: Fix the core clock behaviour



On 10/27/2022 7:59 AM, Maxime Ripard wrote:
> Hi Florian,
>
> On Thu, Oct 27, 2022 at 02:52:40PM +0200, Maxime Ripard wrote:
>> Hi,
>>
>> Those patches used to be part of a larger clock fixes series:
>> https://lore.kernel.org/linux-clk/[email protected]/
>>
>> However, that series doesn't seem to be getting anywhere, so I've split out
>> these patches that fix a regression that has been there since 5.18 and that
>> prevents the 4k output from working on the RaspberryPi4.
>>
>> Hopefully, we will be able to merge those patches through the DRM tree to avoid
>> any further disruption.
>
> I intend to get this through drm-misc, but you just gave your
> Reviewed-by on all the firmware patches but the first. Are you ok with
> this? If so, can I add your Acked-by?

I don't feel legitimate on any of those patches, but the firmware part
is something that I can understand, gave you an Acked-by for patch #3,
hopefully this allows you to merge through drm-misc now.
--
Florian

2022-10-27 16:51:36

by Florian Fainelli

[permalink] [raw]
Subject: Re: [PATCH v5 3/7] firmware: raspberrypi: Provide a helper to query a clock max rate



On 10/27/2022 5:52 AM, Maxime Ripard wrote:
> The firmware allows to query for its clocks the operating range of a
> given clock. We'll need this for some drivers (KMS, in particular) to
> infer the state of some configuration options, so let's create a
> function to do so.
>
> Acked-by: Stephen Boyd <[email protected]>
> Reviewed-by: Florian Fainelli <[email protected]>
> Signed-off-by: Maxime Ripard <[email protected]>

Acked-by: Florian Fainelli <[email protected]>
--
Florian

2022-10-28 11:39:45

by Maxime Ripard

[permalink] [raw]
Subject: Re: [PATCH v5 0/7] drm/vc4: Fix the core clock behaviour

On Thu, 27 Oct 2022 14:52:40 +0200, Maxime Ripard wrote:
> Those patches used to be part of a larger clock fixes series:
> https://lore.kernel.org/linux-clk/[email protected]/
>
> However, that series doesn't seem to be getting anywhere, so I've split out
> these patches that fix a regression that has been there since 5.18 and that
> prevents the 4k output from working on the RaspberryPi4.
>
> [...]

Applied to drm/drm-misc (drm-misc-next).

Thanks!
Maxime