From cddd4591404fb4c53dc0b3c0b15b942cdbed4356 Mon Sep 17 00:00:00 2001 From: Yangbo Lu Date: Fri, 10 Apr 2020 10:47:05 +0800 Subject: 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 --- ...u-cdn-imx8qm-Add-firmware-loading-support.patch | 268 +++++++++++++++++++++ 1 file changed, 268 insertions(+) create mode 100644 target/linux/layerscape/patches-5.4/805-display-0056-LF-794-3-gpu-cdn-imx8qm-Add-firmware-loading-support.patch (limited to 'target/linux/layerscape/patches-5.4/805-display-0056-LF-794-3-gpu-cdn-imx8qm-Add-firmware-loading-support.patch') 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 +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 +Reviewed-by: Sandor Yu +Acked-by: Wen He +Signed-off-by: Dong Aisheng +--- + 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 + #include ++#include + #include + #include + #include + + #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); + -- cgit v1.2.3