summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorandroid-build-team Robot <android-build-team-robot@google.com>2018-03-27 18:17:09 +0000
committerandroid-build-team Robot <android-build-team-robot@google.com>2018-03-27 18:17:09 +0000
commit82f3b4dc122e3637b5650988d6bb116c8336d22b (patch)
tree3d4da2293feb7669428e8cf050b9325c82ba4df0
parent030c02f3e0eacf33bed0a4a0111caa7bb4329518 (diff)
parent89c77eb12b4aca41e2776d838b00ed7d2eed8ec5 (diff)
downloadpi-v4.4-o-mr1-iot-preview-8.tar.gz
Change-Id: I943cc4be634340df13c02da3c0f417eff6726a06
-rw-r--r--arch/arm/boot/dts/bcm2710-rpi-3-b.dts4
-rw-r--r--drivers/gpu/drm/vc4/Kconfig8
-rw-r--r--drivers/gpu/drm/vc4/vc4_hdmi.c73
3 files changed, 85 insertions, 0 deletions
diff --git a/arch/arm/boot/dts/bcm2710-rpi-3-b.dts b/arch/arm/boot/dts/bcm2710-rpi-3-b.dts
index 7aff6b77b272..a4857ebb6a30 100644
--- a/arch/arm/boot/dts/bcm2710-rpi-3-b.dts
+++ b/arch/arm/boot/dts/bcm2710-rpi-3-b.dts
@@ -154,6 +154,10 @@
pinctrl-0 = <&i2s_pins>;
};
+&hdmi {
+ hpd-gpios = <&gpio 46 GPIO_ACTIVE_HIGH>;
+};
+
&random {
status = "okay";
};
diff --git a/drivers/gpu/drm/vc4/Kconfig b/drivers/gpu/drm/vc4/Kconfig
index 19b1ec8a6dfb..d41a0499587f 100644
--- a/drivers/gpu/drm/vc4/Kconfig
+++ b/drivers/gpu/drm/vc4/Kconfig
@@ -15,3 +15,11 @@ config DRM_VC4
This driver requires that "avoid_warnings=2" be present in
the config.txt for the firmware, to keep it from smashing
our display setup.
+
+config DRM_VC4_RPIFIRMWARE_EDID
+ bool "EDID from Raspberry Pi Firmware"
+ depends on DRM_VC4
+ default n
+ help
+ Choose this option if you have trouble reading EDID from monitors.
+ This option makes drm driver searches Raspberry Pi firmware to get EDID.
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 2684003343c2..aafbd0cbe072 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -36,6 +36,10 @@
#include "vc4_drv.h"
#include "vc4_regs.h"
+#ifdef CONFIG_DRM_VC4_RPIFIRMWARE_EDID
+#include "soc/bcm2835/raspberrypi-firmware.h"
+#endif /* CONFIG_DRM_VC4_RPIFIRMWARE_EDID */
+
/* General HDMI hardware state. */
struct vc4_hdmi {
struct platform_device *pdev;
@@ -189,6 +193,71 @@ static void vc4_hdmi_connector_destroy(struct drm_connector *connector)
drm_connector_cleanup(connector);
}
+#ifdef CONFIG_DRM_VC4_RPIFIRMWARE_EDID
+static struct edid *vc4_hdmi_connector_rpifirmare_edid(void)
+{
+ struct {
+ u32 no;
+ u32 status;
+ u8 block[EDID_LENGTH];
+ } buffer;
+ struct rpi_firmware *fw;
+ int i, extensions, valid_extensions = 0;
+ u8 *edid, *temp_edid;
+
+ fw = rpi_firmware_get(NULL);
+ if (!fw)
+ return NULL;
+
+ /* read the first block of EDID */
+ buffer.no = 0;
+ if (rpi_firmware_property(fw, RPI_FIRMWARE_GET_EDID_BLOCK,
+ &buffer, sizeof(buffer))) {
+ DRM_ERROR("Failed to get EDID block from RPI firmware\n");
+ return NULL;
+ }
+ if (!drm_edid_block_valid(buffer.block, buffer.no, false, NULL))
+ return NULL;
+
+ extensions = buffer.block[0x7e];
+ edid = kzalloc(EDID_LENGTH * (extensions + 1), GFP_KERNEL);
+ if (!edid)
+ return NULL;
+ memcpy(edid, buffer.block, EDID_LENGTH);
+
+ /* read the rest part(extensions) of EDID, if any */
+ for (i = 1; i <= extensions && !buffer.status; i++) {
+ buffer.no = i;
+ if (rpi_firmware_property(fw, RPI_FIRMWARE_GET_EDID_BLOCK,
+ &buffer, sizeof(buffer))) {
+ DRM_ERROR("Failed to get EDID block from RPI firmware\n");
+ goto fail;
+ }
+ if (!drm_edid_block_valid(buffer.block, buffer.no, false, NULL))
+ continue;
+ memcpy(edid + (valid_extensions + 1) * EDID_LENGTH,
+ buffer.block, EDID_LENGTH);
+ valid_extensions++;
+ }
+
+ if (valid_extensions != extensions) {
+ edid[EDID_LENGTH - 1] += extensions - valid_extensions;
+ edid[0x7e] = valid_extensions;
+ temp_edid = krealloc(edid, (valid_extensions + 1) * EDID_LENGTH,
+ GFP_KERNEL);
+ if (!temp_edid)
+ goto fail;
+ edid = temp_edid;
+ }
+
+ return (struct edid *)edid;
+
+fail:
+ kfree(edid);
+ return NULL;
+}
+#endif /* CONFIG_DRM_VC4_RPIFIRMWARE_EDID */
+
static int vc4_hdmi_connector_get_modes(struct drm_connector *connector)
{
struct vc4_hdmi_connector *vc4_connector =
@@ -201,6 +270,10 @@ static int vc4_hdmi_connector_get_modes(struct drm_connector *connector)
struct edid *edid;
edid = drm_get_edid(connector, vc4->hdmi->ddc);
+#ifdef CONFIG_DRM_VC4_RPIFIRMWARE_EDID
+ if (!edid)
+ edid = vc4_hdmi_connector_rpifirmare_edid();
+#endif /* CONFIG_DRM_VC4_RPIFIRMWARE_EDID */
if (!edid)
return -ENODEV;