drm/vc4_hdmi: Allow hotplug detect to be forced

See: https://forum.libreelec.tv/thread/24783-tv-avr-turns-back-on-right-after-turning-them-off

While the kernel provides a :D flag for assuming device is connected,
it doesn't stop this function from being called and generating a cec_phys_addr_invalidate
message when hotplug is deasserted.

That message provokes a flurry of CEC messages which for many users results in the TV
switching back on again and it's very hard to get it to stay switched off.

It seems to only occur with an AVR and TV connected but has been observed across a
number of manufacturers.

The issue started with https://github.com/raspberrypi/linux/pull/4371
and this provides an optional way of getting back the old behaviour

Signed-off-by: Dom Cobley <popcornmix@gmail.com>
This commit is contained in:
Dom Cobley
2022-06-01 15:43:51 +01:00
parent e6f88767ea
commit 427c6bd883

View File

@@ -39,6 +39,8 @@
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/component.h> #include <linux/component.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/of_address.h> #include <linux/of_address.h>
#include <linux/of_gpio.h> #include <linux/of_gpio.h>
#include <linux/of_platform.h> #include <linux/of_platform.h>
@@ -111,6 +113,10 @@
#define CEC_CLOCK_FREQ 40000 #define CEC_CLOCK_FREQ 40000
#define HDMI_14_MAX_TMDS_CLK (340 * 1000 * 1000) #define HDMI_14_MAX_TMDS_CLK (340 * 1000 * 1000)
/* bit field to force hotplug detection. bit0 = HDMI0 */
static int force_hotplug = 0;
module_param(force_hotplug, int, 0644);
static const char * const output_format_str[] = { static const char * const output_format_str[] = {
[VC4_HDMI_OUTPUT_RGB] = "RGB", [VC4_HDMI_OUTPUT_RGB] = "RGB",
[VC4_HDMI_OUTPUT_YUV420] = "YUV 4:2:0", [VC4_HDMI_OUTPUT_YUV420] = "YUV 4:2:0",
@@ -247,7 +253,9 @@ vc4_hdmi_connector_detect(struct drm_connector *connector, bool force)
WARN_ON(pm_runtime_resume_and_get(&vc4_hdmi->pdev->dev)); WARN_ON(pm_runtime_resume_and_get(&vc4_hdmi->pdev->dev));
if (vc4_hdmi->hpd_gpio) { if (force_hotplug & BIT(vc4_hdmi->encoder.base.type - VC4_ENCODER_TYPE_HDMI0))
connected = true;
else if (vc4_hdmi->hpd_gpio) {
if (gpio_get_value_cansleep(vc4_hdmi->hpd_gpio) ^ if (gpio_get_value_cansleep(vc4_hdmi->hpd_gpio) ^
vc4_hdmi->hpd_active_low) vc4_hdmi->hpd_active_low)
connected = true; connected = true;