Compare commits

3 Commits

Author SHA1 Message Date
Andreas Kemnade
4b51ff1cf5 Merge branch 'kobo/epdc-drm-6.15' into kobo/drm-merged-6.15 2026-07-02 18:02:36 +01:00
Andreas Kemnade
9c0a2dfb19 arm: dts: imx: add epdc for imx6sl
copied over from freescale kernels

Signed-off-by: Andreas Kemnade <andreas@kemnade.info>
2026-07-02 17:59:46 +01:00
70c5dfde43 added wario_defconfig, based on experimental work 2026-07-02 17:41:32 +01:00
21 changed files with 3894 additions and 0 deletions

View File

@@ -0,0 +1,159 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/display/imx/fsl,mxc-epdc.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Freescale i.MX6 EPDC
maintainers:
- Andreas Kemnade <andreas@kemnade.info>
description: |
The EPDC is a controller for handling electronic paper displays found in
i.MX6 SoCs.
properties:
compatible:
enum:
- fsl,imx6sl-epdc
- fsl,imx6sll-epdc
reg:
maxItems: 1
clocks:
items:
- description: Bus clock
- description: Pixel clock
clock-names:
items:
- const: axi
- const: pix
interrupts:
maxItems: 1
vscan-holdoff:
$ref: /schemas/types.yaml#/definitions/uint32
maxItems: 1
sdoed-width:
$ref: /schemas/types.yaml#/definitions/uint32
maxItems: 1
sdoed-delay:
$ref: /schemas/types.yaml#/definitions/uint32
maxItems: 1
sdoez-width:
$ref: /schemas/types.yaml#/definitions/uint32
maxItems: 1
sdoez-delay:
$ref: /schemas/types.yaml#/definitions/uint32
maxItems: 1
gdclk-hp-offs:
$ref: /schemas/types.yaml#/definitions/uint32
maxItems: 1
gdsp-offs:
$ref: /schemas/types.yaml#/definitions/uint32
maxItems: 1
gdoe-offs:
$ref: /schemas/types.yaml#/definitions/uint32
maxItems: 1
gdclk-offs:
$ref: /schemas/types.yaml#/definitions/uint32
maxItems: 1
num-ce:
$ref: /schemas/types.yaml#/definitions/uint32
maxItems: 1
timing:
$ref: /display/panel/panel-timing.yaml#
DISPLAY-supply:
description:
A couple of +/- voltages automatically powered on in a defintive order
VCOM-supply:
description: compensation voltage
V3P3-supply:
description: V3P3 supply
epd-thermal-zone:
description:
Zone to get temperature of the EPD from, practically ambient temperature.
required:
- compatible
- reg
- clocks
- clock-names
- interrupts
- vscan-holdoff
- sdoed-width
- sdoed-delay
- sdoez-width
- sdoez-delay
- gdclk-hp-offs
- gdsp-offs
- gdoe-offs
- gdclk-offs
- num-ce
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/imx6sl-clock.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
epdc: epdc@20f4000 {
compatible = "fsl,imx6sl-epdc";
reg = <0x020f4000 0x4000>;
interrupts = <0 97 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6SL_CLK_EPDC_AXI>, <&clks IMX6SL_CLK_EPDC_PIX>;
clock-names = "axi", "pix";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_epdc0>;
V3P3-supply = <&V3P3_reg>;
VCOM-supply = <&VCOM_reg>;
DISPLAY-supply = <&DISPLAY_reg>;
epd-thermal-zone = "epd-thermal";
vscan-holdoff = <4>;
sdoed-width = <10>;
sdoed-delay = <20>;
sdoez-width = <10>;
sdoez-delay = <20>;
gdclk-hp-offs = <562>;
gdsp-offs = <662>;
gdoe-offs = <0>;
gdclk-offs = <225>;
num-ce = <3>;
status = "okay";
timing {
clock-frequency = <80000000>;
hactive = <1448>;
hback-porch = <16>;
hfront-porch = <102>;
hsync-len = <28>;
vactive = <1072>;
vback-porch = <4>;
vfront-porch = <4>;
vsync-len = <2>;
};
};
...

View File

