diff options
author | android-build-team Robot <android-build-team-robot@google.com> | 2018-03-27 18:17:09 +0000 |
---|---|---|
committer | android-build-team Robot <android-build-team-robot@google.com> | 2018-03-27 18:17:09 +0000 |
commit | 82f3b4dc122e3637b5650988d6bb116c8336d22b (patch) | |
tree | 3d4da2293feb7669428e8cf050b9325c82ba4df0 | |
parent | 030c02f3e0eacf33bed0a4a0111caa7bb4329518 (diff) | |
parent | 89c77eb12b4aca41e2776d838b00ed7d2eed8ec5 (diff) | |
download | pi-v4.4-o-mr1-iot-preview-8.tar.gz |
Snap for 4620303 from 89c77eb12b4aca41e2776d838b00ed7d2eed8ec5 to oc-mr1-iot-releaseandroid-o-mr1-iot-release-1.0.8android-o-mr1-iot-release-1.0.7android-o-mr1-iot-release-1.0.5android-o-mr1-iot-release-1.0.4android-o-mr1-iot-release-1.0.3android-o-mr1-iot-release-1.0.2android-o-mr1-iot-release-1.0.14android-o-mr1-iot-release-1.0.13android-o-mr1-iot-release-1.0.12android-o-mr1-iot-release-1.0.10android-o-mr1-iot-release-1.0.1android-o-mr1-iot-release-1.0.0android-o-mr1-iot-preview-8oreo-mr1-iot-releaseo-mr1-iot-preview-8
Change-Id: I943cc4be634340df13c02da3c0f417eff6726a06
-rw-r--r-- | arch/arm/boot/dts/bcm2710-rpi-3-b.dts | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/vc4/Kconfig | 8 | ||||
-rw-r--r-- | drivers/gpu/drm/vc4/vc4_hdmi.c | 73 |
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; |