Compare commits
8 Commits
v6.15
...
kindle-pw3
| Author | SHA1 | Date | |
|---|---|---|---|
| 90358030ad | |||
| 804ce77a86 | |||
| 9c61d889a0 | |||
| b496c40170 | |||
| e18fd1b573 | |||
|
|
4b51ff1cf5 | ||
|
|
9c0a2dfb19 | ||
| 70c5dfde43 |
159
Documentation/devicetree/bindings/display/imx/fsl,mxc-epdc.yaml
Normal file
159
Documentation/devicetree/bindings/display/imx/fsl,mxc-epdc.yaml
Normal 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>;
|
||||
};
|
||||
};
|
||||
...
|
||||
@@ -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 {
|
||||
clock-frequency = <100000>;
|
||||
|
||||
@@ -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 {
|
||||
pinctrl-names = "default","sleep";
|
||||
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 {
|
||||
fsl,pins = <
|
||||
MX6SL_PAD_LCD_DAT0__GPIO2_IO20 0x79
|
||||
|
||||
@@ -26,6 +26,11 @@
|
||||
compatible = "kobo,tolino-shine3", "fsl,imx6sl";
|
||||
};
|
||||
|
||||
&epdc {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinctrl_epdc0>;
|
||||
};
|
||||
|
||||
&gpio_keys {
|
||||
pinctrl-names = "default";
|
||||
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 {
|
||||
fsl,pins = <
|
||||
MX6SL_PAD_SD1_DAT1__GPIO5_IO08 0x17059 /* PWR_SW */
|
||||
|
||||
@@ -771,8 +771,11 @@
|
||||
};
|
||||
|
||||
epdc: epdc@20f4000 {
|
||||
compatible = "fsl,imx6sl-epdc", "fsl,imx6dl-epdc";
|
||||
reg = <0x020f4000 0x4000>;
|
||||
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 {
|
||||
|
||||
@@ -36,6 +36,11 @@
|
||||
soc-supply = <&dcdc1_reg>;
|
||||
};
|
||||
|
||||
&epdc {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinctrl_epdc0>;
|
||||
};
|
||||
|
||||
&gpio_keys {
|
||||
pinctrl-names = "default";
|
||||
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 {
|
||||
fsl,pins = <
|
||||
MX6SLL_PAD_SD1_DATA1__GPIO5_IO08 0x17059 /* PWR_SW */
|
||||
|
||||
@@ -656,6 +656,15 @@
|
||||
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 {
|
||||
compatible = "fsl,imx6sll-lcdif", "fsl,imx28-lcdif";
|
||||
reg = <0x020f8000 0x4000>;
|
||||
|
||||
494
arch/arm/configs/wario_defconfig
Normal file
494
arch/arm/configs/wario_defconfig
Normal file
@@ -0,0 +1,494 @@
|
||||
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
|
||||
@@ -460,6 +460,8 @@ source "drivers/gpu/drm/sprd/Kconfig"
|
||||
|
||||
source "drivers/gpu/drm/imagination/Kconfig"
|
||||
|
||||
source "drivers/gpu/drm/mxc-epdc/Kconfig"
|
||||
|
||||
config DRM_HYPERV
|
||||
tristate "DRM Support for Hyper-V synthetic video device"
|
||||
depends on DRM && PCI && MMU && HYPERV
|
||||
|
||||
@@ -216,6 +216,7 @@ obj-$(CONFIG_DRM_PANTHOR) += panthor/
|
||||
obj-$(CONFIG_DRM_ASPEED_GFX) += aspeed/
|
||||
obj-$(CONFIG_DRM_MCDE) += mcde/
|
||||
obj-$(CONFIG_DRM_TIDSS) += tidss/
|
||||
obj-$(CONFIG_DRM_MXC_EPDC) += mxc-epdc/
|
||||
obj-y += xlnx/
|
||||
obj-y += gud/
|
||||
obj-$(CONFIG_DRM_HYPERV) += hyperv/
|
||||
|
||||
16
drivers/gpu/drm/mxc-epdc/Kconfig
Normal file
16
drivers/gpu/drm/mxc-epdc/Kconfig
Normal 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.
|
||||
5
drivers/gpu/drm/mxc-epdc/Makefile
Normal file
5
drivers/gpu/drm/mxc-epdc/Makefile
Normal 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
|
||||
|
||||
497
drivers/gpu/drm/mxc-epdc/epdc_hw.c
Normal file
497
drivers/gpu/drm/mxc-epdc/epdc_hw.c
Normal 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;
|
||||
}
|
||||
8
drivers/gpu/drm/mxc-epdc/epdc_hw.h
Normal file
8
drivers/gpu/drm/mxc-epdc/epdc_hw.h
Normal 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);
|
||||
|
||||
442
drivers/gpu/drm/mxc-epdc/epdc_regs.h
Normal file
442
drivers/gpu/drm/mxc-epdc/epdc_regs.h
Normal 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__ */
|
||||
1242
drivers/gpu/drm/mxc-epdc/epdc_update.c
Normal file
1242
drivers/gpu/drm/mxc-epdc/epdc_update.c
Normal file
File diff suppressed because it is too large
Load Diff
9
drivers/gpu/drm/mxc-epdc/epdc_update.h
Normal file
9
drivers/gpu/drm/mxc-epdc/epdc_update.h
Normal 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);
|
||||
|
||||
185
drivers/gpu/drm/mxc-epdc/epdc_waveform.c
Normal file
185
drivers/gpu/drm/mxc-epdc/epdc_waveform.c
Normal 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;
|
||||
}
|
||||
7
drivers/gpu/drm/mxc-epdc/epdc_waveform.h
Normal file
7
drivers/gpu/drm/mxc-epdc/epdc_waveform.h
Normal 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);
|
||||
153
drivers/gpu/drm/mxc-epdc/mxc_epdc.h
Normal file
153
drivers/gpu/drm/mxc-epdc/mxc_epdc.h
Normal 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);
|
||||
}
|
||||
|
||||
368
drivers/gpu/drm/mxc-epdc/mxc_epdc_drv.c
Normal file
368
drivers/gpu/drm/mxc-epdc/mxc_epdc_drv.c
Normal 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");
|
||||
|
||||
@@ -267,6 +267,36 @@ config TOUCHSCREEN_CYTTSP_SPI
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called cyttsp_spi.
|
||||
|
||||
config TOUCHSCREEN_CYTTSP4_CORE
|
||||
tristate "Cypress TrueTouch Gen4 Touchscreen Driver"
|
||||
help
|
||||
Core driver for Cypress TrueTouch(tm) Standard Product
|
||||
Generation4 touchscreen controllers.
|
||||
|
||||
Say Y here if you have a Cypress Gen4 touchscreen.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
To compile this driver as a module, choose M here.
|
||||
|
||||
config TOUCHSCREEN_CYTTSP4_I2C
|
||||
tristate "support I2C bus connection"
|
||||
depends on TOUCHSCREEN_CYTTSP4_CORE && I2C
|
||||
help
|
||||
Say Y here if the touchscreen is connected via I2C bus.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called cyttsp4_i2c.
|
||||
|
||||
config TOUCHSCREEN_CYTTSP4_SPI
|
||||
tristate "support SPI bus connection"
|
||||
depends on TOUCHSCREEN_CYTTSP4_CORE && SPI_MASTER
|
||||
help
|
||||
Say Y here if the touchscreen is connected via SPI bus.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called cyttsp4_spi.
|
||||
|
||||
config TOUCHSCREEN_CYTTSP5
|
||||
tristate "Cypress TrueTouch Gen5 Touchscreen Driver"
|
||||
depends on I2C
|
||||
|
||||
@@ -27,6 +27,9 @@ obj-$(CONFIG_TOUCHSCREEN_CY8CTMA140) += cy8ctma140.o
|
||||
obj-$(CONFIG_TOUCHSCREEN_CY8CTMG110) += cy8ctmg110_ts.o
|
||||
obj-$(CONFIG_TOUCHSCREEN_CYTTSP_CORE) += cyttsp_core.o
|
||||
obj-$(CONFIG_TOUCHSCREEN_CYTTSP_I2C) += cyttsp_i2c.o
|
||||
obj-$(CONFIG_TOUCHSCREEN_CYTTSP4_CORE) += cyttsp4_core.o
|
||||
obj-$(CONFIG_TOUCHSCREEN_CYTTSP4_I2C) += cyttsp4_i2c.o
|
||||
obj-$(CONFIG_TOUCHSCREEN_CYTTSP4_SPI) += cyttsp4_spi.o
|
||||
obj-$(CONFIG_TOUCHSCREEN_CYTTSP_SPI) += cyttsp_spi.o
|
||||
obj-$(CONFIG_TOUCHSCREEN_CYTTSP5) += cyttsp5.o
|
||||
obj-$(CONFIG_TOUCHSCREEN_DA9034) += da9034-ts.o
|
||||
|
||||
2180
drivers/input/touchscreen/cyttsp4_core.c
Normal file
2180
drivers/input/touchscreen/cyttsp4_core.c
Normal file
File diff suppressed because it is too large
Load Diff
446
drivers/input/touchscreen/cyttsp4_core.h
Normal file
446
drivers/input/touchscreen/cyttsp4_core.h
Normal file
@@ -0,0 +1,446 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* cyttsp4_core.h
|
||||
* Cypress TrueTouch(TM) Standard Product V4 Core driver module.
|
||||
* For use with Cypress Txx4xx parts.
|
||||
* Supported parts include:
|
||||
* TMA4XX
|
||||
* TMA1036
|
||||
*
|
||||
* Copyright (C) 2012 Cypress Semiconductor
|
||||
*
|
||||
* Contact Cypress Semiconductor at www.cypress.com <ttdrivers@cypress.com>
|
||||
*/
|
||||
|
||||
#ifndef _LINUX_CYTTSP4_CORE_H
|
||||
#define _LINUX_CYTTSP4_CORE_H
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/limits.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/stringify.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/platform_data/cyttsp4.h>
|
||||
#include <linux/of_gpio.h>
|
||||
|
||||
#define CY_REG_BASE 0x00
|
||||
|
||||
#define CY_POST_CODEL_WDG_RST 0x01
|
||||
#define CY_POST_CODEL_CFG_DATA_CRC_FAIL 0x02
|
||||
#define CY_POST_CODEL_PANEL_TEST_FAIL 0x04
|
||||
|
||||
#define CY_NUM_BTN_PER_REG 4
|
||||
|
||||
/* touch record system information offset masks and shifts */
|
||||
#define CY_BYTE_OFS_MASK 0x1F
|
||||
#define CY_BOFS_MASK 0xE0
|
||||
#define CY_BOFS_SHIFT 5
|
||||
|
||||
#define CY_TMA1036_TCH_REC_SIZE 6
|
||||
#define CY_TMA4XX_TCH_REC_SIZE 9
|
||||
#define CY_TMA1036_MAX_TCH 0x0E
|
||||
#define CY_TMA4XX_MAX_TCH 0x1E
|
||||
|
||||
#define CY_NORMAL_ORIGIN 0 /* upper, left corner */
|
||||
#define CY_INVERT_ORIGIN 1 /* lower, right corner */
|
||||
|
||||
/* helpers */
|
||||
#define GET_NUM_TOUCHES(x) ((x) & 0x1F)
|
||||
#define IS_LARGE_AREA(x) ((x) & 0x20)
|
||||
#define IS_BAD_PKT(x) ((x) & 0x20)
|
||||
#define IS_BOOTLOADER(hst_mode, reset_detect) \
|
||||
((hst_mode) & 0x01 || (reset_detect) != 0)
|
||||
#define IS_TMO(t) ((t) == 0)
|
||||
|
||||
|
||||
enum cyttsp_cmd_bits {
|
||||
CY_CMD_COMPLETE = (1 << 6),
|
||||
};
|
||||
|
||||
/* Timeout in ms. */
|
||||
#define CY_WATCHDOG_TIMEOUT 1000
|
||||
|
||||
#define CY_MAX_PRINT_SIZE 512
|
||||
#ifdef VERBOSE_DEBUG
|
||||
#define CY_MAX_PRBUF_SIZE PIPE_BUF
|
||||
#define CY_PR_TRUNCATED " truncated..."
|
||||
#endif
|
||||
|
||||
enum cyttsp4_ic_grpnum {
|
||||
CY_IC_GRPNUM_RESERVED,
|
||||
CY_IC_GRPNUM_CMD_REGS,
|
||||
CY_IC_GRPNUM_TCH_REP,
|
||||
CY_IC_GRPNUM_DATA_REC,
|
||||
CY_IC_GRPNUM_TEST_REC,
|
||||
CY_IC_GRPNUM_PCFG_REC,
|
||||
CY_IC_GRPNUM_TCH_PARM_VAL,
|
||||
CY_IC_GRPNUM_TCH_PARM_SIZE,
|
||||
CY_IC_GRPNUM_RESERVED1,
|
||||
CY_IC_GRPNUM_RESERVED2,
|
||||
CY_IC_GRPNUM_OPCFG_REC,
|
||||
CY_IC_GRPNUM_DDATA_REC,
|
||||
CY_IC_GRPNUM_MDATA_REC,
|
||||
CY_IC_GRPNUM_TEST_REGS,
|
||||
CY_IC_GRPNUM_BTN_KEYS,
|
||||
CY_IC_GRPNUM_TTHE_REGS,
|
||||
CY_IC_GRPNUM_NUM
|
||||
};
|
||||
|
||||
enum cyttsp4_int_state {
|
||||
CY_INT_NONE,
|
||||
CY_INT_IGNORE = (1 << 0),
|
||||
CY_INT_MODE_CHANGE = (1 << 1),
|
||||
CY_INT_EXEC_CMD = (1 << 2),
|
||||
CY_INT_AWAKE = (1 << 3),
|
||||
};
|
||||
|
||||
enum cyttsp4_mode {
|
||||
CY_MODE_UNKNOWN,
|
||||
CY_MODE_BOOTLOADER = (1 << 1),
|
||||
CY_MODE_OPERATIONAL = (1 << 2),
|
||||
CY_MODE_SYSINFO = (1 << 3),
|
||||
CY_MODE_CAT = (1 << 4),
|
||||
CY_MODE_STARTUP = (1 << 5),
|
||||
CY_MODE_LOADER = (1 << 6),
|
||||
CY_MODE_CHANGE_MODE = (1 << 7),
|
||||
CY_MODE_CHANGED = (1 << 8),
|
||||
CY_MODE_CMD_COMPLETE = (1 << 9),
|
||||
};
|
||||
|
||||
enum cyttsp4_sleep_state {
|
||||
SS_SLEEP_OFF,
|
||||
SS_SLEEP_ON,
|
||||
SS_SLEEPING,
|
||||
SS_WAKING,
|
||||
};
|
||||
|
||||
enum cyttsp4_startup_state {
|
||||
STARTUP_NONE,
|
||||
STARTUP_QUEUED,
|
||||
STARTUP_RUNNING,
|
||||
};
|
||||
|
||||
#define CY_NUM_REVCTRL 8
|
||||
struct cyttsp4_cydata {
|
||||
u8 ttpidh;
|
||||
u8 ttpidl;
|
||||
u8 fw_ver_major;
|
||||
u8 fw_ver_minor;
|
||||
u8 revctrl[CY_NUM_REVCTRL];
|
||||
u8 blver_major;
|
||||
u8 blver_minor;
|
||||
u8 jtag_si_id3;
|
||||
u8 jtag_si_id2;
|
||||
u8 jtag_si_id1;
|
||||
u8 jtag_si_id0;
|
||||
u8 mfgid_sz;
|
||||
u8 cyito_idh;
|
||||
u8 cyito_idl;
|
||||
u8 cyito_verh;
|
||||
u8 cyito_verl;
|
||||
u8 ttsp_ver_major;
|
||||
u8 ttsp_ver_minor;
|
||||
u8 device_info;
|
||||
u8 mfg_id[];
|
||||
} __packed;
|
||||
|
||||
struct cyttsp4_test {
|
||||
u8 post_codeh;
|
||||
u8 post_codel;
|
||||
} __packed;
|
||||
|
||||
struct cyttsp4_pcfg {
|
||||
u8 electrodes_x;
|
||||
u8 electrodes_y;
|
||||
u8 len_xh;
|
||||
u8 len_xl;
|
||||
u8 len_yh;
|
||||
u8 len_yl;
|
||||
u8 res_xh;
|
||||
u8 res_xl;
|
||||
u8 res_yh;
|
||||
u8 res_yl;
|
||||
u8 max_zh;
|
||||
u8 max_zl;
|
||||
u8 panel_info0;
|
||||
} __packed;
|
||||
|
||||
struct cyttsp4_tch_rec_params {
|
||||
u8 loc;
|
||||
u8 size;
|
||||
} __packed;
|
||||
|
||||
#define CY_NUM_TCH_FIELDS 7
|
||||
#define CY_NUM_EXT_TCH_FIELDS 3
|
||||
struct cyttsp4_opcfg {
|
||||
u8 cmd_ofs;
|
||||
u8 rep_ofs;
|
||||
u8 rep_szh;
|
||||
u8 rep_szl;
|
||||
u8 num_btns;
|
||||
u8 tt_stat_ofs;
|
||||
u8 obj_cfg0;
|
||||
u8 max_tchs;
|
||||
u8 tch_rec_size;
|
||||
struct cyttsp4_tch_rec_params tch_rec_old[CY_NUM_TCH_FIELDS];
|
||||
u8 btn_rec_size; /* btn record size (in bytes) */
|
||||
u8 btn_diff_ofs; /* btn data loc, diff counts */
|
||||
u8 btn_diff_size; /* btn size of diff counts (in bits) */
|
||||
struct cyttsp4_tch_rec_params tch_rec_new[CY_NUM_EXT_TCH_FIELDS];
|
||||
} __packed;
|
||||
|
||||
struct cyttsp4_sysinfo_ptr {
|
||||
struct cyttsp4_cydata *cydata;
|
||||
struct cyttsp4_test *test;
|
||||
struct cyttsp4_pcfg *pcfg;
|
||||
struct cyttsp4_opcfg *opcfg;
|
||||
struct cyttsp4_ddata *ddata;
|
||||
struct cyttsp4_mdata *mdata;
|
||||
} __packed;
|
||||
|
||||
struct cyttsp4_sysinfo_data {
|
||||
u8 hst_mode;
|
||||
u8 reserved;
|
||||
u8 map_szh;
|
||||
u8 map_szl;
|
||||
u8 cydata_ofsh;
|
||||
u8 cydata_ofsl;
|
||||
u8 test_ofsh;
|
||||
u8 test_ofsl;
|
||||
u8 pcfg_ofsh;
|
||||
u8 pcfg_ofsl;
|
||||
u8 opcfg_ofsh;
|
||||
u8 opcfg_ofsl;
|
||||
u8 ddata_ofsh;
|
||||
u8 ddata_ofsl;
|
||||
u8 mdata_ofsh;
|
||||
u8 mdata_ofsl;
|
||||
} __packed;
|
||||
|
||||
enum cyttsp4_tch_abs { /* for ordering within the extracted touch data array */
|
||||
CY_TCH_X, /* X */
|
||||
CY_TCH_Y, /* Y */
|
||||
CY_TCH_P, /* P (Z) */
|
||||
CY_TCH_T, /* TOUCH ID */
|
||||
CY_TCH_E, /* EVENT ID */
|
||||
CY_TCH_O, /* OBJECT ID */
|
||||
CY_TCH_W, /* SIZE */
|
||||
CY_TCH_MAJ, /* TOUCH_MAJOR */
|
||||
CY_TCH_MIN, /* TOUCH_MINOR */
|
||||
CY_TCH_OR, /* ORIENTATION */
|
||||
CY_TCH_NUM_ABS
|
||||
};
|
||||
|
||||
struct cyttsp4_touch {
|
||||
int abs[CY_TCH_NUM_ABS];
|
||||
};
|
||||
|
||||
struct cyttsp4_tch_abs_params {
|
||||
size_t ofs; /* abs byte offset */
|
||||
size_t size; /* size in bits */
|
||||
size_t max; /* max value */
|
||||
size_t bofs; /* bit offset */
|
||||
};
|
||||
|
||||
struct cyttsp4_sysinfo_ofs {
|
||||
size_t chip_type;
|
||||
size_t cmd_ofs;
|
||||
size_t rep_ofs;
|
||||
size_t rep_sz;
|
||||
size_t num_btns;
|
||||
size_t num_btn_regs; /* ceil(num_btns/4) */
|
||||
size_t tt_stat_ofs;
|
||||
size_t tch_rec_size;
|
||||
size_t obj_cfg0;
|
||||
size_t max_tchs;
|
||||
size_t mode_size;
|
||||
size_t data_size;
|
||||
size_t map_sz;
|
||||
size_t max_x;
|
||||
size_t x_origin; /* left or right corner */
|
||||
size_t max_y;
|
||||
size_t y_origin; /* upper or lower corner */
|
||||
size_t max_p;
|
||||
size_t cydata_ofs;
|
||||
size_t test_ofs;
|
||||
size_t pcfg_ofs;
|
||||
size_t opcfg_ofs;
|
||||
size_t ddata_ofs;
|
||||
size_t mdata_ofs;
|
||||
size_t cydata_size;
|
||||
size_t test_size;
|
||||
size_t pcfg_size;
|
||||
size_t opcfg_size;
|
||||
size_t ddata_size;
|
||||
size_t mdata_size;
|
||||
size_t btn_keys_size;
|
||||
struct cyttsp4_tch_abs_params tch_abs[CY_TCH_NUM_ABS];
|
||||
size_t btn_rec_size; /* btn record size (in bytes) */
|
||||
size_t btn_diff_ofs;/* btn data loc ,diff counts, (Op-Mode byte ofs) */
|
||||
size_t btn_diff_size;/* btn size of diff counts (in bits) */
|
||||
};
|
||||
|
||||
enum cyttsp4_btn_state {
|
||||
CY_BTN_RELEASED,
|
||||
CY_BTN_PRESSED,
|
||||
CY_BTN_NUM_STATE
|
||||
};
|
||||
|
||||
struct cyttsp4_btn {
|
||||
bool enabled;
|
||||
int state; /* CY_BTN_PRESSED, CY_BTN_RELEASED */
|
||||
int key_code;
|
||||
};
|
||||
|
||||
struct cyttsp4_sysinfo {
|
||||
bool ready;
|
||||
struct cyttsp4_sysinfo_data si_data;
|
||||
struct cyttsp4_sysinfo_ptr si_ptrs;
|
||||
struct cyttsp4_sysinfo_ofs si_ofs;
|
||||
struct cyttsp4_btn *btn; /* button states */
|
||||
u8 *btn_rec_data; /* button diff count data */
|
||||
u8 *xy_mode; /* operational mode and status regs */
|
||||
u8 *xy_data; /* operational touch regs */
|
||||
};
|
||||
|
||||
struct cyttsp4_mt_data {
|
||||
struct cyttsp4_mt_platform_data *pdata;
|
||||
struct cyttsp4_sysinfo *si;
|
||||
struct input_dev *input;
|
||||
struct mutex report_lock;
|
||||
bool is_suspended;
|
||||
char phys[NAME_MAX];
|
||||
int num_prv_tch;
|
||||
};
|
||||
|
||||
struct cyttsp4 {
|
||||
struct device *dev;
|
||||
struct mutex system_lock;
|
||||
struct mutex adap_lock;
|
||||
enum cyttsp4_mode mode;
|
||||
enum cyttsp4_sleep_state sleep_state;
|
||||
enum cyttsp4_startup_state startup_state;
|
||||
int int_status;
|
||||
wait_queue_head_t wait_q;
|
||||
int irq;
|
||||
struct work_struct startup_work;
|
||||
struct work_struct watchdog_work;
|
||||
struct timer_list watchdog_timer;
|
||||
struct cyttsp4_sysinfo sysinfo;
|
||||
void *exclusive_dev;
|
||||
int exclusive_waits;
|
||||
atomic_t ignore_irq;
|
||||
bool invalid_touch_app;
|
||||
struct cyttsp4_mt_data md;
|
||||
struct cyttsp4_platform_data *pdata;
|
||||
struct cyttsp4_core_platform_data *cpdata;
|
||||
const struct cyttsp4_bus_ops *bus_ops;
|
||||
u8 *xfer_buf;
|
||||
#ifdef VERBOSE_DEBUG
|
||||
u8 pr_buf[CY_MAX_PRBUF_SIZE];
|
||||
#endif
|
||||
};
|
||||
|
||||
struct cyttsp4_bus_ops {
|
||||
u16 bustype;
|
||||
int (*write)(struct device *dev, u8 *xfer_buf, u16 addr, u8 length,
|
||||
const void *values);
|
||||
int (*read)(struct device *dev, u8 *xfer_buf, u16 addr, u8 length,
|
||||
void *values);
|
||||
};
|
||||
|
||||
enum cyttsp4_hst_mode_bits {
|
||||
CY_HST_TOGGLE = (1 << 7),
|
||||
CY_HST_MODE_CHANGE = (1 << 3),
|
||||
CY_HST_MODE = (7 << 4),
|
||||
CY_HST_OPERATE = (0 << 4),
|
||||
CY_HST_SYSINFO = (1 << 4),
|
||||
CY_HST_CAT = (2 << 4),
|
||||
CY_HST_LOWPOW = (1 << 2),
|
||||
CY_HST_SLEEP = (1 << 1),
|
||||
CY_HST_RESET = (1 << 0),
|
||||
};
|
||||
|
||||
/* abs settings */
|
||||
#define CY_IGNORE_VALUE 0xFFFF
|
||||
|
||||
/* abs signal capabilities offsets in the frameworks array */
|
||||
enum cyttsp4_sig_caps {
|
||||
CY_SIGNAL_OST,
|
||||
CY_MIN_OST,
|
||||
CY_MAX_OST,
|
||||
CY_FUZZ_OST,
|
||||
CY_FLAT_OST,
|
||||
CY_NUM_ABS_SET /* number of signal capability fields */
|
||||
};
|
||||
|
||||
/* abs axis signal offsets in the framworks array */
|
||||
enum cyttsp4_sig_ost {
|
||||
CY_ABS_X_OST,
|
||||
CY_ABS_Y_OST,
|
||||
CY_ABS_P_OST,
|
||||
CY_ABS_W_OST,
|
||||
CY_ABS_ID_OST,
|
||||
CY_ABS_MAJ_OST,
|
||||
CY_ABS_MIN_OST,
|
||||
CY_ABS_OR_OST,
|
||||
CY_NUM_ABS_OST /* number of abs signals */
|
||||
};
|
||||
|
||||
enum cyttsp4_flags {
|
||||
CY_FLAG_NONE = 0x00,
|
||||
CY_FLAG_HOVER = 0x04,
|
||||
CY_FLAG_FLIP = 0x08,
|
||||
CY_FLAG_INV_X = 0x10,
|
||||
CY_FLAG_INV_Y = 0x20,
|
||||
CY_FLAG_VKEYS = 0x40,
|
||||
};
|
||||
|
||||
enum cyttsp4_object_id {
|
||||
CY_OBJ_STANDARD_FINGER,
|
||||
CY_OBJ_LARGE_OBJECT,
|
||||
CY_OBJ_STYLUS,
|
||||
CY_OBJ_HOVER,
|
||||
};
|
||||
|
||||
enum cyttsp4_event_id {
|
||||
CY_EV_NO_EVENT,
|
||||
CY_EV_TOUCHDOWN,
|
||||
CY_EV_MOVE, /* significant displacement (> act dist) */
|
||||
CY_EV_LIFTOFF, /* record reports last position */
|
||||
};
|
||||
|
||||
/* x-axis resolution of panel in pixels */
|
||||
#define CY_PCFG_RESOLUTION_X_MASK 0x7F
|
||||
|
||||
/* y-axis resolution of panel in pixels */
|
||||
#define CY_PCFG_RESOLUTION_Y_MASK 0x7F
|
||||
|
||||
/* x-axis, 0:origin is on left side of panel, 1: right */
|
||||
#define CY_PCFG_ORIGIN_X_MASK 0x80
|
||||
|
||||
/* y-axis, 0:origin is on top side of panel, 1: bottom */
|
||||
#define CY_PCFG_ORIGIN_Y_MASK 0x80
|
||||
|
||||
static inline int cyttsp4_adap_read(struct cyttsp4 *ts, u16 addr, int size,
|
||||
void *buf)
|
||||
{
|
||||
return ts->bus_ops->read(ts->dev, ts->xfer_buf, addr, size, buf);
|
||||
}
|
||||
|
||||
static inline int cyttsp4_adap_write(struct cyttsp4 *ts, u16 addr, int size,
|
||||
const void *buf)
|
||||
{
|
||||
return ts->bus_ops->write(ts->dev, ts->xfer_buf, addr, size, buf);
|
||||
}
|
||||
|
||||
extern struct cyttsp4 *cyttsp4_probe(const struct cyttsp4_bus_ops *ops,
|
||||
struct device *dev, u16 irq, size_t xfer_buf_size);
|
||||
extern int cyttsp4_remove(struct cyttsp4 *ts);
|
||||
|
||||
extern const struct dev_pm_ops cyttsp4_pm_ops;
|
||||
|
||||
#endif /* _LINUX_CYTTSP4_CORE_H */
|
||||
178
drivers/input/touchscreen/cyttsp4_i2c.c
Normal file
178
drivers/input/touchscreen/cyttsp4_i2c.c
Normal file
@@ -0,0 +1,178 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* cyttsp_i2c.c
|
||||
* Cypress TrueTouch(TM) Standard Product (TTSP) I2C touchscreen driver.
|
||||
* For use with Cypress Txx4xx parts.
|
||||
* Supported parts include:
|
||||
* TMA4XX
|
||||
* TMA1036
|
||||
*
|
||||
* Copyright (C) 2009, 2010, 2011 Cypress Semiconductor, Inc.
|
||||
* Copyright (C) 2012 Javier Martinez Canillas <javier@dowhile0.org>
|
||||
* Copyright (C) 2013 Cypress Semiconductor
|
||||
*
|
||||
* Contact Cypress Semiconductor at www.cypress.com <ttdrivers@cypress.com>
|
||||
*/
|
||||
|
||||
#include "cyttsp4_core.h"
|
||||
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#define CYTTSP4_I2C_DATA_SIZE (3 * 256)
|
||||
|
||||
static int cyttsp4_i2c_read_block_data(struct device *dev, u8 *xfer_buf,
|
||||
u16 addr, u8 length, void *values)
|
||||
{
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
int rc;
|
||||
|
||||
xfer_buf[0] = addr;
|
||||
rc = i2c_master_send(client, xfer_buf, 1);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
rc = i2c_master_recv(client, values, length);
|
||||
return rc < 0 ? rc : 0;
|
||||
}
|
||||
|
||||
static int cyttsp4_i2c_write_block_data(struct device *dev, u8 *xfer_buf,
|
||||
u16 addr, u8 length, const void *values)
|
||||
{
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
|
||||
xfer_buf[0] = addr;
|
||||
memcpy(&xfer_buf[1], values, length);
|
||||
return i2c_master_send(client, xfer_buf, length + 1) < 0 ? -EIO : 0;
|
||||
}
|
||||
|
||||
static const struct cyttsp4_bus_ops cyttsp4_i2c_bus_ops = {
|
||||
.bustype = BUS_I2C,
|
||||
.write = cyttsp4_i2c_write_block_data,
|
||||
.read = cyttsp4_i2c_read_block_data,
|
||||
};
|
||||
|
||||
static const int16_t cyttsp4_abs[] = {
|
||||
ABS_MT_POSITION_X, 0, 758, 0, 0,
|
||||
ABS_MT_POSITION_Y, 0, 1024, 0, 0,
|
||||
ABS_MT_PRESSURE, 0, 255, 0, 0,
|
||||
ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0,
|
||||
ABS_MT_TRACKING_ID, 0, 15, 0, 0,
|
||||
CY_IGNORE_VALUE, 0, 255, 0, 0,
|
||||
CY_IGNORE_VALUE, 0, 255, 0, 0,
|
||||
CY_IGNORE_VALUE, -128, 127, 0, 0,
|
||||
};
|
||||
|
||||
static struct touch_framework cyttsp4_framework = {
|
||||
.abs = cyttsp4_abs,
|
||||
.size = ARRAY_SIZE(cyttsp4_abs),
|
||||
.enable_vkeys = 0,
|
||||
};
|
||||
|
||||
static int cyttsp4_xres(struct cyttsp4_core_platform_data *pdata,
|
||||
struct device *dev)
|
||||
{
|
||||
int rst_gpio = pdata->rst_gpio;
|
||||
|
||||
gpio_set_value(rst_gpio, 1);
|
||||
msleep(20);
|
||||
gpio_set_value(rst_gpio, 0);
|
||||
msleep(40);
|
||||
gpio_set_value(rst_gpio, 1);
|
||||
msleep(20);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cyttsp4_i2c_probe(struct i2c_client *client)
|
||||
{
|
||||
struct cyttsp4_platform_data *pdata;
|
||||
struct cyttsp4_core_platform_data *core_pdata;
|
||||
struct cyttsp4_mt_platform_data *mt_pdata;
|
||||
struct gpio_desc *irq_desc, *rst_desc;
|
||||
struct cyttsp4 *ts;
|
||||
|
||||
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
|
||||
dev_err(&client->dev, "I2C functionality not Supported\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL);
|
||||
core_pdata = devm_kzalloc(&client->dev, sizeof(*core_pdata), GFP_KERNEL);
|
||||
mt_pdata = devm_kzalloc(&client->dev, sizeof(*mt_pdata), GFP_KERNEL);
|
||||
if (!pdata || !core_pdata || !mt_pdata)
|
||||
return -ENOMEM;
|
||||
|
||||
irq_desc = devm_gpiod_get(&client->dev, "irq", GPIOD_IN);
|
||||
if (IS_ERR(irq_desc))
|
||||
return PTR_ERR(irq_desc);
|
||||
|
||||
rst_desc = devm_gpiod_get(&client->dev, "reset", GPIOD_OUT_HIGH);
|
||||
if (IS_ERR(rst_desc))
|
||||
return PTR_ERR(rst_desc);
|
||||
|
||||
core_pdata->irq_gpio = desc_to_gpio(irq_desc);
|
||||
core_pdata->rst_gpio = desc_to_gpio(rst_desc);
|
||||
mt_pdata->inp_dev_name = CYTTSP4_MT_NAME;
|
||||
|
||||
|
||||
mt_pdata->frmwrk = &cyttsp4_framework;
|
||||
|
||||
pdata->core_pdata = core_pdata;
|
||||
pdata->mt_pdata = mt_pdata;
|
||||
client->dev.platform_data = pdata;
|
||||
|
||||
/* Reset the touch controller */
|
||||
gpiod_set_value(rst_desc, 1);
|
||||
msleep(20);
|
||||
gpiod_set_value(rst_desc, 0);
|
||||
msleep(40);
|
||||
gpiod_set_value(rst_desc, 1);
|
||||
msleep(20);
|
||||
|
||||
core_pdata->xres = cyttsp4_xres;
|
||||
|
||||
ts = cyttsp4_probe(&cyttsp4_i2c_bus_ops, &client->dev, client->irq,
|
||||
CYTTSP4_I2C_DATA_SIZE);
|
||||
|
||||
return PTR_ERR_OR_ZERO(ts);
|
||||
}
|
||||
|
||||
static void cyttsp4_i2c_remove(struct i2c_client *client)
|
||||
{
|
||||
struct cyttsp4 *ts = i2c_get_clientdata(client);
|
||||
|
||||
cyttsp4_remove(ts);
|
||||
}
|
||||
|
||||
#define CYTTSP4_I2C_NAME "cyttsp4_i2c_adapter"
|
||||
|
||||
static const struct i2c_device_id cyttsp4_i2c_id[] = {
|
||||
{ CYTTSP4_I2C_NAME, 0 },
|
||||
{ }
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(i2c, cyttsp4_i2c_id);
|
||||
|
||||
static const struct of_device_id cyttsp4_of_match[] = {
|
||||
{ .compatible = "cypress,cyttsp4-i2c", },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, cyttsp4_of_match);
|
||||
|
||||
static struct i2c_driver cyttsp4_i2c_driver = {
|
||||
.driver = {
|
||||
.name = CYTTSP4_I2C_NAME,
|
||||
.of_match_table = cyttsp4_of_match,
|
||||
.pm = &cyttsp4_pm_ops,
|
||||
},
|
||||
.probe = cyttsp4_i2c_probe,
|
||||
.remove = cyttsp4_i2c_remove,
|
||||
.id_table = cyttsp4_i2c_id,
|
||||
};
|
||||
|
||||
module_i2c_driver(cyttsp4_i2c_driver);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("Cypress TrueTouch(R) Standard Product (TTSP) I2C driver");
|
||||
MODULE_AUTHOR("Cypress");
|
||||
187
drivers/input/touchscreen/cyttsp4_spi.c
Normal file
187
drivers/input/touchscreen/cyttsp4_spi.c
Normal file
@@ -0,0 +1,187 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Source for:
|
||||
* Cypress TrueTouch(TM) Standard Product (TTSP) SPI touchscreen driver.
|
||||
* For use with Cypress Txx4xx parts.
|
||||
* Supported parts include:
|
||||
* TMA4XX
|
||||
* TMA1036
|
||||
*
|
||||
* Copyright (C) 2009, 2010, 2011 Cypress Semiconductor, Inc.
|
||||
* Copyright (C) 2012 Javier Martinez Canillas <javier@dowhile0.org>
|
||||
* Copyright (C) 2013 Cypress Semiconductor
|
||||
*
|
||||
* Contact Cypress Semiconductor at www.cypress.com <ttdrivers@cypress.com>
|
||||
*/
|
||||
|
||||
#include "cyttsp4_core.h"
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/spi/spi.h>
|
||||
|
||||
#define CY_SPI_WR_OP 0x00 /* r/~w */
|
||||
#define CY_SPI_RD_OP 0x01
|
||||
#define CY_SPI_BITS_PER_WORD 8
|
||||
#define CY_SPI_A8_BIT 0x02
|
||||
#define CY_SPI_WR_HEADER_BYTES 2
|
||||
#define CY_SPI_RD_HEADER_BYTES 1
|
||||
#define CY_SPI_CMD_BYTES 2
|
||||
#define CY_SPI_SYNC_BYTE 0
|
||||
#define CY_SPI_SYNC_ACK 0x62 /* from TRM *A protocol */
|
||||
#define CY_SPI_DATA_SIZE (2 * 256)
|
||||
|
||||
#define CY_SPI_DATA_BUF_SIZE (CY_SPI_CMD_BYTES + CY_SPI_DATA_SIZE)
|
||||
|
||||
static int cyttsp_spi_xfer(struct device *dev, u8 *xfer_buf,
|
||||
u8 op, u16 reg, u8 *buf, int length)
|
||||
{
|
||||
struct spi_device *spi = to_spi_device(dev);
|
||||
struct spi_message msg;
|
||||
struct spi_transfer xfer[2];
|
||||
u8 *wr_buf = &xfer_buf[0];
|
||||
u8 rd_buf[CY_SPI_CMD_BYTES];
|
||||
int retval;
|
||||
int i;
|
||||
|
||||
if (length > CY_SPI_DATA_SIZE) {
|
||||
dev_err(dev, "%s: length %d is too big.\n",
|
||||
__func__, length);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
memset(wr_buf, 0, CY_SPI_DATA_BUF_SIZE);
|
||||
memset(rd_buf, 0, CY_SPI_CMD_BYTES);
|
||||
|
||||
wr_buf[0] = op + (((reg >> 8) & 0x1) ? CY_SPI_A8_BIT : 0);
|
||||
if (op == CY_SPI_WR_OP) {
|
||||
wr_buf[1] = reg & 0xFF;
|
||||
if (length > 0)
|
||||
memcpy(wr_buf + CY_SPI_CMD_BYTES, buf, length);
|
||||
}
|
||||
|
||||
memset(xfer, 0, sizeof(xfer));
|
||||
spi_message_init(&msg);
|
||||
|
||||
/*
|
||||
We set both TX and RX buffers because Cypress TTSP
|
||||
requires full duplex operation.
|
||||
*/
|
||||
xfer[0].tx_buf = wr_buf;
|
||||
xfer[0].rx_buf = rd_buf;
|
||||
switch (op) {
|
||||
case CY_SPI_WR_OP:
|
||||
xfer[0].len = length + CY_SPI_CMD_BYTES;
|
||||
spi_message_add_tail(&xfer[0], &msg);
|
||||
break;
|
||||
|
||||
case CY_SPI_RD_OP:
|
||||
xfer[0].len = CY_SPI_RD_HEADER_BYTES;
|
||||
spi_message_add_tail(&xfer[0], &msg);
|
||||
|
||||
xfer[1].rx_buf = buf;
|
||||
xfer[1].len = length;
|
||||
spi_message_add_tail(&xfer[1], &msg);
|
||||
break;
|
||||
|
||||
default:
|
||||
dev_err(dev, "%s: bad operation code=%d\n", __func__, op);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
retval = spi_sync(spi, &msg);
|
||||
if (retval < 0) {
|
||||
dev_dbg(dev, "%s: spi_sync() error %d, len=%d, op=%d\n",
|
||||
__func__, retval, xfer[1].len, op);
|
||||
|
||||
/*
|
||||
* do not return here since was a bad ACK sequence
|
||||
* let the following ACK check handle any errors and
|
||||
* allow silent retries
|
||||
*/
|
||||
}
|
||||
|
||||
if (rd_buf[CY_SPI_SYNC_BYTE] != CY_SPI_SYNC_ACK) {
|
||||
dev_dbg(dev, "%s: operation %d failed\n", __func__, op);
|
||||
|
||||
for (i = 0; i < CY_SPI_CMD_BYTES; i++)
|
||||
dev_dbg(dev, "%s: test rd_buf[%d]:0x%02x\n",
|
||||
__func__, i, rd_buf[i]);
|
||||
for (i = 0; i < length; i++)
|
||||
dev_dbg(dev, "%s: test buf[%d]:0x%02x\n",
|
||||
__func__, i, buf[i]);
|
||||
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cyttsp_spi_read_block_data(struct device *dev, u8 *xfer_buf,
|
||||
u16 addr, u8 length, void *data)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = cyttsp_spi_xfer(dev, xfer_buf, CY_SPI_WR_OP, addr, NULL, 0);
|
||||
if (rc)
|
||||
return rc;
|
||||
else
|
||||
return cyttsp_spi_xfer(dev, xfer_buf, CY_SPI_RD_OP, addr, data,
|
||||
length);
|
||||
}
|
||||
|
||||
static int cyttsp_spi_write_block_data(struct device *dev, u8 *xfer_buf,
|
||||
u16 addr, u8 length, const void *data)
|
||||
{
|
||||
return cyttsp_spi_xfer(dev, xfer_buf, CY_SPI_WR_OP, addr, (void *)data,
|
||||
length);
|
||||
}
|
||||
|
||||
static const struct cyttsp4_bus_ops cyttsp_spi_bus_ops = {
|
||||
.bustype = BUS_SPI,
|
||||
.write = cyttsp_spi_write_block_data,
|
||||
.read = cyttsp_spi_read_block_data,
|
||||
};
|
||||
|
||||
static int cyttsp4_spi_probe(struct spi_device *spi)
|
||||
{
|
||||
struct cyttsp4 *ts;
|
||||
int error;
|
||||
|
||||
/* Set up SPI*/
|
||||
spi->bits_per_word = CY_SPI_BITS_PER_WORD;
|
||||
spi->mode = SPI_MODE_0;
|
||||
error = spi_setup(spi);
|
||||
if (error < 0) {
|
||||
dev_err(&spi->dev, "%s: SPI setup error %d\n",
|
||||
__func__, error);
|
||||
return error;
|
||||
}
|
||||
|
||||
ts = cyttsp4_probe(&cyttsp_spi_bus_ops, &spi->dev, spi->irq,
|
||||
CY_SPI_DATA_BUF_SIZE);
|
||||
|
||||
return PTR_ERR_OR_ZERO(ts);
|
||||
}
|
||||
|
||||
static void cyttsp4_spi_remove(struct spi_device *spi)
|
||||
{
|
||||
struct cyttsp4 *ts = spi_get_drvdata(spi);
|
||||
cyttsp4_remove(ts);
|
||||
}
|
||||
|
||||
static struct spi_driver cyttsp4_spi_driver = {
|
||||
.driver = {
|
||||
.name = CYTTSP4_SPI_NAME,
|
||||
.pm = &cyttsp4_pm_ops,
|
||||
},
|
||||
.probe = cyttsp4_spi_probe,
|
||||
.remove = cyttsp4_spi_remove,
|
||||
};
|
||||
|
||||
module_spi_driver(cyttsp4_spi_driver);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("Cypress TrueTouch(R) Standard Product (TTSP) SPI driver");
|
||||
MODULE_AUTHOR("Cypress");
|
||||
MODULE_ALIAS("spi:cyttsp4");
|
||||
@@ -916,6 +916,20 @@ config MFD_MAX77693
|
||||
additional drivers must be enabled in order to use the functionality
|
||||
of the device.
|
||||
|
||||
config MFD_MAX77696
|
||||
tristate "Maxim MAX77696 PMIC Support"
|
||||
depends on I2C
|
||||
depends on OF
|
||||
select MFD_CORE
|
||||
select REGMAP_I2C
|
||||
help
|
||||
Say Y here to add support for Maxim Semiconductor MAX77696
|
||||
Power Management ICs. This is the core multifunction
|
||||
driver for interacting with the device. The module name is
|
||||
'max77696'. Additional drivers can be enabled in order to use
|
||||
the following functionalities of the device: GPIO, regulator,
|
||||
charger, LED.
|
||||
|
||||
config MFD_MAX77705
|
||||
tristate "Maxim MAX77705 PMIC Support"
|
||||
depends on I2C
|
||||
|
||||
@@ -167,6 +167,7 @@ obj-$(CONFIG_MFD_MAX77620) += max77620.o
|
||||
obj-$(CONFIG_MFD_MAX77650) += max77650.o
|
||||
obj-$(CONFIG_MFD_MAX77686) += max77686.o
|
||||
obj-$(CONFIG_MFD_MAX77693) += max77693.o
|
||||
obj-$(CONFIG_MFD_MAX77696) += max77696.o
|
||||
obj-$(CONFIG_MFD_MAX77705) += max77705.o
|
||||
obj-$(CONFIG_MFD_MAX77714) += max77714.o
|
||||
obj-$(CONFIG_MFD_MAX77843) += max77843.o
|
||||
|
||||
84
drivers/mfd/max77696.c
Normal file
84
drivers/mfd/max77696.c
Normal file
@@ -0,0 +1,84 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
//
|
||||
// Copyright (C) 2026 smallsoalr
|
||||
// Author: smallsolar <solarcene@protonmail.com>
|
||||
//
|
||||
// Core MFD driver for MAXIM 77696 power-supply.
|
||||
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/mfd/core.h>
|
||||
#include <linux/mfd/max77696.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
static const struct mfd_cell max77696_cells[] = {
|
||||
{
|
||||
.name = "max77696-regulator",
|
||||
.of_compatible = "maxim,max77696-regulator",
|
||||
}, {
|
||||
.name = "max77696-epd",
|
||||
.of_compatible = "maxim,max77696-epd",
|
||||
}, {
|
||||
.name = "max77696-wled",
|
||||
.of_compatible = "maxim,max77696-wled",
|
||||
},
|
||||
};
|
||||
|
||||
static const struct regmap_config max77696_regmap_config = {
|
||||
.name = "max77696",
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
};
|
||||
|
||||
static int max77696_i2c_probe(struct i2c_client *client)
|
||||
{
|
||||
struct max77696 *chip;
|
||||
unsigned int val;
|
||||
int rv;
|
||||
|
||||
chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
|
||||
if (!chip)
|
||||
return -ENOMEM;
|
||||
|
||||
chip->dev = &client->dev;
|
||||
i2c_set_clientdata(client, chip);
|
||||
|
||||
chip->regmap = devm_regmap_init_i2c(client, &max77696_regmap_config);
|
||||
if (IS_ERR(chip->regmap)) {
|
||||
dev_err(chip->dev, "Unable to initialise I2C Regmap\n");
|
||||
return PTR_ERR(chip->regmap);
|
||||
}
|
||||
|
||||
rv = regmap_read(chip->regmap, MAX77696_REG_CID, &val);
|
||||
if (rv) {
|
||||
dev_err(chip->dev, "Unable to read Chip ID\n");
|
||||
return rv;
|
||||
}
|
||||
|
||||
dev_info(chip->dev, "Chip Detected ID: 0x%02x\n", val);
|
||||
|
||||
return devm_mfd_add_devices(chip->dev, PLATFORM_DEVID_NONE,
|
||||
max77696_cells, ARRAY_SIZE(max77696_cells),
|
||||
NULL, 0, NULL);
|
||||
}
|
||||
|
||||
static const struct of_device_id max77696_of_match[] = {
|
||||
{ .compatible = "maxim,max77696" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, max77696_of_match);
|
||||
|
||||
static struct i2c_driver max77696_i2c_driver = {
|
||||
.driver = {
|
||||
.name = "max77696",
|
||||
.of_match_table = max77696_of_match,
|
||||
},
|
||||
.probe = max77696_i2c_probe,
|
||||
};
|
||||
module_i2c_driver(max77696_i2c_driver);
|
||||
|
||||
MODULE_DESCRIPTION("MAXIM 77696 multi-function core driver");
|
||||
MODULE_AUTHOR("smallsolar <solarcene@protonmail.com>");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
@@ -747,6 +747,12 @@ config REGULATOR_MAX77693
|
||||
and one current regulator 'CHARGER'. This is suitable for
|
||||
Exynos-4x12 (MAX77693) or Exynos5433 (MAX77843) SoC chips.
|
||||
|
||||
config REGULATOR_MAX77696
|
||||
tristate "Maxim 77696 regulator"
|
||||
depends on MFD_MAX77696 || COMPILE_TEST
|
||||
help
|
||||
This driver controls a Maxim 77693/77843 regulators via I2C bus.
|
||||
|
||||
config REGULATOR_MAX77802
|
||||
tristate "Maxim 77802 regulator"
|
||||
depends on MFD_MAX77686 || COMPILE_TEST
|
||||
|
||||
@@ -89,6 +89,7 @@ obj-$(CONFIG_REGULATOR_MAX20086) += max20086-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_MAX20411) += max20411-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_MAX77686) += max77686-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_MAX77693) += max77693-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_MAX77696) += max77696-epd.o
|
||||
obj-$(CONFIG_REGULATOR_MAX77802) += max77802-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_MAX77826) += max77826-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_MAX77857) += max77857-regulator.o
|
||||
|
||||
236
drivers/regulator/max77696-epd.c
Normal file
236
drivers/regulator/max77696-epd.c
Normal file
@@ -0,0 +1,236 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* MAX77696 EPD (E-Paper Display) power supply driver
|
||||
*
|
||||
* Drives the EPD regulator block of the MAX77696 PMIC.
|
||||
* Registers DISPLAY, VCOM and V3P3 regulators needed by
|
||||
* the i.MX6SL EPDC driver.
|
||||
*
|
||||
* Copyright (C) 2026 smallsolar <solarcene@protonmail.com>
|
||||
*/
|
||||
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/mfd/max77696.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regulator/driver.h>
|
||||
#include <linux/regulator/machine.h>
|
||||
#include <linux/regulator/of_regulator.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
enum {
|
||||
MAX77696_EPD_DISPLAY,
|
||||
MAX77696_EPD_VCOM,
|
||||
MAX77696_EPD_V3P3,
|
||||
MAX77696_EPD_NUM_REGS,
|
||||
};
|
||||
|
||||
/*
|
||||
* max77696_epd_vcom_enable - enable VCOM with fault detection and retry.
|
||||
*
|
||||
* EPDINT (0x62) is read-to-clear: a single read both samples and clears
|
||||
* the fault bit, so no separate clear step is needed.
|
||||
*
|
||||
* Called by the regulator core as the .enable op for VCOM only.
|
||||
* DISPLAY and V3P3 use the generic regmap enable op.
|
||||
*/
|
||||
static int max77696_vcom_enable(struct regulator_dev *rdev)
|
||||
{
|
||||
|
||||
struct max77696 *chip = rdev_get_drvdata(rdev);
|
||||
struct regmap *regmap = chip->regmap;
|
||||
struct device *dev = chip->dev;
|
||||
|
||||
unsigned int val;
|
||||
int i, ret;
|
||||
|
||||
for (i = 0; i < MAX77696_EPD_VCOM_FAULT_RETRIES; i++) {
|
||||
/* Enable VCOM via the standard regmap bit */
|
||||
ret = regulator_enable_regmap(rdev);
|
||||
if (ret) {
|
||||
dev_err(dev, "VCOM enable failed (attempt %d): %d\n",
|
||||
i + 1, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
msleep(MAX77696_EPD_VCOM_SETTLE_MS);
|
||||
|
||||
/*
|
||||
* Read EPDINT. This is read-to-clear, so a single read
|
||||
* both samples and clears the fault status.
|
||||
*/
|
||||
ret = regmap_read(regmap, EPDINT_REG, &val);
|
||||
if (ret) {
|
||||
dev_err(dev, "EPDINT read failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!(val & EPDINT_VCOM_FAULT)) {
|
||||
if (i > 0)
|
||||
dev_info(dev,
|
||||
"VCOM stable after %d attempt(s)\n",
|
||||
i + 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
dev_warn(chip->dev,
|
||||
"VCOM fault detected (EPDINT=0x%02x), "
|
||||
"retrying (%d/%d)\n",
|
||||
val, i + 1, MAX77696_EPD_VCOM_FAULT_RETRIES);
|
||||
|
||||
ret = regulator_disable_regmap(rdev);
|
||||
if (ret) {
|
||||
dev_err(dev, "VCOM disable (for retry) failed: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
msleep(MAX77696_EPD_VCOM_RETRY_DELAY_MS);
|
||||
}
|
||||
|
||||
dev_err(dev,
|
||||
"VCOM failed to stabilise after %d attempts; "
|
||||
"last EPDINT=0x%02x\n",
|
||||
MAX77696_EPD_VCOM_FAULT_RETRIES, val);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
static const struct regulator_ops max77696_regmap_ops = {
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
};
|
||||
|
||||
static const struct regulator_ops max77696_vcom_ops = {
|
||||
.enable = max77696_vcom_enable,
|
||||
.disable = regulator_disable_regmap,
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
};
|
||||
|
||||
static const struct regulator_desc max77696_regs[] = {
|
||||
[MAX77696_EPD_DISPLAY] = {
|
||||
.name = "DISPLAY",
|
||||
.of_match = "DISPLAY",
|
||||
.regulators_node = "regulators",
|
||||
.id = MAX77696_EPD_DISPLAY,
|
||||
.ops = &max77696_regmap_ops,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
.enable_reg = EPDCNFG_REG,
|
||||
.enable_mask = EPDCNFG_EPDEN,
|
||||
},
|
||||
[MAX77696_EPD_VCOM] = {
|
||||
.name = "VCOM",
|
||||
.of_match = "VCOM",
|
||||
.regulators_node = "regulators",
|
||||
.id = MAX77696_EPD_VCOM,
|
||||
.ops = &max77696_vcom_ops, /* fault-aware enable */
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
.enable_reg = EPDCNFG_REG,
|
||||
.enable_mask = EPDCNFG_VCOMEN,
|
||||
},
|
||||
[MAX77696_EPD_V3P3] = {
|
||||
.name = "V3P3",
|
||||
.of_match = "V3P3",
|
||||
.regulators_node = "regulators",
|
||||
.id = MAX77696_EPD_V3P3,
|
||||
.ops = &max77696_regmap_ops,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
.enable_reg = EPDCNFG_REG,
|
||||
.enable_mask = EPDCNFG_SSHVDDH,
|
||||
},
|
||||
};
|
||||
|
||||
static int max77696_regulator_probe(struct platform_device *pdev)
|
||||
{
|
||||
|
||||
struct max77696 *chip = dev_get_drvdata(pdev->dev.parent);
|
||||
struct regulator_config config = { };
|
||||
struct regulator_dev *rdev;
|
||||
|
||||
unsigned int vcom_val, vcomr_val, lsw4;
|
||||
|
||||
int i, ret;
|
||||
|
||||
config.dev = &pdev->dev;
|
||||
config.regmap = chip->regmap;
|
||||
config.driver_data = chip;
|
||||
|
||||
|
||||
dev_info(&pdev->dev, "of_node = %pOF\n", pdev->dev.of_node);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(max77696_regs); i++) {
|
||||
rdev = devm_regulator_register(&pdev->dev, &max77696_regs[i], &config);
|
||||
|
||||
if (IS_ERR(rdev))
|
||||
return dev_err_probe(chip->dev, PTR_ERR(rdev),
|
||||
"register %s failed\n",
|
||||
max77696_regs[i].name);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set VCOM to its factory-calibrated voltage. Written unconditionally
|
||||
* at probe, independent of enable state, matching the vendor driver's
|
||||
* behaviour of voltage being a separate concern from enable/disable.
|
||||
*/
|
||||
ret = regmap_update_bits(chip->regmap, EPDVCOMR_REG, EPDVCOMR_VCOMR, EPDVCOMR_VCOMR);
|
||||
if (ret)
|
||||
return dev_err_probe(chip->dev, ret, "failed to set VCOMR\n");
|
||||
|
||||
ret = regmap_write(chip->regmap, EPDVCOM_REG, VCOM_CAL_REG_VALUE);
|
||||
if (ret)
|
||||
return dev_err_probe(chip->dev, ret, "failed to set VCOM calibration\n");
|
||||
|
||||
|
||||
regmap_read(chip->regmap, EPDVCOM_REG, &vcom_val);
|
||||
regmap_read(chip->regmap, EPDVCOMR_REG, &vcomr_val);
|
||||
dev_info(chip->dev, "VCOM readback: EPDVCOM=0x%02x EPDVCOMR=0x%02x\n",
|
||||
vcom_val, vcomr_val & EPDVCOMR_VCOMR);
|
||||
|
||||
/* Enable LSW4 (DISP_GATED) — gates 3.3V to panel logic on Muscat WFO.
|
||||
* LSW4 = DISP_GATED-old per board-mx6sl_wario.c MAX77696_VREG_CONSUMERS.
|
||||
*/
|
||||
ret = regmap_update_bits(chip->regmap, LSW4_CNTRL_REG, LSW4_OUTLS, LSW4_OUTLS);
|
||||
if (ret)
|
||||
return dev_err_probe(chip->dev, ret, "failed to enable LSW4 (DISP_GATED)\n");
|
||||
|
||||
/* Verify LSW4 enable latched */
|
||||
regmap_read(chip->regmap, LSW4_CNTRL_REG, &lsw4);
|
||||
dev_info(chip->dev, "LSW4: 0x%02x\n", lsw4);
|
||||
|
||||
dev_info(chip->dev, "MAX77696 v0.8 EPD regulators registered (VCOM=%d uV)\n",
|
||||
(VCOM_CAL_REG_VALUE + 0xFF) * 9985);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id max77696_regulator_of_match[] = {
|
||||
{ .compatible = "maxim,max77696-epd" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, max77696_regulator_of_match);
|
||||
|
||||
static const struct platform_device_id max77696_regulator_id[] = {
|
||||
{ "max77696-epd", 0 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(platform, max77696_regulator_id);
|
||||
|
||||
static struct platform_driver max77696_regulator_driver = {
|
||||
.driver = {
|
||||
.name = "max77696-epd",
|
||||
.of_match_table = max77696_regulator_of_match,
|
||||
},
|
||||
.probe = max77696_regulator_probe,
|
||||
.id_table = max77696_regulator_id,
|
||||
};
|
||||
module_platform_driver(max77696_regulator_driver);
|
||||
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_DESCRIPTION("MAX77696 EPD power supply driver");
|
||||
MODULE_AUTHOR("smallsolar");
|
||||
@@ -262,6 +262,12 @@ config BACKLIGHT_DA9052
|
||||
help
|
||||
Enable the Backlight Driver for DA9052-BC and DA9053-AA/Bx PMICs.
|
||||
|
||||
config BACKLIGHT_MAX77696
|
||||
tristate "Backlight driver for MAX77696"
|
||||
depends on MFD_MAX77696 || COMPILE_TEST
|
||||
help
|
||||
Enable driver for MAX77696 Front WLEDs (Kindle PW3).
|
||||
|
||||
config BACKLIGHT_MAX8925
|
||||
tristate "Backlight driver for MAX8925"
|
||||
depends on MFD_MAX8925
|
||||
|
||||
@@ -46,6 +46,7 @@ obj-$(CONFIG_BACKLIGHT_LP855X) += lp855x_bl.o
|
||||
obj-$(CONFIG_BACKLIGHT_LP8788) += lp8788_bl.o
|
||||
obj-$(CONFIG_BACKLIGHT_LV5207LP) += lv5207lp.o
|
||||
obj-$(CONFIG_BACKLIGHT_MAX8925) += max8925_bl.o
|
||||
obj-$(CONFIG_BACKLIGHT_MAX77696) += max77696-wled.o
|
||||
obj-$(CONFIG_BACKLIGHT_MP3309C) += mp3309c.o
|
||||
obj-$(CONFIG_BACKLIGHT_MT6370) += mt6370-backlight.o
|
||||
obj-$(CONFIG_BACKLIGHT_OMAP1) += omap1_bl.o
|
||||
|
||||
201
drivers/video/backlight/max77696-wled.c
Normal file
201
drivers/video/backlight/max77696-wled.c
Normal file
@@ -0,0 +1,201 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* MAX77696 WLED Backlight Driver
|
||||
*
|
||||
* Controls the WLED boost regulator block of the MAX77696 PMIC,
|
||||
* used as the frontlight driver on the Amazon Kindle Paperwhite 3
|
||||
* (Wario/Muscat platform).
|
||||
*
|
||||
* Register map (from vendor kernel):
|
||||
* 0x6C LEDBST_CNTRL1 — bit 7 = LED1EN (boost + LED enable)
|
||||
* 0x6D LED1CURRENT_1 — bits 11:4 of 12-bit current DAC (MSB)
|
||||
* 0x6E LED1CURRENT_2 — bits 3:0 of 12-bit current DAC (LSB)
|
||||
*
|
||||
* Brightness is a 12-bit value (0–4095). The stock driver uses
|
||||
* DUET_FL_LEVEL12_MID = 240 as the default brightness on Muscat WFO.
|
||||
*
|
||||
* Copyright (C) 2026 smallsolar <solarcene@protonmail.com>
|
||||
*/
|
||||
|
||||
#include <linux/backlight.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/mfd/max77696.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
/*
|
||||
* Default brightness on probe: DUET_FL_LEVEL12_MID from vendor
|
||||
* frontlight.h. Matches the stock kernel's initial setting on
|
||||
* Muscat WFO (KPW3). Set to 0 to start with backlight off.
|
||||
*/
|
||||
#define MAX77696_BL_DEFAULT_BRIGHTNESS 240
|
||||
|
||||
struct max77696_bl {
|
||||
struct regmap *regmap;
|
||||
struct device *dev;
|
||||
int brightness;
|
||||
};
|
||||
|
||||
/*
|
||||
* max77696_bl_set - write brightness to hardware.
|
||||
*
|
||||
* Brightness is a 12-bit value split across two registers:
|
||||
* LED1CURRENT_1 = bits 11:4 (upper 8 bits)
|
||||
* LED1CURRENT_2 = bits 3:0 (lower 4 bits)
|
||||
*
|
||||
* At brightness=0, disable the boost converter (LED1EN=0).
|
||||
* At brightness>0, write current registers then enable (LED1EN=1).
|
||||
* This matches the sequence in the vendor max77696_bl_set().
|
||||
*/
|
||||
static int max77696_bl_set(struct max77696_bl *bl, int brightness)
|
||||
{
|
||||
int ret;
|
||||
|
||||
brightness = clamp(brightness,
|
||||
MAX77696_BL_MIN_BRIGHTNESS,
|
||||
MAX77696_BL_MAX_BRIGHTNESS);
|
||||
|
||||
if (brightness == MAX77696_BL_MIN_BRIGHTNESS) {
|
||||
/* Disable boost converter */
|
||||
ret = regmap_update_bits(bl->regmap, LEDBST_CNTRL1_REG,
|
||||
LEDBST_CNTRL1_LED1EN, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
bl->brightness = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Write 12-bit brightness: MSB in LED1CURRENT_1, LSB in LED1CURRENT_2 */
|
||||
ret = regmap_write(bl->regmap, LED1CURRENT_1_REG,
|
||||
(brightness >> 4) & 0xFF);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = regmap_write(bl->regmap, LED1CURRENT_2_REG,
|
||||
brightness & 0x0F);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Enable boost converter */
|
||||
ret = regmap_update_bits(bl->regmap, LEDBST_CNTRL1_REG,
|
||||
LEDBST_CNTRL1_LED1EN, LEDBST_CNTRL1_LED1EN);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
bl->brightness = brightness;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int max77696_bl_update_status(struct backlight_device *bd)
|
||||
{
|
||||
struct max77696_bl *bl = bl_get_data(bd);
|
||||
int brightness = backlight_get_brightness(bd);
|
||||
|
||||
return max77696_bl_set(bl, brightness);
|
||||
}
|
||||
|
||||
static int max77696_bl_get_brightness(struct backlight_device *bd)
|
||||
{
|
||||
struct max77696_bl *bl = bl_get_data(bd);
|
||||
unsigned int msb, lsb, enabled;
|
||||
int ret;
|
||||
|
||||
ret = regmap_read(bl->regmap, LEDBST_CNTRL1_REG, &enabled);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!(enabled & LEDBST_CNTRL1_LED1EN))
|
||||
return 0;
|
||||
|
||||
ret = regmap_read(bl->regmap, LED1CURRENT_1_REG, &msb);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = regmap_read(bl->regmap, LED1CURRENT_2_REG, &lsb);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return (msb << 4) | (lsb & 0x0F);
|
||||
}
|
||||
|
||||
static const struct backlight_ops max77696_bl_ops = {
|
||||
.options = BL_CORE_SUSPENDRESUME,
|
||||
.update_status = max77696_bl_update_status,
|
||||
.get_brightness = max77696_bl_get_brightness,
|
||||
};
|
||||
|
||||
static int max77696_bl_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct max77696 *chip = dev_get_drvdata(pdev->dev.parent);
|
||||
|
||||
struct device *dev = &pdev->dev;
|
||||
struct max77696_bl *bl;
|
||||
struct backlight_device *bd;
|
||||
struct backlight_properties props = {
|
||||
.type = BACKLIGHT_RAW,
|
||||
.max_brightness = MAX77696_BL_MAX_BRIGHTNESS,
|
||||
.brightness = MAX77696_BL_DEFAULT_BRIGHTNESS,
|
||||
};
|
||||
u32 brightness;
|
||||
int ret;
|
||||
|
||||
bl = devm_kzalloc(dev, sizeof(*bl), GFP_KERNEL);
|
||||
if (!bl)
|
||||
return -ENOMEM;
|
||||
|
||||
bl->regmap = chip->regmap;
|
||||
bl->dev = dev;
|
||||
|
||||
/* Allow DT override of default brightness */
|
||||
if (!of_property_read_u32(dev->of_node, "default-brightness", &brightness))
|
||||
props.brightness = clamp_t(u32, brightness,
|
||||
MAX77696_BL_MIN_BRIGHTNESS,
|
||||
MAX77696_BL_MAX_BRIGHTNESS);
|
||||
|
||||
bd = devm_backlight_device_register(dev, "max77696-wled", dev, bl,
|
||||
&max77696_bl_ops, &props);
|
||||
if (IS_ERR(bd))
|
||||
return dev_err_probe(dev, PTR_ERR(bd),
|
||||
"backlight device register failed\n");
|
||||
|
||||
platform_set_drvdata(pdev, bd);
|
||||
|
||||
/* Apply initial brightness */
|
||||
ret = max77696_bl_set(bl, props.brightness);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret,
|
||||
"failed to set initial brightness\n");
|
||||
|
||||
dev_info(dev, "MAX77696 WLED backlight registered (brightness=%d/%d)\n",
|
||||
props.brightness, MAX77696_BL_MAX_BRIGHTNESS);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id max77696_bl_of_match[] = {
|
||||
{ .compatible = "maxim,max77696-wled" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, max77696_bl_of_match);
|
||||
|
||||
static const struct platform_device_id max77696_bl_id[] = {
|
||||
{ "max77696-wled", 0 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(platform, max77696_bl_id);
|
||||
|
||||
static struct platform_driver max77696_bl_driver = {
|
||||
.driver = {
|
||||
.name = "max77696-wled",
|
||||
.of_match_table = max77696_bl_of_match,
|
||||
},
|
||||
.probe = max77696_bl_probe,
|
||||
.id_table = max77696_bl_id,
|
||||
};
|
||||
module_platform_driver(max77696_bl_driver);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("MAX77696 WLED Backlight Driver");
|
||||
MODULE_AUTHOR("smallsolar");
|
||||
87
include/linux/mfd/max77696.h
Normal file
87
include/linux/mfd/max77696.h
Normal file
@@ -0,0 +1,87 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2026 smallsolar
|
||||
* Author: smallsolar
|
||||
*
|
||||
* Common definitions for MAXIM 77696 charger/power-supply.
|
||||
*/
|
||||
|
||||
#ifndef MAX77696_H
|
||||
#define MAX77696_H
|
||||
|
||||
#include <linux/bits.h>
|
||||
|
||||
struct max77696 {
|
||||
struct regmap *regmap;
|
||||
struct device *dev;
|
||||
};
|
||||
|
||||
#define MAX77696_REG_CID 0x0
|
||||
|
||||
#define EPDCNFG_REG 0x60
|
||||
#define EPDCNFG_EPDEN BIT(7)
|
||||
#define EPDCNFG_VCOMEN BIT(6)
|
||||
#define EPDCNFG_SSHVDDH BIT(1)
|
||||
|
||||
#define EPDVCOM_REG 0x64
|
||||
#define EPDVCOMR_REG 0xB4
|
||||
#define EPDVCOMR_VCOMR BIT(0)
|
||||
|
||||
/*
|
||||
* EPDINT (0x62) — interrupt/fault status register.
|
||||
* Bit 6 (0x40): VCOM fault. Set when VCOM rail fails to reach
|
||||
* target voltage. Cleared on read (read-to-clear behaviour confirmed
|
||||
* from stock kernel: max77696_epd_isr() does a single regmap_read
|
||||
* of EPDINT and acts on the result without a separate clear step).
|
||||
*
|
||||
* The stock driver retries up to MAX77696_EPD_VCOM_FAULT_RETRIES
|
||||
* times with a fixed inter-retry delay before giving up.
|
||||
*/
|
||||
|
||||
#define EPDINT_REG 0x62
|
||||
#define EPDINT_VCOM_FAULT BIT(6)
|
||||
#define MAX77696_EPD_VCOM_FAULT_RETRIES 5
|
||||
#define MAX77696_EPD_VCOM_SETTLE_MS 100
|
||||
#define MAX77696_EPD_VCOM_RETRY_DELAY_MS 100
|
||||
|
||||
/*
|
||||
* VCOM is a factory-calibrated, per-panel value (Amazon's stock driver
|
||||
* reads it from a dedicated SPI NOR flash chip on the panel module —
|
||||
* see panel_flash_spi / panel_get_vcom_str() in the vendor 3.0.35 kernel,
|
||||
* drivers/video/mxc/mxc_epdc_fb_lab126.c). Mainline has no driver for
|
||||
* that SPI flash yet, so this value is hardcoded from a one-time read
|
||||
* via the stock firmware's sysfs:
|
||||
* /sys/devices/platform/imx-i2c.0/i2c-0/0-003c/max77696-epd.0/vcom_microvolt
|
||||
* = 2476280 (µV magnitude; VCOM is a negative bias, per
|
||||
* reg_data[MAX77696_EPD_ID_EPDVCOM].neg_sign in the vendor
|
||||
* drivers/regulator/max77696-epd.c).
|
||||
*
|
||||
* Register encoding (from vendor max77696_epd_vcom_set_voltage()):
|
||||
* step_uV = 9985, value = round(target_uV / step_uV)
|
||||
* if (value >= 0xFF) { value -= 0xFF; EPDVCOMR.VCOMR = 1 }
|
||||
* else EPDVCOMR.VCOMR = 0
|
||||
* EPDVCOM = (u8)value
|
||||
*
|
||||
* 2476280 / 9985 = 248 exactly (248 * 9985 = 2476280, no rounding loss).
|
||||
* 248 < 0xFF, so VCOMR stays 0 and only EPDVCOM needs writing.
|
||||
*
|
||||
* THIS VALUE IS SPECIFIC TO THE PANEL THIS WAS CALIBRATED AGAINST.
|
||||
* Do not reuse on a different physical unit without re-reading its own
|
||||
* factory calibration first.
|
||||
*/
|
||||
#define VCOM_CAL_REG_VALUE 0x0B
|
||||
|
||||
#define LSW4_CNTRL_REG 0x5F
|
||||
#define LSW4_OUTLS BIT(0)
|
||||
|
||||
/* WLED register addresses */
|
||||
#define LEDBST_CNTRL1_REG 0x6C
|
||||
#define LEDBST_CNTRL1_LED1EN BIT(7) /* boost + LED enable */
|
||||
|
||||
#define LED1CURRENT_1_REG 0x6D /* bits 11:4 of brightness (MSB) */
|
||||
#define LED1CURRENT_2_REG 0x6E /* bits 3:0 of brightness (LSB) */
|
||||
|
||||
#define MAX77696_BL_MAX_BRIGHTNESS 0xFFF /* 12-bit DAC */
|
||||
#define MAX77696_BL_MIN_BRIGHTNESS 0
|
||||
|
||||
#endif /* MAX77696_H */
|
||||
62
include/linux/platform_data/cyttsp4.h
Normal file
62
include/linux/platform_data/cyttsp4.h
Normal file
@@ -0,0 +1,62 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Header file for:
|
||||
* Cypress TrueTouch(TM) Standard Product (TTSP) touchscreen drivers.
|
||||
* For use with Cypress Txx3xx parts.
|
||||
* Supported parts include:
|
||||
* CY8CTST341
|
||||
* CY8CTMA340
|
||||
*
|
||||
* Copyright (C) 2009, 2010, 2011 Cypress Semiconductor, Inc.
|
||||
* Copyright (C) 2012 Javier Martinez Canillas <javier@dowhile0.org>
|
||||
*
|
||||
* Contact Cypress Semiconductor at www.cypress.com (kev@cypress.com)
|
||||
*/
|
||||
#ifndef _CYTTSP4_H_
|
||||
#define _CYTTSP4_H_
|
||||
|
||||
#define CYTTSP4_MT_NAME "cyttsp4_mt"
|
||||
#define CYTTSP4_I2C_NAME "cyttsp4_i2c_adapter"
|
||||
#define CYTTSP4_SPI_NAME "cyttsp4_spi_adapter"
|
||||
|
||||
#define CY_TOUCH_SETTINGS_MAX 32
|
||||
|
||||
struct touch_framework {
|
||||
const uint16_t *abs;
|
||||
uint8_t size;
|
||||
uint8_t enable_vkeys;
|
||||
} __packed;
|
||||
|
||||
struct cyttsp4_mt_platform_data {
|
||||
struct touch_framework *frmwrk;
|
||||
unsigned short flags;
|
||||
char const *inp_dev_name;
|
||||
};
|
||||
|
||||
struct touch_settings {
|
||||
const uint8_t *data;
|
||||
uint32_t size;
|
||||
uint8_t tag;
|
||||
} __packed;
|
||||
|
||||
struct cyttsp4_core_platform_data {
|
||||
int irq_gpio;
|
||||
int rst_gpio;
|
||||
int level_irq_udelay;
|
||||
int (*xres)(struct cyttsp4_core_platform_data *pdata,
|
||||
struct device *dev);
|
||||
int (*init)(struct cyttsp4_core_platform_data *pdata,
|
||||
int on, struct device *dev);
|
||||
int (*power)(struct cyttsp4_core_platform_data *pdata,
|
||||
int on, struct device *dev, atomic_t *ignore_irq);
|
||||
int (*irq_stat)(struct cyttsp4_core_platform_data *pdata,
|
||||
struct device *dev);
|
||||
struct touch_settings *sett[CY_TOUCH_SETTINGS_MAX];
|
||||
};
|
||||
|
||||
struct cyttsp4_platform_data {
|
||||
struct cyttsp4_core_platform_data *core_pdata;
|
||||
struct cyttsp4_mt_platform_data *mt_pdata;
|
||||
};
|
||||
|
||||
#endif /* _CYTTSP4_H_ */
|
||||
Reference in New Issue
Block a user