Commit d9303e79126526507441f59d8eafc90f70e56e85
1 parent
338223a98b
Exists in
emb_lf_v2022.04
MLK-24958-3 video: mxsfb: Add iMX8DXL support to LCDIF driver
Support iMX8DXL in mxsfb driver by below changes: 1. Enable iMX8 in lcdif registers file 2. Add u-boot clock driver support for iMX8 3. Change the FB buffer alignment to align it at allocation. So it won't overlay with other memory at mmu_set_region_dcache_behaviour Signed-off-by: Ye Li <ye.li@nxp.com> Reviewed-by: Peng Fan <peng.fan@nxp.com> (cherry picked from commit 6f02d6894509e0aa79df9d1bdf5029136e1493b5) (cherry picked from commit 9df950e79963c328b1b04d6eb42f43f41217e752) (cherry picked from commit 082b8d3c6e17691edf902781d4bb5d978bcecaa5) (cherry picked from commit 3367dd0c8e9a8a6b868a40e3b4b16523a078289e)
Showing 3 changed files with 66 additions and 9 deletions Inline Diff
arch/arm/include/asm/arch-imx8/imx-regs.h
| 1 | /* SPDX-License-Identifier: GPL-2.0+ */ | 1 | /* SPDX-License-Identifier: GPL-2.0+ */ |
| 2 | /* | 2 | /* |
| 3 | * Copyright 2018, 2021 NXP | 3 | * Copyright 2018, 2021 NXP |
| 4 | */ | 4 | */ |
| 5 | 5 | ||
| 6 | #ifndef __ASM_ARCH_IMX8_REGS_H__ | 6 | #ifndef __ASM_ARCH_IMX8_REGS_H__ |
| 7 | #define __ASM_ARCH_IMX8_REGS_H__ | 7 | #define __ASM_ARCH_IMX8_REGS_H__ |
| 8 | 8 | ||
| 9 | #include <asm/mach-imx/regs-lcdif.h> | ||
| 10 | |||
| 9 | #define ARCH_MXC | 11 | #define ARCH_MXC |
| 10 | 12 | ||
| 11 | #define LPUART_BASE 0x5A060000 | 13 | #define LPUART_BASE 0x5A060000 |
| 12 | 14 | ||
| 13 | #define GPT1_BASE_ADDR 0x5D140000 | 15 | #define GPT1_BASE_ADDR 0x5D140000 |
| 14 | #define SCU_LPUART_BASE 0x33220000 | 16 | #define SCU_LPUART_BASE 0x33220000 |
| 15 | #define GPIO1_BASE_ADDR 0x5D080000 | 17 | #define GPIO1_BASE_ADDR 0x5D080000 |
| 16 | #define GPIO2_BASE_ADDR 0x5D090000 | 18 | #define GPIO2_BASE_ADDR 0x5D090000 |
| 17 | #define GPIO3_BASE_ADDR 0x5D0A0000 | 19 | #define GPIO3_BASE_ADDR 0x5D0A0000 |
| 18 | #define GPIO4_BASE_ADDR 0x5D0B0000 | 20 | #define GPIO4_BASE_ADDR 0x5D0B0000 |
| 19 | #define GPIO5_BASE_ADDR 0x5D0C0000 | 21 | #define GPIO5_BASE_ADDR 0x5D0C0000 |
| 20 | #define GPIO6_BASE_ADDR 0x5D0D0000 | 22 | #define GPIO6_BASE_ADDR 0x5D0D0000 |
| 21 | #define GPIO7_BASE_ADDR 0x5D0E0000 | 23 | #define GPIO7_BASE_ADDR 0x5D0E0000 |
| 22 | #define GPIO8_BASE_ADDR 0x5D0F0000 | 24 | #define GPIO8_BASE_ADDR 0x5D0F0000 |
| 23 | #define LPI2C1_BASE_ADDR 0x5A800000 | 25 | #define LPI2C1_BASE_ADDR 0x5A800000 |
| 24 | #define LPI2C2_BASE_ADDR 0x5A810000 | 26 | #define LPI2C2_BASE_ADDR 0x5A810000 |
| 25 | #define LPI2C3_BASE_ADDR 0x5A820000 | 27 | #define LPI2C3_BASE_ADDR 0x5A820000 |
| 26 | #define LPI2C4_BASE_ADDR 0x5A830000 | 28 | #define LPI2C4_BASE_ADDR 0x5A830000 |
| 27 | #define LPI2C5_BASE_ADDR 0x5A840000 | 29 | #define LPI2C5_BASE_ADDR 0x5A840000 |
| 28 | 30 | ||
| 29 | #define FEC_QUIRK_ENET_MAC | 31 | #define FEC_QUIRK_ENET_MAC |
| 30 | 32 | ||
| 31 | #ifdef CONFIG_IMX8QXP | 33 | #ifdef CONFIG_IMX8QXP |
| 32 | #define LVDS0_PHYCTRL_BASE 0x56221000 | 34 | #define LVDS0_PHYCTRL_BASE 0x56221000 |
| 33 | #define LVDS1_PHYCTRL_BASE 0x56241000 | 35 | #define LVDS1_PHYCTRL_BASE 0x56241000 |
| 34 | #define MIPI0_SS_BASE 0x56220000 | 36 | #define MIPI0_SS_BASE 0x56220000 |
| 35 | #define MIPI1_SS_BASE 0x56240000 | 37 | #define MIPI1_SS_BASE 0x56240000 |
| 36 | #endif | 38 | #endif |
| 37 | 39 | ||
| 38 | #ifdef CONFIG_IMX8QM | 40 | #ifdef CONFIG_IMX8QM |
| 39 | #define LVDS0_PHYCTRL_BASE 0x56241000 | 41 | #define LVDS0_PHYCTRL_BASE 0x56241000 |
| 40 | #define LVDS1_PHYCTRL_BASE 0x57241000 | 42 | #define LVDS1_PHYCTRL_BASE 0x57241000 |
| 41 | #define MIPI0_SS_BASE 0x56220000 | 43 | #define MIPI0_SS_BASE 0x56220000 |
| 42 | #define MIPI1_SS_BASE 0x57220000 | 44 | #define MIPI1_SS_BASE 0x57220000 |
| 43 | #endif | 45 | #endif |
| 44 | 46 | ||
| 45 | #define APBH_DMA_ARB_BASE_ADDR 0x5B810000 | 47 | #define APBH_DMA_ARB_BASE_ADDR 0x5B810000 |
| 46 | #define APBH_DMA_ARB_END_ADDR 0x5B81FFFF | 48 | #define APBH_DMA_ARB_END_ADDR 0x5B81FFFF |
| 47 | #define MXS_APBH_BASE APBH_DMA_ARB_BASE_ADDR | 49 | #define MXS_APBH_BASE APBH_DMA_ARB_BASE_ADDR |
| 48 | 50 | ||
| 49 | #define MXS_GPMI_BASE (APBH_DMA_ARB_BASE_ADDR + 0x02000) | 51 | #define MXS_GPMI_BASE (APBH_DMA_ARB_BASE_ADDR + 0x02000) |
| 50 | #define MXS_BCH_BASE (APBH_DMA_ARB_BASE_ADDR + 0x04000) | 52 | #define MXS_BCH_BASE (APBH_DMA_ARB_BASE_ADDR + 0x04000) |
| 51 | 53 | ||
| 52 | #define PASS_OVER_INFO_ADDR 0x0010fe00 | 54 | #define PASS_OVER_INFO_ADDR 0x0010fe00 |
| 53 | 55 | ||
| 54 | #define USB_BASE_ADDR 0x5b0d0000 | 56 | #define USB_BASE_ADDR 0x5b0d0000 |
| 55 | #define USB_PHY0_BASE_ADDR 0x5b100000 | 57 | #define USB_PHY0_BASE_ADDR 0x5b100000 |
| 56 | #define USB_PHY1_BASE_ADDR 0x5b110000 | 58 | #define USB_PHY1_BASE_ADDR 0x5b110000 |
| 57 | 59 | ||
| 58 | #define CONFIG_SYS_FSL_SEC_ADDR (0x31400000) | 60 | #define CONFIG_SYS_FSL_SEC_ADDR (0x31400000) |
| 59 | #define CONFIG_SYS_FSL_MAX_NUM_OF_SEC 1 | 61 | #define CONFIG_SYS_FSL_MAX_NUM_OF_SEC 1 |
| 60 | 62 | ||
| 61 | #if !(defined(__KERNEL_STRICT_NAMES) || defined(__ASSEMBLY__)) | 63 | #if !(defined(__KERNEL_STRICT_NAMES) || defined(__ASSEMBLY__)) |
| 62 | #include <asm/types.h> | 64 | #include <asm/types.h> |
| 63 | #include <stdbool.h> | 65 | #include <stdbool.h> |
| 64 | 66 | ||
| 65 | bool is_usb_boot(void); | 67 | bool is_usb_boot(void); |
| 66 | void disconnect_from_pc(void); | 68 | void disconnect_from_pc(void); |
| 67 | #define is_boot_from_usb is_usb_boot | 69 | #define is_boot_from_usb is_usb_boot |
| 68 | 70 | ||
| 69 | struct usbphy_regs { | 71 | struct usbphy_regs { |
| 70 | u32 usbphy_pwd; /* 0x000 */ | 72 | u32 usbphy_pwd; /* 0x000 */ |
| 71 | u32 usbphy_pwd_set; /* 0x004 */ | 73 | u32 usbphy_pwd_set; /* 0x004 */ |
| 72 | u32 usbphy_pwd_clr; /* 0x008 */ | 74 | u32 usbphy_pwd_clr; /* 0x008 */ |
| 73 | u32 usbphy_pwd_tog; /* 0x00c */ | 75 | u32 usbphy_pwd_tog; /* 0x00c */ |
| 74 | u32 usbphy_tx; /* 0x010 */ | 76 | u32 usbphy_tx; /* 0x010 */ |
| 75 | u32 usbphy_tx_set; /* 0x014 */ | 77 | u32 usbphy_tx_set; /* 0x014 */ |
| 76 | u32 usbphy_tx_clr; /* 0x018 */ | 78 | u32 usbphy_tx_clr; /* 0x018 */ |
| 77 | u32 usbphy_tx_tog; /* 0x01c */ | 79 | u32 usbphy_tx_tog; /* 0x01c */ |
| 78 | u32 usbphy_rx; /* 0x020 */ | 80 | u32 usbphy_rx; /* 0x020 */ |
| 79 | u32 usbphy_rx_set; /* 0x024 */ | 81 | u32 usbphy_rx_set; /* 0x024 */ |
| 80 | u32 usbphy_rx_clr; /* 0x028 */ | 82 | u32 usbphy_rx_clr; /* 0x028 */ |
| 81 | u32 usbphy_rx_tog; /* 0x02c */ | 83 | u32 usbphy_rx_tog; /* 0x02c */ |
| 82 | u32 usbphy_ctrl; /* 0x030 */ | 84 | u32 usbphy_ctrl; /* 0x030 */ |
| 83 | u32 usbphy_ctrl_set; /* 0x034 */ | 85 | u32 usbphy_ctrl_set; /* 0x034 */ |
| 84 | u32 usbphy_ctrl_clr; /* 0x038 */ | 86 | u32 usbphy_ctrl_clr; /* 0x038 */ |
| 85 | u32 usbphy_ctrl_tog; /* 0x03c */ | 87 | u32 usbphy_ctrl_tog; /* 0x03c */ |
| 86 | u32 usbphy_status; /* 0x040 */ | 88 | u32 usbphy_status; /* 0x040 */ |
| 87 | u32 reserved0[3]; | 89 | u32 reserved0[3]; |
| 88 | u32 usbphy_debug0; /* 0x050 */ | 90 | u32 usbphy_debug0; /* 0x050 */ |
| 89 | u32 usbphy_debug0_set; /* 0x054 */ | 91 | u32 usbphy_debug0_set; /* 0x054 */ |
| 90 | u32 usbphy_debug0_clr; /* 0x058 */ | 92 | u32 usbphy_debug0_clr; /* 0x058 */ |
| 91 | u32 usbphy_debug0_tog; /* 0x05c */ | 93 | u32 usbphy_debug0_tog; /* 0x05c */ |
| 92 | u32 reserved1[4]; | 94 | u32 reserved1[4]; |
| 93 | u32 usbphy_debug1; /* 0x070 */ | 95 | u32 usbphy_debug1; /* 0x070 */ |
| 94 | u32 usbphy_debug1_set; /* 0x074 */ | 96 | u32 usbphy_debug1_set; /* 0x074 */ |
| 95 | u32 usbphy_debug1_clr; /* 0x078 */ | 97 | u32 usbphy_debug1_clr; /* 0x078 */ |
| 96 | u32 usbphy_debug1_tog; /* 0x07c */ | 98 | u32 usbphy_debug1_tog; /* 0x07c */ |
| 97 | u32 usbphy_version; /* 0x080 */ | 99 | u32 usbphy_version; /* 0x080 */ |
| 98 | u32 reserved2[7]; | 100 | u32 reserved2[7]; |
| 99 | u32 usb1_pll_480_ctrl; /* 0x0a0 */ | 101 | u32 usb1_pll_480_ctrl; /* 0x0a0 */ |
| 100 | u32 usb1_pll_480_ctrl_set; /* 0x0a4 */ | 102 | u32 usb1_pll_480_ctrl_set; /* 0x0a4 */ |
| 101 | u32 usb1_pll_480_ctrl_clr; /* 0x0a8 */ | 103 | u32 usb1_pll_480_ctrl_clr; /* 0x0a8 */ |
| 102 | u32 usb1_pll_480_ctrl_tog; /* 0x0ac */ | 104 | u32 usb1_pll_480_ctrl_tog; /* 0x0ac */ |
| 103 | u32 reserved3[4]; | 105 | u32 reserved3[4]; |
| 104 | u32 usb1_vbus_detect; /* 0xc0 */ | 106 | u32 usb1_vbus_detect; /* 0xc0 */ |
| 105 | u32 usb1_vbus_detect_set; /* 0xc4 */ | 107 | u32 usb1_vbus_detect_set; /* 0xc4 */ |
| 106 | u32 usb1_vbus_detect_clr; /* 0xc8 */ | 108 | u32 usb1_vbus_detect_clr; /* 0xc8 */ |
| 107 | u32 usb1_vbus_detect_tog; /* 0xcc */ | 109 | u32 usb1_vbus_detect_tog; /* 0xcc */ |
| 108 | u32 usb1_vbus_det_stat; /* 0xd0 */ | 110 | u32 usb1_vbus_det_stat; /* 0xd0 */ |
| 109 | u32 reserved4[3]; | 111 | u32 reserved4[3]; |
| 110 | u32 usb1_chrg_detect; /* 0xe0 */ | 112 | u32 usb1_chrg_detect; /* 0xe0 */ |
| 111 | u32 usb1_chrg_detect_set; /* 0xe4 */ | 113 | u32 usb1_chrg_detect_set; /* 0xe4 */ |
| 112 | u32 usb1_chrg_detect_clr; /* 0xe8 */ | 114 | u32 usb1_chrg_detect_clr; /* 0xe8 */ |
| 113 | u32 usb1_chrg_detect_tog; /* 0xec */ | 115 | u32 usb1_chrg_detect_tog; /* 0xec */ |
| 114 | u32 usb1_chrg_det_stat; /* 0xf0 */ | 116 | u32 usb1_chrg_det_stat; /* 0xf0 */ |
| 115 | u32 reserved5[3]; | 117 | u32 reserved5[3]; |
| 116 | u32 usbphy_anactrl; /* 0x100 */ | 118 | u32 usbphy_anactrl; /* 0x100 */ |
| 117 | u32 usbphy_anactrl_set; /* 0x104 */ | 119 | u32 usbphy_anactrl_set; /* 0x104 */ |
| 118 | u32 usbphy_anactrl_clr; /* 0x108 */ | 120 | u32 usbphy_anactrl_clr; /* 0x108 */ |
| 119 | u32 usbphy_anactrl_tog; /* 0x10c */ | 121 | u32 usbphy_anactrl_tog; /* 0x10c */ |
| 120 | u32 usb1_loopback; /* 0x110 */ | 122 | u32 usb1_loopback; /* 0x110 */ |
| 121 | u32 usb1_loopback_set; /* 0x114 */ | 123 | u32 usb1_loopback_set; /* 0x114 */ |
| 122 | u32 usb1_loopback_clr; /* 0x118 */ | 124 | u32 usb1_loopback_clr; /* 0x118 */ |
| 123 | u32 usb1_loopback_tog; /* 0x11c */ | 125 | u32 usb1_loopback_tog; /* 0x11c */ |
| 124 | u32 usb1_loopback_hsfscnt; /* 0x120 */ | 126 | u32 usb1_loopback_hsfscnt; /* 0x120 */ |
| 125 | u32 usb1_loopback_hsfscnt_set; /* 0x124 */ | 127 | u32 usb1_loopback_hsfscnt_set; /* 0x124 */ |
| 126 | u32 usb1_loopback_hsfscnt_clr; /* 0x128 */ | 128 | u32 usb1_loopback_hsfscnt_clr; /* 0x128 */ |
| 127 | u32 usb1_loopback_hsfscnt_tog; /* 0x12c */ | 129 | u32 usb1_loopback_hsfscnt_tog; /* 0x12c */ |
| 128 | u32 usphy_trim_override_en; /* 0x130 */ | 130 | u32 usphy_trim_override_en; /* 0x130 */ |
| 129 | u32 usphy_trim_override_en_set; /* 0x134 */ | 131 | u32 usphy_trim_override_en_set; /* 0x134 */ |
| 130 | u32 usphy_trim_override_en_clr; /* 0x138 */ | 132 | u32 usphy_trim_override_en_clr; /* 0x138 */ |
| 131 | u32 usphy_trim_override_en_tog; /* 0x13c */ | 133 | u32 usphy_trim_override_en_tog; /* 0x13c */ |
| 132 | u32 usb1_pfda_ctrl1; /* 0x140 */ | 134 | u32 usb1_pfda_ctrl1; /* 0x140 */ |
| 133 | u32 usb1_pfda_ctrl1_set; /* 0x144 */ | 135 | u32 usb1_pfda_ctrl1_set; /* 0x144 */ |
| 134 | u32 usb1_pfda_ctrl1_clr; /* 0x148 */ | 136 | u32 usb1_pfda_ctrl1_clr; /* 0x148 */ |
| 135 | u32 usb1_pfda_ctrl1_tog; /* 0x14c */ | 137 | u32 usb1_pfda_ctrl1_tog; /* 0x14c */ |
| 136 | }; | 138 | }; |
| 137 | #endif | 139 | #endif |
| 138 | 140 | ||
| 139 | #endif /* __ASM_ARCH_IMX8_REGS_H__ */ | 141 | #endif /* __ASM_ARCH_IMX8_REGS_H__ */ |
| 140 | 142 |
arch/arm/include/asm/mach-imx/regs-lcdif.h
| 1 | /* SPDX-License-Identifier: GPL-2.0+ */ | 1 | /* SPDX-License-Identifier: GPL-2.0+ */ |
| 2 | /* | 2 | /* |
| 3 | * Freescale i.MX28/6SX/6UL/7D LCDIF Register Definitions | 3 | * Freescale i.MX28/6SX/6UL/7D LCDIF Register Definitions |
| 4 | * | 4 | * |
| 5 | * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com> | 5 | * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com> |
| 6 | * on behalf of DENX Software Engineering GmbH | 6 | * on behalf of DENX Software Engineering GmbH |
| 7 | * | 7 | * |
| 8 | * Based on code from LTIB: | 8 | * Based on code from LTIB: |
| 9 | * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved. | 9 | * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved. |
| 10 | */ | 10 | */ |
| 11 | 11 | ||
| 12 | #ifndef __IMX_REGS_LCDIF_H__ | 12 | #ifndef __IMX_REGS_LCDIF_H__ |
| 13 | #define __IMX_REGS_LCDIF_H__ | 13 | #define __IMX_REGS_LCDIF_H__ |
| 14 | 14 | ||
| 15 | #ifndef __ASSEMBLY__ | 15 | #ifndef __ASSEMBLY__ |
| 16 | #include <asm/mach-imx/regs-common.h> | 16 | #include <asm/mach-imx/regs-common.h> |
| 17 | 17 | ||
| 18 | struct mxs_lcdif_regs { | 18 | struct mxs_lcdif_regs { |
| 19 | mxs_reg_32(hw_lcdif_ctrl) /* 0x00 */ | 19 | mxs_reg_32(hw_lcdif_ctrl) /* 0x00 */ |
| 20 | mxs_reg_32(hw_lcdif_ctrl1) /* 0x10 */ | 20 | mxs_reg_32(hw_lcdif_ctrl1) /* 0x10 */ |
| 21 | #if defined(CONFIG_MX28) || defined(CONFIG_MX6SX) || \ | 21 | #if defined(CONFIG_MX28) || defined(CONFIG_MX6SX) || \ |
| 22 | defined(CONFIG_MX6SL) || defined(CONFIG_MX6SLL) || \ | 22 | defined(CONFIG_MX6SL) || defined(CONFIG_MX6SLL) || \ |
| 23 | defined(CONFIG_MX6UL) || defined(CONFIG_MX6ULL) || \ | 23 | defined(CONFIG_MX6UL) || defined(CONFIG_MX6ULL) || \ |
| 24 | defined(CONFIG_MX7) || defined(CONFIG_MX7ULP) || \ | 24 | defined(CONFIG_MX7) || defined(CONFIG_MX7ULP) || \ |
| 25 | defined(CONFIG_IMX8M) || defined(CONFIG_IMXRT) | 25 | defined(CONFIG_IMX8M) || defined(CONFIG_IMX8) || defined(CONFIG_IMXRT) |
| 26 | mxs_reg_32(hw_lcdif_ctrl2) /* 0x20 */ | 26 | mxs_reg_32(hw_lcdif_ctrl2) /* 0x20 */ |
| 27 | #endif | 27 | #endif |
| 28 | mxs_reg_32(hw_lcdif_transfer_count) /* 0x20/0x30 */ | 28 | mxs_reg_32(hw_lcdif_transfer_count) /* 0x20/0x30 */ |
| 29 | mxs_reg_32(hw_lcdif_cur_buf) /* 0x30/0x40 */ | 29 | mxs_reg_32(hw_lcdif_cur_buf) /* 0x30/0x40 */ |
| 30 | mxs_reg_32(hw_lcdif_next_buf) /* 0x40/0x50 */ | 30 | mxs_reg_32(hw_lcdif_next_buf) /* 0x40/0x50 */ |
| 31 | 31 | ||
| 32 | #if defined(CONFIG_MX23) | 32 | #if defined(CONFIG_MX23) |
| 33 | uint32_t reserved1[4]; | 33 | uint32_t reserved1[4]; |
| 34 | #endif | 34 | #endif |
| 35 | 35 | ||
| 36 | mxs_reg_32(hw_lcdif_timing) /* 0x60 */ | 36 | mxs_reg_32(hw_lcdif_timing) /* 0x60 */ |
| 37 | mxs_reg_32(hw_lcdif_vdctrl0) /* 0x70 */ | 37 | mxs_reg_32(hw_lcdif_vdctrl0) /* 0x70 */ |
| 38 | mxs_reg_32(hw_lcdif_vdctrl1) /* 0x80 */ | 38 | mxs_reg_32(hw_lcdif_vdctrl1) /* 0x80 */ |
| 39 | mxs_reg_32(hw_lcdif_vdctrl2) /* 0x90 */ | 39 | mxs_reg_32(hw_lcdif_vdctrl2) /* 0x90 */ |
| 40 | mxs_reg_32(hw_lcdif_vdctrl3) /* 0xa0 */ | 40 | mxs_reg_32(hw_lcdif_vdctrl3) /* 0xa0 */ |
| 41 | mxs_reg_32(hw_lcdif_vdctrl4) /* 0xb0 */ | 41 | mxs_reg_32(hw_lcdif_vdctrl4) /* 0xb0 */ |
| 42 | mxs_reg_32(hw_lcdif_dvictrl0) /* 0xc0 */ | 42 | mxs_reg_32(hw_lcdif_dvictrl0) /* 0xc0 */ |
| 43 | mxs_reg_32(hw_lcdif_dvictrl1) /* 0xd0 */ | 43 | mxs_reg_32(hw_lcdif_dvictrl1) /* 0xd0 */ |
| 44 | mxs_reg_32(hw_lcdif_dvictrl2) /* 0xe0 */ | 44 | mxs_reg_32(hw_lcdif_dvictrl2) /* 0xe0 */ |
| 45 | mxs_reg_32(hw_lcdif_dvictrl3) /* 0xf0 */ | 45 | mxs_reg_32(hw_lcdif_dvictrl3) /* 0xf0 */ |
| 46 | mxs_reg_32(hw_lcdif_dvictrl4) /* 0x100 */ | 46 | mxs_reg_32(hw_lcdif_dvictrl4) /* 0x100 */ |
| 47 | mxs_reg_32(hw_lcdif_csc_coeffctrl0) /* 0x110 */ | 47 | mxs_reg_32(hw_lcdif_csc_coeffctrl0) /* 0x110 */ |
| 48 | mxs_reg_32(hw_lcdif_csc_coeffctrl1) /* 0x120 */ | 48 | mxs_reg_32(hw_lcdif_csc_coeffctrl1) /* 0x120 */ |
| 49 | mxs_reg_32(hw_lcdif_csc_coeffctrl2) /* 0x130 */ | 49 | mxs_reg_32(hw_lcdif_csc_coeffctrl2) /* 0x130 */ |
| 50 | mxs_reg_32(hw_lcdif_csc_coeffctrl3) /* 0x140 */ | 50 | mxs_reg_32(hw_lcdif_csc_coeffctrl3) /* 0x140 */ |
| 51 | mxs_reg_32(hw_lcdif_csc_coeffctrl4) /* 0x150 */ | 51 | mxs_reg_32(hw_lcdif_csc_coeffctrl4) /* 0x150 */ |
| 52 | mxs_reg_32(hw_lcdif_csc_offset) /* 0x160 */ | 52 | mxs_reg_32(hw_lcdif_csc_offset) /* 0x160 */ |
| 53 | mxs_reg_32(hw_lcdif_csc_limit) /* 0x170 */ | 53 | mxs_reg_32(hw_lcdif_csc_limit) /* 0x170 */ |
| 54 | 54 | ||
| 55 | #if defined(CONFIG_MX23) | 55 | #if defined(CONFIG_MX23) |
| 56 | uint32_t reserved2[12]; | 56 | uint32_t reserved2[12]; |
| 57 | #endif | 57 | #endif |
| 58 | mxs_reg_32(hw_lcdif_data) /* 0x1b0/0x180 */ | 58 | mxs_reg_32(hw_lcdif_data) /* 0x1b0/0x180 */ |
| 59 | mxs_reg_32(hw_lcdif_bm_error_stat) /* 0x1c0/0x190 */ | 59 | mxs_reg_32(hw_lcdif_bm_error_stat) /* 0x1c0/0x190 */ |
| 60 | #if defined(CONFIG_MX28) || defined(CONFIG_MX6SX) || \ | 60 | #if defined(CONFIG_MX28) || defined(CONFIG_MX6SX) || \ |
| 61 | defined(CONFIG_MX6SL) || defined(CONFIG_MX6SLL) || \ | 61 | defined(CONFIG_MX6SL) || defined(CONFIG_MX6SLL) || \ |
| 62 | defined(CONFIG_MX6UL) || defined(CONFIG_MX6ULL) || \ | 62 | defined(CONFIG_MX6UL) || defined(CONFIG_MX6ULL) || \ |
| 63 | defined(CONFIG_MX7) || defined(CONFIG_MX7ULP) || \ | 63 | defined(CONFIG_MX7) || defined(CONFIG_MX7ULP) || \ |
| 64 | defined(CONFIG_IMX8M) || defined(CONFIG_IMXRT) | 64 | defined(CONFIG_IMX8M) || defined(CONFIG_IMX8) || defined(CONFIG_IMXRT) |
| 65 | mxs_reg_32(hw_lcdif_crc_stat) /* 0x1a0 */ | 65 | mxs_reg_32(hw_lcdif_crc_stat) /* 0x1a0 */ |
| 66 | #endif | 66 | #endif |
| 67 | mxs_reg_32(hw_lcdif_lcdif_stat) /* 0x1d0/0x1b0 */ | 67 | mxs_reg_32(hw_lcdif_lcdif_stat) /* 0x1d0/0x1b0 */ |
| 68 | mxs_reg_32(hw_lcdif_version) /* 0x1e0/0x1c0 */ | 68 | mxs_reg_32(hw_lcdif_version) /* 0x1e0/0x1c0 */ |
| 69 | mxs_reg_32(hw_lcdif_debug0) /* 0x1f0/0x1d0 */ | 69 | mxs_reg_32(hw_lcdif_debug0) /* 0x1f0/0x1d0 */ |
| 70 | mxs_reg_32(hw_lcdif_debug1) /* 0x200/0x1e0 */ | 70 | mxs_reg_32(hw_lcdif_debug1) /* 0x200/0x1e0 */ |
| 71 | mxs_reg_32(hw_lcdif_debug2) /* 0x1f0 */ | 71 | mxs_reg_32(hw_lcdif_debug2) /* 0x1f0 */ |
| 72 | #if defined(CONFIG_MX6SX) || \ | 72 | #if defined(CONFIG_MX6SX) || \ |
| 73 | defined(CONFIG_MX6SL) || defined(CONFIG_MX6SLL) || \ | 73 | defined(CONFIG_MX6SL) || defined(CONFIG_MX6SLL) || \ |
| 74 | defined(CONFIG_MX6UL) || defined(CONFIG_MX6ULL) || \ | 74 | defined(CONFIG_MX6UL) || defined(CONFIG_MX6ULL) || \ |
| 75 | defined(CONFIG_MX7) || defined(CONFIG_MX7ULP) || \ | 75 | defined(CONFIG_MX7) || defined(CONFIG_MX7ULP) || \ |
| 76 | defined(CONFIG_IMX8M) | 76 | defined(CONFIG_IMX8M) || defined(CONFIG_IMX8) |
| 77 | mxs_reg_32(hw_lcdif_thres) | 77 | mxs_reg_32(hw_lcdif_thres) |
| 78 | mxs_reg_32(hw_lcdif_as_ctrl) | 78 | mxs_reg_32(hw_lcdif_as_ctrl) |
| 79 | mxs_reg_32(hw_lcdif_as_buf) | 79 | mxs_reg_32(hw_lcdif_as_buf) |
| 80 | mxs_reg_32(hw_lcdif_as_next_buf) | 80 | mxs_reg_32(hw_lcdif_as_next_buf) |
| 81 | mxs_reg_32(hw_lcdif_as_clrkeylow) | 81 | mxs_reg_32(hw_lcdif_as_clrkeylow) |
| 82 | mxs_reg_32(hw_lcdif_as_clrkeyhigh) | 82 | mxs_reg_32(hw_lcdif_as_clrkeyhigh) |
| 83 | mxs_reg_32(hw_lcdif_as_sync_delay) | 83 | mxs_reg_32(hw_lcdif_as_sync_delay) |
| 84 | mxs_reg_32(hw_lcdif_as_debug3) | 84 | mxs_reg_32(hw_lcdif_as_debug3) |
| 85 | mxs_reg_32(hw_lcdif_as_debug4) | 85 | mxs_reg_32(hw_lcdif_as_debug4) |
| 86 | mxs_reg_32(hw_lcdif_as_debug5) | 86 | mxs_reg_32(hw_lcdif_as_debug5) |
| 87 | #endif | 87 | #endif |
| 88 | }; | 88 | }; |
| 89 | #endif | 89 | #endif |
| 90 | 90 | ||
| 91 | #define LCDIF_CTRL_SFTRST (1 << 31) | 91 | #define LCDIF_CTRL_SFTRST (1 << 31) |
| 92 | #define LCDIF_CTRL_CLKGATE (1 << 30) | 92 | #define LCDIF_CTRL_CLKGATE (1 << 30) |
| 93 | #define LCDIF_CTRL_YCBCR422_INPUT (1 << 29) | 93 | #define LCDIF_CTRL_YCBCR422_INPUT (1 << 29) |
| 94 | #define LCDIF_CTRL_READ_WRITEB (1 << 28) | 94 | #define LCDIF_CTRL_READ_WRITEB (1 << 28) |
| 95 | #define LCDIF_CTRL_WAIT_FOR_VSYNC_EDGE (1 << 27) | 95 | #define LCDIF_CTRL_WAIT_FOR_VSYNC_EDGE (1 << 27) |
| 96 | #define LCDIF_CTRL_DATA_SHIFT_DIR (1 << 26) | 96 | #define LCDIF_CTRL_DATA_SHIFT_DIR (1 << 26) |
| 97 | #define LCDIF_CTRL_SHIFT_NUM_BITS_MASK (0x1f << 21) | 97 | #define LCDIF_CTRL_SHIFT_NUM_BITS_MASK (0x1f << 21) |
| 98 | #define LCDIF_CTRL_SHIFT_NUM_BITS_OFFSET 21 | 98 | #define LCDIF_CTRL_SHIFT_NUM_BITS_OFFSET 21 |
| 99 | #define LCDIF_CTRL_DVI_MODE (1 << 20) | 99 | #define LCDIF_CTRL_DVI_MODE (1 << 20) |
| 100 | #define LCDIF_CTRL_BYPASS_COUNT (1 << 19) | 100 | #define LCDIF_CTRL_BYPASS_COUNT (1 << 19) |
| 101 | #define LCDIF_CTRL_VSYNC_MODE (1 << 18) | 101 | #define LCDIF_CTRL_VSYNC_MODE (1 << 18) |
| 102 | #define LCDIF_CTRL_DOTCLK_MODE (1 << 17) | 102 | #define LCDIF_CTRL_DOTCLK_MODE (1 << 17) |
| 103 | #define LCDIF_CTRL_DATA_SELECT (1 << 16) | 103 | #define LCDIF_CTRL_DATA_SELECT (1 << 16) |
| 104 | #define LCDIF_CTRL_INPUT_DATA_SWIZZLE_MASK (0x3 << 14) | 104 | #define LCDIF_CTRL_INPUT_DATA_SWIZZLE_MASK (0x3 << 14) |
| 105 | #define LCDIF_CTRL_INPUT_DATA_SWIZZLE_OFFSET 14 | 105 | #define LCDIF_CTRL_INPUT_DATA_SWIZZLE_OFFSET 14 |
| 106 | #define LCDIF_CTRL_CSC_DATA_SWIZZLE_MASK (0x3 << 12) | 106 | #define LCDIF_CTRL_CSC_DATA_SWIZZLE_MASK (0x3 << 12) |
| 107 | #define LCDIF_CTRL_CSC_DATA_SWIZZLE_OFFSET 12 | 107 | #define LCDIF_CTRL_CSC_DATA_SWIZZLE_OFFSET 12 |
| 108 | #define LCDIF_CTRL_LCD_DATABUS_WIDTH_MASK (0x3 << 10) | 108 | #define LCDIF_CTRL_LCD_DATABUS_WIDTH_MASK (0x3 << 10) |
| 109 | #define LCDIF_CTRL_LCD_DATABUS_WIDTH_OFFSET 10 | 109 | #define LCDIF_CTRL_LCD_DATABUS_WIDTH_OFFSET 10 |
| 110 | #define LCDIF_CTRL_LCD_DATABUS_WIDTH_16BIT (0 << 10) | 110 | #define LCDIF_CTRL_LCD_DATABUS_WIDTH_16BIT (0 << 10) |
| 111 | #define LCDIF_CTRL_LCD_DATABUS_WIDTH_8BIT (1 << 10) | 111 | #define LCDIF_CTRL_LCD_DATABUS_WIDTH_8BIT (1 << 10) |
| 112 | #define LCDIF_CTRL_LCD_DATABUS_WIDTH_18BIT (2 << 10) | 112 | #define LCDIF_CTRL_LCD_DATABUS_WIDTH_18BIT (2 << 10) |
| 113 | #define LCDIF_CTRL_LCD_DATABUS_WIDTH_24BIT (3 << 10) | 113 | #define LCDIF_CTRL_LCD_DATABUS_WIDTH_24BIT (3 << 10) |
| 114 | #define LCDIF_CTRL_WORD_LENGTH_MASK (0x3 << 8) | 114 | #define LCDIF_CTRL_WORD_LENGTH_MASK (0x3 << 8) |
| 115 | #define LCDIF_CTRL_WORD_LENGTH_OFFSET 8 | 115 | #define LCDIF_CTRL_WORD_LENGTH_OFFSET 8 |
| 116 | #define LCDIF_CTRL_WORD_LENGTH_16BIT (0 << 8) | 116 | #define LCDIF_CTRL_WORD_LENGTH_16BIT (0 << 8) |
| 117 | #define LCDIF_CTRL_WORD_LENGTH_8BIT (1 << 8) | 117 | #define LCDIF_CTRL_WORD_LENGTH_8BIT (1 << 8) |
| 118 | #define LCDIF_CTRL_WORD_LENGTH_18BIT (2 << 8) | 118 | #define LCDIF_CTRL_WORD_LENGTH_18BIT (2 << 8) |
| 119 | #define LCDIF_CTRL_WORD_LENGTH_24BIT (3 << 8) | 119 | #define LCDIF_CTRL_WORD_LENGTH_24BIT (3 << 8) |
| 120 | #define LCDIF_CTRL_RGB_TO_YCBCR422_CSC (1 << 7) | 120 | #define LCDIF_CTRL_RGB_TO_YCBCR422_CSC (1 << 7) |
| 121 | #define LCDIF_CTRL_LCDIF_MASTER (1 << 5) | 121 | #define LCDIF_CTRL_LCDIF_MASTER (1 << 5) |
| 122 | #define LCDIF_CTRL_DATA_FORMAT_16_BIT (1 << 3) | 122 | #define LCDIF_CTRL_DATA_FORMAT_16_BIT (1 << 3) |
| 123 | #define LCDIF_CTRL_DATA_FORMAT_18_BIT (1 << 2) | 123 | #define LCDIF_CTRL_DATA_FORMAT_18_BIT (1 << 2) |
| 124 | #define LCDIF_CTRL_DATA_FORMAT_24_BIT (1 << 1) | 124 | #define LCDIF_CTRL_DATA_FORMAT_24_BIT (1 << 1) |
| 125 | #define LCDIF_CTRL_RUN (1 << 0) | 125 | #define LCDIF_CTRL_RUN (1 << 0) |
| 126 | 126 | ||
| 127 | #define LCDIF_CTRL1_COMBINE_MPU_WR_STRB (1 << 27) | 127 | #define LCDIF_CTRL1_COMBINE_MPU_WR_STRB (1 << 27) |
| 128 | #define LCDIF_CTRL1_BM_ERROR_IRQ_EN (1 << 26) | 128 | #define LCDIF_CTRL1_BM_ERROR_IRQ_EN (1 << 26) |
| 129 | #define LCDIF_CTRL1_BM_ERROR_IRQ (1 << 25) | 129 | #define LCDIF_CTRL1_BM_ERROR_IRQ (1 << 25) |
| 130 | #define LCDIF_CTRL1_RECOVER_ON_UNDERFLOW (1 << 24) | 130 | #define LCDIF_CTRL1_RECOVER_ON_UNDERFLOW (1 << 24) |
| 131 | #define LCDIF_CTRL1_INTERLACE_FIELDS (1 << 23) | 131 | #define LCDIF_CTRL1_INTERLACE_FIELDS (1 << 23) |
| 132 | #define LCDIF_CTRL1_START_INTERLACE_FROM_SECOND_FIELD (1 << 22) | 132 | #define LCDIF_CTRL1_START_INTERLACE_FROM_SECOND_FIELD (1 << 22) |
| 133 | #define LCDIF_CTRL1_FIFO_CLEAR (1 << 21) | 133 | #define LCDIF_CTRL1_FIFO_CLEAR (1 << 21) |
| 134 | #define LCDIF_CTRL1_IRQ_ON_ALTERNATE_FIELDS (1 << 20) | 134 | #define LCDIF_CTRL1_IRQ_ON_ALTERNATE_FIELDS (1 << 20) |
| 135 | #define LCDIF_CTRL1_BYTE_PACKING_FORMAT_MASK (0xf << 16) | 135 | #define LCDIF_CTRL1_BYTE_PACKING_FORMAT_MASK (0xf << 16) |
| 136 | #define LCDIF_CTRL1_BYTE_PACKING_FORMAT_OFFSET 16 | 136 | #define LCDIF_CTRL1_BYTE_PACKING_FORMAT_OFFSET 16 |
| 137 | #define LCDIF_CTRL1_OVERFLOW_IRQ_EN (1 << 15) | 137 | #define LCDIF_CTRL1_OVERFLOW_IRQ_EN (1 << 15) |
| 138 | #define LCDIF_CTRL1_UNDERFLOW_IRQ_EN (1 << 14) | 138 | #define LCDIF_CTRL1_UNDERFLOW_IRQ_EN (1 << 14) |
| 139 | #define LCDIF_CTRL1_CUR_FRAME_DONE_IRQ_EN (1 << 13) | 139 | #define LCDIF_CTRL1_CUR_FRAME_DONE_IRQ_EN (1 << 13) |
| 140 | #define LCDIF_CTRL1_VSYNC_EDGE_IRQ_EN (1 << 12) | 140 | #define LCDIF_CTRL1_VSYNC_EDGE_IRQ_EN (1 << 12) |
| 141 | #define LCDIF_CTRL1_OVERFLOW_IRQ (1 << 11) | 141 | #define LCDIF_CTRL1_OVERFLOW_IRQ (1 << 11) |
| 142 | #define LCDIF_CTRL1_UNDERFLOW_IRQ (1 << 10) | 142 | #define LCDIF_CTRL1_UNDERFLOW_IRQ (1 << 10) |
| 143 | #define LCDIF_CTRL1_CUR_FRAME_DONE_IRQ (1 << 9) | 143 | #define LCDIF_CTRL1_CUR_FRAME_DONE_IRQ (1 << 9) |
| 144 | #define LCDIF_CTRL1_VSYNC_EDGE_IRQ (1 << 8) | 144 | #define LCDIF_CTRL1_VSYNC_EDGE_IRQ (1 << 8) |
| 145 | #define LCDIF_CTRL1_BUSY_ENABLE (1 << 2) | 145 | #define LCDIF_CTRL1_BUSY_ENABLE (1 << 2) |
| 146 | #define LCDIF_CTRL1_MODE86 (1 << 1) | 146 | #define LCDIF_CTRL1_MODE86 (1 << 1) |
| 147 | #define LCDIF_CTRL1_RESET (1 << 0) | 147 | #define LCDIF_CTRL1_RESET (1 << 0) |
| 148 | 148 | ||
| 149 | #define LCDIF_CTRL2_OUTSTANDING_REQS_MASK (0x7 << 21) | 149 | #define LCDIF_CTRL2_OUTSTANDING_REQS_MASK (0x7 << 21) |
| 150 | #define LCDIF_CTRL2_OUTSTANDING_REQS_OFFSET 21 | 150 | #define LCDIF_CTRL2_OUTSTANDING_REQS_OFFSET 21 |
| 151 | #define LCDIF_CTRL2_OUTSTANDING_REQS_REQ_1 (0x0 << 21) | 151 | #define LCDIF_CTRL2_OUTSTANDING_REQS_REQ_1 (0x0 << 21) |
| 152 | #define LCDIF_CTRL2_OUTSTANDING_REQS_REQ_2 (0x1 << 21) | 152 | #define LCDIF_CTRL2_OUTSTANDING_REQS_REQ_2 (0x1 << 21) |
| 153 | #define LCDIF_CTRL2_OUTSTANDING_REQS_REQ_4 (0x2 << 21) | 153 | #define LCDIF_CTRL2_OUTSTANDING_REQS_REQ_4 (0x2 << 21) |
| 154 | #define LCDIF_CTRL2_OUTSTANDING_REQS_REQ_8 (0x3 << 21) | 154 | #define LCDIF_CTRL2_OUTSTANDING_REQS_REQ_8 (0x3 << 21) |
| 155 | #define LCDIF_CTRL2_OUTSTANDING_REQS_REQ_16 (0x4 << 21) | 155 | #define LCDIF_CTRL2_OUTSTANDING_REQS_REQ_16 (0x4 << 21) |
| 156 | #define LCDIF_CTRL2_BURST_LEN_8 (1 << 20) | 156 | #define LCDIF_CTRL2_BURST_LEN_8 (1 << 20) |
| 157 | #define LCDIF_CTRL2_ODD_LINE_PATTERN_MASK (0x7 << 16) | 157 | #define LCDIF_CTRL2_ODD_LINE_PATTERN_MASK (0x7 << 16) |
| 158 | #define LCDIF_CTRL2_ODD_LINE_PATTERN_OFFSET 16 | 158 | #define LCDIF_CTRL2_ODD_LINE_PATTERN_OFFSET 16 |
| 159 | #define LCDIF_CTRL2_ODD_LINE_PATTERN_RGB (0x0 << 16) | 159 | #define LCDIF_CTRL2_ODD_LINE_PATTERN_RGB (0x0 << 16) |
| 160 | #define LCDIF_CTRL2_ODD_LINE_PATTERN_RBG (0x1 << 16) | 160 | #define LCDIF_CTRL2_ODD_LINE_PATTERN_RBG (0x1 << 16) |
| 161 | #define LCDIF_CTRL2_ODD_LINE_PATTERN_GBR (0x2 << 16) | 161 | #define LCDIF_CTRL2_ODD_LINE_PATTERN_GBR (0x2 << 16) |
| 162 | #define LCDIF_CTRL2_ODD_LINE_PATTERN_GRB (0x3 << 16) | 162 | #define LCDIF_CTRL2_ODD_LINE_PATTERN_GRB (0x3 << 16) |
| 163 | #define LCDIF_CTRL2_ODD_LINE_PATTERN_BRG (0x4 << 16) | 163 | #define LCDIF_CTRL2_ODD_LINE_PATTERN_BRG (0x4 << 16) |
| 164 | #define LCDIF_CTRL2_ODD_LINE_PATTERN_BGR (0x5 << 16) | 164 | #define LCDIF_CTRL2_ODD_LINE_PATTERN_BGR (0x5 << 16) |
| 165 | #define LCDIF_CTRL2_EVEN_LINE_PATTERN_MASK (0x7 << 12) | 165 | #define LCDIF_CTRL2_EVEN_LINE_PATTERN_MASK (0x7 << 12) |
| 166 | #define LCDIF_CTRL2_EVEN_LINE_PATTERN_OFFSET 12 | 166 | #define LCDIF_CTRL2_EVEN_LINE_PATTERN_OFFSET 12 |
| 167 | #define LCDIF_CTRL2_EVEN_LINE_PATTERN_RGB (0x0 << 12) | 167 | #define LCDIF_CTRL2_EVEN_LINE_PATTERN_RGB (0x0 << 12) |
| 168 | #define LCDIF_CTRL2_EVEN_LINE_PATTERN_RBG (0x1 << 12) | 168 | #define LCDIF_CTRL2_EVEN_LINE_PATTERN_RBG (0x1 << 12) |
| 169 | #define LCDIF_CTRL2_EVEN_LINE_PATTERN_GBR (0x2 << 12) | 169 | #define LCDIF_CTRL2_EVEN_LINE_PATTERN_GBR (0x2 << 12) |
| 170 | #define LCDIF_CTRL2_EVEN_LINE_PATTERN_GRB (0x3 << 12) | 170 | #define LCDIF_CTRL2_EVEN_LINE_PATTERN_GRB (0x3 << 12) |
| 171 | #define LCDIF_CTRL2_EVEN_LINE_PATTERN_BRG (0x4 << 12) | 171 | #define LCDIF_CTRL2_EVEN_LINE_PATTERN_BRG (0x4 << 12) |
| 172 | #define LCDIF_CTRL2_EVEN_LINE_PATTERN_BGR (0x5 << 12) | 172 | #define LCDIF_CTRL2_EVEN_LINE_PATTERN_BGR (0x5 << 12) |
| 173 | #define LCDIF_CTRL2_READ_PACK_DIR (1 << 10) | 173 | #define LCDIF_CTRL2_READ_PACK_DIR (1 << 10) |
| 174 | #define LCDIF_CTRL2_READ_MODE_OUTPUT_IN_RGB_FORMAT (1 << 9) | 174 | #define LCDIF_CTRL2_READ_MODE_OUTPUT_IN_RGB_FORMAT (1 << 9) |
| 175 | #define LCDIF_CTRL2_READ_MODE_6_BIT_INPUT (1 << 8) | 175 | #define LCDIF_CTRL2_READ_MODE_6_BIT_INPUT (1 << 8) |
| 176 | #define LCDIF_CTRL2_READ_MODE_NUM_PACKED_SUBWORDS_MASK (0x7 << 4) | 176 | #define LCDIF_CTRL2_READ_MODE_NUM_PACKED_SUBWORDS_MASK (0x7 << 4) |
| 177 | #define LCDIF_CTRL2_READ_MODE_NUM_PACKED_SUBWORDS_OFFSET 4 | 177 | #define LCDIF_CTRL2_READ_MODE_NUM_PACKED_SUBWORDS_OFFSET 4 |
| 178 | #define LCDIF_CTRL2_INITIAL_DUMMY_READ_MASK (0x7 << 1) | 178 | #define LCDIF_CTRL2_INITIAL_DUMMY_READ_MASK (0x7 << 1) |
| 179 | #define LCDIF_CTRL2_INITIAL_DUMMY_READ_OFFSET 1 | 179 | #define LCDIF_CTRL2_INITIAL_DUMMY_READ_OFFSET 1 |
| 180 | 180 | ||
| 181 | #define LCDIF_TRANSFER_COUNT_V_COUNT_MASK (0xffff << 16) | 181 | #define LCDIF_TRANSFER_COUNT_V_COUNT_MASK (0xffff << 16) |
| 182 | #define LCDIF_TRANSFER_COUNT_V_COUNT_OFFSET 16 | 182 | #define LCDIF_TRANSFER_COUNT_V_COUNT_OFFSET 16 |
| 183 | #define LCDIF_TRANSFER_COUNT_H_COUNT_MASK (0xffff << 0) | 183 | #define LCDIF_TRANSFER_COUNT_H_COUNT_MASK (0xffff << 0) |
| 184 | #define LCDIF_TRANSFER_COUNT_H_COUNT_OFFSET 0 | 184 | #define LCDIF_TRANSFER_COUNT_H_COUNT_OFFSET 0 |
| 185 | 185 | ||
| 186 | #define LCDIF_CUR_BUF_ADDR_MASK 0xffffffff | 186 | #define LCDIF_CUR_BUF_ADDR_MASK 0xffffffff |
| 187 | #define LCDIF_CUR_BUF_ADDR_OFFSET 0 | 187 | #define LCDIF_CUR_BUF_ADDR_OFFSET 0 |
| 188 | 188 | ||
| 189 | #define LCDIF_NEXT_BUF_ADDR_MASK 0xffffffff | 189 | #define LCDIF_NEXT_BUF_ADDR_MASK 0xffffffff |
| 190 | #define LCDIF_NEXT_BUF_ADDR_OFFSET 0 | 190 | #define LCDIF_NEXT_BUF_ADDR_OFFSET 0 |
| 191 | 191 | ||
| 192 | #define LCDIF_TIMING_CMD_HOLD_MASK (0xff << 24) | 192 | #define LCDIF_TIMING_CMD_HOLD_MASK (0xff << 24) |
| 193 | #define LCDIF_TIMING_CMD_HOLD_OFFSET 24 | 193 | #define LCDIF_TIMING_CMD_HOLD_OFFSET 24 |
| 194 | #define LCDIF_TIMING_CMD_SETUP_MASK (0xff << 16) | 194 | #define LCDIF_TIMING_CMD_SETUP_MASK (0xff << 16) |
| 195 | #define LCDIF_TIMING_CMD_SETUP_OFFSET 16 | 195 | #define LCDIF_TIMING_CMD_SETUP_OFFSET 16 |
| 196 | #define LCDIF_TIMING_DATA_HOLD_MASK (0xff << 8) | 196 | #define LCDIF_TIMING_DATA_HOLD_MASK (0xff << 8) |
| 197 | #define LCDIF_TIMING_DATA_HOLD_OFFSET 8 | 197 | #define LCDIF_TIMING_DATA_HOLD_OFFSET 8 |
| 198 | #define LCDIF_TIMING_DATA_SETUP_MASK (0xff << 0) | 198 | #define LCDIF_TIMING_DATA_SETUP_MASK (0xff << 0) |
| 199 | #define LCDIF_TIMING_DATA_SETUP_OFFSET 0 | 199 | #define LCDIF_TIMING_DATA_SETUP_OFFSET 0 |
| 200 | 200 | ||
| 201 | #define LCDIF_VDCTRL0_VSYNC_OEB (1 << 29) | 201 | #define LCDIF_VDCTRL0_VSYNC_OEB (1 << 29) |
| 202 | #define LCDIF_VDCTRL0_ENABLE_PRESENT (1 << 28) | 202 | #define LCDIF_VDCTRL0_ENABLE_PRESENT (1 << 28) |
| 203 | #define LCDIF_VDCTRL0_VSYNC_POL (1 << 27) | 203 | #define LCDIF_VDCTRL0_VSYNC_POL (1 << 27) |
| 204 | #define LCDIF_VDCTRL0_HSYNC_POL (1 << 26) | 204 | #define LCDIF_VDCTRL0_HSYNC_POL (1 << 26) |
| 205 | #define LCDIF_VDCTRL0_DOTCLK_POL (1 << 25) | 205 | #define LCDIF_VDCTRL0_DOTCLK_POL (1 << 25) |
| 206 | #define LCDIF_VDCTRL0_ENABLE_POL (1 << 24) | 206 | #define LCDIF_VDCTRL0_ENABLE_POL (1 << 24) |
| 207 | #define LCDIF_VDCTRL0_VSYNC_PERIOD_UNIT (1 << 21) | 207 | #define LCDIF_VDCTRL0_VSYNC_PERIOD_UNIT (1 << 21) |
| 208 | #define LCDIF_VDCTRL0_VSYNC_PULSE_WIDTH_UNIT (1 << 20) | 208 | #define LCDIF_VDCTRL0_VSYNC_PULSE_WIDTH_UNIT (1 << 20) |
| 209 | #define LCDIF_VDCTRL0_HALF_LINE (1 << 19) | 209 | #define LCDIF_VDCTRL0_HALF_LINE (1 << 19) |
| 210 | #define LCDIF_VDCTRL0_HALF_LINE_MODE (1 << 18) | 210 | #define LCDIF_VDCTRL0_HALF_LINE_MODE (1 << 18) |
| 211 | #define LCDIF_VDCTRL0_VSYNC_PULSE_WIDTH_MASK 0x3ffff | 211 | #define LCDIF_VDCTRL0_VSYNC_PULSE_WIDTH_MASK 0x3ffff |
| 212 | #define LCDIF_VDCTRL0_VSYNC_PULSE_WIDTH_OFFSET 0 | 212 | #define LCDIF_VDCTRL0_VSYNC_PULSE_WIDTH_OFFSET 0 |
| 213 | 213 | ||
| 214 | #define LCDIF_VDCTRL1_VSYNC_PERIOD_MASK 0xffffffff | 214 | #define LCDIF_VDCTRL1_VSYNC_PERIOD_MASK 0xffffffff |
| 215 | #define LCDIF_VDCTRL1_VSYNC_PERIOD_OFFSET 0 | 215 | #define LCDIF_VDCTRL1_VSYNC_PERIOD_OFFSET 0 |
| 216 | 216 | ||
| 217 | #if defined(CONFIG_MX23) | 217 | #if defined(CONFIG_MX23) |
| 218 | #define LCDIF_VDCTRL2_HSYNC_PULSE_WIDTH_MASK (0xff << 24) | 218 | #define LCDIF_VDCTRL2_HSYNC_PULSE_WIDTH_MASK (0xff << 24) |
| 219 | #define LCDIF_VDCTRL2_HSYNC_PULSE_WIDTH_OFFSET 24 | 219 | #define LCDIF_VDCTRL2_HSYNC_PULSE_WIDTH_OFFSET 24 |
| 220 | #else | 220 | #else |
| 221 | #define LCDIF_VDCTRL2_HSYNC_PULSE_WIDTH_MASK (0x3fff << 18) | 221 | #define LCDIF_VDCTRL2_HSYNC_PULSE_WIDTH_MASK (0x3fff << 18) |
| 222 | #define LCDIF_VDCTRL2_HSYNC_PULSE_WIDTH_OFFSET 18 | 222 | #define LCDIF_VDCTRL2_HSYNC_PULSE_WIDTH_OFFSET 18 |
| 223 | #endif | 223 | #endif |
| 224 | #define LCDIF_VDCTRL2_HSYNC_PERIOD_MASK 0x3ffff | 224 | #define LCDIF_VDCTRL2_HSYNC_PERIOD_MASK 0x3ffff |
| 225 | #define LCDIF_VDCTRL2_HSYNC_PERIOD_OFFSET 0 | 225 | #define LCDIF_VDCTRL2_HSYNC_PERIOD_OFFSET 0 |
| 226 | 226 | ||
| 227 | #define LCDIF_VDCTRL3_MUX_SYNC_SIGNALS (1 << 29) | 227 | #define LCDIF_VDCTRL3_MUX_SYNC_SIGNALS (1 << 29) |
| 228 | #define LCDIF_VDCTRL3_VSYNC_ONLY (1 << 28) | 228 | #define LCDIF_VDCTRL3_VSYNC_ONLY (1 << 28) |
| 229 | #define LCDIF_VDCTRL3_HORIZONTAL_WAIT_CNT_MASK (0xfff << 16) | 229 | #define LCDIF_VDCTRL3_HORIZONTAL_WAIT_CNT_MASK (0xfff << 16) |
| 230 | #define LCDIF_VDCTRL3_HORIZONTAL_WAIT_CNT_OFFSET 16 | 230 | #define LCDIF_VDCTRL3_HORIZONTAL_WAIT_CNT_OFFSET 16 |
| 231 | #define LCDIF_VDCTRL3_VERTICAL_WAIT_CNT_MASK (0xffff << 0) | 231 | #define LCDIF_VDCTRL3_VERTICAL_WAIT_CNT_MASK (0xffff << 0) |
| 232 | #define LCDIF_VDCTRL3_VERTICAL_WAIT_CNT_OFFSET 0 | 232 | #define LCDIF_VDCTRL3_VERTICAL_WAIT_CNT_OFFSET 0 |
| 233 | 233 | ||
| 234 | #define LCDIF_VDCTRL4_DOTCLK_DLY_SEL_MASK (0x7 << 29) | 234 | #define LCDIF_VDCTRL4_DOTCLK_DLY_SEL_MASK (0x7 << 29) |
| 235 | #define LCDIF_VDCTRL4_DOTCLK_DLY_SEL_OFFSET 29 | 235 | #define LCDIF_VDCTRL4_DOTCLK_DLY_SEL_OFFSET 29 |
| 236 | #define LCDIF_VDCTRL4_SYNC_SIGNALS_ON (1 << 18) | 236 | #define LCDIF_VDCTRL4_SYNC_SIGNALS_ON (1 << 18) |
| 237 | #define LCDIF_VDCTRL4_DOTCLK_H_VALID_DATA_CNT_MASK 0x3ffff | 237 | #define LCDIF_VDCTRL4_DOTCLK_H_VALID_DATA_CNT_MASK 0x3ffff |
| 238 | #define LCDIF_VDCTRL4_DOTCLK_H_VALID_DATA_CNT_OFFSET 0 | 238 | #define LCDIF_VDCTRL4_DOTCLK_H_VALID_DATA_CNT_OFFSET 0 |
| 239 | 239 | ||
| 240 | #endif /* __IMX_REGS_LCDIF_H__ */ | 240 | #endif /* __IMX_REGS_LCDIF_H__ */ |
| 241 | 241 |
drivers/video/mxsfb.c
| 1 | // SPDX-License-Identifier: GPL-2.0+ | 1 | // SPDX-License-Identifier: GPL-2.0+ |
| 2 | /* | 2 | /* |
| 3 | * Freescale i.MX23/i.MX28 LCDIF driver | 3 | * Freescale i.MX23/i.MX28 LCDIF driver |
| 4 | * | 4 | * |
| 5 | * Copyright (C) 2011-2013 Marek Vasut <marex@denx.de> | 5 | * Copyright (C) 2011-2013 Marek Vasut <marex@denx.de> |
| 6 | * Copyright (C) 2014-2016 Freescale Semiconductor, Inc. | 6 | * Copyright (C) 2014-2016 Freescale Semiconductor, Inc. |
| 7 | * | 7 | * |
| 8 | */ | 8 | */ |
| 9 | #include <common.h> | 9 | #include <common.h> |
| 10 | #include <clk.h> | 10 | #include <clk.h> |
| 11 | #include <dm.h> | 11 | #include <dm.h> |
| 12 | #include <env.h> | 12 | #include <env.h> |
| 13 | #include <log.h> | 13 | #include <log.h> |
| 14 | #include <asm/cache.h> | 14 | #include <asm/cache.h> |
| 15 | #include <dm/device_compat.h> | 15 | #include <dm/device_compat.h> |
| 16 | #include <linux/delay.h> | 16 | #include <linux/delay.h> |
| 17 | #include <linux/errno.h> | 17 | #include <linux/errno.h> |
| 18 | #include <malloc.h> | 18 | #include <malloc.h> |
| 19 | #include <video.h> | 19 | #include <video.h> |
| 20 | #include <video_fb.h> | 20 | #include <video_fb.h> |
| 21 | 21 | #if CONFIG_IS_ENABLED(CLK) && IS_ENABLED(CONFIG_IMX8) | |
| 22 | #include <clk.h> | ||
| 23 | #else | ||
| 22 | #include <asm/arch/clock.h> | 24 | #include <asm/arch/clock.h> |
| 25 | #endif | ||
| 23 | #include <asm/arch/imx-regs.h> | 26 | #include <asm/arch/imx-regs.h> |
| 24 | #include <asm/arch/sys_proto.h> | 27 | #include <asm/arch/sys_proto.h> |
| 25 | #include <asm/global_data.h> | 28 | #include <asm/global_data.h> |
| 26 | #include <asm/mach-imx/dma.h> | 29 | #include <asm/mach-imx/dma.h> |
| 27 | #include <asm/io.h> | 30 | #include <asm/io.h> |
| 28 | #include <reset.h> | 31 | #include <reset.h> |
| 29 | #include <panel.h> | 32 | #include <panel.h> |
| 30 | #include <video_bridge.h> | 33 | #include <video_bridge.h> |
| 31 | #include <video_link.h> | 34 | #include <video_link.h> |
| 32 | 35 | ||
| 33 | #include "videomodes.h" | 36 | #include "videomodes.h" |
| 34 | #include <linux/string.h> | 37 | #include <linux/string.h> |
| 35 | #include <linux/list.h> | 38 | #include <linux/list.h> |
| 36 | #include <linux/fb.h> | 39 | #include <linux/fb.h> |
| 37 | #include <mxsfb.h> | 40 | #include <mxsfb.h> |
| 38 | #include <dm/device-internal.h> | 41 | #include <dm/device-internal.h> |
| 39 | 42 | ||
| 40 | #ifdef CONFIG_VIDEO_GIS | 43 | #ifdef CONFIG_VIDEO_GIS |
| 41 | #include <gis.h> | 44 | #include <gis.h> |
| 42 | #endif | 45 | #endif |
| 43 | 46 | ||
| 44 | #define PS2KHZ(ps) (1000000000UL / (ps)) | 47 | #define PS2KHZ(ps) (1000000000UL / (ps)) |
| 45 | #define HZ2PS(hz) (1000000000UL / ((hz) / 1000)) | 48 | #define HZ2PS(hz) (1000000000UL / ((hz) / 1000)) |
| 46 | 49 | ||
| 47 | #define BITS_PP 18 | 50 | #define BITS_PP 18 |
| 48 | #define BYTES_PP 4 | 51 | #define BYTES_PP 4 |
| 49 | 52 | ||
| 50 | struct mxs_dma_desc desc; | 53 | struct mxs_dma_desc desc; |
| 51 | 54 | ||
| 52 | /** | 55 | /** |
| 53 | * mxsfb_system_setup() - Fine-tune LCDIF configuration | 56 | * mxsfb_system_setup() - Fine-tune LCDIF configuration |
| 54 | * | 57 | * |
| 55 | * This function is used to adjust the LCDIF configuration. This is usually | 58 | * This function is used to adjust the LCDIF configuration. This is usually |
| 56 | * needed when driving the controller in System-Mode to operate an 8080 or | 59 | * needed when driving the controller in System-Mode to operate an 8080 or |
| 57 | * 6800 connected SmartLCD. | 60 | * 6800 connected SmartLCD. |
| 58 | */ | 61 | */ |
| 59 | __weak void mxsfb_system_setup(void) | 62 | __weak void mxsfb_system_setup(void) |
| 60 | { | 63 | { |
| 61 | } | 64 | } |
| 62 | 65 | ||
| 63 | /* | 66 | /* |
| 64 | * ARIES M28EVK: | 67 | * ARIES M28EVK: |
| 65 | * setenv videomode | 68 | * setenv videomode |
| 66 | * video=ctfb:x:800,y:480,depth:18,mode:0,pclk:30066, | 69 | * video=ctfb:x:800,y:480,depth:18,mode:0,pclk:30066, |
| 67 | * le:0,ri:256,up:0,lo:45,hs:1,vs:1,sync:100663296,vmode:0 | 70 | * le:0,ri:256,up:0,lo:45,hs:1,vs:1,sync:100663296,vmode:0 |
| 68 | * | 71 | * |
| 69 | * Freescale mx23evk/mx28evk with a Seiko 4.3'' WVGA panel: | 72 | * Freescale mx23evk/mx28evk with a Seiko 4.3'' WVGA panel: |
| 70 | * setenv videomode | 73 | * setenv videomode |
| 71 | * video=ctfb:x:800,y:480,depth:24,mode:0,pclk:29851, | 74 | * video=ctfb:x:800,y:480,depth:24,mode:0,pclk:29851, |
| 72 | * le:89,ri:164,up:23,lo:10,hs:10,vs:10,sync:0,vmode:0 | 75 | * le:89,ri:164,up:23,lo:10,hs:10,vs:10,sync:0,vmode:0 |
| 73 | */ | 76 | */ |
| 74 | 77 | ||
| 75 | static void mxs_lcd_init(phys_addr_t reg_base, u32 fb_addr, | 78 | static void mxs_lcd_init(phys_addr_t reg_base, u32 fb_addr, |
| 76 | struct display_timing *timings, int bpp, bool bridge) | 79 | struct display_timing *timings, int bpp, bool bridge) |
| 77 | { | 80 | { |
| 78 | struct mxs_lcdif_regs *regs = (struct mxs_lcdif_regs *)(reg_base); | 81 | struct mxs_lcdif_regs *regs = (struct mxs_lcdif_regs *)(reg_base); |
| 79 | const enum display_flags flags = timings->flags; | 82 | const enum display_flags flags = timings->flags; |
| 80 | uint32_t word_len = 0, bus_width = 0; | 83 | uint32_t word_len = 0, bus_width = 0; |
| 81 | uint8_t valid_data = 0; | 84 | uint8_t valid_data = 0; |
| 82 | uint32_t vdctrl0; | 85 | uint32_t vdctrl0; |
| 83 | 86 | ||
| 84 | 87 | #if !(CONFIG_IS_ENABLED(CLK) && IS_ENABLED(CONFIG_IMX8)) | |
| 85 | #if !CONFIG_IS_ENABLED(CLK) | ||
| 86 | /* Kick in the LCDIF clock */ | 88 | /* Kick in the LCDIF clock */ |
| 87 | mxs_set_lcdclk((u32)reg_base, timings->pixelclock.typ / 1000); | 89 | mxs_set_lcdclk((u32)reg_base, timings->pixelclock.typ / 1000); |
| 88 | #endif | 90 | #endif |
| 89 | 91 | ||
| 90 | /* Restart the LCDIF block */ | 92 | /* Restart the LCDIF block */ |
| 91 | mxs_reset_block(®s->hw_lcdif_ctrl_reg); | 93 | mxs_reset_block(®s->hw_lcdif_ctrl_reg); |
| 92 | 94 | ||
| 93 | switch (bpp) { | 95 | switch (bpp) { |
| 94 | case 24: | 96 | case 24: |
| 95 | word_len = LCDIF_CTRL_WORD_LENGTH_24BIT; | 97 | word_len = LCDIF_CTRL_WORD_LENGTH_24BIT; |
| 96 | bus_width = LCDIF_CTRL_LCD_DATABUS_WIDTH_24BIT; | 98 | bus_width = LCDIF_CTRL_LCD_DATABUS_WIDTH_24BIT; |
| 97 | valid_data = 0x7; | 99 | valid_data = 0x7; |
| 98 | break; | 100 | break; |
| 99 | case 18: | 101 | case 18: |
| 100 | word_len = LCDIF_CTRL_WORD_LENGTH_24BIT; | 102 | word_len = LCDIF_CTRL_WORD_LENGTH_24BIT; |
| 101 | bus_width = LCDIF_CTRL_LCD_DATABUS_WIDTH_18BIT; | 103 | bus_width = LCDIF_CTRL_LCD_DATABUS_WIDTH_18BIT; |
| 102 | valid_data = 0x7; | 104 | valid_data = 0x7; |
| 103 | break; | 105 | break; |
| 104 | case 16: | 106 | case 16: |
| 105 | word_len = LCDIF_CTRL_WORD_LENGTH_16BIT; | 107 | word_len = LCDIF_CTRL_WORD_LENGTH_16BIT; |
| 106 | bus_width = LCDIF_CTRL_LCD_DATABUS_WIDTH_16BIT; | 108 | bus_width = LCDIF_CTRL_LCD_DATABUS_WIDTH_16BIT; |
| 107 | valid_data = 0xf; | 109 | valid_data = 0xf; |
| 108 | break; | 110 | break; |
| 109 | case 8: | 111 | case 8: |
| 110 | word_len = LCDIF_CTRL_WORD_LENGTH_8BIT; | 112 | word_len = LCDIF_CTRL_WORD_LENGTH_8BIT; |
| 111 | bus_width = LCDIF_CTRL_LCD_DATABUS_WIDTH_8BIT; | 113 | bus_width = LCDIF_CTRL_LCD_DATABUS_WIDTH_8BIT; |
| 112 | valid_data = 0xf; | 114 | valid_data = 0xf; |
| 113 | break; | 115 | break; |
| 114 | } | 116 | } |
| 115 | 117 | ||
| 116 | writel(bus_width | word_len | LCDIF_CTRL_DOTCLK_MODE | | 118 | writel(bus_width | word_len | LCDIF_CTRL_DOTCLK_MODE | |
| 117 | LCDIF_CTRL_BYPASS_COUNT | LCDIF_CTRL_LCDIF_MASTER, | 119 | LCDIF_CTRL_BYPASS_COUNT | LCDIF_CTRL_LCDIF_MASTER, |
| 118 | ®s->hw_lcdif_ctrl); | 120 | ®s->hw_lcdif_ctrl); |
| 119 | 121 | ||
| 120 | writel(valid_data << LCDIF_CTRL1_BYTE_PACKING_FORMAT_OFFSET, | 122 | writel(valid_data << LCDIF_CTRL1_BYTE_PACKING_FORMAT_OFFSET, |
| 121 | ®s->hw_lcdif_ctrl1); | 123 | ®s->hw_lcdif_ctrl1); |
| 122 | 124 | ||
| 123 | if (bridge) | 125 | if (bridge) |
| 124 | writel(LCDIF_CTRL2_OUTSTANDING_REQS_REQ_16, ®s->hw_lcdif_ctrl2); | 126 | writel(LCDIF_CTRL2_OUTSTANDING_REQS_REQ_16, ®s->hw_lcdif_ctrl2); |
| 125 | 127 | ||
| 126 | mxsfb_system_setup(); | 128 | mxsfb_system_setup(); |
| 127 | 129 | ||
| 128 | writel((timings->vactive.typ << LCDIF_TRANSFER_COUNT_V_COUNT_OFFSET) | | 130 | writel((timings->vactive.typ << LCDIF_TRANSFER_COUNT_V_COUNT_OFFSET) | |
| 129 | timings->hactive.typ, ®s->hw_lcdif_transfer_count); | 131 | timings->hactive.typ, ®s->hw_lcdif_transfer_count); |
| 130 | 132 | ||
| 131 | vdctrl0 = LCDIF_VDCTRL0_ENABLE_PRESENT | | 133 | vdctrl0 = LCDIF_VDCTRL0_ENABLE_PRESENT | |
| 132 | LCDIF_VDCTRL0_VSYNC_PERIOD_UNIT | | 134 | LCDIF_VDCTRL0_VSYNC_PERIOD_UNIT | |
| 133 | LCDIF_VDCTRL0_VSYNC_PULSE_WIDTH_UNIT | | 135 | LCDIF_VDCTRL0_VSYNC_PULSE_WIDTH_UNIT | |
| 134 | timings->vsync_len.typ; | 136 | timings->vsync_len.typ; |
| 135 | 137 | ||
| 136 | if(flags & DISPLAY_FLAGS_HSYNC_HIGH) | 138 | if(flags & DISPLAY_FLAGS_HSYNC_HIGH) |
| 137 | vdctrl0 |= LCDIF_VDCTRL0_HSYNC_POL; | 139 | vdctrl0 |= LCDIF_VDCTRL0_HSYNC_POL; |
| 138 | if(flags & DISPLAY_FLAGS_VSYNC_HIGH) | 140 | if(flags & DISPLAY_FLAGS_VSYNC_HIGH) |
| 139 | vdctrl0 |= LCDIF_VDCTRL0_VSYNC_POL; | 141 | vdctrl0 |= LCDIF_VDCTRL0_VSYNC_POL; |
| 140 | if(flags & DISPLAY_FLAGS_PIXDATA_NEGEDGE) | 142 | if(flags & DISPLAY_FLAGS_PIXDATA_NEGEDGE) |
| 141 | vdctrl0 |= LCDIF_VDCTRL0_DOTCLK_POL; | 143 | vdctrl0 |= LCDIF_VDCTRL0_DOTCLK_POL; |
| 142 | if(flags & DISPLAY_FLAGS_DE_HIGH) | 144 | if(flags & DISPLAY_FLAGS_DE_HIGH) |
| 143 | vdctrl0 |= LCDIF_VDCTRL0_ENABLE_POL; | 145 | vdctrl0 |= LCDIF_VDCTRL0_ENABLE_POL; |
| 144 | 146 | ||
| 145 | writel(vdctrl0, ®s->hw_lcdif_vdctrl0); | 147 | writel(vdctrl0, ®s->hw_lcdif_vdctrl0); |
| 146 | writel(timings->vback_porch.typ + timings->vfront_porch.typ + | 148 | writel(timings->vback_porch.typ + timings->vfront_porch.typ + |
| 147 | timings->vsync_len.typ + timings->vactive.typ, | 149 | timings->vsync_len.typ + timings->vactive.typ, |
| 148 | ®s->hw_lcdif_vdctrl1); | 150 | ®s->hw_lcdif_vdctrl1); |
| 149 | writel((timings->hsync_len.typ << LCDIF_VDCTRL2_HSYNC_PULSE_WIDTH_OFFSET) | | 151 | writel((timings->hsync_len.typ << LCDIF_VDCTRL2_HSYNC_PULSE_WIDTH_OFFSET) | |
| 150 | (timings->hback_porch.typ + timings->hfront_porch.typ + | 152 | (timings->hback_porch.typ + timings->hfront_porch.typ + |
| 151 | timings->hsync_len.typ + timings->hactive.typ), | 153 | timings->hsync_len.typ + timings->hactive.typ), |
| 152 | ®s->hw_lcdif_vdctrl2); | 154 | ®s->hw_lcdif_vdctrl2); |
| 153 | writel(((timings->hback_porch.typ + timings->hsync_len.typ) << | 155 | writel(((timings->hback_porch.typ + timings->hsync_len.typ) << |
| 154 | LCDIF_VDCTRL3_HORIZONTAL_WAIT_CNT_OFFSET) | | 156 | LCDIF_VDCTRL3_HORIZONTAL_WAIT_CNT_OFFSET) | |
| 155 | (timings->vback_porch.typ + timings->vsync_len.typ), | 157 | (timings->vback_porch.typ + timings->vsync_len.typ), |
| 156 | ®s->hw_lcdif_vdctrl3); | 158 | ®s->hw_lcdif_vdctrl3); |
| 157 | writel((0 << LCDIF_VDCTRL4_DOTCLK_DLY_SEL_OFFSET) | timings->hactive.typ, | 159 | writel((0 << LCDIF_VDCTRL4_DOTCLK_DLY_SEL_OFFSET) | timings->hactive.typ, |
| 158 | ®s->hw_lcdif_vdctrl4); | 160 | ®s->hw_lcdif_vdctrl4); |
| 159 | 161 | ||
| 160 | writel(fb_addr, ®s->hw_lcdif_cur_buf); | 162 | writel(fb_addr, ®s->hw_lcdif_cur_buf); |
| 161 | writel(fb_addr, ®s->hw_lcdif_next_buf); | 163 | writel(fb_addr, ®s->hw_lcdif_next_buf); |
| 162 | 164 | ||
| 163 | /* Flush FIFO first */ | 165 | /* Flush FIFO first */ |
| 164 | writel(LCDIF_CTRL1_FIFO_CLEAR, ®s->hw_lcdif_ctrl1_set); | 166 | writel(LCDIF_CTRL1_FIFO_CLEAR, ®s->hw_lcdif_ctrl1_set); |
| 165 | 167 | ||
| 166 | #ifndef CONFIG_VIDEO_MXS_MODE_SYSTEM | 168 | #ifndef CONFIG_VIDEO_MXS_MODE_SYSTEM |
| 167 | /* Sync signals ON */ | 169 | /* Sync signals ON */ |
| 168 | setbits_le32(®s->hw_lcdif_vdctrl4, LCDIF_VDCTRL4_SYNC_SIGNALS_ON); | 170 | setbits_le32(®s->hw_lcdif_vdctrl4, LCDIF_VDCTRL4_SYNC_SIGNALS_ON); |
| 169 | #endif | 171 | #endif |
| 170 | 172 | ||
| 171 | /* FIFO cleared */ | 173 | /* FIFO cleared */ |
| 172 | writel(LCDIF_CTRL1_FIFO_CLEAR, ®s->hw_lcdif_ctrl1_clr); | 174 | writel(LCDIF_CTRL1_FIFO_CLEAR, ®s->hw_lcdif_ctrl1_clr); |
| 173 | 175 | ||
| 174 | /* RUN! */ | 176 | /* RUN! */ |
| 175 | writel(LCDIF_CTRL_RUN, ®s->hw_lcdif_ctrl_set); | 177 | writel(LCDIF_CTRL_RUN, ®s->hw_lcdif_ctrl_set); |
| 176 | } | 178 | } |
| 177 | 179 | ||
| 178 | static int mxs_probe_common(phys_addr_t reg_base, struct display_timing *timings, | 180 | static int mxs_probe_common(phys_addr_t reg_base, struct display_timing *timings, |
| 179 | int bpp, u32 fb, bool bridge) | 181 | int bpp, u32 fb, bool bridge) |
| 180 | { | 182 | { |
| 181 | /* Start framebuffer */ | 183 | /* Start framebuffer */ |
| 182 | mxs_lcd_init(reg_base, fb, timings, bpp, bridge); | 184 | mxs_lcd_init(reg_base, fb, timings, bpp, bridge); |
| 183 | 185 | ||
| 184 | #ifdef CONFIG_VIDEO_MXS_MODE_SYSTEM | 186 | #ifdef CONFIG_VIDEO_MXS_MODE_SYSTEM |
| 185 | /* | 187 | /* |
| 186 | * If the LCD runs in system mode, the LCD refresh has to be triggered | 188 | * If the LCD runs in system mode, the LCD refresh has to be triggered |
| 187 | * manually by setting the RUN bit in HW_LCDIF_CTRL register. To avoid | 189 | * manually by setting the RUN bit in HW_LCDIF_CTRL register. To avoid |
| 188 | * having to set this bit manually after every single change in the | 190 | * having to set this bit manually after every single change in the |
| 189 | * framebuffer memory, we set up specially crafted circular DMA, which | 191 | * framebuffer memory, we set up specially crafted circular DMA, which |
| 190 | * sets the RUN bit, then waits until it gets cleared and repeats this | 192 | * sets the RUN bit, then waits until it gets cleared and repeats this |
| 191 | * infinitelly. This way, we get smooth continuous updates of the LCD. | 193 | * infinitelly. This way, we get smooth continuous updates of the LCD. |
| 192 | */ | 194 | */ |
| 193 | struct mxs_lcdif_regs *regs = (struct mxs_lcdif_regs *)reg_base; | 195 | struct mxs_lcdif_regs *regs = (struct mxs_lcdif_regs *)reg_base; |
| 194 | 196 | ||
| 195 | memset(&desc, 0, sizeof(struct mxs_dma_desc)); | 197 | memset(&desc, 0, sizeof(struct mxs_dma_desc)); |
| 196 | desc.address = (dma_addr_t)&desc; | 198 | desc.address = (dma_addr_t)&desc; |
| 197 | desc.cmd.data = MXS_DMA_DESC_COMMAND_NO_DMAXFER | MXS_DMA_DESC_CHAIN | | 199 | desc.cmd.data = MXS_DMA_DESC_COMMAND_NO_DMAXFER | MXS_DMA_DESC_CHAIN | |
| 198 | MXS_DMA_DESC_WAIT4END | | 200 | MXS_DMA_DESC_WAIT4END | |
| 199 | (1 << MXS_DMA_DESC_PIO_WORDS_OFFSET); | 201 | (1 << MXS_DMA_DESC_PIO_WORDS_OFFSET); |
| 200 | desc.cmd.pio_words[0] = readl(®s->hw_lcdif_ctrl) | LCDIF_CTRL_RUN; | 202 | desc.cmd.pio_words[0] = readl(®s->hw_lcdif_ctrl) | LCDIF_CTRL_RUN; |
| 201 | desc.cmd.next = (uint32_t)&desc.cmd; | 203 | desc.cmd.next = (uint32_t)&desc.cmd; |
| 202 | 204 | ||
| 203 | /* Execute the DMA chain. */ | 205 | /* Execute the DMA chain. */ |
| 204 | mxs_dma_circ_start(MXS_DMA_CHANNEL_AHB_APBH_LCDIF, &desc); | 206 | mxs_dma_circ_start(MXS_DMA_CHANNEL_AHB_APBH_LCDIF, &desc); |
| 205 | #endif | 207 | #endif |
| 206 | 208 | ||
| 207 | return 0; | 209 | return 0; |
| 208 | } | 210 | } |
| 209 | 211 | ||
| 210 | static int mxs_remove_common(phys_addr_t reg_base, u32 fb) | 212 | static int mxs_remove_common(phys_addr_t reg_base, u32 fb) |
| 211 | { | 213 | { |
| 212 | struct mxs_lcdif_regs *regs = (struct mxs_lcdif_regs *)(reg_base); | 214 | struct mxs_lcdif_regs *regs = (struct mxs_lcdif_regs *)(reg_base); |
| 213 | int timeout = 1000000; | 215 | int timeout = 1000000; |
| 214 | 216 | ||
| 215 | if (CONFIG_IS_ENABLED(IMX_MODULE_FUSE)) { | 217 | if (CONFIG_IS_ENABLED(IMX_MODULE_FUSE)) { |
| 216 | if (check_module_fused(MODULE_LCDIF)) | 218 | if (check_module_fused(MODULE_LCDIF)) |
| 217 | return -ENODEV; | 219 | return -ENODEV; |
| 218 | } | 220 | } |
| 219 | 221 | ||
| 220 | if (!fb) | 222 | if (!fb) |
| 221 | return -EINVAL; | 223 | return -EINVAL; |
| 222 | 224 | ||
| 223 | writel(fb, ®s->hw_lcdif_cur_buf_reg); | 225 | writel(fb, ®s->hw_lcdif_cur_buf_reg); |
| 224 | writel(fb, ®s->hw_lcdif_next_buf_reg); | 226 | writel(fb, ®s->hw_lcdif_next_buf_reg); |
| 225 | writel(LCDIF_CTRL1_VSYNC_EDGE_IRQ, ®s->hw_lcdif_ctrl1_clr); | 227 | writel(LCDIF_CTRL1_VSYNC_EDGE_IRQ, ®s->hw_lcdif_ctrl1_clr); |
| 226 | while (--timeout) { | 228 | while (--timeout) { |
| 227 | if (readl(®s->hw_lcdif_ctrl1_reg) & | 229 | if (readl(®s->hw_lcdif_ctrl1_reg) & |
| 228 | LCDIF_CTRL1_VSYNC_EDGE_IRQ) | 230 | LCDIF_CTRL1_VSYNC_EDGE_IRQ) |
| 229 | break; | 231 | break; |
| 230 | udelay(1); | 232 | udelay(1); |
| 231 | } | 233 | } |
| 232 | mxs_reset_block((struct mxs_register_32 *)®s->hw_lcdif_ctrl_reg); | 234 | mxs_reset_block((struct mxs_register_32 *)®s->hw_lcdif_ctrl_reg); |
| 233 | 235 | ||
| 234 | return 0; | 236 | return 0; |
| 235 | } | 237 | } |
| 236 | 238 | ||
| 237 | #ifndef CONFIG_DM_VIDEO | 239 | #ifndef CONFIG_DM_VIDEO |
| 238 | 240 | ||
| 239 | static GraphicDevice panel; | 241 | static GraphicDevice panel; |
| 240 | static int setup; | 242 | static int setup; |
| 241 | static struct fb_videomode fbmode; | 243 | static struct fb_videomode fbmode; |
| 242 | static int depth; | 244 | static int depth; |
| 243 | 245 | ||
| 244 | int mxs_lcd_panel_setup(struct fb_videomode mode, int bpp, | 246 | int mxs_lcd_panel_setup(struct fb_videomode mode, int bpp, |
| 245 | uint32_t base_addr) | 247 | uint32_t base_addr) |
| 246 | { | 248 | { |
| 247 | fbmode = mode; | 249 | fbmode = mode; |
| 248 | depth = bpp; | 250 | depth = bpp; |
| 249 | panel.isaBase = base_addr; | 251 | panel.isaBase = base_addr; |
| 250 | 252 | ||
| 251 | setup = 1; | 253 | setup = 1; |
| 252 | 254 | ||
| 253 | return 0; | 255 | return 0; |
| 254 | } | 256 | } |
| 255 | 257 | ||
| 256 | void mxs_lcd_get_panel(struct display_panel *dispanel) | 258 | void mxs_lcd_get_panel(struct display_panel *dispanel) |
| 257 | { | 259 | { |
| 258 | dispanel->width = fbmode.xres; | 260 | dispanel->width = fbmode.xres; |
| 259 | dispanel->height = fbmode.yres; | 261 | dispanel->height = fbmode.yres; |
| 260 | dispanel->reg_base = panel.isaBase; | 262 | dispanel->reg_base = panel.isaBase; |
| 261 | dispanel->gdfindex = panel.gdfIndex; | 263 | dispanel->gdfindex = panel.gdfIndex; |
| 262 | dispanel->gdfbytespp = panel.gdfBytesPP; | 264 | dispanel->gdfbytespp = panel.gdfBytesPP; |
| 263 | } | 265 | } |
| 264 | 266 | ||
| 265 | void lcdif_power_down(void) | 267 | void lcdif_power_down(void) |
| 266 | { | 268 | { |
| 267 | mxs_remove_common(panel.isaBase, panel.frameAdrs); | 269 | mxs_remove_common(panel.isaBase, panel.frameAdrs); |
| 268 | } | 270 | } |
| 269 | 271 | ||
| 270 | void *video_hw_init(void) | 272 | void *video_hw_init(void) |
| 271 | { | 273 | { |
| 272 | int bpp = -1; | 274 | int bpp = -1; |
| 273 | int ret = 0; | 275 | int ret = 0; |
| 274 | char *penv; | 276 | char *penv; |
| 275 | void *fb = NULL; | 277 | void *fb = NULL; |
| 276 | struct ctfb_res_modes mode; | 278 | struct ctfb_res_modes mode; |
| 277 | struct display_timing timings; | 279 | struct display_timing timings; |
| 278 | 280 | ||
| 279 | puts("Video: "); | 281 | puts("Video: "); |
| 280 | 282 | ||
| 281 | if (!setup) { | 283 | if (!setup) { |
| 282 | 284 | ||
| 283 | /* Suck display configuration from "videomode" variable */ | 285 | /* Suck display configuration from "videomode" variable */ |
| 284 | penv = env_get("videomode"); | 286 | penv = env_get("videomode"); |
| 285 | if (!penv) { | 287 | if (!penv) { |
| 286 | printf("MXSFB: 'videomode' variable not set!\n"); | 288 | printf("MXSFB: 'videomode' variable not set!\n"); |
| 287 | return NULL; | 289 | return NULL; |
| 288 | } | 290 | } |
| 289 | 291 | ||
| 290 | bpp = video_get_params(&mode, penv); | 292 | bpp = video_get_params(&mode, penv); |
| 291 | panel.isaBase = MXS_LCDIF_BASE; | 293 | panel.isaBase = MXS_LCDIF_BASE; |
| 292 | } else { | 294 | } else { |
| 293 | mode.xres = fbmode.xres; | 295 | mode.xres = fbmode.xres; |
| 294 | mode.yres = fbmode.yres; | 296 | mode.yres = fbmode.yres; |
| 295 | mode.pixclock = fbmode.pixclock; | 297 | mode.pixclock = fbmode.pixclock; |
| 296 | mode.left_margin = fbmode.left_margin; | 298 | mode.left_margin = fbmode.left_margin; |
| 297 | mode.right_margin = fbmode.right_margin; | 299 | mode.right_margin = fbmode.right_margin; |
| 298 | mode.upper_margin = fbmode.upper_margin; | 300 | mode.upper_margin = fbmode.upper_margin; |
| 299 | mode.lower_margin = fbmode.lower_margin; | 301 | mode.lower_margin = fbmode.lower_margin; |
| 300 | mode.hsync_len = fbmode.hsync_len; | 302 | mode.hsync_len = fbmode.hsync_len; |
| 301 | mode.vsync_len = fbmode.vsync_len; | 303 | mode.vsync_len = fbmode.vsync_len; |
| 302 | mode.sync = fbmode.sync; | 304 | mode.sync = fbmode.sync; |
| 303 | mode.vmode = fbmode.vmode; | 305 | mode.vmode = fbmode.vmode; |
| 304 | bpp = depth; | 306 | bpp = depth; |
| 305 | } | 307 | } |
| 306 | 308 | ||
| 307 | mode.pixclock_khz = PS2KHZ(mode.pixclock); | 309 | mode.pixclock_khz = PS2KHZ(mode.pixclock); |
| 308 | mode.pixclock = mode.pixclock_khz * 1000; | 310 | mode.pixclock = mode.pixclock_khz * 1000; |
| 309 | 311 | ||
| 310 | if (CONFIG_IS_ENABLED(IMX_MODULE_FUSE)) { | 312 | if (CONFIG_IS_ENABLED(IMX_MODULE_FUSE)) { |
| 311 | if (check_module_fused(MODULE_LCDIF)) { | 313 | if (check_module_fused(MODULE_LCDIF)) { |
| 312 | printf("LCDIF@0x%x is fused, disable it\n", MXS_LCDIF_BASE); | 314 | printf("LCDIF@0x%x is fused, disable it\n", MXS_LCDIF_BASE); |
| 313 | return NULL; | 315 | return NULL; |
| 314 | } | 316 | } |
| 315 | } | 317 | } |
| 316 | /* fill in Graphic device struct */ | 318 | /* fill in Graphic device struct */ |
| 317 | sprintf(panel.modeIdent, "%dx%dx%d", mode.xres, mode.yres, bpp); | 319 | sprintf(panel.modeIdent, "%dx%dx%d", mode.xres, mode.yres, bpp); |
| 318 | 320 | ||
| 319 | panel.winSizeX = mode.xres; | 321 | panel.winSizeX = mode.xres; |
| 320 | panel.winSizeY = mode.yres; | 322 | panel.winSizeY = mode.yres; |
| 321 | panel.plnSizeX = mode.xres; | 323 | panel.plnSizeX = mode.xres; |
| 322 | panel.plnSizeY = mode.yres; | 324 | panel.plnSizeY = mode.yres; |
| 323 | 325 | ||
| 324 | switch (bpp) { | 326 | switch (bpp) { |
| 325 | case 24: | 327 | case 24: |
| 326 | case 18: | 328 | case 18: |
| 327 | panel.gdfBytesPP = 4; | 329 | panel.gdfBytesPP = 4; |
| 328 | panel.gdfIndex = GDF_32BIT_X888RGB; | 330 | panel.gdfIndex = GDF_32BIT_X888RGB; |
| 329 | break; | 331 | break; |
| 330 | case 16: | 332 | case 16: |
| 331 | panel.gdfBytesPP = 2; | 333 | panel.gdfBytesPP = 2; |
| 332 | panel.gdfIndex = GDF_16BIT_565RGB; | 334 | panel.gdfIndex = GDF_16BIT_565RGB; |
| 333 | break; | 335 | break; |
| 334 | case 8: | 336 | case 8: |
| 335 | panel.gdfBytesPP = 1; | 337 | panel.gdfBytesPP = 1; |
| 336 | panel.gdfIndex = GDF__8BIT_INDEX; | 338 | panel.gdfIndex = GDF__8BIT_INDEX; |
| 337 | break; | 339 | break; |
| 338 | default: | 340 | default: |
| 339 | printf("MXSFB: Invalid BPP specified! (bpp = %i)\n", bpp); | 341 | printf("MXSFB: Invalid BPP specified! (bpp = %i)\n", bpp); |
| 340 | return NULL; | 342 | return NULL; |
| 341 | } | 343 | } |
| 342 | 344 | ||
| 343 | panel.memSize = mode.xres * mode.yres * panel.gdfBytesPP; | 345 | panel.memSize = mode.xres * mode.yres * panel.gdfBytesPP; |
| 344 | 346 | ||
| 345 | /* Allocate framebuffer */ | 347 | /* Allocate framebuffer */ |
| 346 | fb = memalign(ARCH_DMA_MINALIGN, | 348 | fb = memalign(ARCH_DMA_MINALIGN, |
| 347 | roundup(panel.memSize, ARCH_DMA_MINALIGN)); | 349 | roundup(panel.memSize, ARCH_DMA_MINALIGN)); |
| 348 | if (!fb) { | 350 | if (!fb) { |
| 349 | printf("MXSFB: Error allocating framebuffer!\n"); | 351 | printf("MXSFB: Error allocating framebuffer!\n"); |
| 350 | return NULL; | 352 | return NULL; |
| 351 | } | 353 | } |
| 352 | 354 | ||
| 353 | /* Wipe framebuffer */ | 355 | /* Wipe framebuffer */ |
| 354 | memset(fb, 0, panel.memSize); | 356 | memset(fb, 0, panel.memSize); |
| 355 | 357 | ||
| 356 | panel.frameAdrs = (u32)fb; | 358 | panel.frameAdrs = (u32)fb; |
| 357 | 359 | ||
| 358 | printf("%s\n", panel.modeIdent); | 360 | printf("%s\n", panel.modeIdent); |
| 359 | 361 | ||
| 360 | video_ctfb_mode_to_display_timing(&mode, &timings); | 362 | video_ctfb_mode_to_display_timing(&mode, &timings); |
| 361 | timings.flags |= DISPLAY_FLAGS_DE_HIGH; /* Force enable pol */ | 363 | timings.flags |= DISPLAY_FLAGS_DE_HIGH; /* Force enable pol */ |
| 362 | 364 | ||
| 363 | ret = mxs_probe_common(panel.isaBase, &timings, bpp, (u32)fb, false); | 365 | ret = mxs_probe_common(panel.isaBase, &timings, bpp, (u32)fb, false); |
| 364 | if (ret) | 366 | if (ret) |
| 365 | goto dealloc_fb; | 367 | goto dealloc_fb; |
| 366 | 368 | ||
| 367 | #ifdef CONFIG_VIDEO_GIS | 369 | #ifdef CONFIG_VIDEO_GIS |
| 368 | /* Entry for GIS */ | 370 | /* Entry for GIS */ |
| 369 | mxc_enable_gis(); | 371 | mxc_enable_gis(); |
| 370 | #endif | 372 | #endif |
| 371 | 373 | ||
| 372 | return (void *)&panel; | 374 | return (void *)&panel; |
| 373 | 375 | ||
| 374 | dealloc_fb: | 376 | dealloc_fb: |
| 375 | free(fb); | 377 | free(fb); |
| 376 | 378 | ||
| 377 | return NULL; | 379 | return NULL; |
| 378 | } | 380 | } |
| 379 | #else /* ifndef CONFIG_DM_VIDEO */ | 381 | #else /* ifndef CONFIG_DM_VIDEO */ |
| 380 | 382 | ||
| 381 | struct mxsfb_priv { | 383 | struct mxsfb_priv { |
| 382 | fdt_addr_t reg_base; | 384 | fdt_addr_t reg_base; |
| 383 | struct udevice *disp_dev; | 385 | struct udevice *disp_dev; |
| 384 | 386 | ||
| 385 | #if IS_ENABLED(CONFIG_DM_RESET) | 387 | #if IS_ENABLED(CONFIG_DM_RESET) |
| 386 | struct reset_ctl_bulk soft_resetn; | 388 | struct reset_ctl_bulk soft_resetn; |
| 387 | struct reset_ctl_bulk clk_enable; | 389 | struct reset_ctl_bulk clk_enable; |
| 388 | #endif | 390 | #endif |
| 391 | |||
| 392 | #if CONFIG_IS_ENABLED(CLK) && IS_ENABLED(CONFIG_IMX8) | ||
| 393 | struct clk lcdif_pix; | ||
| 394 | struct clk lcdif_disp_axi; | ||
| 395 | struct clk lcdif_axi; | ||
| 396 | #endif | ||
| 389 | }; | 397 | }; |
| 390 | 398 | ||
| 391 | #if IS_ENABLED(CONFIG_DM_RESET) | 399 | #if IS_ENABLED(CONFIG_DM_RESET) |
| 392 | static int lcdif_rstc_reset(struct reset_ctl_bulk *rstc, bool assert) | 400 | static int lcdif_rstc_reset(struct reset_ctl_bulk *rstc, bool assert) |
| 393 | { | 401 | { |
| 394 | int ret; | 402 | int ret; |
| 395 | 403 | ||
| 396 | if (!rstc) | 404 | if (!rstc) |
| 397 | return 0; | 405 | return 0; |
| 398 | 406 | ||
| 399 | ret = assert ? reset_assert_bulk(rstc) : | 407 | ret = assert ? reset_assert_bulk(rstc) : |
| 400 | reset_deassert_bulk(rstc); | 408 | reset_deassert_bulk(rstc); |
| 401 | 409 | ||
| 402 | return ret; | 410 | return ret; |
| 403 | } | 411 | } |
| 404 | 412 | ||
| 405 | static int lcdif_of_parse_resets(struct udevice *dev) | 413 | static int lcdif_of_parse_resets(struct udevice *dev) |
| 406 | { | 414 | { |
| 407 | int ret; | 415 | int ret; |
| 408 | ofnode parent, child; | 416 | ofnode parent, child; |
| 409 | struct ofnode_phandle_args args; | 417 | struct ofnode_phandle_args args; |
| 410 | struct reset_ctl_bulk rstc; | 418 | struct reset_ctl_bulk rstc; |
| 411 | const char *compat; | 419 | const char *compat; |
| 412 | uint32_t rstc_num = 0; | 420 | uint32_t rstc_num = 0; |
| 413 | 421 | ||
| 414 | struct mxsfb_priv *priv = dev_get_priv(dev); | 422 | struct mxsfb_priv *priv = dev_get_priv(dev); |
| 415 | 423 | ||
| 416 | ret = dev_read_phandle_with_args(dev, "resets", "#reset-cells", 0, | 424 | ret = dev_read_phandle_with_args(dev, "resets", "#reset-cells", 0, |
| 417 | 0, &args); | 425 | 0, &args); |
| 418 | if (ret) | 426 | if (ret) |
| 419 | return ret; | 427 | return ret; |
| 420 | 428 | ||
| 421 | parent = args.node; | 429 | parent = args.node; |
| 422 | ofnode_for_each_subnode(child, parent) { | 430 | ofnode_for_each_subnode(child, parent) { |
| 423 | compat = ofnode_get_property(child, "compatible", NULL); | 431 | compat = ofnode_get_property(child, "compatible", NULL); |
| 424 | if (!compat) | 432 | if (!compat) |
| 425 | continue; | 433 | continue; |
| 426 | 434 | ||
| 427 | ret = reset_get_bulk_nodev(child, &rstc); | 435 | ret = reset_get_bulk_nodev(child, &rstc); |
| 428 | if (ret) | 436 | if (ret) |
| 429 | continue; | 437 | continue; |
| 430 | 438 | ||
| 431 | if (!of_compat_cmp("lcdif,soft-resetn", compat, 0)) { | 439 | if (!of_compat_cmp("lcdif,soft-resetn", compat, 0)) { |
| 432 | priv->soft_resetn = rstc; | 440 | priv->soft_resetn = rstc; |
| 433 | rstc_num++; | 441 | rstc_num++; |
| 434 | } else if (!of_compat_cmp("lcdif,clk-enable", compat, 0)) { | 442 | } else if (!of_compat_cmp("lcdif,clk-enable", compat, 0)) { |
| 435 | priv->clk_enable = rstc; | 443 | priv->clk_enable = rstc; |
| 436 | rstc_num++; | 444 | rstc_num++; |
| 437 | } | 445 | } |
| 438 | else | 446 | else |
| 439 | dev_warn(dev, "invalid lcdif reset node: %s\n", compat); | 447 | dev_warn(dev, "invalid lcdif reset node: %s\n", compat); |
| 440 | } | 448 | } |
| 441 | 449 | ||
| 442 | if (!rstc_num) { | 450 | if (!rstc_num) { |
| 443 | dev_err(dev, "no invalid reset control exists\n"); | 451 | dev_err(dev, "no invalid reset control exists\n"); |
| 444 | return -EINVAL; | 452 | return -EINVAL; |
| 445 | } | 453 | } |
| 446 | 454 | ||
| 447 | return 0; | 455 | return 0; |
| 448 | } | 456 | } |
| 449 | #endif | 457 | #endif |
| 450 | 458 | ||
| 451 | static int mxs_of_get_timings(struct udevice *dev, | 459 | static int mxs_of_get_timings(struct udevice *dev, |
| 452 | struct display_timing *timings, | 460 | struct display_timing *timings, |
| 453 | u32 *bpp) | 461 | u32 *bpp) |
| 454 | { | 462 | { |
| 455 | int ret = 0; | 463 | int ret = 0; |
| 456 | u32 display_phandle; | 464 | u32 display_phandle; |
| 457 | ofnode display_node; | 465 | ofnode display_node; |
| 458 | struct mxsfb_priv *priv = dev_get_priv(dev); | 466 | struct mxsfb_priv *priv = dev_get_priv(dev); |
| 459 | 467 | ||
| 460 | ret = ofnode_read_u32(dev_ofnode(dev), "display", &display_phandle); | 468 | ret = ofnode_read_u32(dev_ofnode(dev), "display", &display_phandle); |
| 461 | if (ret) { | 469 | if (ret) { |
| 462 | dev_err(dev, "required display property isn't provided\n"); | 470 | dev_err(dev, "required display property isn't provided\n"); |
| 463 | return -EINVAL; | 471 | return -EINVAL; |
| 464 | } | 472 | } |
| 465 | 473 | ||
| 466 | display_node = ofnode_get_by_phandle(display_phandle); | 474 | display_node = ofnode_get_by_phandle(display_phandle); |
| 467 | if (!ofnode_valid(display_node)) { | 475 | if (!ofnode_valid(display_node)) { |
| 468 | dev_err(dev, "failed to find display subnode\n"); | 476 | dev_err(dev, "failed to find display subnode\n"); |
| 469 | return -EINVAL; | 477 | return -EINVAL; |
| 470 | } | 478 | } |
| 471 | 479 | ||
| 472 | ret = ofnode_read_u32(display_node, "bits-per-pixel", bpp); | 480 | ret = ofnode_read_u32(display_node, "bits-per-pixel", bpp); |
| 473 | if (ret) { | 481 | if (ret) { |
| 474 | dev_err(dev, | 482 | dev_err(dev, |
| 475 | "required bits-per-pixel property isn't provided\n"); | 483 | "required bits-per-pixel property isn't provided\n"); |
| 476 | return -EINVAL; | 484 | return -EINVAL; |
| 477 | } | 485 | } |
| 478 | 486 | ||
| 479 | priv->disp_dev = video_link_get_next_device(dev); | 487 | priv->disp_dev = video_link_get_next_device(dev); |
| 480 | if (priv->disp_dev) { | 488 | if (priv->disp_dev) { |
| 481 | ret = video_link_get_display_timings(timings); | 489 | ret = video_link_get_display_timings(timings); |
| 482 | if (ret) { | 490 | if (ret) { |
| 483 | dev_err(dev, "failed to get any video link display timings\n"); | 491 | dev_err(dev, "failed to get any video link display timings\n"); |
| 484 | return -EINVAL; | 492 | return -EINVAL; |
| 485 | } | 493 | } |
| 486 | } else { | 494 | } else { |
| 487 | ret = ofnode_decode_display_timing(display_node, 0, timings); | 495 | ret = ofnode_decode_display_timing(display_node, 0, timings); |
| 488 | if (ret) { | 496 | if (ret) { |
| 489 | dev_err(dev, "failed to get any display timings\n"); | 497 | dev_err(dev, "failed to get any display timings\n"); |
| 490 | return -EINVAL; | 498 | return -EINVAL; |
| 491 | } | 499 | } |
| 492 | } | 500 | } |
| 493 | 501 | ||
| 494 | return ret; | 502 | return ret; |
| 495 | } | 503 | } |
| 496 | 504 | ||
| 497 | static int mxs_video_probe(struct udevice *dev) | 505 | static int mxs_video_probe(struct udevice *dev) |
| 498 | { | 506 | { |
| 499 | struct video_uc_plat *plat = dev_get_uclass_plat(dev); | 507 | struct video_uc_plat *plat = dev_get_uclass_plat(dev); |
| 500 | struct video_priv *uc_priv = dev_get_uclass_priv(dev); | 508 | struct video_priv *uc_priv = dev_get_uclass_priv(dev); |
| 501 | struct mxsfb_priv *priv = dev_get_priv(dev); | 509 | struct mxsfb_priv *priv = dev_get_priv(dev); |
| 502 | 510 | ||
| 503 | struct display_timing timings; | 511 | struct display_timing timings; |
| 504 | u32 bpp = 0; | 512 | u32 bpp = 0; |
| 505 | u32 fb_start, fb_end; | 513 | u32 fb_start, fb_end; |
| 506 | int ret; | 514 | int ret; |
| 507 | bool enable_bridge = false; | 515 | bool enable_bridge = false; |
| 508 | 516 | ||
| 509 | debug("%s() plat: base 0x%lx, size 0x%x\n", | 517 | debug("%s() plat: base 0x%lx, size 0x%x\n", |
| 510 | __func__, plat->base, plat->size); | 518 | __func__, plat->base, plat->size); |
| 511 | 519 | ||
| 512 | priv->reg_base = dev_read_addr(dev); | 520 | priv->reg_base = dev_read_addr(dev); |
| 513 | if (priv->reg_base == FDT_ADDR_T_NONE) { | 521 | if (priv->reg_base == FDT_ADDR_T_NONE) { |
| 514 | dev_err(dev, "lcdif base address is not found\n"); | 522 | dev_err(dev, "lcdif base address is not found\n"); |
| 515 | return -EINVAL; | 523 | return -EINVAL; |
| 516 | } | 524 | } |
| 517 | 525 | ||
| 518 | ret = mxs_of_get_timings(dev, &timings, &bpp); | 526 | ret = mxs_of_get_timings(dev, &timings, &bpp); |
| 519 | if (ret) | 527 | if (ret) |
| 520 | return ret; | 528 | return ret; |
| 521 | timings.flags |= DISPLAY_FLAGS_DE_HIGH; | 529 | timings.flags |= DISPLAY_FLAGS_DE_HIGH; |
| 522 | 530 | ||
| 531 | #if CONFIG_IS_ENABLED(CLK) && IS_ENABLED(CONFIG_IMX8) | ||
| 532 | ret = clk_get_by_name(dev, "pix", &priv->lcdif_pix); | ||
| 533 | if (ret) { | ||
| 534 | printf("Failed to get pix clk\n"); | ||
| 535 | return ret; | ||
| 536 | } | ||
| 537 | |||
| 538 | ret = clk_get_by_name(dev, "disp_axi", &priv->lcdif_disp_axi); | ||
| 539 | if (ret) { | ||
| 540 | printf("Failed to get disp_axi clk\n"); | ||
| 541 | return ret; | ||
| 542 | } | ||
| 543 | |||
| 544 | ret = clk_get_by_name(dev, "axi", &priv->lcdif_axi); | ||
| 545 | if (ret) { | ||
| 546 | printf("Failed to get axi clk\n"); | ||
| 547 | return ret; | ||
| 548 | } | ||
| 549 | |||
| 550 | ret = clk_enable(&priv->lcdif_axi); | ||
| 551 | if (ret) { | ||
| 552 | printf("unable to enable lcdif_axi clock\n"); | ||
| 553 | return ret; | ||
| 554 | } | ||
| 555 | |||
| 556 | ret = clk_enable(&priv->lcdif_disp_axi); | ||
| 557 | if (ret) { | ||
| 558 | printf("unable to enable lcdif_disp_axi clock\n"); | ||
| 559 | return ret; | ||
| 560 | } | ||
| 561 | #endif | ||
| 562 | |||
| 523 | #if IS_ENABLED(CONFIG_DM_RESET) | 563 | #if IS_ENABLED(CONFIG_DM_RESET) |
| 524 | ret = lcdif_of_parse_resets(dev); | 564 | ret = lcdif_of_parse_resets(dev); |
| 525 | if (!ret) { | 565 | if (!ret) { |
| 526 | ret = lcdif_rstc_reset(&priv->soft_resetn, false); | 566 | ret = lcdif_rstc_reset(&priv->soft_resetn, false); |
| 527 | if (ret) { | 567 | if (ret) { |
| 528 | dev_err(dev, "deassert soft_resetn failed\n"); | 568 | dev_err(dev, "deassert soft_resetn failed\n"); |
| 529 | return ret; | 569 | return ret; |
| 530 | } | 570 | } |
| 531 | 571 | ||
| 532 | ret = lcdif_rstc_reset(&priv->clk_enable, true); | 572 | ret = lcdif_rstc_reset(&priv->clk_enable, true); |
| 533 | if (ret) { | 573 | if (ret) { |
| 534 | dev_err(dev, "assert clk_enable failed\n"); | 574 | dev_err(dev, "assert clk_enable failed\n"); |
| 535 | return ret; | 575 | return ret; |
| 536 | } | 576 | } |
| 537 | } | 577 | } |
| 538 | #endif | 578 | #endif |
| 539 | 579 | ||
| 540 | if (priv->disp_dev) { | 580 | if (priv->disp_dev) { |
| 541 | #if IS_ENABLED(CONFIG_VIDEO_BRIDGE) | 581 | #if IS_ENABLED(CONFIG_VIDEO_BRIDGE) |
| 542 | if (device_get_uclass_id(priv->disp_dev) == UCLASS_VIDEO_BRIDGE) { | 582 | if (device_get_uclass_id(priv->disp_dev) == UCLASS_VIDEO_BRIDGE) { |
| 543 | ret = video_bridge_attach(priv->disp_dev); | 583 | ret = video_bridge_attach(priv->disp_dev); |
| 544 | if (ret) { | 584 | if (ret) { |
| 545 | dev_err(dev, "fail to attach bridge\n"); | 585 | dev_err(dev, "fail to attach bridge\n"); |
| 546 | return ret; | 586 | return ret; |
| 547 | } | 587 | } |
| 548 | 588 | ||
| 549 | ret = video_bridge_set_backlight(priv->disp_dev, 80); | 589 | ret = video_bridge_set_backlight(priv->disp_dev, 80); |
| 550 | if (ret) { | 590 | if (ret) { |
| 551 | dev_err(dev, "fail to set backlight\n"); | 591 | dev_err(dev, "fail to set backlight\n"); |
| 552 | return ret; | 592 | return ret; |
| 553 | } | 593 | } |
| 554 | 594 | ||
| 555 | enable_bridge = true; | 595 | enable_bridge = true; |
| 556 | 596 | ||
| 557 | /* sec dsim needs enable ploarity at low, default we set to high */ | 597 | /* sec dsim needs enable ploarity at low, default we set to high */ |
| 558 | if (!strcmp(priv->disp_dev->driver->name, "imx_sec_dsim")) | 598 | if (!strcmp(priv->disp_dev->driver->name, "imx_sec_dsim")) |
| 559 | timings.flags &= ~DISPLAY_FLAGS_DE_HIGH; | 599 | timings.flags &= ~DISPLAY_FLAGS_DE_HIGH; |
| 560 | 600 | ||
| 561 | } | 601 | } |
| 562 | #endif | 602 | #endif |
| 563 | 603 | ||
| 564 | if (device_get_uclass_id(priv->disp_dev) == UCLASS_PANEL) { | 604 | if (device_get_uclass_id(priv->disp_dev) == UCLASS_PANEL) { |
| 565 | ret = panel_enable_backlight(priv->disp_dev); | 605 | ret = panel_enable_backlight(priv->disp_dev); |
| 566 | if (ret) { | 606 | if (ret) { |
| 567 | dev_err(dev, "panel %s enable backlight error %d\n", | 607 | dev_err(dev, "panel %s enable backlight error %d\n", |
| 568 | priv->disp_dev->name, ret); | 608 | priv->disp_dev->name, ret); |
| 569 | return ret; | 609 | return ret; |
| 570 | } | 610 | } |
| 571 | } | 611 | } |
| 572 | } | 612 | } |
| 573 | 613 | ||
| 614 | #if CONFIG_IS_ENABLED(CLK) && IS_ENABLED(CONFIG_IMX8) | ||
| 615 | ret = clk_set_rate(&priv->lcdif_pix, timings.pixelclock.typ); | ||
| 616 | if (ret < 0) { | ||
| 617 | printf("Failed to set pix clk rate\n"); | ||
| 618 | return ret; | ||
| 619 | } | ||
| 620 | |||
| 621 | ret = clk_enable(&priv->lcdif_pix); | ||
| 622 | if (ret) { | ||
| 623 | printf("unable to enable lcdif_pix clock\n"); | ||
| 624 | return ret; | ||
| 625 | } | ||
| 626 | #endif | ||
| 627 | |||
| 574 | ret = mxs_probe_common(priv->reg_base, &timings, bpp, plat->base, enable_bridge); | 628 | ret = mxs_probe_common(priv->reg_base, &timings, bpp, plat->base, enable_bridge); |
| 575 | if (ret) | 629 | if (ret) |
| 576 | return ret; | 630 | return ret; |
| 577 | 631 | ||
| 578 | switch (bpp) { | 632 | switch (bpp) { |
| 579 | case 32: | 633 | case 32: |
| 580 | case 24: | 634 | case 24: |
| 581 | case 18: | 635 | case 18: |
| 582 | uc_priv->bpix = VIDEO_BPP32; | 636 | uc_priv->bpix = VIDEO_BPP32; |
| 583 | break; | 637 | break; |
| 584 | case 16: | 638 | case 16: |
| 585 | uc_priv->bpix = VIDEO_BPP16; | 639 | uc_priv->bpix = VIDEO_BPP16; |
| 586 | break; | 640 | break; |
| 587 | case 8: | 641 | case 8: |
| 588 | uc_priv->bpix = VIDEO_BPP8; | 642 | uc_priv->bpix = VIDEO_BPP8; |
| 589 | break; | 643 | break; |
| 590 | default: | 644 | default: |
| 591 | dev_err(dev, "invalid bpp specified (bpp = %i)\n", bpp); | 645 | dev_err(dev, "invalid bpp specified (bpp = %i)\n", bpp); |
| 592 | return -EINVAL; | 646 | return -EINVAL; |
| 593 | } | 647 | } |
| 594 | 648 | ||
| 595 | uc_priv->xsize = timings.hactive.typ; | 649 | uc_priv->xsize = timings.hactive.typ; |
| 596 | uc_priv->ysize = timings.vactive.typ; | 650 | uc_priv->ysize = timings.vactive.typ; |
| 597 | 651 | ||
| 598 | /* Enable dcache for the frame buffer */ | 652 | /* Enable dcache for the frame buffer */ |
| 599 | fb_start = plat->base & ~(MMU_SECTION_SIZE - 1); | 653 | fb_start = plat->base; |
| 600 | fb_end = plat->base + plat->size; | 654 | fb_end = plat->base + plat->size; |
| 601 | fb_end = ALIGN(fb_end, 1 << MMU_SECTION_SHIFT); | 655 | |
| 602 | mmu_set_region_dcache_behaviour(fb_start, fb_end - fb_start, | 656 | mmu_set_region_dcache_behaviour(fb_start, fb_end - fb_start, |
| 603 | DCACHE_WRITEBACK); | 657 | DCACHE_WRITEBACK); |
| 604 | video_set_flush_dcache(dev, true); | 658 | video_set_flush_dcache(dev, true); |
| 605 | gd->fb_base = plat->base; | 659 | gd->fb_base = plat->base; |
| 606 | 660 | ||
| 607 | return ret; | 661 | return ret; |
| 608 | } | 662 | } |
| 609 | 663 | ||
| 610 | static int mxs_video_bind(struct udevice *dev) | 664 | static int mxs_video_bind(struct udevice *dev) |
| 611 | { | 665 | { |
| 612 | struct video_uc_plat *plat = dev_get_uclass_plat(dev); | 666 | struct video_uc_plat *plat = dev_get_uclass_plat(dev); |
| 613 | 667 | ||
| 614 | /* Max size supported by LCDIF, because in bind, we can't probe panel */ | 668 | /* Max size supported by LCDIF, because in bind, we can't probe panel */ |
| 615 | plat->size = 1920 * 1080 *4 * 2; | 669 | plat->size = ALIGN(1920 * 1080 *4 * 2, MMU_SECTION_SIZE); |
| 670 | plat->align = MMU_SECTION_SIZE; | ||
| 616 | 671 | ||
| 617 | return 0; | 672 | return 0; |
| 618 | } | 673 | } |
| 619 | 674 | ||
| 620 | static int mxs_video_remove(struct udevice *dev) | 675 | static int mxs_video_remove(struct udevice *dev) |
| 621 | { | 676 | { |
| 622 | struct video_uc_plat *plat = dev_get_uclass_plat(dev); | 677 | struct video_uc_plat *plat = dev_get_uclass_plat(dev); |
| 623 | struct mxsfb_priv *priv = dev_get_priv(dev); | 678 | struct mxsfb_priv *priv = dev_get_priv(dev); |
| 624 | 679 | ||
| 625 | debug("%s\n", __func__); | 680 | debug("%s\n", __func__); |
| 626 | 681 | ||
| 627 | if (priv->disp_dev) | 682 | if (priv->disp_dev) |
| 628 | device_remove(priv->disp_dev, DM_REMOVE_NORMAL); | 683 | device_remove(priv->disp_dev, DM_REMOVE_NORMAL); |
| 629 | 684 | ||
| 630 | mxs_remove_common(priv->reg_base, plat->base); | 685 | mxs_remove_common(priv->reg_base, plat->base); |
| 631 | 686 | ||
| 632 | return 0; | 687 | return 0; |
| 633 | } | 688 | } |
| 634 | 689 | ||
| 635 | static const struct udevice_id mxs_video_ids[] = { | 690 | static const struct udevice_id mxs_video_ids[] = { |
| 636 | { .compatible = "fsl,imx23-lcdif" }, | 691 | { .compatible = "fsl,imx23-lcdif" }, |
| 637 | { .compatible = "fsl,imx28-lcdif" }, | 692 | { .compatible = "fsl,imx28-lcdif" }, |
| 638 | { .compatible = "fsl,imx7ulp-lcdif" }, | 693 | { .compatible = "fsl,imx7ulp-lcdif" }, |
| 639 | { .compatible = "fsl,imxrt-lcdif" }, | 694 | { .compatible = "fsl,imxrt-lcdif" }, |
| 640 | { .compatible = "fsl,imx8mm-lcdif" }, | 695 | { .compatible = "fsl,imx8mm-lcdif" }, |
| 641 | { .compatible = "fsl,imx8mn-lcdif" }, | 696 | { .compatible = "fsl,imx8mn-lcdif" }, |
| 642 | { /* sentinel */ } | 697 | { /* sentinel */ } |
| 643 | }; | 698 | }; |
| 644 | 699 | ||
| 645 | U_BOOT_DRIVER(mxs_video) = { | 700 | U_BOOT_DRIVER(mxs_video) = { |
| 646 | .name = "mxs_video", | 701 | .name = "mxs_video", |
| 647 | .id = UCLASS_VIDEO, | 702 | .id = UCLASS_VIDEO, |
| 648 | .of_match = mxs_video_ids, | 703 | .of_match = mxs_video_ids, |
| 649 | .bind = mxs_video_bind, | 704 | .bind = mxs_video_bind, |
| 650 | .probe = mxs_video_probe, | 705 | .probe = mxs_video_probe, |
| 651 | .remove = mxs_video_remove, | 706 | .remove = mxs_video_remove, |
| 652 | .flags = DM_FLAG_PRE_RELOC | DM_FLAG_OS_PREPARE, | 707 | .flags = DM_FLAG_PRE_RELOC | DM_FLAG_OS_PREPARE, |
| 653 | .priv_auto = sizeof(struct mxsfb_priv), | 708 | .priv_auto = sizeof(struct mxsfb_priv), |
| 654 | }; | 709 | }; |
| 655 | #endif /* ifndef CONFIG_DM_VIDEO */ | 710 | #endif /* ifndef CONFIG_DM_VIDEO */ |