Commit 86e3a65f authored by Maxime Ripard's avatar Maxime Ripard

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: default avatarThomas Zimmermann <tzimmermann@suse.de>
Reviewed-by: default avatarDave Stevenson <dave.stevenson@raspberrypi.com>
Signed-off-by: default avatarMaxime Ripard <maxime@cerno.tech>
Link: https://patchwork.freedesktop.org/patch/msgid/20210507150515.257424-10-maxime@cerno.tech
parent 7d9061e0
...@@ -94,6 +94,11 @@ ...@@ -94,6 +94,11 @@
#define HDMI_14_MAX_TMDS_CLK (340 * 1000 * 1000) #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) static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused)
{ {
struct drm_info_node *node = (struct drm_info_node *)m->private; 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) ...@@ -210,6 +215,18 @@ static int vc4_hdmi_connector_get_modes(struct drm_connector *connector)
ret = drm_add_edid_modes(connector, edid); ret = drm_add_edid_modes(connector, edid);
kfree(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; return ret;
} }
...@@ -1015,6 +1032,9 @@ static int vc4_hdmi_encoder_atomic_check(struct drm_encoder *encoder, ...@@ -1015,6 +1032,9 @@ static int vc4_hdmi_encoder_atomic_check(struct drm_encoder *encoder,
if (pixel_rate > vc4_hdmi->variant->max_pixel_clock) if (pixel_rate > vc4_hdmi->variant->max_pixel_clock)
return -EINVAL; return -EINVAL;
if (vc4_hdmi->disable_4kp60 && (pixel_rate > HDMI_14_MAX_TMDS_CLK))
return -EINVAL;
vc4_state->pixel_rate = pixel_rate; vc4_state->pixel_rate = pixel_rate;
return 0; return 0;
...@@ -1034,6 +1054,9 @@ vc4_hdmi_encoder_mode_valid(struct drm_encoder *encoder, ...@@ -1034,6 +1054,9 @@ vc4_hdmi_encoder_mode_valid(struct drm_encoder *encoder,
if ((mode->clock * 1000) > vc4_hdmi->variant->max_pixel_clock) if ((mode->clock * 1000) > vc4_hdmi->variant->max_pixel_clock)
return MODE_CLOCK_HIGH; return MODE_CLOCK_HIGH;
if (vc4_hdmi->disable_4kp60 && vc4_hdmi_mode_needs_scrambling(mode))
return MODE_CLOCK_HIGH;
return MODE_OK; return MODE_OK;
} }
...@@ -2049,6 +2072,14 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) ...@@ -2049,6 +2072,14 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
vc4_hdmi->disable_wifi_frequencies = vc4_hdmi->disable_wifi_frequencies =
of_property_read_bool(dev->of_node, "wifi-2.4ghz-coexistence"); 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) if (vc4_hdmi->variant->reset)
vc4_hdmi->variant->reset(vc4_hdmi); vc4_hdmi->variant->reset(vc4_hdmi);
......
...@@ -157,6 +157,14 @@ struct vc4_hdmi { ...@@ -157,6 +157,14 @@ struct vc4_hdmi {
*/ */
bool disable_wifi_frequencies; 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_adapter *cec_adap;
struct cec_msg cec_rx_msg; struct cec_msg cec_rx_msg;
bool cec_tx_ok; bool cec_tx_ok;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment