diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 1b728b5..a1a1c9c 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -584,6 +584,11 @@ config VIDEO_IMX8_HDMI help Support for HDMI i.MX8 processors. +config IMX_MIPI_DSI_BRIDGE + bool + help + Enable MIPI DSI bridge interface for display controller. + config MXC_EPDC bool "i.MX EPDC support" depends on LCD && (MX7 || MX6) diff --git a/drivers/video/Makefile b/drivers/video/Makefile index c7ded02..12e4d19 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -69,6 +69,7 @@ obj-$(CONFIG_VIDEO_CSI) += mxc_csi.o obj-$(CONFIG_VIDEO_PXP) += mxc_pxp.o obj-$(CONFIG_VIDEO_GIS) += mxc_gis.o obj-$(CONFIG_MXC_MIPI_DSI_NORTHWEST) += mipi_dsi_northwest.o +obj-$(CONFIG_IMX_MIPI_DSI_BRIDGE) += imx_mipi_dsi_bridge.o obj-$(CONFIG_HX8363) += hx8363_wvga.o obj-y += bridge/ diff --git a/drivers/video/imx_mipi_dsi_bridge.c b/drivers/video/imx_mipi_dsi_bridge.c new file mode 100644 index 0000000..a3e9e26 --- /dev/null +++ b/drivers/video/imx_mipi_dsi_bridge.c @@ -0,0 +1,104 @@ +/* + * Copyright 2018 NXP + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include + +static struct mipi_dsi_bridge_driver *registered_driver = NULL; + +int imx_mipi_dsi_bridge_attach(struct mipi_dsi_client_dev *dsi_dev) +{ + int ret = 0; + + if (!registered_driver) + return -EPERM; + + if (registered_driver->attach) + ret = registered_driver->attach(registered_driver, dsi_dev); + + return ret; +} + +int imx_mipi_dsi_bridge_mode_set(struct fb_videomode *pvmode) +{ + int ret = 0; + + if (!registered_driver) + return -EPERM; + + if (registered_driver->mode_set) + ret = registered_driver->mode_set(registered_driver, pvmode); + + return ret; +} + +int imx_mipi_dsi_bridge_enable(void) +{ + int ret = 0; + + if (!registered_driver) + return -EPERM; + + if (registered_driver->enable) + ret = registered_driver->enable(registered_driver); + + return ret; +} + +int imx_mipi_dsi_bridge_disable(void) +{ + int ret = 0; + + if (!registered_driver) + return -EPERM; + + if (registered_driver->disable) + ret = registered_driver->disable(registered_driver); + + return ret; +} + +int imx_mipi_dsi_bridge_pkt_write(u8 data_type, const u8 *buf, int len) +{ + int ret = 0; + + if (!registered_driver) + return -EPERM; + + if (registered_driver->pkt_write) + ret = registered_driver->pkt_write(registered_driver, data_type, buf, len); + + return ret; +} + +int imx_mipi_dsi_bridge_add_client_driver(struct mipi_dsi_client_driver *client_driver) +{ + int ret = 0; + + if (!registered_driver) + return -EPERM; + + if (registered_driver->add_client_driver) + ret = registered_driver->add_client_driver(registered_driver, client_driver); + + return ret; +} + +int imx_mipi_dsi_bridge_register_driver(struct mipi_dsi_bridge_driver *driver) +{ + if (!driver) + return -EINVAL; + + if (registered_driver) + return -EBUSY; + + registered_driver = driver; + + return 0; +} diff --git a/include/imx_mipi_dsi_bridge.h b/include/imx_mipi_dsi_bridge.h new file mode 100644 index 0000000..a6f73c1 --- /dev/null +++ b/include/imx_mipi_dsi_bridge.h @@ -0,0 +1,95 @@ +/* + * Copyright 2018 NXP + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __IMX_MIPI_DSIM_BRIDGE_H__ +#define __IMX_MIPI_DSIM_BRIDGE_H__ + +#include + +/* video mode */ +#define MIPI_DSI_MODE_VIDEO BIT(0) +/* video burst mode */ +#define MIPI_DSI_MODE_VIDEO_BURST BIT(1) +/* video pulse mode */ +#define MIPI_DSI_MODE_VIDEO_SYNC_PULSE BIT(2) +/* enable auto vertical count mode */ +#define MIPI_DSI_MODE_VIDEO_AUTO_VERT BIT(3) +/* enable hsync-end packets in vsync-pulse and v-porch area */ +#define MIPI_DSI_MODE_VIDEO_HSE BIT(4) +/* disable hfront-porch area */ +#define MIPI_DSI_MODE_VIDEO_HFP BIT(5) +/* disable hback-porch area */ +#define MIPI_DSI_MODE_VIDEO_HBP BIT(6) +/* disable hsync-active area */ +#define MIPI_DSI_MODE_VIDEO_HSA BIT(7) +/* flush display FIFO on vsync pulse */ +#define MIPI_DSI_MODE_VSYNC_FLUSH BIT(8) +/* disable EoT packets in HS mode */ +#define MIPI_DSI_MODE_EOT_PACKET BIT(9) +/* device supports non-continuous clock behavior (DSI spec 5.6.1) */ +#define MIPI_DSI_CLOCK_NON_CONTINUOUS BIT(10) +/* transmit data in low power */ +#define MIPI_DSI_MODE_LPM BIT(11) + +#define DSI_CMD_BUF_MAXSIZE (128) + +enum mipi_dsi_pixel_format { + MIPI_DSI_FMT_RGB888, + MIPI_DSI_FMT_RGB666, + MIPI_DSI_FMT_RGB666_PACKED, + MIPI_DSI_FMT_RGB565, +}; + +struct mipi_dsi_client_dev { + unsigned int channel; + unsigned int lanes; + enum mipi_dsi_pixel_format format; + unsigned long mode_flags; + const char *name; +}; + +struct mipi_dsi_client_driver { + int (*dsi_client_setup)(struct mipi_dsi_client_dev *panel_dev); + const char *name; +}; + +struct mipi_dsi_bridge_driver { + int (*attach)(struct mipi_dsi_bridge_driver *bridge_driver, struct mipi_dsi_client_dev *dsi_dev); + int (*enable)(struct mipi_dsi_bridge_driver *bridge_driver); + int (*disable)(struct mipi_dsi_bridge_driver *bridge_driver); + int (*mode_set)(struct mipi_dsi_bridge_driver *bridge_driver, struct fb_videomode *pvmode); + int (*pkt_write)(struct mipi_dsi_bridge_driver *bridge_driver, u8 data_type, const u8 *buf, int len); + int (*add_client_driver)(struct mipi_dsi_bridge_driver *bridge_driver, struct mipi_dsi_client_driver *client_driver); + const char *name; + void *driver_private; +}; + +static inline int mipi_dsi_pixel_format_to_bpp(enum mipi_dsi_pixel_format fmt) +{ + switch (fmt) { + case MIPI_DSI_FMT_RGB888: + case MIPI_DSI_FMT_RGB666: + return 24; + + case MIPI_DSI_FMT_RGB666_PACKED: + return 18; + + case MIPI_DSI_FMT_RGB565: + return 16; + } + + return -EINVAL; +} + +int imx_mipi_dsi_bridge_attach(struct mipi_dsi_client_dev *dsi_dev); +int imx_mipi_dsi_bridge_mode_set(struct fb_videomode *pvmode); +int imx_mipi_dsi_bridge_enable(void); +int imx_mipi_dsi_bridge_disable(void); +int imx_mipi_dsi_bridge_pkt_write(u8 data_type, const u8 *buf, int len); +int imx_mipi_dsi_bridge_add_client_driver(struct mipi_dsi_client_driver *client_driver); +int imx_mipi_dsi_bridge_register_driver(struct mipi_dsi_bridge_driver *driver); + +#endif