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@suse.de>
Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
Link: https://patchwork.freedesktop.org/patch/msgid/20210507150515.257424-10-maxime@cerno.tech
This commit is contained in:
Maxime Ripard 2021-05-07 17:05:12 +02:00
parent 7d9061e097
commit 86e3a65fdb
No known key found for this signature in database
GPG key ID: E3EF0D6F671851C5
2 changed files with 39 additions and 0 deletions

View file

@ -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;
}
@ -1015,6 +1032,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;
@ -1034,6 +1054,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;
}
@ -2049,6 +2072,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);

View file

@ -157,6 +157,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;