drivers: display: update MCUX ELCDIF driver to use new lcdif binding

Update MCUX ELCDIF driver to use new LCDIF bindings. This
update also adds support for configuring the root clock of
the ELCDIF module based on the pixel-clock property to the
RT11xx SOC clock init, as this SOC series has this IP block

Signed-off-by: Daniel DeGrasse <daniel.degrasse@nxp.com>
This commit is contained in:
Daniel DeGrasse 2023-01-18 10:40:15 -06:00 committed by Carles Cufí
commit 746758d1f6
13 changed files with 175 additions and 161 deletions

View file

@ -8,6 +8,7 @@
#include <nxp/nxp_rt1050.dtsi>
#include "mimxrt1050_evk-pinctrl.dtsi"
#include <zephyr/dt-bindings/display/panel.h>
/ {
model = "NXP MIMXRT1050-EVK board";
@ -172,15 +173,22 @@ arduino_serial: &lpuart3 {
status = "okay";
width = <480>;
height = <272>;
hsync = <41>;
hfp = <4>;
hbp = <8>;
vsync = <10>;
vfp = <4>;
vbp = <2>;
polarity = <3>;
pixel-format = "bgr-565";
data-buswidth = "16-bit";
display-timings {
compatible = "zephyr,panel-timing";
hsync-len = <41>;
hfront-porch = <4>;
hback-porch = <8>;
vsync-len = <10>;
vfront-porch = <4>;
vback-porch = <2>;
de-active= <1>;
pixelclk-active = <1>;
hsync-active = <0>;
vsync-active = <0>;
clock-frequency = <9210240>;
};
pixel-format = <PANEL_PIXEL_FORMAT_BGR_565>;
data-bus-width = "16-bit";
pinctrl-0 = <&pinmux_lcdif>;
pinctrl-names = "default";
backlight-gpios = <&gpio2 31 GPIO_ACTIVE_HIGH>;

View file

@ -8,6 +8,7 @@
#include <nxp/nxp_rt1060.dtsi>
#include "mimxrt1060_evk-pinctrl.dtsi"
#include <zephyr/dt-bindings/display/panel.h>
/ {
model = "NXP MIMXRT1060-EVK board";
@ -153,15 +154,22 @@ arduino_serial: &lpuart3 {
status = "okay";
width = <480>;
height = <272>;
hsync = <41>;
hfp = <4>;
hbp = <8>;
vsync = <10>;
vfp = <4>;
vbp = <2>;
polarity = <3>;
pixel-format = "bgr-565";
data-buswidth = "16-bit";
display-timings {
compatible = "zephyr,panel-timing";
hsync-len = <41>;
hfront-porch = <4>;
hback-porch = <8>;
vsync-len = <10>;
vfront-porch = <4>;
vback-porch = <2>;
de-active= <1>;
pixelclk-active = <1>;
hsync-active = <0>;
vsync-active = <0>;
clock-frequency = <9210240>;
};
pixel-format = <PANEL_PIXEL_FORMAT_BGR_565>;
data-bus-width = "16-bit";
pinctrl-0 = <&pinmux_lcdif>;
pinctrl-names = "default";
backlight-gpios = <&gpio2 31 GPIO_ACTIVE_HIGH>;

View file

@ -8,6 +8,7 @@
#include <nxp/nxp_rt1064.dtsi>
#include "mimxrt1064_evk-pinctrl.dtsi"
#include <zephyr/dt-bindings/display/panel.h>
/ {
model = "NXP MIMXRT1064-EVK board";
@ -130,15 +131,22 @@ arduino_i2c: &lpi2c1 {};
status = "okay";
width = <480>;
height = <272>;
hsync = <41>;
hfp = <4>;
hbp = <8>;
vsync = <10>;
vfp = <4>;
vbp = <2>;
polarity = <3>;
pixel-format = "bgr-565";
data-buswidth = "16-bit";
display-timings {
compatible = "zephyr,panel-timing";
hsync-len = <41>;
hfront-porch = <4>;
hback-porch = <8>;
vsync-len = <10>;
vfront-porch = <4>;
vback-porch = <2>;
de-active= <1>;
pixelclk-active = <1>;
hsync-active = <0>;
vsync-active = <0>;
clock-frequency = <9210240>;
};
pixel-format = <PANEL_PIXEL_FORMAT_BGR_565>;
data-bus-width = "16-bit";
pinctrl-0 = <&pinmux_lcdif>;
pinctrl-names = "default";
backlight-gpios = <&gpio2 31 GPIO_ACTIVE_HIGH>;

View file

@ -8,6 +8,7 @@
#include <nxp/nxp_rt11xx_cm7.dtsi>
#include "mimxrt1170_evk.dtsi"
#include <zephyr/dt-bindings/display/panel.h>
/ {
model = "NXP MIMXRT1170-EVK board";
@ -51,18 +52,31 @@
&lcdif {
status = "okay";
pixel-format = <PANEL_PIXEL_FORMAT_BGR_565>;
data-bus-width = "24-bit";
backlight-gpios = <&gpio9 29 GPIO_ACTIVE_HIGH>;
width = <720>;
height = <1280>;
hsync = <8>;
hfp = <32>;
hbp = <32>;
vsync = <2>;
vfp = <16>;
vbp = <14>;
polarity = <3>;
pixel-format = "bgr-565";
data-buswidth = "24-bit";
backlight-gpios = <&gpio9 29 GPIO_ACTIVE_HIGH>;
display-timings {
compatible = "zephyr,panel-timing";
hsync-len = <8>;
hfront-porch = <32>;
hback-porch = <32>;
vsync-len = <2>;
vfront-porch = <16>;
vback-porch = <14>;
hsync-active = <0>;
vsync-active = <0>;
de-active = <1>;
pixelclk-active = <0>;
/*
* Pixel clock is given by the following formula:
* (height + vsync-len + vfront-porch + vback-porch) *
* (width + hsync-len + hfront-porch + hback-porch) * frame rate
*/
clock-frequency = <62346240>;
};
};
&mipi_dsi {

View file

@ -298,22 +298,32 @@ static const struct display_driver_api mcux_dcnano_lcdif_api = {
.dpi_config = { \
.panelWidth = DT_INST_PROP(n, width), \
.panelHeight = DT_INST_PROP(n, height), \
.hsw = DT_INST_PROP(n, hsync_len), \
.hfp = DT_INST_PROP(n, hfront_porch), \
.hbp = DT_INST_PROP(n, hback_porch), \
.vsw = DT_INST_PROP(n, vsync_len), \
.vfp = DT_INST_PROP(n, vfront_porch), \
.vbp = DT_INST_PROP(n, vback_porch), \
.polarityFlags = (DT_INST_PROP(n, de_active) ? \
.hsw = DT_PROP(DT_INST_CHILD(n, display_timings), \
hsync_len), \
.hfp = DT_PROP(DT_INST_CHILD(n, display_timings), \
hfront_porch), \
.hbp = DT_PROP(DT_INST_CHILD(n, display_timings), \
hback_porch), \
.vsw = DT_PROP(DT_INST_CHILD(n, display_timings), \
vsync_len), \
.vfp = DT_PROP(DT_INST_CHILD(n, display_timings), \
vfront_porch), \
.vbp = DT_PROP(DT_INST_CHILD(n, display_timings), \
vback_porch), \
.polarityFlags = (DT_PROP(DT_INST_CHILD(n, \
display_timings), de_active) ? \
kLCDIF_DataEnableActiveHigh : \
kLCDIF_DataEnableActiveLow) | \
(DT_INST_PROP(n, pixelclk_active) ? \
(DT_PROP(DT_INST_CHILD(n, \
display_timings), pixelclk_active) ? \
kLCDIF_DriveDataOnRisingClkEdge : \
kLCDIF_DriveDataOnFallingClkEdge) | \
(DT_INST_PROP(n, hsync_active) ? \
(DT_PROP(DT_INST_CHILD(n, \
display_timings), hsync_active) ? \
kLCDIF_HsyncActiveHigh : \
kLCDIF_HsyncActiveLow) | \
(DT_INST_PROP(n, vsync_active) ? \
(DT_PROP(DT_INST_CHILD(n, \
display_timings), vsync_active) ? \
kLCDIF_VsyncActiveHigh : \
kLCDIF_VsyncActiveLow), \
.format = DT_INST_ENUM_IDX(n, data_bus_width), \

View file

@ -216,9 +216,6 @@ static int mcux_elcdif_init(const struct device *dev)
elcdif_rgb_mode_config_t rgb_mode = config->rgb_mode;
/* Shift the polarity bits to the appropriate location in the register */
rgb_mode.polarityFlags = rgb_mode.polarityFlags << LCDIF_VDCTRL0_ENABLE_POL_SHIFT;
/* Set the Pixel format */
if (config->pixel_format == PIXEL_FORMAT_BGR_565) {
rgb_mode.pixelFormat = kELCDIF_PixelFormatRGB565;
@ -259,7 +256,7 @@ static const struct display_driver_api mcux_elcdif_api = {
};
#define MCUX_ELCDIF_PIXEL_BYTES(id) \
COND_CODE_1(DT_INST_ENUM_IDX(id, pixel_format), (2), (3))
(DISPLAY_BITS_PER_PIXEL(DT_INST_PROP(id, pixel_format)) / 8)
#define MCUX_ELCDIF_DEVICE_INIT(id) \
PINCTRL_DT_INST_DEFINE(id); \
@ -270,19 +267,38 @@ static const struct display_driver_api mcux_elcdif_api = {
.rgb_mode = { \
.panelWidth = DT_INST_PROP(id, width), \
.panelHeight = DT_INST_PROP(id, height), \
.hsw = DT_INST_PROP(id, hsync), \
.hfp = DT_INST_PROP(id, hfp), \
.hbp = DT_INST_PROP(id, hbp), \
.vsw = DT_INST_PROP(id, vsync), \
.vfp = DT_INST_PROP(id, vfp), \
.vbp = DT_INST_PROP(id, vbp), \
.polarityFlags = DT_INST_PROP(id, polarity), \
.hsw = DT_PROP(DT_INST_CHILD(id, display_timings), \
hsync_len), \
.hfp = DT_PROP(DT_INST_CHILD(id, display_timings), \
hfront_porch), \
.hbp = DT_PROP(DT_INST_CHILD(id, display_timings), \
hback_porch), \
.vsw = DT_PROP(DT_INST_CHILD(id, display_timings), \
vsync_len), \
.vfp = DT_PROP(DT_INST_CHILD(id, display_timings), \
vfront_porch), \
.vbp = DT_PROP(DT_INST_CHILD(id, display_timings), \
vback_porch), \
.polarityFlags = (DT_PROP(DT_INST_CHILD(id, \
display_timings), hsync_active) ? \
kELCDIF_HsyncActiveHigh : \
kELCDIF_HsyncActiveLow) | \
(DT_PROP(DT_INST_CHILD(id, \
display_timings), vsync_active) ? \
kELCDIF_VsyncActiveHigh : \
kELCDIF_VsyncActiveLow) | \
(DT_PROP(DT_INST_CHILD(id, \
display_timings), de_active) ? \
kELCDIF_DataEnableActiveHigh : \
kELCDIF_DataEnableActiveLow) | \
(DT_PROP(DT_INST_CHILD(id, \
display_timings), pixelclk_active) ? \
kELCDIF_DriveDataOnRisingClkEdge : \
kELCDIF_DriveDataOnFallingClkEdge), \
.dataBus = LCDIF_CTRL_LCD_DATABUS_WIDTH( \
DT_INST_ENUM_IDX(id, data_buswidth)), \
DT_INST_ENUM_IDX(id, data_bus_width)), \
}, \
.pixel_format = COND_CODE_1(DT_INST_ENUM_IDX(id, pixel_format), \
(PIXEL_FORMAT_BGR_565), \
(PIXEL_FORMAT_RGB_888)), \
.pixel_format = DT_INST_PROP(id, pixel_format), \
.pixel_bytes = MCUX_ELCDIF_PIXEL_BYTES(id), \
.fb_bytes = DT_INST_PROP(id, width) * DT_INST_PROP(id, height) \
* MCUX_ELCDIF_PIXEL_BYTES(id), \

View file

@ -81,7 +81,6 @@ static int dsi_mcux_attach(const struct device *dev,
mipi_dsi_dphy_bit_clk_hz = DSI_InitDphy((MIPI_DSI_Type *)&config->base,
&dphy_config, mipi_dsi_dphy_ref_clk_hz);
/* Init DPI interface. */
DSI_SetDpiConfig((MIPI_DSI_Type *)&config->base, &config->dpi_config, mdev->data_lanes,
mipi_dsi_dpi_clk_hz, mipi_dsi_dphy_bit_clk_hz);
@ -187,13 +186,22 @@ static int display_mcux_mipi_dsi_init(const struct device *dev)
.bllpMode = DT_INST_ENUM_IDX(id, dpi_bllp_mode), \
.pixelPayloadSize = DT_INST_PROP_BY_PHANDLE(id, nxp_lcdif, width), \
.panelHeight = DT_INST_PROP_BY_PHANDLE(id, nxp_lcdif, height), \
.polarityFlags = DT_INST_PROP_BY_PHANDLE_IDX( \
id, nxp_lcdif, id, polarity) >> 2, \
.hfp = DT_INST_PROP_BY_PHANDLE(id, nxp_lcdif, hfp), \
.hbp = DT_INST_PROP_BY_PHANDLE(id, nxp_lcdif, hbp), \
.hsw = DT_INST_PROP_BY_PHANDLE(id, nxp_lcdif, hsync), \
.vfp = DT_INST_PROP_BY_PHANDLE(id, nxp_lcdif, vfp), \
.vbp = DT_INST_PROP_BY_PHANDLE(id, nxp_lcdif, vbp), \
.polarityFlags = (DT_PROP(DT_CHILD(DT_INST_PHANDLE(id, nxp_lcdif), \
display_timings), hsync_active) ? \
kDSI_DpiHsyncActiveHigh : kDSI_DpiHsyncActiveLow) | \
(DT_PROP(DT_CHILD(DT_INST_PHANDLE(id, nxp_lcdif), \
display_timings), vsync_active) ? \
kDSI_DpiVsyncActiveHigh : kDSI_DpiVsyncActiveLow), \
.hfp = DT_PROP(DT_CHILD(DT_INST_PHANDLE(id, nxp_lcdif), \
display_timings), hfront_porch), \
.hbp = DT_PROP(DT_CHILD(DT_INST_PHANDLE(id, nxp_lcdif), \
display_timings), hback_porch), \
.hsw = DT_PROP(DT_CHILD(DT_INST_PHANDLE(id, nxp_lcdif), \
display_timings), hsync_len), \
.vfp = DT_PROP(DT_CHILD(DT_INST_PHANDLE(id, nxp_lcdif), \
display_timings), vfront_porch), \
.vbp = DT_PROP(DT_CHILD(DT_INST_PHANDLE(id, nxp_lcdif), \
display_timings), vback_porch), \
}, \
.auto_insert_eotp = DT_INST_PROP(id, autoinsert_eotp), \
.phy_clock = DT_INST_PROP(id, phy_clock), \

View file

@ -210,17 +210,24 @@ static int mcux_mipi_dsi_init(const struct device *dev)
.bllpMode = DT_INST_ENUM_IDX(id, dpi_bllp_mode), \
.pixelPayloadSize = DT_INST_PROP_BY_PHANDLE(id, nxp_lcdif, width), \
.panelHeight = DT_INST_PROP_BY_PHANDLE(id, nxp_lcdif, height), \
.polarityFlags = (DT_INST_PROP_BY_PHANDLE(id, nxp_lcdif, vsync_active) ?\
.polarityFlags = (DT_PROP(DT_CHILD(DT_INST_PHANDLE(id, nxp_lcdif), \
display_timings), vsync_active) ? \
kDSI_DpiVsyncActiveHigh : \
kDSI_DpiVsyncActiveLow) | \
(DT_INST_PROP_BY_PHANDLE(id, nxp_lcdif, hsync_active) ? \
(DT_PROP(DT_CHILD(DT_INST_PHANDLE(id, nxp_lcdif), \
display_timings), hsync_active) ? \
kDSI_DpiHsyncActiveHigh : \
kDSI_DpiHsyncActiveLow), \
.hfp = DT_INST_PROP_BY_PHANDLE(id, nxp_lcdif, hfront_porch), \
.hbp = DT_INST_PROP_BY_PHANDLE(id, nxp_lcdif, hback_porch), \
.hsw = DT_INST_PROP_BY_PHANDLE(id, nxp_lcdif, hsync_len), \
.vfp = DT_INST_PROP_BY_PHANDLE(id, nxp_lcdif, vfront_porch), \
.vbp = DT_INST_PROP_BY_PHANDLE(id, nxp_lcdif, vback_porch), \
.hfp = DT_PROP(DT_CHILD(DT_INST_PHANDLE(id, nxp_lcdif), \
display_timings), hfront_porch), \
.hbp = DT_PROP(DT_CHILD(DT_INST_PHANDLE(id, nxp_lcdif), \
display_timings), hback_porch), \
.hsw = DT_PROP(DT_CHILD(DT_INST_PHANDLE(id, nxp_lcdif), \
display_timings), hsync_len), \
.vfp = DT_PROP(DT_CHILD(DT_INST_PHANDLE(id, nxp_lcdif), \
display_timings), vfront_porch), \
.vbp = DT_PROP(DT_CHILD(DT_INST_PHANDLE(id, nxp_lcdif), \
display_timings), vback_porch), \
}, \
.auto_insert_eotp = DT_INST_PROP(id, autoinsert_eotp), \
.dphy_ref_freq = DT_INST_PROP_OR(id, dphy_ref_frequency, 0), \

View file

@ -5,7 +5,7 @@ description: NXP DCNano LCDIF (LCD Interface) controller
compatible: "nxp,dcnano-lcdif"
include: [panel-controller.yaml, pinctrl-device.yaml]
include: [lcd-controller.yaml, pinctrl-device.yaml]
properties:
reg:

View file

@ -5,7 +5,7 @@ description: NXP i.MX eLCDIF (Enhanced LCD Interface) controller
compatible: "nxp,imx-elcdif"
include: [display-controller.yaml, pinctrl-device.yaml]
include: [lcd-controller.yaml, pinctrl-device.yaml]
properties:
reg:
@ -14,85 +14,7 @@ properties:
interrupts:
required: true
hsync:
type: int
required: true
description: HSYNC pulse width in display clock cycles
hfp:
type: int
required: true
description: Horizontal front porch in display clock cycles
hbp:
type: int
required: true
description: Horizontal back porch in display clock cycles
vsync:
type: int
required: true
description: VSYNC pulse width in display clock cycles
vfp:
type: int
required: true
description: Vertical front porch in display clock cycles
vbp:
type: int
required: true
description: Vertical back porch in display clock cycles
polarity:
type: int
required: true
enum:
- 0
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
description:
OR'ed value of elcdif_polarity_flags, used to control the signal polarity.
0000 VSYNC active low, HSYNC active low, Drive data on falling edge, DE active low.
0001 VSYNC active low, HSYNC active low, Drive data on falling edge, DE active high.
0010 VSYNC active low, HSYNC active low, Drive data on rising edge, DE active low.
0011 VSYNC active low, HSYNC active low, Drive data on rising edge, DE active high.
0100 VSYNC active low, HSYNC active high, Drive data on falling edge, DE active low.
0101 VSYNC active low, HSYNC active high, Drive data on falling edge, DE active high.
0110 VSYNC active low, HSYNC active high, Drive data on rising edge, DE active low.
0111 VSYNC active low, HSYNC active high, Drive data on rising edge, DE active high.
1000 VSYNC active high, HSYNC active low, Drive data on falling edge, DE active low.
1001 VSYNC active high, HSYNC active low, Drive data on falling edge, DE active high.
1010 VSYNC active high, HSYNC active low, Drive data on rising edge, DE active low.
1011 VSYNC active high, HSYNC active low, Drive data on rising edge, DE active high.
1100 VSYNC active high, HSYNC active high, Drive data on falling edge, DE active low.
1101 VSYNC active high, HSYNC active high, Drive data on falling edge, DE active high.
1110 VSYNC active high, HSYNC active high, Drive data on rising edge, DE active low.
1111 VSYNC active high, HSYNC active high, Drive data on rising edge, DE active high.
pixel-format:
type: string
required: true
enum:
- "rgb-888"
- "bgr-565"
description:
Display pixel format.
data-buswidth:
data-bus-width:
type: string
default: "16-bit"
enum:

View file

@ -177,9 +177,15 @@ static ALWAYS_INLINE void clock_init(void)
#endif
#ifdef CONFIG_DISPLAY_MCUX_ELCDIF
/* MUX selects video PLL, which is initialized to 93MHz */
CLOCK_SetMux(kCLOCK_LcdifPreMux, 2);
CLOCK_SetDiv(kCLOCK_LcdifPreDiv, 4);
/* Divide output by 2 */
CLOCK_SetDiv(kCLOCK_LcdifDiv, 1);
/* Set final div based on LCDIF clock-frequency */
CLOCK_SetDiv(kCLOCK_LcdifPreDiv,
((CLOCK_GetPllFreq(kCLOCK_PllVideo) / 2) /
DT_PROP(DT_CHILD(DT_NODELABEL(lcdif), display_timings),
clock_frequency)) - 1);
#endif

View file

@ -454,7 +454,13 @@ static ALWAYS_INLINE void clock_init(void)
#ifdef CONFIG_DISPLAY_MCUX_ELCDIF
rootCfg.mux = kCLOCK_LCDIF_ClockRoot_MuxSysPll2Out;
rootCfg.div = 9;
/*
* PLL2 is fixed at 528MHz. Use desired panel clock clock to
* calculate LCDIF clock.
*/
rootCfg.div = ((SYS_PLL2_FREQ /
DT_PROP(DT_CHILD(DT_NODELABEL(lcdif), display_timings),
clock_frequency)) + 1);
CLOCK_SetRootClock(kCLOCK_Root_Lcdif, &rootCfg);
#endif

View file

@ -317,7 +317,8 @@ static void clock_init(void)
*/
CLOCK_SetClkDiv(kCLOCK_DivDcPixelClk,
((CLOCK_GetSysPfdFreq(kCLOCK_Pfd2) /
DT_PROP(DT_NODELABEL(lcdif), clock_frequency)) + 1));
DT_PROP(DT_CHILD(DT_NODELABEL(lcdif), display_timings),
clock_frequency)) + 1));
CLOCK_EnableClock(kCLOCK_DisplayCtrl);
RESET_ClearPeripheralReset(kDISP_CTRL_RST_SHIFT_RSTn);