aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/layerscape/patches-5.4/805-display-0056-LF-794-3-gpu-cdn-imx8qm-Add-firmware-loading-support.patch
diff options
context:
space:
mode:
authorYangbo Lu <yangbo.lu@nxp.com>2020-04-10 10:47:05 +0800
committerPetr Štetiar <ynezz@true.cz>2020-05-07 12:53:06 +0200
commitcddd4591404fb4c53dc0b3c0b15b942cdbed4356 (patch)
tree392c1179de46b0f804e3789edca19069b64e6b44 /target/linux/layerscape/patches-5.4/805-display-0056-LF-794-3-gpu-cdn-imx8qm-Add-firmware-loading-support.patch
parentd1d2c0b5579ea4f69a42246c9318539d61ba1999 (diff)
downloadupstream-cddd4591404fb4c53dc0b3c0b15b942cdbed4356.tar.gz
upstream-cddd4591404fb4c53dc0b3c0b15b942cdbed4356.tar.bz2
upstream-cddd4591404fb4c53dc0b3c0b15b942cdbed4356.zip
layerscape: add patches-5.4
Add patches for linux-5.4. The patches are from NXP LSDK-20.04 release which was tagged LSDK-20.04-V5.4. https://source.codeaurora.org/external/qoriq/qoriq-components/linux/ For boards LS1021A-IOT, and Traverse-LS1043 which are not involved in LSDK, port the dts patches from 4.14. The patches are sorted into the following categories: 301-arch-xxxx 302-dts-xxxx 303-core-xxxx 701-net-xxxx 801-audio-xxxx 802-can-xxxx 803-clock-xxxx 804-crypto-xxxx 805-display-xxxx 806-dma-xxxx 807-gpio-xxxx 808-i2c-xxxx 809-jailhouse-xxxx 810-keys-xxxx 811-kvm-xxxx 812-pcie-xxxx 813-pm-xxxx 814-qe-xxxx 815-sata-xxxx 816-sdhc-xxxx 817-spi-xxxx 818-thermal-xxxx 819-uart-xxxx 820-usb-xxxx 821-vfio-xxxx Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
Diffstat (limited to 'target/linux/layerscape/patches-5.4/805-display-0056-LF-794-3-gpu-cdn-imx8qm-Add-firmware-loading-support.patch')
-rw-r--r--target/linux/layerscape/patches-5.4/805-display-0056-LF-794-3-gpu-cdn-imx8qm-Add-firmware-loading-support.patch268
1 files changed, 268 insertions, 0 deletions
diff --git a/target/linux/layerscape/patches-5.4/805-display-0056-LF-794-3-gpu-cdn-imx8qm-Add-firmware-loading-support.patch b/target/linux/layerscape/patches-5.4/805-display-0056-LF-794-3-gpu-cdn-imx8qm-Add-firmware-loading-support.patch
new file mode 100644
index 0000000000..ca7f488b8b
--- /dev/null
+++ b/target/linux/layerscape/patches-5.4/805-display-0056-LF-794-3-gpu-cdn-imx8qm-Add-firmware-loading-support.patch
@@ -0,0 +1,268 @@
+From 020578dd022e5d869db52e79c5aba95c1f1a84ec Mon Sep 17 00:00:00 2001
+From: Abel Vesa <abel.vesa@nxp.com>
+Date: Wed, 11 Dec 2019 09:21:23 +0200
+Subject: [PATCH] LF-794-3 gpu: cdn: imx8qm: Add firmware loading support
+
+This allows the HDP i.MX8QM driver to load the firmware on init
+and resume. In order to have backward compatibility, if there is
+no firmware-name property defined in the hdmi node, the driver
+probing sequence skips the firmware loading.
+
+Also, if u-boot has loaded already a firmware, we run with that
+but when probing the driver, the request_firmware_nowait is used
+to locate and keep safe the firmware for when suspend/resume happens.
+
+This leads to 4 possible scenarios:
+
+1. u-boot loads the firmware, the kernel driver finds the firmware
+when rootfs is mounted. This is the most desirable scenario. Also
+this is the only scenario that allows the hdmi to work after resume.
+
+2. u-boot loads the firmware, the kernel driver _doesn't_ find
+the firmware in rootfs. If there is no suspend ever happening,
+the kernel driver will keep using the firmware that was loaded by
+u-boot. On the first suspend/resume, the firmware is lost
+because the HDMI IP gets powered down.
+
+3. u-boot doesn't load the firmare, the kernel driver probing
+tries to load the firmware, assuming this is available
+(see CONFIG_EXTRA_FIRMWARE).
+
+4. u-boot doesn't load the firmware and the kernel driver is not
+able to find it either. The probing fails and there is no HDMI
+available in linux.
+
+Signed-off-by: Abel Vesa <abel.vesa@nxp.com>
+Reviewed-by: Sandor Yu <sandor.yu@nxp.com>
+Acked-by: Wen He <wen.he_1@nxp.com>
+Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
+---
+ drivers/gpu/drm/imx/cdn-mhdp-imx8qm.c | 78 +++++++++++++++++++++++++++++++++--
+ drivers/gpu/drm/imx/cdn-mhdp-imxdrv.c | 30 ++++++++++++++
+ drivers/gpu/drm/imx/cdns-mhdp-imx.h | 4 ++
+ include/drm/bridge/cdns-mhdp-common.h | 3 ++
+ 4 files changed, 111 insertions(+), 4 deletions(-)
+
+--- a/drivers/gpu/drm/imx/cdn-mhdp-imx8qm.c
++++ b/drivers/gpu/drm/imx/cdn-mhdp-imx8qm.c
+@@ -7,12 +7,17 @@
+ */
+ #include <dt-bindings/firmware/imx/rsrc.h>
+ #include <linux/firmware/imx/sci.h>
++#include <linux/firmware.h>
+ #include <linux/pm_domain.h>
+ #include <linux/clk.h>
+ #include <drm/drmP.h>
+
+ #include "cdns-mhdp-imx.h"
+
++#define FW_IRAM_OFFSET 0x2000
++#define FW_IRAM_SIZE 0x10000
++#define FW_DRAM_SIZE 0x8000
++
+ #define PLL_800MHZ (800000000)
+
+ #define HDP_DUAL_MODE_MIN_PCLK_RATE 300000 /* KHz */
+@@ -517,24 +522,69 @@ void cdns_mhdp_pclk_rate_imx8qm(struct c
+ imx8qm_pixel_link_mux(imx_mhdp);
+ }
+
+-int cdns_mhdp_firmware_init_imx8qm(struct cdns_mhdp_device *mhdp)
++static void cdns_mhdp_firmware_load_cont(const struct firmware *fw, void *context)
+ {
+- struct imx_mhdp_device *imx_mhdp =
+- container_of(mhdp, struct imx_mhdp_device, mhdp);
++ struct imx_mhdp_device *imx_mhdp = context;
++
++ imx_mhdp->fw = fw;
++}
++
++static int cdns_mhdp_load_firmware_imx8qm(struct imx_mhdp_device *imx_mhdp)
++{
++ const u8 *iram;
++ const u8 *dram;
+ u32 rate;
+ int ret;
+
+ /* configure HDMI/DP core clock */
+ rate = clk_get_rate(imx_mhdp->clks.clk_core);
+- if (mhdp->is_ls1028a)
++ if (imx_mhdp->mhdp.is_ls1028a)
+ rate = rate / 4;
+
+ cdns_mhdp_set_fw_clk(&imx_mhdp->mhdp, rate);
+
++ /* skip fw loading if none is specified */
++ if (!imx_mhdp->firmware_name)
++ goto out;
++
++ if (!imx_mhdp->fw) {
++ ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOHOTPLUG,
++ imx_mhdp->firmware_name,
++ imx_mhdp->mhdp.dev, GFP_KERNEL,
++ imx_mhdp,
++ cdns_mhdp_firmware_load_cont);
++ if (ret < 0) {
++ DRM_ERROR("failed to load firmware\n");
++ return -ENOENT;
++ }
++ } else {
++ iram = imx_mhdp->fw->data + FW_IRAM_OFFSET;
++ dram = iram + FW_IRAM_SIZE;
++
++ cdns_mhdp_load_firmware(&imx_mhdp->mhdp,
++ (const u32 *) iram, FW_IRAM_SIZE,
++ (const u32 *) dram, FW_DRAM_SIZE);
++ }
++
++out:
+ /* un-reset ucpu */
+ cdns_mhdp_bus_write(0, &imx_mhdp->mhdp, APB_CTRL);
+ DRM_INFO("Started firmware!\n");
+
++ return 0;
++}
++
++int cdns_mhdp_firmware_init_imx8qm(struct cdns_mhdp_device *mhdp)
++{
++ struct imx_mhdp_device *imx_mhdp =
++ container_of(mhdp, struct imx_mhdp_device, mhdp);
++ int ret;
++
++ /* load firmware */
++ ret = cdns_mhdp_load_firmware_imx8qm(imx_mhdp);
++ if (ret)
++ return ret;
++
+ ret = cdns_mhdp_check_alive(&imx_mhdp->mhdp);
+ if (ret == false) {
+ DRM_ERROR("NO HDMI FW running\n");
+@@ -550,3 +600,23 @@ int cdns_mhdp_firmware_init_imx8qm(struc
+
+ return 0;
+ }
++
++int cdns_mhdp_suspend_imx8qm(struct cdns_mhdp_device *mhdp)
++{
++ struct imx_mhdp_device *imx_mhdp =
++ container_of(mhdp, struct imx_mhdp_device, mhdp);
++
++ imx8qm_pixel_clk_disable(imx_mhdp);
++
++ return 0;
++}
++
++int cdns_mhdp_resume_imx8qm(struct cdns_mhdp_device *mhdp)
++{
++ struct imx_mhdp_device *imx_mhdp =
++ container_of(mhdp, struct imx_mhdp_device, mhdp);
++
++ imx8qm_pixel_clk_enable(imx_mhdp);
++
++ return cdns_mhdp_firmware_init_imx8qm(mhdp);
++}
+--- a/drivers/gpu/drm/imx/cdn-mhdp-imxdrv.c
++++ b/drivers/gpu/drm/imx/cdn-mhdp-imxdrv.c
+@@ -82,6 +82,8 @@ static struct cdns_plat_data imx8qm_hdmi
+ .phy_video_valid = cdns_hdmi_phy_video_valid_imx8qm,
+ .power_on = cdns_mhdp_power_on_imx8qm,
+ .firmware_init = cdns_mhdp_firmware_init_imx8qm,
++ .resume = cdns_mhdp_resume_imx8qm,
++ .suspend = cdns_mhdp_suspend_imx8qm,
+ .pclk_rate = cdns_mhdp_pclk_rate_imx8qm,
+ .plat_init = cdns_mhdp_plat_init_imx8qm,
+ .plat_deinit = cdns_mhdp_plat_deinit_imx8qm,
+@@ -96,6 +98,8 @@ static struct cdns_plat_data imx8qm_dp_d
+ .phy_set = cdns_dp_phy_set_imx8qm,
+ .power_on = cdns_mhdp_power_on_imx8qm,
+ .firmware_init = cdns_mhdp_firmware_init_imx8qm,
++ .resume = cdns_mhdp_resume_imx8qm,
++ .suspend = cdns_mhdp_suspend_imx8qm,
+ .pclk_rate = cdns_mhdp_pclk_rate_imx8qm,
+ .plat_init = cdns_mhdp_plat_init_imx8qm,
+ .plat_deinit = cdns_mhdp_plat_deinit_imx8qm,
+@@ -157,6 +161,9 @@ static int cdns_mhdp_imx_bind(struct dev
+ encoder = &imx_mhdp->encoder;
+
+ encoder->possible_crtcs = drm_of_find_possible_crtcs(drm, dev->of_node);
++
++ ret = of_property_read_string(pdev->dev.of_node, "firmware-name",
++ &imx_mhdp->firmware_name);
+ /*
+ * If we failed to find the CRTC(s) which this encoder is
+ * supposed to be connected to, it's because the CRTC has
+@@ -198,6 +205,24 @@ static const struct component_ops cdns_m
+ .unbind = cdns_mhdp_imx_unbind,
+ };
+
++static int cdns_mhdp_imx_suspend(struct device *dev)
++{
++ struct imx_mhdp_device *imx_mhdp = dev_get_drvdata(dev);
++
++ cdns_mhdp_plat_call(&imx_mhdp->mhdp, suspend);
++
++ return 0;
++}
++
++static int cdns_mhdp_imx_resume(struct device *dev)
++{
++ struct imx_mhdp_device *imx_mhdp = dev_get_drvdata(dev);
++
++ cdns_mhdp_plat_call(&imx_mhdp->mhdp, resume);
++
++ return 0;
++}
++
+ static int cdns_mhdp_imx_probe(struct platform_device *pdev)
+ {
+ return component_add(&pdev->dev, &cdns_mhdp_imx_ops);
+@@ -210,12 +235,17 @@ static int cdns_mhdp_imx_remove(struct p
+ return 0;
+ }
+
++static const struct dev_pm_ops cdns_mhdp_imx_pm_ops = {
++ SET_LATE_SYSTEM_SLEEP_PM_OPS(cdns_mhdp_imx_suspend, cdns_mhdp_imx_resume)
++};
++
+ static struct platform_driver cdns_mhdp_imx_platform_driver = {
+ .probe = cdns_mhdp_imx_probe,
+ .remove = cdns_mhdp_imx_remove,
+ .driver = {
+ .name = "cdns-mhdp-imx",
+ .of_match_table = cdns_mhdp_imx_dt_ids,
++ .pm = &cdns_mhdp_imx_pm_ops,
+ },
+ };
+
+--- a/drivers/gpu/drm/imx/cdns-mhdp-imx.h
++++ b/drivers/gpu/drm/imx/cdns-mhdp-imx.h
+@@ -50,6 +50,8 @@ struct imx_mhdp_device {
+ bool active;
+ bool suspended;
+ struct imx_hdp_clks clks;
++ const struct firmware *fw;
++ const char *firmware_name;
+
+ int bus_type;
+
+@@ -65,6 +67,8 @@ void cdns_mhdp_plat_init_imx8qm(struct c
+ void cdns_mhdp_plat_deinit_imx8qm(struct cdns_mhdp_device *mhdp);
+ void cdns_mhdp_pclk_rate_imx8qm(struct cdns_mhdp_device *mhdp);
+ int cdns_mhdp_firmware_init_imx8qm(struct cdns_mhdp_device *mhdp);
++int cdns_mhdp_resume_imx8qm(struct cdns_mhdp_device *mhdp);
++int cdns_mhdp_suspend_imx8qm(struct cdns_mhdp_device *mhdp);
+ int cdns_mhdp_power_on_imx8qm(struct cdns_mhdp_device *mhdp);
+ int cdns_mhdp_power_on_ls1028a(struct cdns_mhdp_device *mhdp);
+ void cdns_mhdp_pclk_rate_ls1028a(struct cdns_mhdp_device *mhdp);
+--- a/include/drm/bridge/cdns-mhdp-common.h
++++ b/include/drm/bridge/cdns-mhdp-common.h
+@@ -645,6 +645,9 @@ struct cdns_plat_data {
+ int (*firmware_init)(struct cdns_mhdp_device *mhdp);
+ void (*pclk_rate)(struct cdns_mhdp_device *mhdp);
+
++ int (*suspend)(struct cdns_mhdp_device *mhdp);
++ int (*resume)(struct cdns_mhdp_device *mhdp);
++
+ int (*power_on)(struct cdns_mhdp_device *mhdp);
+ int (*power_off)(struct cdns_mhdp_device *mhdp);
+