[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20210507150515.257424-10-maxime@cerno.tech>
Date: Fri, 7 May 2021 17:05:12 +0200
From: Maxime Ripard <maxime@...no.tech>
To: Maarten Lankhorst <maarten.lankhorst@...ux.intel.com>,
Thomas Zimmermann <tzimmermann@...e.de>,
Maxime Ripard <maxime@...no.tech>,
dri-devel@...ts.freedesktop.org,
Daniel Vetter <daniel.vetter@...el.com>,
David Airlie <airlied@...ux.ie>
Cc: Eric Anholt <eric@...olt.net>,
Nicolas Saenz Julienne <nsaenz@...nel.org>,
bcm-kernel-feedback-list@...adcom.com,
linux-rpi-kernel@...ts.infradead.org,
Dave Stevenson <dave.stevenson@...pberrypi.com>,
Phil Elwell <phil@...pberrypi.com>,
Tim Gover <tim.gover@...pberrypi.com>,
Dom Cobley <dom@...pberrypi.com>, linux-kernel@...r.kernel.org
Subject: [PATCH v4 09/12] drm/vc4: hdmi: Check and warn if we can't reach 4kp60 frequencies
In order to reach the frequencies needed to output at 594MHz, the
firmware needs to be configured with the appropriate parameters in the
config.txt file (enable_hdmi_4kp60 and force_turbo).
Let's detect it at bind time, warn the user if we can't, and filter out
the relevant modes.
Acked-by: Thomas Zimmermann <tzimmermann@...e.de>
Reviewed-by: Dave Stevenson <dave.stevenson@...pberrypi.com>
Signed-off-by: Maxime Ripard <maxime@...no.tech>
---
drivers/gpu/drm/vc4/vc4_hdmi.c | 31 +++++++++++++++++++++++++++++++
drivers/gpu/drm/vc4/vc4_hdmi.h | 8 ++++++++
2 files changed, 39 insertions(+)
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index c50dc5a59b2f..01d24ce8a795 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -94,6 +94,11 @@
#define HDMI_14_MAX_TMDS_CLK (340 * 1000 * 1000)
+static bool vc4_hdmi_mode_needs_scrambling(const struct drm_display_mode *mode)
+{
+ return (mode->clock * 1000) > HDMI_14_MAX_TMDS_CLK;
+}
+
static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused)
{
struct drm_info_node *node = (struct drm_info_node *)m->private;
@@ -210,6 +215,18 @@ 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) {
+ struct drm_device *drm = connector->dev;
+ struct drm_display_mode *mode;
+
+ list_for_each_entry(mode, &connector->probed_modes, head) {
+ if (vc4_hdmi_mode_needs_scrambling(mode)) {
+ drm_warn_once(drm, "The core clock cannot reach frequencies high enough to support 4k @ 60Hz.");
+ drm_warn_once(drm, "Please change your config.txt file to add hdmi_enable_4kp60.");
+ }
+ }
+ }
+
return ret;
}
@@ -959,6 +976,9 @@ static int vc4_hdmi_encoder_atomic_check(struct drm_encoder *encoder,
if (pixel_rate > vc4_hdmi->variant->max_pixel_clock)
return -EINVAL;
+ if (vc4_hdmi->disable_4kp60 && (pixel_rate > HDMI_14_MAX_TMDS_CLK))
+ return -EINVAL;
+
vc4_state->pixel_rate = pixel_rate;
return 0;
@@ -978,6 +998,9 @@ vc4_hdmi_encoder_mode_valid(struct drm_encoder *encoder,
if ((mode->clock * 1000) > vc4_hdmi->variant->max_pixel_clock)
return MODE_CLOCK_HIGH;
+ if (vc4_hdmi->disable_4kp60 && vc4_hdmi_mode_needs_scrambling(mode))
+ return MODE_CLOCK_HIGH;
+
return MODE_OK;
}
@@ -1993,6 +2016,14 @@ 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);
+ long max_rate = clk_round_rate(vc4->hvs->core_clk, 550000000);
+
+ if (max_rate < 550000000)
+ vc4_hdmi->disable_4kp60 = true;
+ }
+
if (vc4_hdmi->variant->reset)
vc4_hdmi->variant->reset(vc4_hdmi);
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
index 3cebd1fd00fc..3cd021136402 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
@@ -154,6 +154,14 @@ 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;
--
2.31.1
Powered by blists - more mailing lists