@@ -73,6 +73,38 @@
}; };
}; };
&epdc {
safe-ticks-turnoff-ep3v3=<800>;
V3P3-supply = <&V3P3_reg>;
VCOM-supply = <&VCOM_reg>;
DISPLAY-supply = <&DISPLAY_reg>;
epd-thermal-zone = "epd-thermal";
vscan-holdoff = <4>;
sdoed-width = <10>;
sdoed-delay = <20>;
sdoez-width = <10>;
sdoez-delay = <20>;
gdclk-hp-offs = <562>;
gdsp-offs = <662>;
gdoe-offs = <0>;
gdclk-offs = <225>;
num-ce = <3>;
status = "okay";
timing {
clock-frequency = <80000000>;
hactive = <1448>;
hback-porch = <16>;
hfront-porch = <102>;
hsync-len = <28>;
vactive = <1072>;
vback-porch = <4>;
vfront-porch = <4>;
vsync-len = <2>;
};
};
&i2c1 { &i2c1 {
clock-frequency = <100000>; clock-frequency = <100000>;

View File

@@ -112,6 +112,40 @@
}; };
}; };
&epdc {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_epdc0>;
safe-ticks-turnoff-ep3v3 = <800>;
V3P3-supply = <&V3P3_reg>;
VCOM-supply = <&VCOM_reg>;
DISPLAY-supply = <&DISPLAY_reg>;
epd-thermal-zone = "epd-thermal";
vscan-holdoff = <4>;
sdoed-width = <10>;
sdoed-delay = <20>;
sdoez-width = <10>;
sdoez-delay = <20>;
gdclk-hp-offs = <562>;
gdsp-offs = <662>;
gdoe-offs = <0>;
gdclk-offs = <225>;
num-ce = <3>;
status = "okay";
timing {
clock-frequency = <80000000>;
hactive = <1448>;
hback-porch = <16>;
hfront-porch = <102>;
hsync-len = <28>;
vactive = <1072>;
vback-porch = <4>;
vfront-porch = <4>;
vsync-len = <2>;
};
};
&i2c1 { &i2c1 {
pinctrl-names = "default","sleep"; pinctrl-names = "default","sleep";
pinctrl-0 = <&pinctrl_i2c1>; pinctrl-0 = <&pinctrl_i2c1>;
@@ -337,6 +371,36 @@
>; >;
}; };
pinctrl_epdc0: epdcgrp0 {
fsl,pins = <
MX6SL_PAD_EPDC_D0__EPDC_DATA00 0x4100b1
MX6SL_PAD_EPDC_D1__EPDC_DATA01 0x4100b1
MX6SL_PAD_EPDC_D2__EPDC_DATA02 0x4100b1
MX6SL_PAD_EPDC_D3__EPDC_DATA03 0x4100b1
MX6SL_PAD_EPDC_D4__EPDC_DATA04 0x4100b1
MX6SL_PAD_EPDC_D5__EPDC_DATA05 0x4100b1
MX6SL_PAD_EPDC_D6__EPDC_DATA06 0x4100b1
MX6SL_PAD_EPDC_D7__EPDC_DATA07 0x4100b1
MX6SL_PAD_EPDC_D8__EPDC_DATA08 0x4100b1
MX6SL_PAD_EPDC_D9__EPDC_DATA09 0x4100b1
MX6SL_PAD_EPDC_D10__EPDC_DATA10 0x4100b1
MX6SL_PAD_EPDC_D11__EPDC_DATA11 0x4100b1
MX6SL_PAD_EPDC_D12__EPDC_DATA12 0x4100b1
MX6SL_PAD_EPDC_D13__EPDC_DATA13 0x4100b1
MX6SL_PAD_EPDC_D14__EPDC_DATA14 0x4100b1
MX6SL_PAD_EPDC_D15__EPDC_DATA15 0x4100b1
MX6SL_PAD_EPDC_SDCLK__EPDC_SDCLK_P 0x4100b1
MX6SL_PAD_EPDC_SDLE__EPDC_SDLE 0x4100b1
MX6SL_PAD_EPDC_SDOE__EPDC_SDOE 0x4100b1
MX6SL_PAD_EPDC_SDSHR__EPDC_SDSHR 0x4100b1
MX6SL_PAD_EPDC_SDCE0__EPDC_SDCE0 0x4100b1
MX6SL_PAD_EPDC_GDCLK__EPDC_GDCLK 0x4100b1
MX6SL_PAD_EPDC_GDOE__EPDC_GDOE 0x4100b1
MX6SL_PAD_EPDC_GDRL__EPDC_GDRL 0x4100b1
MX6SL_PAD_EPDC_GDSP__EPDC_GDSP 0x4100b1
>;
};
pinctrl_hog: hoggrp { pinctrl_hog: hoggrp {
fsl,pins = < fsl,pins = <
MX6SL_PAD_LCD_DAT0__GPIO2_IO20 0x79 MX6SL_PAD_LCD_DAT0__GPIO2_IO20 0x79

View File

@@ -26,6 +26,11 @@
compatible = "kobo,tolino-shine3", "fsl,imx6sl"; compatible = "kobo,tolino-shine3", "fsl,imx6sl";
}; };
&epdc {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_epdc0>;
};
&gpio_keys { &gpio_keys {
pinctrl-names = "default"; pinctrl-names = "default";
pinctrl-0 = <&pinctrl_gpio_keys>; pinctrl-0 = <&pinctrl_gpio_keys>;
@@ -59,6 +64,36 @@
>; >;
}; };
pinctrl_epdc0: epdcgrp0 {
fsl,pins = <
MX6SL_PAD_EPDC_D0__EPDC_DATA00 0x4100b1
MX6SL_PAD_EPDC_D1__EPDC_DATA01 0x4100b1
MX6SL_PAD_EPDC_D2__EPDC_DATA02 0x4100b1
MX6SL_PAD_EPDC_D3__EPDC_DATA03 0x4100b1
MX6SL_PAD_EPDC_D4__EPDC_DATA04 0x4100b1
MX6SL_PAD_EPDC_D5__EPDC_DATA05 0x4100b1
MX6SL_PAD_EPDC_D6__EPDC_DATA06 0x4100b1
MX6SL_PAD_EPDC_D7__EPDC_DATA07 0x4100b1
MX6SL_PAD_EPDC_D8__EPDC_DATA08 0x4100b1
MX6SL_PAD_EPDC_D9__EPDC_DATA09 0x4100b1
MX6SL_PAD_EPDC_D10__EPDC_DATA10 0x4100b1
MX6SL_PAD_EPDC_D11__EPDC_DATA11 0x4100b1
MX6SL_PAD_EPDC_D12__EPDC_DATA12 0x4100b1
MX6SL_PAD_EPDC_D13__EPDC_DATA13 0x4100b1
MX6SL_PAD_EPDC_D14__EPDC_DATA14 0x4100b1
MX6SL_PAD_EPDC_D15__EPDC_DATA15 0x4100b1
MX6SL_PAD_EPDC_SDCLK__EPDC_SDCLK_P 0x4100b1
MX6SL_PAD_EPDC_SDLE__EPDC_SDLE 0x4100b1
MX6SL_PAD_EPDC_SDOE__EPDC_SDOE 0x4100b1
MX6SL_PAD_EPDC_SDSHR__EPDC_SDSHR 0x4100b1
MX6SL_PAD_EPDC_SDCE0__EPDC_SDCE0 0x4100b1
MX6SL_PAD_EPDC_GDCLK__EPDC_GDCLK 0x4100b1
MX6SL_PAD_EPDC_GDOE__EPDC_GDOE 0x4100b1
MX6SL_PAD_EPDC_GDRL__EPDC_GDRL 0x4100b1
MX6SL_PAD_EPDC_GDSP__EPDC_GDSP 0x4100b1
>;
};
pinctrl_gpio_keys: gpio-keysgrp { pinctrl_gpio_keys: gpio-keysgrp {
fsl,pins = < fsl,pins = <
MX6SL_PAD_SD1_DAT1__GPIO5_IO08 0x17059 /* PWR_SW */ MX6SL_PAD_SD1_DAT1__GPIO5_IO08 0x17059 /* PWR_SW */

View File

@@ -771,8 +771,11 @@
}; };
epdc: epdc@20f4000 { epdc: epdc@20f4000 {
compatible = "fsl,imx6sl-epdc", "fsl,imx6dl-epdc";
reg = <0x020f4000 0x4000>; reg = <0x020f4000 0x4000>;
interrupts = <0 97 IRQ_TYPE_LEVEL_HIGH>; interrupts = <0 97 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6SL_CLK_EPDC_AXI>, <&clks IMX6SL_CLK_EPDC_PIX>;
clock-names = "epdc_axi", "epdc_pix";
}; };
lcdif: lcdif@20f8000 { lcdif: lcdif@20f8000 {

View File

@@ -36,6 +36,11 @@
soc-supply = <&dcdc1_reg>; soc-supply = <&dcdc1_reg>;
}; };
&epdc {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_epdc0>;
};
&gpio_keys { &gpio_keys {
pinctrl-names = "default"; pinctrl-names = "default";
pinctrl-0 = <&pinctrl_gpio_keys>; pinctrl-0 = <&pinctrl_gpio_keys>;
@@ -69,6 +74,36 @@
>; >;
}; };
pinctrl_epdc0: epdcgrp0 {
fsl,pins = <
MX6SLL_PAD_EPDC_DATA00__EPDC_DATA00 0x4100b1
MX6SLL_PAD_EPDC_DATA01__EPDC_DATA01 0x4100b1
MX6SLL_PAD_EPDC_DATA02__EPDC_DATA02 0x4100b1
MX6SLL_PAD_EPDC_DATA03__EPDC_DATA03 0x4100b1
MX6SLL_PAD_EPDC_DATA04__EPDC_DATA04 0x4100b1
MX6SLL_PAD_EPDC_DATA05__EPDC_DATA05 0x4100b1
MX6SLL_PAD_EPDC_DATA06__EPDC_DATA06 0x4100b1
MX6SLL_PAD_EPDC_DATA07__EPDC_DATA07 0x4100b1
MX6SLL_PAD_EPDC_DATA08__EPDC_DATA08 0x4100b1
MX6SLL_PAD_EPDC_DATA09__EPDC_DATA09 0x4100b1
MX6SLL_PAD_EPDC_DATA10__EPDC_DATA10 0x4100b1
MX6SLL_PAD_EPDC_DATA11__EPDC_DATA11 0x4100b1
MX6SLL_PAD_EPDC_DATA12__EPDC_DATA12 0x4100b1
MX6SLL_PAD_EPDC_DATA13__EPDC_DATA13 0x4100b1
MX6SLL_PAD_EPDC_DATA14__EPDC_DATA14 0x4100b1
MX6SLL_PAD_EPDC_DATA15__EPDC_DATA15 0x4100b1
MX6SLL_PAD_EPDC_SDCLK__EPDC_SDCLK_P 0x4100b1
MX6SLL_PAD_EPDC_SDLE__EPDC_SDLE 0x4100b1
MX6SLL_PAD_EPDC_SDOE__EPDC_SDOE 0x4100b1
MX6SLL_PAD_EPDC_SDSHR__EPDC_SDSHR 0x4100b1
MX6SLL_PAD_EPDC_SDCE0__EPDC_SDCE0 0x4100b1
MX6SLL_PAD_EPDC_GDCLK__EPDC_GDCLK 0x4100b1
MX6SLL_PAD_EPDC_GDOE__EPDC_GDOE 0x4100b1
MX6SLL_PAD_EPDC_GDRL__EPDC_GDRL 0x4100b1
MX6SLL_PAD_EPDC_GDSP__EPDC_GDSP 0x4100b1
>;
};
pinctrl_gpio_keys: gpio-keysgrp { pinctrl_gpio_keys: gpio-keysgrp {
fsl,pins = < fsl,pins = <
MX6SLL_PAD_SD1_DATA1__GPIO5_IO08 0x17059 /* PWR_SW */ MX6SLL_PAD_SD1_DATA1__GPIO5_IO08 0x17059 /* PWR_SW */

View File

@@ -656,6 +656,15 @@
clock-names = "axi"; clock-names = "axi";
}; };
epdc: epdc@20f4000 {
compatible = "fsl,imx6sll-epdc", "fsl,imx7d-epdc";
reg = <0x020f4000 0x4000>;
interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6SLL_CLK_EPDC_AXI>, <&clks IMX6SLL_CLK_EPDC_PIX>;
clock-names = "epdc_axi", "epdc_pix";
status = "disabled";
};
lcdif: lcd-controller@20f8000 { lcdif: lcd-controller@20f8000 {
compatible = "fsl,imx6sll-lcdif", "fsl,imx28-lcdif"; compatible = "fsl,imx6sll-lcdif", "fsl,imx28-lcdif";
reg = <0x020f8000 0x4000>; reg = <0x020f8000 0x4000>;

View File

@@ -0,0 +1,622 @@
CONFIG_SYSVIPC=y
CONFIG_NO_HZ_IDLE=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_BPF_SYSCALL=y
CONFIG_PREEMPT_VOLUNTARY=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=18
CONFIG_CGROUPS=y
CONFIG_CGROUP_BPF=y
CONFIG_NAMESPACES=y
CONFIG_RELAY=y
CONFIG_BLK_DEV_INITRD=y
CONFIG_EXPERT=y
CONFIG_PERF_EVENTS=y
CONFIG_KEXEC=y
CONFIG_ARCH_MULTI_V6=y
CONFIG_ARCH_MXC=y
CONFIG_SOC_IMX31=y
CONFIG_SOC_IMX35=y
CONFIG_SOC_IMX50=y
CONFIG_SOC_IMX51=y
CONFIG_SOC_IMX53=y
CONFIG_SOC_IMX6Q=y
CONFIG_SOC_IMX6SL=y
CONFIG_SOC_IMX6SLL=y
CONFIG_SOC_IMX6SX=y
CONFIG_SOC_IMX6UL=y
CONFIG_SOC_IMX7D=y
CONFIG_SOC_IMX7ULP=y
CONFIG_SOC_VF610=y
CONFIG_SMP=y
CONFIG_ARM_PSCI=y
CONFIG_HIGHMEM=y
CONFIG_ARCH_FORCE_MAX_ORDER=13
CONFIG_CMDLINE="noinitrd console=ttymxc0,115200"
CONFIG_CPU_FREQ=y
CONFIG_CPU_FREQ_STAT=y
CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
CONFIG_CPU_FREQ_GOV_POWERSAVE=y
CONFIG_CPU_FREQ_GOV_USERSPACE=y
CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
CONFIG_CPUFREQ_DT=y
CONFIG_ARM_IMX6Q_CPUFREQ=y
CONFIG_ARM_IMX_CPUFREQ_DT=y
CONFIG_CPU_IDLE=y
CONFIG_ARM_CPUIDLE=y
CONFIG_ARM_PSCI_CPUIDLE=y
CONFIG_VFP=y
CONFIG_NEON=y
CONFIG_PM_DEBUG=y
CONFIG_PM_TEST_SUSPEND=y
CONFIG_KPROBES=y
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
CONFIG_MODVERSIONS=y
CONFIG_MODULE_SRCVERSION_ALL=y
CONFIG_BINFMT_MISC=m
# CONFIG_COMPAT_BRK is not set
CONFIG_NET=y
CONFIG_PACKET=y
CONFIG_UNIX=y
CONFIG_INET=y
CONFIG_IP_PNP=y
CONFIG_IP_PNP_DHCP=y
CONFIG_NETFILTER=y
CONFIG_CAN=y
CONFIG_BT=y
CONFIG_BT_BNEP=m
CONFIG_BT_HCIUART=y
CONFIG_BT_HCIUART_LL=y
CONFIG_BT_NXPUART=m
CONFIG_CFG80211=y
CONFIG_CFG80211_WEXT=y
CONFIG_MAC80211=y
CONFIG_RFKILL=y
CONFIG_RFKILL_INPUT=y
CONFIG_PCI=y
CONFIG_PCI_MSI=y
CONFIG_PCI_IMX6_HOST=y
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
# CONFIG_STANDALONE is not set
CONFIG_EXTRA_FIRMWARE="ath6k/AR6003/hw2.1.1/bdata.SD31.bin ath6k/AR6003/hw2.1.1/athwlan.bin ath6k/AR6003/hw2.1.1/otp.bin ath6k/AR6003/hw2.1.1/data.patch.bin"
CONFIG_IMX_WEIM=y
CONFIG_CONNECTOR=y
CONFIG_MTD=y
CONFIG_MTD_CMDLINE_PARTS=y
CONFIG_MTD_BLOCK=y
CONFIG_MTD_CFI=y
CONFIG_MTD_JEDECPROBE=y
CONFIG_MTD_CFI_INTELEXT=y
CONFIG_MTD_CFI_AMDSTD=y
CONFIG_MTD_CFI_STAA=y
CONFIG_MTD_PHYSMAP=y
CONFIG_MTD_PHYSMAP_OF=y
CONFIG_MTD_DATAFLASH=y
CONFIG_MTD_SST25L=y
CONFIG_MTD_RAW_NAND=y
CONFIG_MTD_NAND_GPMI_NAND=y
CONFIG_MTD_NAND_VF610_NFC=y
CONFIG_MTD_NAND_MXC=y
CONFIG_MTD_SPI_NOR=y
CONFIG_MTD_UBI=y
CONFIG_MTD_UBI_FASTMAP=y
CONFIG_MTD_UBI_BLOCK=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=65536
CONFIG_EEPROM_AT24=y
CONFIG_EEPROM_AT25=y
# CONFIG_SCSI_PROC_FS is not set
CONFIG_BLK_DEV_SD=y
# CONFIG_BLK_DEV_BSG is not set
CONFIG_SCSI_CONSTANTS=y
CONFIG_SCSI_LOGGING=y
CONFIG_SCSI_SCAN_ASYNC=y
CONFIG_ATA=y
CONFIG_SATA_AHCI_PLATFORM=y
CONFIG_AHCI_IMX=y
CONFIG_PATA_IMX=y
CONFIG_NETDEVICES=y
# CONFIG_NET_VENDOR_BROADCOM is not set
CONFIG_CS89x0_PLATFORM=y
# CONFIG_NET_VENDOR_FARADAY is not set
# CONFIG_NET_VENDOR_INTEL is not set
# CONFIG_NET_VENDOR_MARVELL is not set
# CONFIG_NET_VENDOR_MICREL is not set
# CONFIG_NET_VENDOR_MICROCHIP is not set
# CONFIG_NET_VENDOR_NATSEMI is not set
CONFIG_QCA7000_SPI=m
# CONFIG_NET_VENDOR_SEEQ is not set
CONFIG_SMC91X=y
CONFIG_SMSC911X=y
# CONFIG_NET_VENDOR_STMICRO is not set
CONFIG_MICREL_PHY=y
CONFIG_AT803X_PHY=y
CONFIG_DP83867_PHY=y
CONFIG_CAN_FLEXCAN=y
CONFIG_USB_PEGASUS=m
CONFIG_USB_RTL8150=m
CONFIG_USB_RTL8152=y
CONFIG_USB_LAN78XX=y
CONFIG_USB_USBNET=y
CONFIG_USB_NET_CDC_EEM=m
CONFIG_USB_NET_SMSC95XX=y
CONFIG_USB_NET_MCS7830=y
CONFIG_ATH6KL=y
CONFIG_ATH6KL_SDIO=y
CONFIG_ATH10K=m
CONFIG_ATH10K_SDIO=m
CONFIG_BRCMFMAC=m
CONFIG_MWIFIEX=m
CONFIG_MWIFIEX_SDIO=m
CONFIG_MWIFIEX_PCIE=m
CONFIG_WL12XX=m
CONFIG_WL18XX=m
CONFIG_WLCORE_SDIO=m
CONFIG_INPUT_EVDEV=y
CONFIG_KEYBOARD_GPIO=y
CONFIG_KEYBOARD_SNVS_PWRKEY=y
CONFIG_KEYBOARD_IMX=y
CONFIG_MOUSE_PS2=m
CONFIG_MOUSE_PS2_ELANTECH=y
CONFIG_INPUT_TOUCHSCREEN=y
CONFIG_TOUCHSCREEN_ADS7846=y
CONFIG_TOUCHSCREEN_AD7879=y
CONFIG_TOUCHSCREEN_AD7879_I2C=y
CONFIG_TOUCHSCREEN_ATMEL_MXT=y
CONFIG_TOUCHSCREEN_CYTTSP_CORE=m
CONFIG_TOUCHSCREEN_CYTTSP_I2C=m
CONFIG_TOUCHSCREEN_CYTTSP4_CORE=m
CONFIG_TOUCHSCREEN_CYTTSP4_I2C=m
CONFIG_TOUCHSCREEN_CYTTSP5=y
CONFIG_TOUCHSCREEN_DA9052=y
CONFIG_TOUCHSCREEN_EGALAX=y
CONFIG_TOUCHSCREEN_GOODIX=y
CONFIG_TOUCHSCREEN_ILI210X=y
CONFIG_TOUCHSCREEN_MAX11801=y
CONFIG_TOUCHSCREEN_IMX6UL_TSC=y
CONFIG_TOUCHSCREEN_EDT_FT5X06=y
CONFIG_TOUCHSCREEN_MC13783=y
CONFIG_TOUCHSCREEN_TSC2004=y
CONFIG_TOUCHSCREEN_TSC2007=y
CONFIG_TOUCHSCREEN_STMPE=y
CONFIG_TOUCHSCREEN_SX8654=y
CONFIG_TOUCHSCREEN_COLIBRI_VF50=y
CONFIG_INPUT_MISC=y
CONFIG_INPUT_MMA8450=y
CONFIG_INPUT_GPIO_BEEPER=m
CONFIG_INPUT_UINPUT=m
CONFIG_SERIO_SERPORT=m
# CONFIG_LEGACY_PTYS is not set
CONFIG_SERIAL_IMX=y
CONFIG_SERIAL_IMX_CONSOLE=y
CONFIG_SERIAL_FSL_LPUART=y
CONFIG_SERIAL_FSL_LPUART_CONSOLE=y
CONFIG_SERIAL_DEV_BUS=y
CONFIG_I2C_CHARDEV=y
CONFIG_I2C_MUX_GPIO=y
# CONFIG_I2C_HELPER_AUTO is not set
CONFIG_I2C_ALGOPCF=m
CONFIG_I2C_ALGOPCA=m
CONFIG_I2C_GPIO=y
CONFIG_I2C_IMX=y
CONFIG_SPI=y
CONFIG_SPI_FSL_QUADSPI=y
CONFIG_SPI_GPIO=y
CONFIG_SPI_IMX=y
CONFIG_SPI_FSL_DSPI=y
CONFIG_PINCTRL_IMX8MM=y
CONFIG_PINCTRL_IMX8MN=y
CONFIG_PINCTRL_IMX8MP=y
CONFIG_PINCTRL_IMX8MQ=y
CONFIG_GPIO_SYSFS=y
CONFIG_GPIO_MXC=y
CONFIG_GPIO_SIOX=m
CONFIG_GPIO_MAX732X=y
CONFIG_GPIO_PCA953X=y
CONFIG_GPIO_PCA953X_IRQ=y
CONFIG_GPIO_PCF857X=y
CONFIG_GPIO_BD71815=y
CONFIG_GPIO_STMPE=y
CONFIG_GPIO_74X164=y
CONFIG_W1=m
CONFIG_W1_MASTER_DS2482=m
CONFIG_W1_SLAVE_THERM=m
CONFIG_POWER_RESET=y
CONFIG_POWER_RESET_SYSCON=y
CONFIG_POWER_RESET_SYSCON_POWEROFF=y
CONFIG_RN5T618_POWER=m
CONFIG_SENSORS_MC13783_ADC=y
CONFIG_SENSORS_GPIO_FAN=y
CONFIG_SENSORS_IIO_HWMON=y
CONFIG_SENSORS_JC42=m
CONFIG_SENSORS_LM75=m
CONFIG_SENSORS_PWM_FAN=y
CONFIG_SENSORS_SY7636A=y
CONFIG_THERMAL_STATISTICS=y
CONFIG_CPU_THERMAL=y
CONFIG_IMX_THERMAL=y
CONFIG_WATCHDOG=y
CONFIG_WATCHDOG_SYSFS=y
CONFIG_DA9063_WATCHDOG=m
CONFIG_DA9062_WATCHDOG=y
CONFIG_RN5T618_WATCHDOG=y
CONFIG_IMX2_WDT=y
CONFIG_IMX7ULP_WDT=y
CONFIG_MFD_DA9052_I2C=y
CONFIG_MFD_DA9062=y
CONFIG_MFD_DA9063=y
CONFIG_MFD_MC13XXX_SPI=y
CONFIG_MFD_MC13XXX_I2C=y
CONFIG_MFD_SY7636A=y
CONFIG_MFD_RN5T618=y
CONFIG_MFD_STMPE=y
CONFIG_MFD_ROHM_BD71828=y
CONFIG_REGULATOR_FIXED_VOLTAGE=y
CONFIG_REGULATOR_ANATOP=y
CONFIG_REGULATOR_BD71815=y
CONFIG_REGULATOR_BD71828=y
CONFIG_REGULATOR_DA9052=y
CONFIG_REGULATOR_DA9062=y
CONFIG_REGULATOR_DA9063=y
CONFIG_REGULATOR_GPIO=y
CONFIG_REGULATOR_LTC3676=y
CONFIG_REGULATOR_MAX77696=m
CONFIG_REGULATOR_MC13783=y
CONFIG_REGULATOR_MC13892=y
CONFIG_REGULATOR_PFUZE100=y
CONFIG_REGULATOR_RN5T618=y
CONFIG_REGULATOR_SY7636A=y
CONFIG_RC_CORE=y
CONFIG_RC_DEVICES=y
CONFIG_IR_GPIO_CIR=y
CONFIG_MEDIA_SUPPORT=y
CONFIG_MEDIA_USB_SUPPORT=y
CONFIG_USB_VIDEO_CLASS=m
CONFIG_V4L_PLATFORM_DRIVERS=y
CONFIG_V4L_MEM2MEM_DRIVERS=y
CONFIG_VIDEO_MUX=y
CONFIG_VIDEO_CODA=m
CONFIG_VIDEO_IMX_PXP=y
CONFIG_VIDEO_OV2680=m
CONFIG_VIDEO_OV5640=m
CONFIG_VIDEO_OV5645=m
CONFIG_VIDEO_ADV7180=m
CONFIG_IMX_IPUV3_CORE=y
CONFIG_DRM=y
CONFIG_DRM_MSM=y
CONFIG_DRM_PANEL_LVDS=y
CONFIG_DRM_PANEL_SEIKO_43WVF1G=y
CONFIG_DRM_PANEL_EDP=y
CONFIG_DRM_PANEL_SIMPLE=y
CONFIG_DRM_DISPLAY_CONNECTOR=y
CONFIG_DRM_I2C_NXP_TDA998X=y
CONFIG_DRM_LVDS_CODEC=m
CONFIG_DRM_SII902X=y
CONFIG_DRM_TI_TFP410=y
CONFIG_DRM_DW_HDMI_AHB_AUDIO=m
CONFIG_DRM_DW_HDMI_CEC=y
CONFIG_DRM_IMX=y
CONFIG_DRM_IMX_PARALLEL_DISPLAY=y
CONFIG_DRM_IMX_TVE=y
CONFIG_DRM_IMX_LDB=y
CONFIG_DRM_IMX_HDMI=y
CONFIG_DRM_ETNAVIV=y
CONFIG_DRM_MXSFB=y
CONFIG_DRM_MXC_EPDC=m
CONFIG_FB=y
CONFIG_FB_MODE_HELPERS=y
CONFIG_LCD_CLASS_DEVICE=y
CONFIG_LCD_L4F00242T03=y
CONFIG_LCD_PLATFORM=y
CONFIG_BACKLIGHT_CLASS_DEVICE=y
CONFIG_BACKLIGHT_PWM=y
CONFIG_BACKLIGHT_MAX77696=m
CONFIG_BACKLIGHT_GPIO=y
CONFIG_LOGO=y
CONFIG_SOUND=y
CONFIG_SND=y
CONFIG_SND_USB_AUDIO=m
CONFIG_SND_SOC=y
CONFIG_SND_SOC_FSL_ASRC=y
CONFIG_SND_IMX_SOC=y
CONFIG_SND_SOC_EUKREA_TLV320=y
CONFIG_SND_SOC_IMX_ES8328=y
CONFIG_SND_SOC_IMX_SGTL5000=y
CONFIG_SND_SOC_FSL_ASOC_CARD=y
CONFIG_SND_SOC_AC97_CODEC=y
CONFIG_SND_SOC_CS42XX8_I2C=y
CONFIG_SND_SOC_SPDIF=y
CONFIG_SND_SOC_TLV320AIC3X_I2C=y
CONFIG_SND_SOC_WM8960=y
CONFIG_SND_SOC_WM8962=y
CONFIG_SND_SIMPLE_CARD=y
CONFIG_HID_MULTITOUCH=y
CONFIG_HID_WACOM=y
CONFIG_I2C_HID_OF=y
CONFIG_USB=y
CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_ACM=m
CONFIG_USB_STORAGE=y
CONFIG_USB_CHIPIDEA=y
CONFIG_USB_CHIPIDEA_UDC=y
CONFIG_USB_CHIPIDEA_HOST=y
CONFIG_USB_SERIAL=m
CONFIG_USB_SERIAL_GENERIC=y
CONFIG_USB_SERIAL_FTDI_SIO=m
CONFIG_USB_SERIAL_OPTION=m
CONFIG_USB_TEST=m
CONFIG_USB_EHSET_TEST_FIXTURE=m
CONFIG_USB_ONBOARD_DEV=y
CONFIG_NOP_USB_XCEIV=y
CONFIG_USB_MXS_PHY=y
CONFIG_USB_GADGET=y
CONFIG_USB_CONFIGFS=y
CONFIG_USB_CONFIGFS_SERIAL=y
CONFIG_USB_CONFIGFS_ACM=y
CONFIG_USB_CONFIGFS_OBEX=y
CONFIG_USB_CONFIGFS_NCM=y
CONFIG_USB_CONFIGFS_ECM=y
CONFIG_USB_CONFIGFS_ECM_SUBSET=y
CONFIG_USB_CONFIGFS_RNDIS=y
CONFIG_USB_CONFIGFS_EEM=y
CONFIG_USB_CONFIGFS_MASS_STORAGE=y
CONFIG_USB_CONFIGFS_F_LB_SS=y
CONFIG_USB_CONFIGFS_F_FS=y
CONFIG_USB_CONFIGFS_F_UAC1=y
CONFIG_USB_CONFIGFS_F_UAC2=y
CONFIG_USB_CONFIGFS_F_MIDI=y
CONFIG_USB_CONFIGFS_F_HID=y
CONFIG_USB_CONFIGFS_F_UVC=y
CONFIG_USB_CONFIGFS_F_PRINTER=y
CONFIG_USB_ZERO=m
CONFIG_USB_AUDIO=m
CONFIG_USB_ETH=m
CONFIG_USB_G_NCM=m
CONFIG_USB_GADGETFS=m
CONFIG_USB_FUNCTIONFS=m
CONFIG_USB_MASS_STORAGE=m
CONFIG_USB_G_SERIAL=m
CONFIG_MMC=y
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_PLTFM=y
CONFIG_MMC_SDHCI_ESDHC_IMX=y
CONFIG_LEDS_GPIO=y
CONFIG_LEDS_PWM=y
CONFIG_LEDS_TRIGGER_TIMER=y
CONFIG_LEDS_TRIGGER_ONESHOT=y
CONFIG_LEDS_TRIGGER_HEARTBEAT=y
CONFIG_LEDS_TRIGGER_BACKLIGHT=y
CONFIG_LEDS_TRIGGER_GPIO=y
CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_INTF_DEV_UIE_EMUL=y
CONFIG_RTC_DRV_DS1307=y
CONFIG_RTC_DRV_ISL1208=y
CONFIG_RTC_DRV_PCF8523=y
CONFIG_RTC_DRV_PCF8563=y
CONFIG_RTC_DRV_M41T80=y
CONFIG_RTC_DRV_BD70528=y
CONFIG_RTC_DRV_RC5T619=y
CONFIG_RTC_DRV_RV3029C2=y
CONFIG_RTC_DRV_DA9063=y
CONFIG_RTC_DRV_MC13XXX=y
CONFIG_RTC_DRV_MXC=y
CONFIG_RTC_DRV_MXC_V2=y
CONFIG_RTC_DRV_SNVS=y
CONFIG_DMADEVICES=y
CONFIG_FSL_EDMA=y
CONFIG_IMX_SDMA=m
CONFIG_MXS_DMA=y
CONFIG_DMATEST=m
CONFIG_STAGING=y
CONFIG_STAGING_MEDIA=y
CONFIG_VIDEO_IMX_MEDIA=y
CONFIG_COMMON_CLK_PWM=y
CONFIG_COMMON_CLK_BD718XX=y
CONFIG_CLK_IMX8MM=y
CONFIG_CLK_IMX8MN=y
CONFIG_CLK_IMX8MP=y
CONFIG_CLK_IMX8MQ=y
CONFIG_SOC_IMX8M=y
CONFIG_EXTCON_USB_GPIO=y
CONFIG_IIO=y
CONFIG_IIO_ST_ACCEL_3AXIS=m
CONFIG_MMA8452=y
CONFIG_IMX7D_ADC=y
CONFIG_RN5T618_ADC=y
CONFIG_STMPE_ADC=y
CONFIG_VF610_ADC=y
CONFIG_SENSORS_ISL29018=y
CONFIG_MAG3110=y
CONFIG_MPL3115=y
CONFIG_PWM=y
CONFIG_PWM_FSL_FTM=y
CONFIG_PWM_IMX27=y
CONFIG_PWM_IMX_TPM=y
CONFIG_NVMEM_IMX_OCOTP=y
CONFIG_NVMEM_SNVS_LPGPR=y
CONFIG_NVMEM_VF610_OCOTP=y
CONFIG_TEE=y
CONFIG_OPTEE=y
CONFIG_MUX_MMIO=y
CONFIG_SIOX=m
CONFIG_SIOX_BUS_GPIO=m
CONFIG_EXT2_FS=y
CONFIG_EXT2_FS_XATTR=y
CONFIG_EXT2_FS_POSIX_ACL=y
CONFIG_EXT2_FS_SECURITY=y
CONFIG_EXT3_FS=y
CONFIG_EXT3_FS_POSIX_ACL=y
CONFIG_EXT3_FS_SECURITY=y
CONFIG_QUOTA=y
CONFIG_QUOTA_NETLINK_INTERFACE=y
CONFIG_AUTOFS_FS=y
CONFIG_FUSE_FS=y
CONFIG_ISO9660_FS=m
CONFIG_JOLIET=y
CONFIG_ZISOFS=y
CONFIG_UDF_FS=m
CONFIG_MSDOS_FS=m
CONFIG_VFAT_FS=y
CONFIG_TMPFS_POSIX_ACL=y
CONFIG_JFFS2_FS=y
CONFIG_UBIFS_FS=y
CONFIG_NFS_FS=y
CONFIG_NFS_V3_ACL=y
CONFIG_NFS_V4=y
CONFIG_NFS_V4_1=y
CONFIG_NFS_V4_2=y
CONFIG_ROOT_NFS=y
CONFIG_NLS_DEFAULT="cp437"
CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_ASCII=y
CONFIG_NLS_ISO8859_1=y
CONFIG_NLS_ISO8859_15=m
CONFIG_NLS_UTF8=y
CONFIG_SECURITYFS=y
CONFIG_CRYPTO_DEV_FSL_CAAM=y
CONFIG_CRYPTO_DEV_SAHARA=y
CONFIG_CRYPTO_DEV_MXS_DCP=y
CONFIG_CMA_SIZE_MBYTES=64
CONFIG_FONTS=y
CONFIG_FONT_8x8=y
CONFIG_FONT_8x16=y
CONFIG_PRINTK_TIME=y
# CONFIG_DEBUG_BUGVERBOSE is not set
CONFIG_MAGIC_SYSRQ=y
CONFIG_DEBUG_FS=y
# CONFIG_SLUB_DEBUG is not set
# CONFIG_FTRACE is not set
<<<<<<< HEAD:arch/arm/configs/wario_defconfig
=======
CONFIG_FB=y
# Net stuff
CONFIG_TUN=m
CONFIG_WIREGUARD=m
CONFIG_USB_USBNET=m
CONFIG_NF_CONNTRACK=m
CONFIG_NF_CONNTRACK_ZONES=y
CONFIG_NF_CONNTRACK_TIMEOUT=y
CONFIG_NF_CONNTRACK_LABELS=y
CONFIG_NF_CONNTRACK_FTP=m
CONFIG_NF_CONNTRACK_SIP=m
CONFIG_NF_CT_NETLINK=m
CONFIG_NF_CT_NETLINK_TIMEOUT=m
CONFIG_NF_TABLES=m
CONFIG_NF_TABLES_INET=y
CONFIG_NF_TABLES_NETDEV=y
CONFIG_NFT_CT=m
CONFIG_NFT_LOG=m
CONFIG_NFT_LIMIT=m
CONFIG_NFT_MASQ=m
CONFIG_NFT_REDIR=m
CONFIG_NFT_NAT=m
CONFIG_NFT_TUNNEL=m
CONFIG_NFT_COMPAT=m
CONFIG_NFT_SOCKET=m
CONFIG_NFT_TPROXY=m
CONFIG_NFT_SYNPROXY=m
CONFIG_NFT_FWD_NETDEV=m
CONFIG_NETFILTER_XTABLES=m
CONFIG_NETFILTER_XT_TARGET_LOG=m
CONFIG_NETFILTER_XT_NAT=m
CONFIG_NETFILTER_XT_TARGET_NFLOG=m
CONFIG_NETFILTER_XT_TARGET_MASQUERADE=m
CONFIG_NETFILTER_XT_TARGET_TEE=m
CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m
CONFIG_IP6_NF_FILTER=m
CONFIG_IP6_NF_IPTABLES=m
CONFIG_IP6_NF_MANGLE=m
CONFIG_IP6_NF_RAW=m
CONFIG_IP6_NF_TARGET_REJECT=m
CONFIG_IP_NF_FILTER=m
CONFIG_IP_NF_IPTABLES=m
CONFIG_IP_NF_MANGLE=m
CONFIG_IP_NF_NAT=m
CONFIG_IP_NF_TARGET_MASQUERADE=m
CONFIG_IP_NF_TARGET_REJECT=m
CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
CONFIG_NETFILTER_XT_MATCH_MARK=m
CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
CONFIG_NETFILTER_XT_TARGET_MARK=m
CONFIG_NFT_FIB_IPV4=m
CONFIG_NFT_REJECT=m
CONFIG_NFT_REJECT_NETDEV=m
# Crypto
CONFIG_MD=y
CONFIG_BLK_DEV_DM=m
CONFIG_DM_CRYPT=m
CONFIG_CRYPTO_CBC=y
CONFIG_CRYPTO_CTS=m
CONFIG_CRYPTO_ECB=y
CONFIG_CRYPTO_LRW=m
CONFIG_CRYPTO_PCBC=m
CONFIG_CRYPTO_DES=m
CONFIG_CRYPTO_XTS=m
CONFIG_CRYPTO_XCBC=m
CONFIG_CRYPTO_MD5=y
CONFIG_CRYPTO_MICHAEL_MIC=y
CONFIG_CRYPTO_RMD128=m
CONFIG_CRYPTO_RMD160=m
CONFIG_CRYPTO_RMD256=m
CONFIG_CRYPTO_RMD320=m
CONFIG_CRYPTO_SHA256=y
CONFIG_CRYPTO_TGR192=m
CONFIG_CRYPTO_WP512=m
CONFIG_KEY_DH_OPERATIONS=y
# Tolino Shine 2 HD stuff
CONFIG_MFD_NTXEC=y
CONFIG_PWM_NTXEC=m
CONFIG_TOUCHSCREEN_ZFORCE=m
CONFIG_BRCMFMAC=m
CONFIG_BRCMFMAC_SDIO=y
# commonly found in other readers
CONFIG_TOUCHSCREEN_EKTF2127=m
CONFIG_RTC_DRV_NTXEC=m
CONFIG_MFD_SY7636=m
CONFIG_REGULATOR_SY7636=m
CONFIG_SENSORS_SY7636=m
CONFIG_MFD_JD9930=m
CONFIG_REGULATOR_JD9930=m
CONFIG_SENSORS_JD9930=m
CONFIG_GPIO_BD71815=m
CONFIG_GPIO_BD71828=m
CONFIG_MFD_ROHM_BD71828=y
CONFIG_RTC_DRV_BD70528=m
CONFIG_REGULATOR_BD71815=m
CONFIG_REGULATOR_BD71828=y
CONFIG_COMMON_CLK_BD718XX=m
CONFIG_MWIFIEX=m
CONFIG_MWIFIEX_SDIO=m
CONFIG_TOUCHSCREEN_EDT_FT5X06=m
# BT (found in clara2e)
CONFIG_BT_AOSPEXT=y
CONFIG_BT_BNEP=m
CONFIG_BT_HCIBTSDIO=m
CONFIG_BT_HCIBTUSB=m
CONFIG_BT_HCIBTUSB_MTK=y
CONFIG_BT_HCIUART_BCSP=y
CONFIG_BT_HCIUART_LL=y
CONFIG_BT_HCIUART=m
CONFIG_BT_HCIUART_MRVL=y
CONFIG_BT_HIDP=m
CONFIG_BT_HS=y
CONFIG_BT_LEDS=y
CONFIG_BT=m
CONFIG_BT_MSFTEXT=y
CONFIG_BT_NXPUART=m
CONFIG_BT_RFCOMM=m

View File

@@ -460,6 +460,8 @@ source "drivers/gpu/drm/sprd/Kconfig"
source "drivers/gpu/drm/imagination/Kconfig" source "drivers/gpu/drm/imagination/Kconfig"
source "drivers/gpu/drm/mxc-epdc/Kconfig"
config DRM_HYPERV config DRM_HYPERV
tristate "DRM Support for Hyper-V synthetic video device" tristate "DRM Support for Hyper-V synthetic video device"
depends on DRM && PCI && MMU && HYPERV depends on DRM && PCI && MMU && HYPERV

View File

@@ -216,6 +216,7 @@ obj-$(CONFIG_DRM_PANTHOR) += panthor/
obj-$(CONFIG_DRM_ASPEED_GFX) += aspeed/ obj-$(CONFIG_DRM_ASPEED_GFX) += aspeed/
obj-$(CONFIG_DRM_MCDE) += mcde/ obj-$(CONFIG_DRM_MCDE) += mcde/
obj-$(CONFIG_DRM_TIDSS) += tidss/ obj-$(CONFIG_DRM_TIDSS) += tidss/
obj-$(CONFIG_DRM_MXC_EPDC) += mxc-epdc/
obj-y += xlnx/ obj-y += xlnx/
obj-y += gud/ obj-y += gud/
obj-$(CONFIG_DRM_HYPERV) += hyperv/ obj-$(CONFIG_DRM_HYPERV) += hyperv/

View File

@@ -0,0 +1,16 @@
# SPDX-License-Identifier: GPL-2.0
config DRM_MXC_EPDC
tristate "i.MX EPD Controller"
depends on DRM && OF
depends on (COMPILE_TEST || ARCH_MXC)
select DRM_KMS_HELPER
select DRM_KMS_CMA_HELPER
select DRM_TTM_HELPER
select DRM_CLIENT_SELECTION
select DMA_CMA if HAVE_DMA_CONTIGUOUS
select CMA if HAVE_DMA_CONTIGUOUS
select VIDEOMODE_HELPERS
help
Choose this option if you have an i.MX system with an EPDC.
If M is selected this module will be called mxc_epdc_drm.

View File

@@ -0,0 +1,5 @@
# SPDX-License-Identifier: GPL-2.0
mxc_epdc_drm-y := mxc_epdc_drv.o epdc_hw.o epdc_update.o epdc_waveform.o
obj-$(CONFIG_DRM_MXC_EPDC) += mxc_epdc_drm.o

View File

@@ -0,0 +1,497 @@
// SPDX-License-Identifier: GPL-2.0+
// Copyright (C) 2020 Andreas Kemnade
//
/*
* based on the EPDC framebuffer driver
* Copyright (C) 2010-2016 Freescale Semiconductor, Inc.
* Copyright 2017 NXP
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/pinctrl/consumer.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/regulator/consumer.h>
#include "mxc_epdc.h"
#include "epdc_regs.h"
#include "epdc_hw.h"
/* TODO: should probably be untangled */
#include "epdc_update.h"
#include "epdc_waveform.h"
void mxc_epdc_powerup(struct mxc_epdc *priv)
{
int ret = 0;
mutex_lock(&priv->power_mutex);
/*
* If power down request is pending, clear
* powering_down to cancel the request.
*/
if (priv->powering_down)
priv->powering_down = false;
if (priv->powered) {
mutex_unlock(&priv->power_mutex);
return;
}
dev_dbg(priv->drm.dev, "EPDC Powerup\n");
priv->updates_active = true;
/* Enable the v3p3 regulator */
ret = regulator_enable(priv->v3p3_regulator);
if (IS_ERR((void *)ret)) {
dev_err(priv->drm.dev,
"Unable to enable V3P3 regulator. err = 0x%x\n",
ret);
mutex_unlock(&priv->power_mutex);
return;
}
usleep_range(1000, 2000);
pm_runtime_get_sync(priv->drm.dev);
/* Enable clocks to EPDC */
clk_prepare_enable(priv->epdc_clk_axi);
clk_prepare_enable(priv->epdc_clk_pix);
epdc_write(priv, EPDC_CTRL_CLEAR, EPDC_CTRL_CLKGATE);
/* Enable power to the EPD panel */
ret = regulator_enable(priv->display_regulator);
if (IS_ERR((void *)ret)) {
dev_err(priv->drm.dev,
"Unable to enable DISPLAY regulator. err = 0x%x\n",
ret);
mutex_unlock(&priv->power_mutex);
return;
}
ret = regulator_enable(priv->vcom_regulator);
if (IS_ERR((void *)ret)) {
dev_err(priv->drm.dev,
"Unable to enable VCOM regulator. err = 0x%x\n",
ret);
mutex_unlock(&priv->power_mutex);
return;
}
priv->powered = true;
mutex_unlock(&priv->power_mutex);
}
void mxc_epdc_powerdown(struct mxc_epdc *priv)
{
mutex_lock(&priv->power_mutex);
/* If powering_down has been cleared, a powerup
* request is pre-empting this powerdown request.
*/
if (!priv->powering_down
|| (!priv->powered)) {
mutex_unlock(&priv->power_mutex);
return;
}
dev_dbg(priv->drm.dev, "EPDC Powerdown\n");
/* Disable power to the EPD panel */
regulator_disable(priv->vcom_regulator);
regulator_disable(priv->display_regulator);
/* Disable clocks to EPDC */
epdc_write(priv, EPDC_CTRL_SET, EPDC_CTRL_CLKGATE);
clk_disable_unprepare(priv->epdc_clk_pix);
clk_disable_unprepare(priv->epdc_clk_axi);
pm_runtime_put_sync_suspend(priv->drm.dev);
/* turn off the V3p3 */
regulator_disable(priv->v3p3_regulator);
priv->powered = false;
priv->powering_down = false;
if (priv->wait_for_powerdown) {
priv->wait_for_powerdown = false;
complete(&priv->powerdown_compl);
}
mutex_unlock(&priv->power_mutex);
}
static void epdc_set_horizontal_timing(struct mxc_epdc *priv, u32 horiz_start,
u32 horiz_end,
u32 hsync_width, u32 hsync_line_length)
{
u32 reg_val =
((hsync_width << EPDC_TCE_HSCAN1_LINE_SYNC_WIDTH_OFFSET) &
EPDC_TCE_HSCAN1_LINE_SYNC_WIDTH_MASK)
| ((hsync_line_length << EPDC_TCE_HSCAN1_LINE_SYNC_OFFSET) &
EPDC_TCE_HSCAN1_LINE_SYNC_MASK);
epdc_write(priv, EPDC_TCE_HSCAN1, reg_val);
reg_val =
((horiz_start << EPDC_TCE_HSCAN2_LINE_BEGIN_OFFSET) &
EPDC_TCE_HSCAN2_LINE_BEGIN_MASK)
| ((horiz_end << EPDC_TCE_HSCAN2_LINE_END_OFFSET) &
EPDC_TCE_HSCAN2_LINE_END_MASK);
epdc_write(priv, EPDC_TCE_HSCAN2, reg_val);
}
static void epdc_set_vertical_timing(struct mxc_epdc *priv,
u32 vert_start,
u32 vert_end,
u32 vsync_width)
{
u32 reg_val =
((vert_start << EPDC_TCE_VSCAN_FRAME_BEGIN_OFFSET) &
EPDC_TCE_VSCAN_FRAME_BEGIN_MASK)
| ((vert_end << EPDC_TCE_VSCAN_FRAME_END_OFFSET) &
EPDC_TCE_VSCAN_FRAME_END_MASK)
| ((vsync_width << EPDC_TCE_VSCAN_FRAME_SYNC_OFFSET) &
EPDC_TCE_VSCAN_FRAME_SYNC_MASK);
epdc_write(priv, EPDC_TCE_VSCAN, reg_val);
}
static inline void epdc_set_screen_res(struct mxc_epdc *priv,
u32 width, u32 height)
{
u32 val = (height << EPDC_RES_VERTICAL_OFFSET) | width;
epdc_write(priv, EPDC_RES, val);
}
void epdc_init_settings(struct mxc_epdc *priv, struct drm_display_mode *m)
{
u32 reg_val;
int num_ce;
int i;
/* Enable clocks to access EPDC regs */
clk_prepare_enable(priv->epdc_clk_axi);
clk_prepare_enable(priv->epdc_clk_pix);
/* Reset */
epdc_write(priv, EPDC_CTRL_SET, EPDC_CTRL_SFTRST);
while (!(epdc_read(priv, EPDC_CTRL) & EPDC_CTRL_CLKGATE))
;
epdc_write(priv, EPDC_CTRL_CLEAR, EPDC_CTRL_SFTRST);
/* Enable clock gating (clear to enable) */
epdc_write(priv, EPDC_CTRL_CLEAR, EPDC_CTRL_CLKGATE);
while (epdc_read(priv, EPDC_CTRL) & (EPDC_CTRL_SFTRST | EPDC_CTRL_CLKGATE))
;
/* EPDC_CTRL */
reg_val = epdc_read(priv, EPDC_CTRL);
reg_val &= ~EPDC_CTRL_UPD_DATA_SWIZZLE_MASK;
reg_val |= EPDC_CTRL_UPD_DATA_SWIZZLE_NO_SWAP;
reg_val &= ~EPDC_CTRL_LUT_DATA_SWIZZLE_MASK;
reg_val |= EPDC_CTRL_LUT_DATA_SWIZZLE_NO_SWAP;
epdc_write(priv, EPDC_CTRL_SET, reg_val);
/* EPDC_FORMAT - 2bit TFT and buf_pix_fmt Buf pixel format */
reg_val = EPDC_FORMAT_TFT_PIXEL_FORMAT_2BIT
| priv->buf_pix_fmt
| ((0x0 << EPDC_FORMAT_DEFAULT_TFT_PIXEL_OFFSET) &
EPDC_FORMAT_DEFAULT_TFT_PIXEL_MASK);
epdc_write(priv, EPDC_FORMAT, reg_val);
if (priv->rev >= 30) {
if (priv->buf_pix_fmt == EPDC_FORMAT_BUF_PIXEL_FORMAT_P5N) {
/* 110 00101 0101 0100*/
epdc_write(priv, EPDC_WB_FIELD2, 0xc554);
/* 101 00000 0000 0100*/
epdc_write(priv, EPDC_WB_FIELD1, 0xa004);
} else {
/* 110 00101 0101 0100*/
epdc_write(priv, EPDC_WB_FIELD2, 0xc443);
/* 101 00000 0000 0100*/
epdc_write(priv, EPDC_WB_FIELD1, 0xa003);
}
}
/* EPDC_FIFOCTRL (disabled) */
reg_val =
((100 << EPDC_FIFOCTRL_FIFO_INIT_LEVEL_OFFSET) &
EPDC_FIFOCTRL_FIFO_INIT_LEVEL_MASK)
| ((200 << EPDC_FIFOCTRL_FIFO_H_LEVEL_OFFSET) &
EPDC_FIFOCTRL_FIFO_H_LEVEL_MASK)
| ((100 << EPDC_FIFOCTRL_FIFO_L_LEVEL_OFFSET) &
EPDC_FIFOCTRL_FIFO_L_LEVEL_MASK);
epdc_write(priv, EPDC_FIFOCTRL, reg_val);
/* EPDC_TEMP - Use default temp to get index */
epdc_write(priv, EPDC_TEMP,
mxc_epdc_fb_get_temp_index(priv, TEMP_USE_AMBIENT));
/* EPDC_RES */
epdc_set_screen_res(priv, m->hdisplay, m->vdisplay);
/* EPDC_AUTOWV_LUT */
/* Initialize all auto-wavefrom look-up values to 2 - GC16 */
for (i = 0; i < 8; i++)
epdc_write(priv, EPDC_AUTOWV_LUT,
(2 << EPDC_AUTOWV_LUT_DATA_OFFSET) |
(i << EPDC_AUTOWV_LUT_ADDR_OFFSET));
/*
* EPDC_TCE_CTRL
* VSCAN_HOLDOFF = 4
* VCOM_MODE = MANUAL
* VCOM_VAL = 0
* DDR_MODE = DISABLED
* LVDS_MODE_CE = DISABLED
* LVDS_MODE = DISABLED
* DUAL_SCAN = DISABLED
* SDDO_WIDTH = 8bit
* PIXELS_PER_SDCLK = 4
*/
reg_val =
((priv->imx_mode.vscan_holdoff << EPDC_TCE_CTRL_VSCAN_HOLDOFF_OFFSET) &
EPDC_TCE_CTRL_VSCAN_HOLDOFF_MASK)
| EPDC_TCE_CTRL_PIXELS_PER_SDCLK_4;
epdc_write(priv, EPDC_TCE_CTRL, reg_val);
/* EPDC_TCE_HSCAN */
epdc_set_horizontal_timing(priv, m->hsync_start - m->hdisplay,
m->htotal - m->hsync_end,
m->hsync_end - m->hsync_start,
m->hsync_end - m->hsync_start);
/* EPDC_TCE_VSCAN */
epdc_set_vertical_timing(priv, m->vsync_start - m->vdisplay,
m->vtotal - m->vsync_end,
m->vsync_end - m->vsync_start);
/* EPDC_TCE_OE */
reg_val =
((priv->imx_mode.sdoed_width << EPDC_TCE_OE_SDOED_WIDTH_OFFSET) &
EPDC_TCE_OE_SDOED_WIDTH_MASK)
| ((priv->imx_mode.sdoed_delay << EPDC_TCE_OE_SDOED_DLY_OFFSET) &
EPDC_TCE_OE_SDOED_DLY_MASK)
| ((priv->imx_mode.sdoez_width << EPDC_TCE_OE_SDOEZ_WIDTH_OFFSET) &
EPDC_TCE_OE_SDOEZ_WIDTH_MASK)
| ((priv->imx_mode.sdoez_delay << EPDC_TCE_OE_SDOEZ_DLY_OFFSET) &
EPDC_TCE_OE_SDOEZ_DLY_MASK);
epdc_write(priv, EPDC_TCE_OE, reg_val);
/* EPDC_TCE_TIMING1 */
epdc_write(priv, EPDC_TCE_TIMING1, 0x0);
/* EPDC_TCE_TIMING2 */
reg_val =
((priv->imx_mode.gdclk_hp_offs << EPDC_TCE_TIMING2_GDCLK_HP_OFFSET) &
EPDC_TCE_TIMING2_GDCLK_HP_MASK)
| ((priv->imx_mode.gdsp_offs << EPDC_TCE_TIMING2_GDSP_OFFSET_OFFSET) &
EPDC_TCE_TIMING2_GDSP_OFFSET_MASK);
epdc_write(priv, EPDC_TCE_TIMING2, reg_val);
/* EPDC_TCE_TIMING3 */
reg_val =
((priv->imx_mode.gdoe_offs << EPDC_TCE_TIMING3_GDOE_OFFSET_OFFSET) &
EPDC_TCE_TIMING3_GDOE_OFFSET_MASK)
| ((priv->imx_mode.gdclk_offs << EPDC_TCE_TIMING3_GDCLK_OFFSET_OFFSET) &
EPDC_TCE_TIMING3_GDCLK_OFFSET_MASK);
epdc_write(priv, EPDC_TCE_TIMING3, reg_val);
/*
* EPDC_TCE_SDCFG
* SDCLK_HOLD = 1
* SDSHR = 1
* NUM_CE = 1
* SDDO_REFORMAT = FLIP_PIXELS
* SDDO_INVERT = DISABLED
* PIXELS_PER_CE = display horizontal resolution
*/
num_ce = priv->imx_mode.num_ce;
if (num_ce == 0)
num_ce = 1;
reg_val = EPDC_TCE_SDCFG_SDCLK_HOLD | EPDC_TCE_SDCFG_SDSHR
| ((num_ce << EPDC_TCE_SDCFG_NUM_CE_OFFSET) &
EPDC_TCE_SDCFG_NUM_CE_MASK)
| EPDC_TCE_SDCFG_SDDO_REFORMAT_FLIP_PIXELS
| ((priv->epdc_mem_width/num_ce << EPDC_TCE_SDCFG_PIXELS_PER_CE_OFFSET) &
EPDC_TCE_SDCFG_PIXELS_PER_CE_MASK);
epdc_write(priv, EPDC_TCE_SDCFG, reg_val);
/*
* EPDC_TCE_GDCFG
* GDRL = 1
* GDOE_MODE = 0;
* GDSP_MODE = 0;
*/
reg_val = EPDC_TCE_SDCFG_GDRL;
epdc_write(priv, EPDC_TCE_GDCFG, reg_val);
/*
* EPDC_TCE_POLARITY
* SDCE_POL = ACTIVE LOW
* SDLE_POL = ACTIVE HIGH
* SDOE_POL = ACTIVE HIGH
* GDOE_POL = ACTIVE HIGH
* GDSP_POL = ACTIVE LOW
*/
reg_val = EPDC_TCE_POLARITY_SDLE_POL_ACTIVE_HIGH
| EPDC_TCE_POLARITY_SDOE_POL_ACTIVE_HIGH
| EPDC_TCE_POLARITY_GDOE_POL_ACTIVE_HIGH;
epdc_write(priv, EPDC_TCE_POLARITY, reg_val);
/* EPDC_IRQ_MASK */
epdc_write(priv, EPDC_IRQ_MASK, EPDC_IRQ_TCE_UNDERRUN_IRQ);
/*
* EPDC_GPIO
* PWRCOM = ?
* PWRCTRL = ?
* BDR = ?
*/
reg_val = ((0 << EPDC_GPIO_PWRCTRL_OFFSET) & EPDC_GPIO_PWRCTRL_MASK)
| ((0 << EPDC_GPIO_BDR_OFFSET) & EPDC_GPIO_BDR_MASK);
epdc_write(priv, EPDC_GPIO, reg_val);
epdc_write(priv, EPDC_WVADDR, priv->waveform_buffer_phys);
epdc_write(priv, EPDC_WB_ADDR, priv->working_buffer_phys);
if (priv->rev >= 30)
epdc_write(priv, EPDC_WB_ADDR_TCE_V3,
priv->working_buffer_phys);
else
epdc_write(priv, EPDC_WB_ADDR_TCE,
priv->working_buffer_phys);
/* Disable clock */
clk_disable_unprepare(priv->epdc_clk_axi);
clk_disable_unprepare(priv->epdc_clk_pix);
}
void mxc_epdc_init_sequence(struct mxc_epdc *priv, struct drm_display_mode *m)
{
/* Initialize EPDC, passing pointer to EPDC registers */
struct clk *epdc_parent;
unsigned long rounded_parent_rate, epdc_pix_rate,
rounded_pix_clk, target_pix_clk;
/* Enable pix clk for EPDC */
clk_prepare_enable(priv->epdc_clk_axi);
target_pix_clk = m->clock * 1000;
rounded_pix_clk = clk_round_rate(priv->epdc_clk_pix, target_pix_clk);
if (((rounded_pix_clk >= target_pix_clk + target_pix_clk/100) ||
(rounded_pix_clk <= target_pix_clk - target_pix_clk/100))) {
/* Can't get close enough without changing parent clk */
epdc_parent = clk_get_parent(priv->epdc_clk_pix);
rounded_parent_rate = clk_round_rate(epdc_parent, target_pix_clk);
epdc_pix_rate = target_pix_clk;
while (epdc_pix_rate < rounded_parent_rate)
epdc_pix_rate *= 2;
clk_set_rate(epdc_parent, epdc_pix_rate);
rounded_pix_clk = clk_round_rate(priv->epdc_clk_pix, target_pix_clk);
if (((rounded_pix_clk >= target_pix_clk + target_pix_clk/100) ||
(rounded_pix_clk <= target_pix_clk - target_pix_clk/100)))
/* Still can't get a good clock, provide warning */
dev_err(priv->drm.dev, "Unable to get an accurate EPDC pix clk"
"desired = %lu, actual = %lu\n", target_pix_clk,
rounded_pix_clk);
}
clk_set_rate(priv->epdc_clk_pix, rounded_pix_clk);
clk_prepare_enable(priv->epdc_clk_pix);
epdc_init_settings(priv, m);
priv->in_init = true;
mxc_epdc_powerup(priv);
mxc_epdc_draw_mode0(priv);
/* Force power down event */
priv->powering_down = true;
mxc_epdc_powerdown(priv);
priv->updates_active = false;
/* Disable clocks */
clk_disable_unprepare(priv->epdc_clk_axi);
clk_disable_unprepare(priv->epdc_clk_pix);
priv->hw_ready = true;
priv->hw_initializing = false;
}
int mxc_epdc_init_hw(struct mxc_epdc *priv)
{
struct pinctrl *pinctrl;
const char *thermal = NULL;
u32 val;
/* get pmic regulators */
priv->display_regulator = devm_regulator_get(priv->drm.dev, "DISPLAY");
if (IS_ERR(priv->display_regulator))
return dev_err_probe(priv->drm.dev, PTR_ERR(priv->display_regulator),
"Unable to get display PMIC regulator\n");
priv->vcom_regulator = devm_regulator_get(priv->drm.dev, "VCOM");
if (IS_ERR(priv->vcom_regulator))
return dev_err_probe(priv->drm.dev, PTR_ERR(priv->vcom_regulator),
"Unable to get VCOM regulator\n");
priv->v3p3_regulator = devm_regulator_get(priv->drm.dev, "V3P3");
if (IS_ERR(priv->v3p3_regulator))
return dev_err_probe(priv->drm.dev, PTR_ERR(priv->v3p3_regulator),
"Unable to get V3P3 regulator\n");
of_property_read_string(priv->drm.dev->of_node,
"epd-thermal-zone", &thermal);
if (thermal) {
priv->thermal = thermal_zone_get_zone_by_name(thermal);
if (IS_ERR(priv->thermal))
return dev_err_probe(priv->drm.dev, PTR_ERR(priv->thermal),
"unable to get thermal");
}
priv->iobase = devm_platform_get_and_ioremap_resource(to_platform_device(priv->drm.dev),
0, NULL);
if (priv->iobase == NULL)
return -ENOMEM;
// priv->auto_mode = AUTO_UPDATE_MODE_REGION_MODE;
priv->epdc_clk_axi = devm_clk_get(priv->drm.dev, "epdc_axi");
if (IS_ERR(priv->epdc_clk_axi))
return dev_err_probe(priv->drm.dev, PTR_ERR(priv->epdc_clk_axi),
"Unable to get EPDC AXI clk\n");
priv->epdc_clk_pix = devm_clk_get(priv->drm.dev, "epdc_pix");
if (IS_ERR(priv->epdc_clk_pix))
return dev_err_probe(priv->drm.dev, PTR_ERR(priv->epdc_clk_pix),
"Unable to get EPDC pix clk\n");
clk_prepare_enable(priv->epdc_clk_axi);
val = epdc_read(priv, EPDC_VERSION);
clk_disable_unprepare(priv->epdc_clk_axi);
priv->rev = ((val & EPDC_VERSION_MAJOR_MASK) >>
EPDC_VERSION_MAJOR_OFFSET) * 10
+ ((val & EPDC_VERSION_MINOR_MASK) >>
EPDC_VERSION_MINOR_OFFSET);
dev_dbg(priv->drm.dev, "EPDC version = %d\n", priv->rev);
/* Initialize EPDC pins */
pinctrl = devm_pinctrl_get_select_default(priv->drm.dev);
if (IS_ERR(pinctrl)) {
dev_err(priv->drm.dev, "can't get/select pinctrl\n");
return PTR_ERR(pinctrl);
}
mutex_init(&priv->power_mutex);
return 0;
}

View File

@@ -0,0 +1,8 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/* Copyright (C) 2020 Andreas Kemnade */
void mxc_epdc_init_sequence(struct mxc_epdc *priv, struct drm_display_mode *m);
int mxc_epdc_init_hw(struct mxc_epdc *priv);
void mxc_epdc_powerup(struct mxc_epdc *priv);
void mxc_epdc_powerdown(struct mxc_epdc *priv);

View File

@@ -0,0 +1,442 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/* Copyright (C) 2010-2013 Freescale Semiconductor, Inc. */
#ifndef __EPDC_REGS_INCLUDED__
#define __EPDC_REGS_INCLUDED__
/*************************************
* Register addresses
**************************************/
#define EPDC_CTRL 0x000
#define EPDC_CTRL_SET 0x004
#define EPDC_CTRL_CLEAR 0x008
#define EPDC_CTRL_TOGGLE 0x00C
#define EPDC_WB_ADDR_TCE_V3 0x010
#define EPDC_WVADDR 0x020
#define EPDC_WB_ADDR 0x030
#define EPDC_RES 0x040
#define EPDC_FORMAT 0x050
#define EPDC_FORMAT_SET 0x054
#define EPDC_FORMAT_CLEAR 0x058
#define EPDC_FORMAT_TOGGLE 0x05C
#define EPDC_WB_FIELD0 0x060
#define EPDC_WB_FIELD0_SET 0x064
#define EPDC_WB_FIELD0_CLEAR 0x068
#define EPDC_WB_FIELD0_TOGGLE 0x06C
#define EPDC_WB_FIELD1 0x070
#define EPDC_WB_FIELD1_SET 0x074
#define EPDC_WB_FIELD1_CLEAR 0x078
#define EPDC_WB_FIELD1_TOGGLE 0x07C
#define EPDC_WB_FIELD2 0x080
#define EPDC_WB_FIELD2_SET 0x084
#define EPDC_WB_FIELD2_CLEAR 0x088
#define EPDC_WB_FIELD2_TOGGLE 0x08C
#define EPDC_WB_FIELD3 0x090
#define EPDC_WB_FIELD3_SET 0x094
#define EPDC_WB_FIELD3_CLEAR 0x098
#define EPDC_WB_FIELD3_TOGGLE 0x09C
#define EPDC_FIFOCTRL 0x0A0
#define EPDC_FIFOCTRL_SET 0x0A4
#define EPDC_FIFOCTRL_CLEAR 0x0A8
#define EPDC_FIFOCTRL_TOGGLE 0x0AC
#define EPDC_UPD_ADDR 0x100
#define EPDC_UPD_STRIDE 0x110
#define EPDC_UPD_CORD 0x120
#define EPDC_UPD_SIZE 0x140
#define EPDC_UPD_CTRL 0x160
#define EPDC_UPD_FIXED 0x180
#define EPDC_TEMP 0x1A0
#define EPDC_AUTOWV_LUT 0x1C0
#define EPDC_TCE_CTRL 0x200
#define EPDC_TCE_SDCFG 0x220
#define EPDC_TCE_GDCFG 0x240
#define EPDC_TCE_HSCAN1 0x260
#define EPDC_TCE_HSCAN2 0x280
#define EPDC_TCE_VSCAN 0x2A0
#define EPDC_TCE_OE 0x2C0
#define EPDC_TCE_POLARITY 0x2E0
#define EPDC_TCE_TIMING1 0x300
#define EPDC_TCE_TIMING2 0x310
#define EPDC_TCE_TIMING3 0x320
#define EPDC_PIGEON_CTRL0 0x380
#define EPDC_PIGEON_CTRL1 0x390
#define EPDC_IRQ_MASK1 0x3C0
#define EPDC_IRQ_MASK1_SET 0x3C4
#define EPDC_IRQ_MASK1_CLEAR 0x3C8
#define EPDC_IRQ_MASK1_TOGGLE 0x3CC
#define EPDC_IRQ_MASK2 0x3D0
#define EPDC_IRQ_MASK2_SET 0x3D4
#define EPDC_IRQ_MASK2_CLEAR 0x3D8
#define EPDC_IRQ_MASK2_TOGGLE 0x3DC
#define EPDC_IRQ1 0x3E0
#define EPDC_IRQ1_SET 0x3E4
#define EPDC_IRQ1_CLEAR 0x3E8
#define EPDC_IRQ1_TOGGLE 0x3EC
#define EPDC_IRQ2 0x3F0
#define EPDC_IRQ2_SET 0x3F4
#define EPDC_IRQ2_CLEAR 0x3F8
#define EPDC_IRQ2_TOGGLE 0x3FC
#define EPDC_IRQ_MASK 0x400
#define EPDC_IRQ_MASK_SET 0x404
#define EPDC_IRQ_MASK_CLEAR 0x408
#define EPDC_IRQ_MASK_TOGGLE 0x40C
#define EPDC_IRQ 0x420
#define EPDC_IRQ_SET 0x424
#define EPDC_IRQ_CLEAR 0x428
#define EPDC_IRQ_TOGGLE 0x42C
#define EPDC_STATUS_LUTS 0x440
#define EPDC_STATUS_LUTS_SET 0x444
#define EPDC_STATUS_LUTS_CLEAR 0x448
#define EPDC_STATUS_LUTS_TOGGLE 0x44C
#define EPDC_STATUS_LUTS2 0x450
#define EPDC_STATUS_LUTS2_SET 0x454
#define EPDC_STATUS_LUTS2_CLEAR 0x458
#define EPDC_STATUS_LUTS2_TOGGLE 0x45C
#define EPDC_STATUS_NEXTLUT 0x460
#define EPDC_STATUS_COL 0x480
#define EPDC_STATUS_COL2 0x490
#define EPDC_STATUS 0x4A0
#define EPDC_STATUS_SET 0x4A4
#define EPDC_STATUS_CLEAR 0x4A8
#define EPDC_STATUS_TOGGLE 0x4AC
#define EPDC_UPD_COL_CORD 0x4C0
#define EPDC_UPD_COL_SIZE 0x4E0
#define EPDC_DEBUG 0x500
#define EPDC_DEBUG_LUT 0x530
#define EPDC_HIST1_PARAM 0x600
#define EPDC_HIST2_PARAM 0x610
#define EPDC_HIST4_PARAM 0x620
#define EPDC_HIST8_PARAM0 0x630
#define EPDC_HIST8_PARAM1 0x640
#define EPDC_HIST16_PARAM0 0x650
#define EPDC_HIST16_PARAM1 0x660
#define EPDC_HIST16_PARAM2 0x670
#define EPDC_HIST16_PARAM3 0x680
#define EPDC_GPIO 0x700
#define EPDC_VERSION 0x7F0
#define EPDC_PIGEON_0_0 0x800
#define EPDC_PIGEON_0_1 0x810
#define EPDC_PIGEON_0_2 0x820
#define EPDC_PIGEON_1_0 0x840
#define EPDC_PIGEON_1_1 0x850
#define EPDC_PIGEON_1_2 0x860
#define EPDC_PIGEON_2_0 0x880
#define EPDC_PIGEON_2_1 0x890
#define EPDC_PIGEON_2_2 0x8A0
#define EPDC_PIGEON_3_0 0x8C0
#define EPDC_PIGEON_3_1 0x8D0
#define EPDC_PIGEON_3_2 0x8E0
#define EPDC_PIGEON_4_0 0x900
#define EPDC_PIGEON_4_1 0x910
#define EPDC_PIGEON_4_2 0x920
#define EPDC_PIGEON_5_0 0x940
#define EPDC_PIGEON_5_1 0x950
#define EPDC_PIGEON_5_2 0x960
#define EPDC_PIGEON_6_0 0x980
#define EPDC_PIGEON_6_1 0x990
#define EPDC_PIGEON_6_2 0x9A0
#define EPDC_PIGEON_7_0 0x9C0
#define EPDC_PIGEON_7_1 0x9D0
#define EPDC_PIGEON_7_2 0x9E0
#define EPDC_PIGEON_8_0 0xA00
#define EPDC_PIGEON_8_1 0xA10
#define EPDC_PIGEON_8_2 0xA20
#define EPDC_PIGEON_9_0 0xA40
#define EPDC_PIGEON_9_1 0xA50
#define EPDC_PIGEON_9_2 0xA60
#define EPDC_PIGEON_10_0 0xA80
#define EPDC_PIGEON_10_1 0xA90
#define EPDC_PIGEON_10_2 0xAA0
#define EPDC_PIGEON_11_0 0xAC0
#define EPDC_PIGEON_11_1 0xAD0
#define EPDC_PIGEON_11_2 0xAE0
#define EPDC_PIGEON_12_0 0xB00
#define EPDC_PIGEON_12_1 0xB10
#define EPDC_PIGEON_12_2 0xB20
#define EPDC_PIGEON_13_0 0xB40
#define EPDC_PIGEON_13_1 0xB50
#define EPDC_PIGEON_13_2 0xB60
#define EPDC_PIGEON_14_0 0xB80
#define EPDC_PIGEON_14_1 0xB90
#define EPDC_PIGEON_14_2 0xBA0
#define EPDC_PIGEON_15_0 0xBC0
#define EPDC_PIGEON_15_1 0xBD0
#define EPDC_PIGEON_15_2 0xBE0
#define EPDC_WB_ADDR_TCE 0xC10
/*
* Register field definitions
*/
enum {
/* EPDC_CTRL field values */
EPDC_CTRL_SFTRST = 0x80000000,
EPDC_CTRL_CLKGATE = 0x40000000,
EPDC_CTRL_SRAM_POWERDOWN = 0x100,
EPDC_CTRL_UPD_DATA_SWIZZLE_MASK = 0xC0,
EPDC_CTRL_UPD_DATA_SWIZZLE_NO_SWAP = 0,
EPDC_CTRL_UPD_DATA_SWIZZLE_ALL_BYTES_SWAP = 0x40,
EPDC_CTRL_UPD_DATA_SWIZZLE_HWD_SWAP = 0x80,
EPDC_CTRL_UPD_DATA_SWIZZLE_HWD_BYTE_SWAP = 0xC0,
EPDC_CTRL_LUT_DATA_SWIZZLE_MASK = 0x30,
EPDC_CTRL_LUT_DATA_SWIZZLE_NO_SWAP = 0,
EPDC_CTRL_LUT_DATA_SWIZZLE_ALL_BYTES_SWAP = 0x10,
EPDC_CTRL_LUT_DATA_SWIZZLE_HWD_SWAP = 0x20,
EPDC_CTRL_LUT_DATA_SWIZZLE_HWD_BYTE_SWAP = 0x30,
EPDC_CTRL_BURST_LEN_8_8 = 0x1,
EPDC_CTRL_BURST_LEN_8_16 = 0,
/* EPDC_RES field values */
EPDC_RES_VERTICAL_MASK = 0x1FFF0000,
EPDC_RES_VERTICAL_OFFSET = 16,
EPDC_RES_HORIZONTAL_MASK = 0x1FFF,
EPDC_RES_HORIZONTAL_OFFSET = 0,
/* EPDC_FORMAT field values */
EPDC_FORMAT_BUF_PIXEL_SCALE_ROUND = 0x1000000,
EPDC_FORMAT_DEFAULT_TFT_PIXEL_MASK = 0xFF0000,
EPDC_FORMAT_DEFAULT_TFT_PIXEL_OFFSET = 16,
EPDC_FORMAT_BUF_PIXEL_FORMAT_MASK = 0x700,
EPDC_FORMAT_BUF_PIXEL_FORMAT_P2N = 0x200,
EPDC_FORMAT_BUF_PIXEL_FORMAT_P3N = 0x300,
EPDC_FORMAT_BUF_PIXEL_FORMAT_P4N = 0x400,
EPDC_FORMAT_BUF_PIXEL_FORMAT_P5N = 0x500,
EPDC_FORMAT_TFT_PIXEL_FORMAT_2BIT = 0x0,
EPDC_FORMAT_TFT_PIXEL_FORMAT_2BIT_VCOM = 0x1,
EPDC_FORMAT_TFT_PIXEL_FORMAT_4BIT = 0x2,
EPDC_FORMAT_TFT_PIXEL_FORMAT_4BIT_VCOM = 0x3,
/* EPDC_FIFOCTRL field values */
EPDC_FIFOCTRL_ENABLE_PRIORITY = 0x80000000,
EPDC_FIFOCTRL_FIFO_INIT_LEVEL_MASK = 0xFF0000,
EPDC_FIFOCTRL_FIFO_INIT_LEVEL_OFFSET = 16,
EPDC_FIFOCTRL_FIFO_H_LEVEL_MASK = 0xFF00,
EPDC_FIFOCTRL_FIFO_H_LEVEL_OFFSET = 8,
EPDC_FIFOCTRL_FIFO_L_LEVEL_MASK = 0xFF,
EPDC_FIFOCTRL_FIFO_L_LEVEL_OFFSET = 0,
/* EPDC_UPD_CORD field values */
EPDC_UPD_CORD_YCORD_MASK = 0x1FFF0000,
EPDC_UPD_CORD_YCORD_OFFSET = 16,
EPDC_UPD_CORD_XCORD_MASK = 0x1FFF,
EPDC_UPD_CORD_XCORD_OFFSET = 0,
/* EPDC_UPD_SIZE field values */
EPDC_UPD_SIZE_HEIGHT_MASK = 0x1FFF0000,
EPDC_UPD_SIZE_HEIGHT_OFFSET = 16,
EPDC_UPD_SIZE_WIDTH_MASK = 0x1FFF,
EPDC_UPD_SIZE_WIDTH_OFFSET = 0,
/* EPDC_UPD_CTRL field values */
EPDC_UPD_CTRL_USE_FIXED = 0x80000000,
EPDC_UPD_CTRL_LUT_SEL_MASK = 0x3F0000,
EPDC_UPD_CTRL_LUT_SEL_OFFSET = 16,
EPDC_UPD_CTRL_WAVEFORM_MODE_MASK = 0xFF00,
EPDC_UPD_CTRL_WAVEFORM_MODE_OFFSET = 8,
EPDC_UPD_CTRL_AUTOWV_PAUSE = 0x8,
EPDC_UPD_CTRL_AUTOWV = 0x4,
EPDC_UPD_CTRL_DRY_RUN = 0x2,
EPDC_UPD_CTRL_UPDATE_MODE_FULL = 0x1,
/* EPDC_UPD_FIXED field values */
EPDC_UPD_FIXED_FIXNP_EN = 0x80000000,
EPDC_UPD_FIXED_FIXCP_EN = 0x40000000,
EPDC_UPD_FIXED_FIXNP_MASK = 0xFF00,
EPDC_UPD_FIXED_FIXNP_OFFSET = 8,
EPDC_UPD_FIXED_FIXCP_MASK = 0xFF,
EPDC_UPD_FIXED_FIXCP_OFFSET = 0,
/* EPDC_AUTOWV_LUT field values */
EPDC_AUTOWV_LUT_DATA_MASK = 0xFF0000,
EPDC_AUTOWV_LUT_DATA_OFFSET = 16,
EPDC_AUTOWV_LUT_ADDR_MASK = 0xFF,
EPDC_AUTOWV_LUT_ADDR_OFFSET = 0,
/* EPDC_TCE_CTRL field values */
EPDC_TCE_CTRL_VSCAN_HOLDOFF_MASK = 0x1FF0000,
EPDC_TCE_CTRL_VSCAN_HOLDOFF_OFFSET = 16,
EPDC_TCE_CTRL_VCOM_VAL_MASK = 0xC00,
EPDC_TCE_CTRL_VCOM_VAL_OFFSET = 10,
EPDC_TCE_CTRL_VCOM_MODE_AUTO = 0x200,
EPDC_TCE_CTRL_VCOM_MODE_MANUAL = 0x000,
EPDC_TCE_CTRL_DDR_MODE_ENABLE = 0x100,
EPDC_TCE_CTRL_LVDS_MODE_CE_ENABLE = 0x80,
EPDC_TCE_CTRL_LVDS_MODE_ENABLE = 0x40,
EPDC_TCE_CTRL_SCAN_DIR_1_UP = 0x20,
EPDC_TCE_CTRL_SCAN_DIR_0_UP = 0x10,
EPDC_TCE_CTRL_DUAL_SCAN_ENABLE = 0x8,
EPDC_TCE_CTRL_SDDO_WIDTH_16BIT = 0x4,
EPDC_TCE_CTRL_PIXELS_PER_SDCLK_2 = 1,
EPDC_TCE_CTRL_PIXELS_PER_SDCLK_4 = 2,
EPDC_TCE_CTRL_PIXELS_PER_SDCLK_8 = 3,
/* EPDC_TCE_SDCFG field values */
EPDC_TCE_SDCFG_SDCLK_HOLD = 0x200000,
EPDC_TCE_SDCFG_SDSHR = 0x100000,
EPDC_TCE_SDCFG_NUM_CE_MASK = 0xF0000,
EPDC_TCE_SDCFG_NUM_CE_OFFSET = 16,
EPDC_TCE_SDCFG_SDDO_REFORMAT_STANDARD = 0,
EPDC_TCE_SDCFG_SDDO_REFORMAT_FLIP_PIXELS = 0x4000,
EPDC_TCE_SDCFG_SDDO_INVERT_ENABLE = 0x2000,
EPDC_TCE_SDCFG_PIXELS_PER_CE_MASK = 0x1FFF,
EPDC_TCE_SDCFG_PIXELS_PER_CE_OFFSET = 0,
/* EPDC_TCE_GDCFG field values */
EPDC_TCE_SDCFG_GDRL = 0x10,
EPDC_TCE_SDCFG_GDOE_MODE_DELAYED_GDCLK = 0x2,
EPDC_TCE_SDCFG_GDSP_MODE_FRAME_SYNC = 0x1,
EPDC_TCE_SDCFG_GDSP_MODE_ONE_LINE = 0x0,
/* EPDC_TCE_HSCAN1 field values */
EPDC_TCE_HSCAN1_LINE_SYNC_WIDTH_MASK = 0xFFF0000,
EPDC_TCE_HSCAN1_LINE_SYNC_WIDTH_OFFSET = 16,
EPDC_TCE_HSCAN1_LINE_SYNC_MASK = 0xFFF,
EPDC_TCE_HSCAN1_LINE_SYNC_OFFSET = 0,
/* EPDC_TCE_HSCAN2 field values */
EPDC_TCE_HSCAN2_LINE_END_MASK = 0xFFF0000,
EPDC_TCE_HSCAN2_LINE_END_OFFSET = 16,
EPDC_TCE_HSCAN2_LINE_BEGIN_MASK = 0xFFF,
EPDC_TCE_HSCAN2_LINE_BEGIN_OFFSET = 0,
/* EPDC_TCE_VSCAN field values */
EPDC_TCE_VSCAN_FRAME_END_MASK = 0xFF0000,
EPDC_TCE_VSCAN_FRAME_END_OFFSET = 16,
EPDC_TCE_VSCAN_FRAME_BEGIN_MASK = 0xFF00,
EPDC_TCE_VSCAN_FRAME_BEGIN_OFFSET = 8,
EPDC_TCE_VSCAN_FRAME_SYNC_MASK = 0xFF,
EPDC_TCE_VSCAN_FRAME_SYNC_OFFSET = 0,
/* EPDC_TCE_OE field values */
EPDC_TCE_OE_SDOED_WIDTH_MASK = 0xFF000000,
EPDC_TCE_OE_SDOED_WIDTH_OFFSET = 24,
EPDC_TCE_OE_SDOED_DLY_MASK = 0xFF0000,
EPDC_TCE_OE_SDOED_DLY_OFFSET = 16,
EPDC_TCE_OE_SDOEZ_WIDTH_MASK = 0xFF00,
EPDC_TCE_OE_SDOEZ_WIDTH_OFFSET = 8,
EPDC_TCE_OE_SDOEZ_DLY_MASK = 0xFF,
EPDC_TCE_OE_SDOEZ_DLY_OFFSET = 0,
/* EPDC_TCE_POLARITY field values */
EPDC_TCE_POLARITY_GDSP_POL_ACTIVE_HIGH = 0x10,
EPDC_TCE_POLARITY_GDOE_POL_ACTIVE_HIGH = 0x8,
EPDC_TCE_POLARITY_SDOE_POL_ACTIVE_HIGH = 0x4,
EPDC_TCE_POLARITY_SDLE_POL_ACTIVE_HIGH = 0x2,
EPDC_TCE_POLARITY_SDCE_POL_ACTIVE_HIGH = 0x1,
/* EPDC_TCE_TIMING1 field values */
EPDC_TCE_TIMING1_SDLE_SHIFT_NONE = 0x00,
EPDC_TCE_TIMING1_SDLE_SHIFT_1 = 0x10,
EPDC_TCE_TIMING1_SDLE_SHIFT_2 = 0x20,
EPDC_TCE_TIMING1_SDLE_SHIFT_3 = 0x30,
EPDC_TCE_TIMING1_SDCLK_INVERT = 0x8,
EPDC_TCE_TIMING1_SDCLK_SHIFT_NONE = 0,
EPDC_TCE_TIMING1_SDCLK_SHIFT_1CYCLE = 1,
EPDC_TCE_TIMING1_SDCLK_SHIFT_2CYCLES = 2,
EPDC_TCE_TIMING1_SDCLK_SHIFT_3CYCLES = 3,
/* EPDC_TCE_TIMING2 field values */
EPDC_TCE_TIMING2_GDCLK_HP_MASK = 0xFFFF0000,
EPDC_TCE_TIMING2_GDCLK_HP_OFFSET = 16,
EPDC_TCE_TIMING2_GDSP_OFFSET_MASK = 0xFFFF,
EPDC_TCE_TIMING2_GDSP_OFFSET_OFFSET = 0,
/* EPDC_TCE_TIMING3 field values */
EPDC_TCE_TIMING3_GDOE_OFFSET_MASK = 0xFFFF0000,
EPDC_TCE_TIMING3_GDOE_OFFSET_OFFSET = 16,
EPDC_TCE_TIMING3_GDCLK_OFFSET_MASK = 0xFFFF,
EPDC_TCE_TIMING3_GDCLK_OFFSET_OFFSET = 0,
/* EPDC_IRQ_MASK/EPDC_IRQ field values */
EPDC_IRQ_WB_CMPLT_IRQ = 0x10000,
EPDC_IRQ_LUT_COL_IRQ = 0x20000,
EPDC_IRQ_TCE_UNDERRUN_IRQ = 0x40000,
EPDC_IRQ_FRAME_END_IRQ = 0x80000,
EPDC_IRQ_BUS_ERROR_IRQ = 0x100000,
EPDC_IRQ_TCE_IDLE_IRQ = 0x200000,
EPDC_IRQ_UPD_DONE_IRQ = 0x400000,
EPDC_IRQ_PWR_IRQ = 0x800000,
/* EPDC_STATUS_NEXTLUT field values */
EPDC_STATUS_NEXTLUT_NEXT_LUT_VALID = 0x100,
EPDC_STATUS_NEXTLUT_NEXT_LUT_MASK = 0x3F,
EPDC_STATUS_NEXTLUT_NEXT_LUT_OFFSET = 0,
/* EPDC_STATUS field values */
EPDC_STATUS_HISTOGRAM_CP_MASK = 0x1F0000,
EPDC_STATUS_HISTOGRAM_CP_OFFSET = 16,
EPDC_STATUS_HISTOGRAM_NP_MASK = 0x1F00,
EPDC_STATUS_HISTOGRAM_NP_OFFSET = 8,
EPDC_STATUS_UPD_VOID = 0x8,
EPDC_STATUS_LUTS_UNDERRUN = 0x4,
EPDC_STATUS_LUTS_BUSY = 0x2,
EPDC_STATUS_WB_BUSY = 0x1,
/* EPDC_UPD_COL_CORD field values */
EPDC_UPD_COL_CORD_YCORD_MASK = 0x1FFF0000,
EPDC_UPD_COL_CORD_YCORD_OFFSET = 16,
EPDC_UPD_COL_CORD_XCORD_MASK = 0x1FFF,
EPDC_UPD_COL_CORD_XCORD_OFFSET = 0,
/* EPDC_UPD_COL_SIZE field values */
EPDC_UPD_COL_SIZE_HEIGHT_MASK = 0x1FFF0000,
EPDC_UPD_COL_SIZE_HEIGHT_OFFSET = 16,
EPDC_UPD_COL_SIZE_WIDTH_MASK = 0x1FFF,
EPDC_UPD_COL_SIZE_WIDTH_OFFSET = 0,
/* EPDC_DEBUG field values */
EPDC_DEBUG_UNDERRUN_RECOVER = 0x2,
EPDC_DEBUG_COLLISION_OFF = 0x1,
/* EPDC_HISTx_PARAM field values */
EPDC_HIST_PARAM_VALUE0_MASK = 0x1F,
EPDC_HIST_PARAM_VALUE0_OFFSET = 0,
EPDC_HIST_PARAM_VALUE1_MASK = 0x1F00,
EPDC_HIST_PARAM_VALUE1_OFFSET = 8,
EPDC_HIST_PARAM_VALUE2_MASK = 0x1F0000,
EPDC_HIST_PARAM_VALUE2_OFFSET = 16,
EPDC_HIST_PARAM_VALUE3_MASK = 0x1F000000,
EPDC_HIST_PARAM_VALUE3_OFFSET = 24,
EPDC_HIST_PARAM_VALUE4_MASK = 0x1F,
EPDC_HIST_PARAM_VALUE4_OFFSET = 0,
EPDC_HIST_PARAM_VALUE5_MASK = 0x1F00,
EPDC_HIST_PARAM_VALUE5_OFFSET = 8,
EPDC_HIST_PARAM_VALUE6_MASK = 0x1F0000,
EPDC_HIST_PARAM_VALUE6_OFFSET = 16,
EPDC_HIST_PARAM_VALUE7_MASK = 0x1F000000,
EPDC_HIST_PARAM_VALUE7_OFFSET = 24,
EPDC_HIST_PARAM_VALUE8_MASK = 0x1F,
EPDC_HIST_PARAM_VALUE8_OFFSET = 0,
EPDC_HIST_PARAM_VALUE9_MASK = 0x1F00,
EPDC_HIST_PARAM_VALUE9_OFFSET = 8,
EPDC_HIST_PARAM_VALUE10_MASK = 0x1F0000,
EPDC_HIST_PARAM_VALUE10_OFFSET = 16,
EPDC_HIST_PARAM_VALUE11_MASK = 0x1F000000,
EPDC_HIST_PARAM_VALUE11_OFFSET = 24,
EPDC_HIST_PARAM_VALUE12_MASK = 0x1F,
EPDC_HIST_PARAM_VALUE12_OFFSET = 0,
EPDC_HIST_PARAM_VALUE13_MASK = 0x1F00,
EPDC_HIST_PARAM_VALUE13_OFFSET = 8,
EPDC_HIST_PARAM_VALUE14_MASK = 0x1F0000,
EPDC_HIST_PARAM_VALUE14_OFFSET = 16,
EPDC_HIST_PARAM_VALUE15_MASK = 0x1F000000,
EPDC_HIST_PARAM_VALUE15_OFFSET = 24,
/* EPDC_GPIO field values */
EPDC_GPIO_PWRCOM = 0x40,
EPDC_GPIO_PWRCTRL_MASK = 0x3C,
EPDC_GPIO_PWRCTRL_OFFSET = 2,
EPDC_GPIO_BDR_MASK = 0x3,
EPDC_GPIO_BDR_OFFSET = 0,
/* EPDC_VERSION field values */
EPDC_VERSION_MAJOR_MASK = 0xFF000000,
EPDC_VERSION_MAJOR_OFFSET = 24,
EPDC_VERSION_MINOR_MASK = 0xFF0000,
EPDC_VERSION_MINOR_OFFSET = 16,
EPDC_VERSION_STEP_MASK = 0xFFFF,
EPDC_VERSION_STEP_OFFSET = 0,
};
#endif /* __EPDC_REGS_INCLUDED__ */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,9 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/* Copyright (C) 2020 Andreas Kemnade */
int mxc_epdc_send_single_update(struct drm_rect *clip, int pitch,
void *vaddr,
struct mxc_epdc *priv);
void mxc_epdc_draw_mode0(struct mxc_epdc *priv);
int mxc_epdc_init_update(struct mxc_epdc *priv);
void mxc_epdc_flush_updates(struct mxc_epdc *priv);

View File

@@ -0,0 +1,185 @@
// SPDX-License-Identifier: GPL-2.0+
// Copyright (C) 2020 Andreas Kemnade
//
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/dma-mapping.h>
#include "mxc_epdc.h"
#define DEFAULT_TEMP_INDEX 0
#define DEFAULT_TEMP 20 /* room temp in deg Celsius */
struct waveform_data_header {
unsigned int wi0;
unsigned int wi1;
unsigned int wi2;
unsigned int wi3;
unsigned int wi4;
unsigned int wi5;
unsigned int wi6;
unsigned int xwia:24;
unsigned int cs1:8;
unsigned int wmta:24;
unsigned int fvsn:8;
unsigned int luts:8;
unsigned int mc:8;
unsigned int trc:8;
unsigned int reserved0_0:8;
unsigned int eb:8;
unsigned int sb:8;
unsigned int reserved0_1:8;
unsigned int reserved0_2:8;
unsigned int reserved0_3:8;
unsigned int reserved0_4:8;
unsigned int reserved0_5:8;
unsigned int cs2:8;
};
struct mxcfb_waveform_data_file {
struct waveform_data_header wdh;
u32 *data; /* Temperature Range Table + Waveform Data */
};
void mxc_epdc_set_update_waveform(struct mxc_epdc *priv,
struct mxcfb_waveform_modes *wv_modes)
{
u32 val;
/* Configure the auto-waveform look-up table based on waveform modes */
/* Entry 1 = DU, 2 = GC4, 3 = GC8, etc. */
val = (wv_modes->mode_du << EPDC_AUTOWV_LUT_DATA_OFFSET) |
(0 << EPDC_AUTOWV_LUT_ADDR_OFFSET);
epdc_write(priv, EPDC_AUTOWV_LUT, val);
val = (wv_modes->mode_du << EPDC_AUTOWV_LUT_DATA_OFFSET) |
(1 << EPDC_AUTOWV_LUT_ADDR_OFFSET);
epdc_write(priv, EPDC_AUTOWV_LUT, val);
val = (wv_modes->mode_gc4 << EPDC_AUTOWV_LUT_DATA_OFFSET) |
(2 << EPDC_AUTOWV_LUT_ADDR_OFFSET);
epdc_write(priv, EPDC_AUTOWV_LUT, val);
val = (wv_modes->mode_gc8 << EPDC_AUTOWV_LUT_DATA_OFFSET) |
(3 << EPDC_AUTOWV_LUT_ADDR_OFFSET);
epdc_write(priv, EPDC_AUTOWV_LUT, val);
val = (wv_modes->mode_gc16 << EPDC_AUTOWV_LUT_DATA_OFFSET) |
(4 << EPDC_AUTOWV_LUT_ADDR_OFFSET);
epdc_write(priv, EPDC_AUTOWV_LUT, val);
val = (wv_modes->mode_gc32 << EPDC_AUTOWV_LUT_DATA_OFFSET) |
(5 << EPDC_AUTOWV_LUT_ADDR_OFFSET);
epdc_write(priv, EPDC_AUTOWV_LUT, val);
}
int mxc_epdc_fb_get_temp_index(struct mxc_epdc *priv, int temp)
{
int i;
int index = -1;
if (temp == TEMP_USE_AMBIENT) {
if (priv->thermal) {
if (thermal_zone_get_temp(priv->thermal, &temp)) {
dev_err(priv->drm.dev,
"reading temperature failed");
return DEFAULT_TEMP_INDEX;
}
temp /= 1000;
} else
temp = DEFAULT_TEMP;
}
if (priv->trt_entries == 0) {
dev_err(priv->drm.dev,
"No TRT exists...using default temp index\n");
return DEFAULT_TEMP_INDEX;
}
/* Search temperature ranges for a match */
for (i = 0; i < priv->trt_entries - 1; i++) {
if ((temp >= priv->temp_range_bounds[i])
&& (temp < priv->temp_range_bounds[i+1])) {
index = i;
break;
}
}
if (index < 0) {
dev_err(priv->drm.dev,
"No TRT index match...using lowest/highest\n");
if (temp < priv->temp_range_bounds[0]) {
dev_dbg(priv->drm.dev, "temperature < minimum range\n");
return 0;
}
if (temp >= priv->temp_range_bounds[priv->trt_entries-1]) {
dev_dbg(priv->drm.dev, "temperature >= maximum range\n");
return priv->trt_entries-1;
}
return DEFAULT_TEMP_INDEX;
}
dev_dbg(priv->drm.dev, "Using temperature index %d\n", index);
return index;
}
int mxc_epdc_prepare_waveform(struct mxc_epdc *priv,
const u8 *data, size_t size)
{
int ret;
const struct mxcfb_waveform_data_file *wv_file;
int wv_data_offs;
int i;
priv->wv_modes.mode_init = 0;
priv->wv_modes.mode_du = 1;
priv->wv_modes.mode_gc4 = 3;
priv->wv_modes.mode_gc8 = 2;
priv->wv_modes.mode_gc16 = 2;
priv->wv_modes.mode_gc32 = 2;
priv->wv_modes_update = true;
wv_file = (struct mxcfb_waveform_data_file *)data;
/* Get size and allocate temperature range table */
priv->trt_entries = wv_file->wdh.trc + 1;
priv->temp_range_bounds = devm_kzalloc(priv->drm.dev, priv->trt_entries, GFP_KERNEL);
for (i = 0; i < priv->trt_entries; i++)
dev_dbg(priv->drm.dev, "trt entry #%d = 0x%x\n", i, *((u8 *)&wv_file->data + i));
/* Copy TRT data */
memcpy(priv->temp_range_bounds, &wv_file->data, priv->trt_entries);
/* Set default temperature index using TRT and room temp */
priv->temp_index = mxc_epdc_fb_get_temp_index(priv, DEFAULT_TEMP);
/* Get offset and size for waveform data */
wv_data_offs = sizeof(wv_file->wdh) + priv->trt_entries + 1;
priv->waveform_buffer_size = size - wv_data_offs;
/* Allocate memory for waveform data */
priv->waveform_buffer_virt = dmam_alloc_coherent(priv->drm.dev,
priv->waveform_buffer_size,
&priv->waveform_buffer_phys,
GFP_DMA | GFP_KERNEL);
if (priv->waveform_buffer_virt == NULL) {
dev_err(priv->drm.dev, "Can't allocate mem for waveform!\n");
return -ENOMEM;
}
memcpy(priv->waveform_buffer_virt, (u8 *)(data) + wv_data_offs,
priv->waveform_buffer_size);
/* Read field to determine if 4-bit or 5-bit mode */
if ((wv_file->wdh.luts & 0xC) == 0x4)
priv->buf_pix_fmt = EPDC_FORMAT_BUF_PIXEL_FORMAT_P5N;
else
priv->buf_pix_fmt = EPDC_FORMAT_BUF_PIXEL_FORMAT_P4N;
dev_info(priv->drm.dev, "EPDC pix format: %x\n",
priv->buf_pix_fmt);
return 0;
}

View File

@@ -0,0 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/* Copyright (C) 2020 Andreas Kemnade */
int mxc_epdc_fb_get_temp_index(struct mxc_epdc *priv, int temp);
int mxc_epdc_prepare_waveform(struct mxc_epdc *priv,
const u8 *waveform, size_t size);
void mxc_epdc_set_update_waveform(struct mxc_epdc *priv,
struct mxcfb_waveform_modes *wv_modes);

View File

@@ -0,0 +1,153 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/* Copyright (C) 2020 Andreas Kemnade */
#include <video/display_timing.h>
#include <video/of_display_timing.h>
#include <video/videomode.h>
#include <drm/drm_drv.h>
#include <drm/drm_connector.h>
#include <drm/drm_simple_kms_helper.h>
#include <linux/thermal.h>
#include "epdc_regs.h"
#define GRAYSCALE_8BIT 0x1
#define GRAYSCALE_8BIT_INVERTED 0x2
#define GRAYSCALE_4BIT 0x3
#define GRAYSCALE_4BIT_INVERTED 0x4
#define AUTO_UPDATE_MODE_REGION_MODE 0
#define AUTO_UPDATE_MODE_AUTOMATIC_MODE 1
#define UPDATE_SCHEME_SNAPSHOT 0
#define UPDATE_SCHEME_QUEUE 1
#define UPDATE_SCHEME_QUEUE_AND_MERGE 2
#define UPDATE_MODE_PARTIAL 0x0
#define UPDATE_MODE_FULL 0x1
#define WAVEFORM_MODE_GLR16 4
#define WAVEFORM_MODE_GLD16 5
#define WAVEFORM_MODE_AUTO 257
#define TEMP_USE_AMBIENT 0x1000
#define FB_POWERDOWN_DISABLE -1
struct mxcfb_update_data {
struct drm_rect update_region;
u32 waveform_mode;
u32 update_mode;
int temp;
int dither_mode;
int quant_bit;
};
struct mxcfb_waveform_modes {
int mode_init;
int mode_du;
int mode_gc4;
int mode_gc8;
int mode_gc16;
int mode_gc32;
};
struct imx_epdc_fb_mode {
u32 vscan_holdoff;
u32 sdoed_width;
u32 sdoed_delay;
u32 sdoez_width;
u32 sdoez_delay;
u32 gdclk_hp_offs;
u32 gdsp_offs;
u32 gdoe_offs;
u32 gdclk_offs;
u32 num_ce;
};
struct clk;
struct regulator;
struct mxc_epdc {
struct drm_device drm;
struct drm_simple_display_pipe pipe;
struct drm_connector connector;
struct display_timing timing;
struct imx_epdc_fb_mode imx_mode;
void __iomem *iobase;
struct completion powerdown_compl;
struct clk *epdc_clk_axi;
struct clk *epdc_clk_pix;
struct regulator *display_regulator;
struct regulator *vcom_regulator;
struct regulator *v3p3_regulator;
struct thermal_zone_device *thermal;
int rev;
dma_addr_t epdc_mem_phys;
void *epdc_mem_virt;
int epdc_mem_width;
int epdc_mem_height;
u32 *working_buffer_virt;
dma_addr_t working_buffer_phys;
u32 working_buffer_size;
/* waveform related stuff */
int trt_entries;
int temp_index;
u8 *temp_range_bounds;
int buf_pix_fmt;
struct mxcfb_waveform_modes wv_modes;
bool wv_modes_update;
u32 *waveform_buffer_virt;
dma_addr_t waveform_buffer_phys;
u32 waveform_buffer_size;
struct mutex power_mutex;
bool powered;
bool powering_down;
bool updates_active;
int wait_for_powerdown;
int pwrdown_delay;
/* elements related to EPDC updates */
int num_luts;
int max_num_updates;
#warning take of init of in_init hw_ready, hw_initializing
bool in_init;
bool hw_ready;
bool hw_initializing;
bool waiting_for_idle;
int order_cnt;
struct list_head upd_pending_list;
struct list_head upd_buf_queue;
struct list_head upd_buf_free_list;
struct list_head upd_buf_collision_list;
struct update_data_list *cur_update;
struct mutex queue_mutex;
int epdc_irq;
struct list_head full_marker_list;
u32 *lut_update_order;
u64 epdc_colliding_luts;
u64 luts_complete_wb;
struct completion updates_done;
struct delayed_work epdc_done_work;
struct workqueue_struct *epdc_submit_workqueue;
struct work_struct epdc_submit_work;
struct workqueue_struct *epdc_intr_workqueue;
struct work_struct epdc_intr_work;
bool waiting_for_wb;
bool waiting_for_lut;
struct completion update_res_free;
};
static inline u32 epdc_read(struct mxc_epdc *priv, u32 reg)
{
return readl(priv->iobase + reg);
}
static inline void epdc_write(struct mxc_epdc *priv, u32 reg, u32 data)
{
writel(data, priv->iobase + reg);
}

View File

@@ -0,0 +1,368 @@
// SPDX-License-Identifier: GPL-2.0+
// Copyright (C) 2020 Andreas Kemnade
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/dma-mapping.h>
#include <linux/firmware.h>
#include <linux/fs.h>
#include <linux/of_graph.h>
#include <linux/platform_device.h>
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <drm/clients/drm_client_setup.h>
#include <drm/drm_crtc_helper.h>
#include <drm/drm_damage_helper.h>
#include <drm/drm_drv.h>
#include <drm/drm_fb_dma_helper.h>
#include <drm/drm_fb_helper.h>
#include <drm/drm_fbdev_ttm.h>
#include <drm/drm_file.h>
#include <drm/drm_format_helper.h>
#include <drm/drm_framebuffer.h>
#include <drm/drm_gem_atomic_helper.h>
#include <drm/drm_gem_dma_helper.h>
#include <drm/drm_gem_framebuffer_helper.h>
#include <drm/drm_ioctl.h>
#include <drm/drm_panel.h>
#include <drm/drm_prime.h>
#include <drm/drm_probe_helper.h>
#include "mxc_epdc.h"
#include "epdc_hw.h"
#include "epdc_update.h"
#include "epdc_waveform.h"
#define DRIVER_NAME "mxc_epdc"
#define DRIVER_DESC "IMX EPDC"
#define DRIVER_MAJOR 1
#define DRIVER_MINOR 0
#define DRIVER_PATCHLEVEL 0
#define to_mxc_epdc(x) container_of(x, struct mxc_epdc, drm)
static const struct drm_mode_config_funcs mxc_epdc_mode_config_funcs = {
.fb_create = drm_gem_fb_create_with_dirty,
.atomic_check = drm_atomic_helper_check,
.atomic_commit = drm_atomic_helper_commit,
};
static struct mxc_epdc *
drm_pipe_to_mxc_epdc(struct drm_simple_display_pipe *pipe)
{
return container_of(pipe, struct mxc_epdc, pipe);
}
static struct mxc_epdc *
drm_connector_to_mxc_epdc(struct drm_connector *connector)
{
return container_of(connector, struct mxc_epdc, connector);
}
static void mxc_epdc_setup_mode_config(struct drm_device *drm)
{
drm_mode_config_init(drm);
drm->mode_config.min_width = 0;
drm->mode_config.min_height = 0;
/*
* Maximum update buffer image width due to v2.0 and v2.1 errata
* ERR005313.
*/
drm->mode_config.max_width = 2047;
drm->mode_config.max_height = 2048;
drm->mode_config.funcs = &mxc_epdc_mode_config_funcs;
}
DEFINE_DRM_GEM_DMA_FOPS(fops);
static int mxc_epdc_get_modes(struct drm_connector *connector)
{
struct mxc_epdc *priv = drm_connector_to_mxc_epdc(connector);
struct drm_display_mode *mode;
struct videomode vm;
videomode_from_timing(&priv->timing, &vm);
mode = drm_mode_create(connector->dev);
if (!mode) {
dev_err(priv->drm.dev, "failed to add mode\n");
return 0;
}
drm_display_mode_from_videomode(&vm, mode);
mode->type |= DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
drm_mode_probed_add(connector, mode);
return 1;
}
static const struct
drm_connector_helper_funcs mxc_epdc_connector_helper_funcs = {
.get_modes = mxc_epdc_get_modes,
};
static const struct drm_connector_funcs mxc_epdc_connector_funcs = {
.fill_modes = drm_helper_probe_single_connector_modes,
.destroy = drm_connector_cleanup,
.reset = drm_atomic_helper_connector_reset,
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
};
int mxc_epdc_output(struct drm_device *drm)
{
struct mxc_epdc *priv = to_mxc_epdc(drm);
int ret;
priv->connector.dpms = DRM_MODE_DPMS_OFF;
priv->connector.polled = 0;
drm_connector_helper_add(&priv->connector,
&mxc_epdc_connector_helper_funcs);
ret = drm_connector_init(drm, &priv->connector,
&mxc_epdc_connector_funcs,
DRM_MODE_CONNECTOR_Unknown);
if (ret)
return ret;
ret = of_property_read_u32(drm->dev->of_node, "vscan-holdoff",
&priv->imx_mode.vscan_holdoff);
if (ret)
return ret;
ret = of_property_read_u32(drm->dev->of_node, "sdoed-width",
&priv->imx_mode.sdoed_width);
if (ret)
return ret;
ret = of_property_read_u32(drm->dev->of_node, "sdoed-delay",
&priv->imx_mode.sdoed_delay);
if (ret)
return ret;
ret = of_property_read_u32(drm->dev->of_node, "sdoez-width",
&priv->imx_mode.sdoez_width);
if (ret)
return ret;
ret = of_property_read_u32(drm->dev->of_node, "sdoez-delay",
&priv->imx_mode.sdoez_delay);
if (ret)
return ret;
ret = of_property_read_u32(drm->dev->of_node, "gdclk-hp-offs",
&priv->imx_mode.gdclk_hp_offs);
if (ret)
return ret;
ret = of_property_read_u32(drm->dev->of_node, "gdsp-offs",
&priv->imx_mode.gdsp_offs);
if (ret)
return ret;
ret = of_property_read_u32(drm->dev->of_node, "gdoe-offs",
&priv->imx_mode.gdoe_offs);
if (ret)
return ret;
ret = of_property_read_u32(drm->dev->of_node, "gdclk-offs",
&priv->imx_mode.gdclk_offs);
if (ret)
return ret;
ret = of_property_read_u32(drm->dev->of_node, "num-ce",
&priv->imx_mode.num_ce);
if (ret)
return ret;
ret = of_get_display_timing(drm->dev->of_node, "timing", &priv->timing);
if (ret)
return ret;
return 0;
}
static void mxc_epdc_pipe_enable(struct drm_simple_display_pipe *pipe,
struct drm_crtc_state *crtc_state,
struct drm_plane_state *plane_state)
{
struct mxc_epdc *priv = drm_pipe_to_mxc_epdc(pipe);
struct drm_display_mode *m = &pipe->crtc.state->adjusted_mode;
dev_info(priv->drm.dev, "Mode: %d x %d\n", m->hdisplay, m->vdisplay);
priv->epdc_mem_width = m->hdisplay;
priv->epdc_mem_height = m->vdisplay;
priv->epdc_mem_virt = dma_alloc_wc(priv->drm.dev,
m->hdisplay * m->vdisplay,
&priv->epdc_mem_phys, GFP_DMA | GFP_KERNEL);
priv->working_buffer_size = m->hdisplay * m->vdisplay * 2;
priv->working_buffer_virt =
dma_alloc_coherent(priv->drm.dev,
priv->working_buffer_size,
&priv->working_buffer_phys,
GFP_DMA | GFP_KERNEL);
if (priv->working_buffer_virt && priv->epdc_mem_virt)
mxc_epdc_init_sequence(priv, m);
}
static void mxc_epdc_pipe_disable(struct drm_simple_display_pipe *pipe)
{
struct mxc_epdc *priv = drm_pipe_to_mxc_epdc(pipe);
dev_dbg(priv->drm.dev, "pipe disable\n");
mxc_epdc_flush_updates(priv);
if (priv->epdc_mem_virt) {
dma_free_wc(priv->drm.dev, priv->epdc_mem_width * priv->epdc_mem_height,
priv->epdc_mem_virt, priv->epdc_mem_phys);
priv->epdc_mem_virt = NULL;
}
if (priv->working_buffer_virt) {
dma_free_wc(priv->drm.dev, priv->working_buffer_size,
priv->working_buffer_virt,
priv->working_buffer_phys);
priv->working_buffer_virt = NULL;
}
}
static void mxc_epdc_pipe_update(struct drm_simple_display_pipe *pipe,
struct drm_plane_state *old_state)
{
struct mxc_epdc *priv = drm_pipe_to_mxc_epdc(pipe);
struct drm_gem_dma_object *gem;
struct drm_atomic_helper_damage_iter iter;
struct drm_rect clip;
dev_dbg(priv->drm.dev, "pipe update\n");
if (!old_state->fb) {
dev_dbg(priv->drm.dev, "no fb, nothing to update\n");
return;
}
if (priv->epdc_mem_virt == NULL)
return;
gem = drm_fb_dma_get_gem_obj(pipe->plane.state->fb, 0);
drm_atomic_helper_damage_iter_init(&iter, old_state, pipe->plane.state);
drm_atomic_for_each_plane_damage(&iter, &clip) {
dev_dbg(priv->drm.dev, "damaged: %d,%d-%d,%d\n",
clip.x1, clip.y1, clip.x2, clip.y2);
mxc_epdc_send_single_update(&clip, old_state->fb->pitches[0],
gem->vaddr, priv);
}
return;
}
static const struct drm_simple_display_pipe_funcs mxc_epdc_funcs = {
.enable = mxc_epdc_pipe_enable,
.disable = mxc_epdc_pipe_disable,
.update = mxc_epdc_pipe_update,
};
static const uint32_t mxc_epdc_formats[] = {
DRM_FORMAT_XRGB8888,
};
static struct drm_driver mxc_epdc_driver = {
.driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
.fops = &fops,
.dumb_create = drm_gem_dma_dumb_create,
.gem_prime_import_sg_table = drm_gem_dma_prime_import_sg_table,
DRM_FBDEV_TTM_DRIVER_OPS,
.name = DRIVER_NAME,
.desc = DRIVER_DESC,
.major = DRIVER_MAJOR,
.minor = DRIVER_MINOR,
.patchlevel = DRIVER_PATCHLEVEL,
};
static int mxc_epdc_probe(struct platform_device *pdev)
{
struct mxc_epdc *priv;
const struct firmware *firmware;
int ret;
priv = devm_drm_dev_alloc(&pdev->dev, &mxc_epdc_driver, struct mxc_epdc, drm);
if (IS_ERR(priv))
return PTR_ERR(priv);
platform_set_drvdata(pdev, priv);
ret = mxc_epdc_init_hw(priv);
if (ret)
return ret;
ret = mxc_epdc_init_update(priv);
if (ret)
return ret;
ret = request_firmware(&firmware, "imx/epdc/epdc.fw", priv->drm.dev);
if (ret)
return ret;
ret = mxc_epdc_prepare_waveform(priv, firmware->data, firmware->size);
release_firmware(firmware);
if (ret)
return ret;
mxc_epdc_setup_mode_config(&priv->drm);
ret = mxc_epdc_output(&priv->drm);
if (ret)
return ret;
drm_simple_display_pipe_init(&priv->drm, &priv->pipe, &mxc_epdc_funcs,
mxc_epdc_formats,
ARRAY_SIZE(mxc_epdc_formats),
NULL,
&priv->connector);
drm_plane_enable_fb_damage_clips(&priv->pipe.plane);
drm_mode_config_reset(&priv->drm);
ret = drm_dev_register(&priv->drm, 0);
drm_client_setup(&priv->drm, NULL);
return 0;
}
static void mxc_epdc_remove(struct platform_device *pdev)
{
struct mxc_epdc *priv = platform_get_drvdata(pdev);
drm_dev_unregister(&priv->drm);
drm_kms_helper_poll_fini(&priv->drm);
drm_mode_config_cleanup(&priv->drm);
}
static const struct of_device_id imx_epdc_dt_ids[] = {
{ .compatible = "fsl,imx6sl-epdc", },
{ .compatible = "fsl,imx6sll-epdc", },
{ .compatible = "fsl,imx6ull-epdc", },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, imx_epdc_dt_ids);
static struct platform_driver pdev = {
.driver = {
.name = "mxc_epdc",
.of_match_table = of_match_ptr(imx_epdc_dt_ids),
},
.probe = mxc_epdc_probe,
.remove = mxc_epdc_remove,
};
module_platform_driver(pdev);
MODULE_DESCRIPTION("IMX EPDC driver");
MODULE_LICENSE("GPL");