MLK-18945-2 video: Update mipi dsi northwest to implement bridge interface

Update the mipi_dsi_northwest driver to implement mipi dsi bridge interfaces
and register it as a bridge controller. Users can call bridge common interfaces
to access the northwest driver, don't need to call its private driver functions.

We also add a kconfig entry for this driver, the name is changed to
CONFIG_IMX_NORTHWEST_MIPI_DSI

Signed-off-by: Ye Li <ye.li@nxp.com>
(cherry picked from commit a668cdb1ef5bcef4a574640f5c06ff07520254df)
This commit is contained in:
Ye Li 2018-07-17 19:13:13 -07:00
parent 2880a49732
commit f7a9859569
5 changed files with 94 additions and 121 deletions

View File

@ -548,6 +548,14 @@ config IMX_MIPI_DSI_BRIDGE
help
Enable MIPI DSI bridge interface for display controller.
config IMX_NORTHWEST_MIPI_DSI
bool "i.MX northwest's MIPI DSI"
default n
select IMX_MIPI_DSI_BRIDGE
depends on VIDEO && MX7ULP
help
Support for i.MX7ULP MIPI DSI controller.
config MXC_EPDC
bool "i.MX EPDC support"
depends on LCD && (MX7 || MX6)

View File

@ -63,7 +63,7 @@ obj-$(CONFIG_VIDEO_VADC) += mxc_vadc.o
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_NORTHWEST_MIPI_DSI) += mipi_dsi_northwest.o
obj-$(CONFIG_IMX_MIPI_DSI_BRIDGE) += imx_mipi_dsi_bridge.o
obj-$(CONFIG_HX8363) += hx8363_wvga.o

View File

@ -17,6 +17,7 @@
#include "mipi_dsi_northwest_regs.h"
#include <mipi_dsi_northwest.h>
#include <mipi_display.h>
#include <imx_mipi_dsi_bridge.h>
#define MIPI_LCD_SLEEP_MODE_DELAY (120)
#define MIPI_FIFO_TIMEOUT 250000 /* 250ms */
@ -34,6 +35,18 @@ enum mipi_dsi_payload {
DSI_PAYLOAD_VIDEO,
};
/*
* mipi-dsi northwest driver information structure, holds useful data for the driver.
*/
struct mipi_dsi_northwest_info {
u32 mmio_base;
u32 sim_base;
int enabled;
struct mipi_dsi_client_dev *dsi_panel_dev;
struct mipi_dsi_client_driver *dsi_panel_drv;
struct fb_videomode mode;
};
/**
* board_mipi_panel_reset - give a reset cycle for mipi dsi panel
*
@ -141,7 +154,7 @@ static int mipi_dsi_host_init(struct mipi_dsi_northwest_info *mipi_dsi)
{
uint32_t lane_num;
switch (mipi_dsi->dsi_panel_dev->data_lane_num) {
switch (mipi_dsi->dsi_panel_dev->lanes) {
case 1:
lane_num = 0x0;
break;
@ -171,9 +184,11 @@ static int mipi_dsi_host_init(struct mipi_dsi_northwest_info *mipi_dsi)
static int mipi_dsi_dpi_init(struct mipi_dsi_northwest_info *mipi_dsi)
{
uint32_t bpp, color_coding, pixel_fmt;
struct fb_videomode *mode = &(mipi_dsi->dsi_panel_dev->mode);
struct fb_videomode *mode = &(mipi_dsi->mode);
bpp = mipi_dsi->dsi_panel_dev->bpp;
bpp = mipi_dsi_pixel_format_to_bpp(mipi_dsi->dsi_panel_dev->format);
if (bpp < 0)
return -EINVAL;
writel(mode->xres, mipi_dsi->mmio_base + DPI_PIXEL_PAYLOAD_SIZE);
writel(mode->xres, mipi_dsi->mmio_base + DPI_PIXEL_FIFO_SEND_LEVEL);
@ -293,8 +308,8 @@ static int mipi_dsi_enable(struct mipi_dsi_northwest_info *mipi_dsi)
mipi_dsi_init_interrupt(mipi_dsi);
/* Call panel driver's setup */
if (mipi_dsi->dsi_panel_drv->mipi_panel_setup) {
ret = mipi_dsi->dsi_panel_drv->mipi_panel_setup(mipi_dsi->dsi_panel_dev);
if (mipi_dsi->dsi_panel_drv->dsi_client_setup) {
ret = mipi_dsi->dsi_panel_drv->dsi_client_setup(mipi_dsi->dsi_panel_dev);
if (ret < 0) {
printf("failed to init mipi lcd.\n");
return ret;
@ -393,7 +408,7 @@ static int wait_for_pkt_done(struct mipi_dsi_northwest_info *mipi_dsi, unsigned
}
static int mipi_dsi_pkt_write(struct mipi_dsi_northwest_info *mipi_dsi,
u8 data_type, const u32 *buf, int len)
u8 data_type, const u8 *buf, int len)
{
int ret = 0;
const uint8_t *data = (const uint8_t *)buf;
@ -437,7 +452,7 @@ static int mipi_dsi_dcs_cmd(struct mipi_dsi_northwest_info *mipi_dsi,
buf[0] = cmd;
buf[1] = 0x0;
err = mipi_dsi_pkt_write(mipi_dsi,
MIPI_DSI_DCS_SHORT_WRITE, buf, 0);
MIPI_DSI_DCS_SHORT_WRITE, (u8 *)buf, 0);
break;
default:
@ -468,34 +483,11 @@ static void mipi_dsi_shutdown(struct mipi_dsi_northwest_info *mipi_dsi)
clrbits_le32(mipi_dsi->sim_base + SIM_SOPT1CFG, DSI_RST_DPI_N);
}
struct mipi_dsi_northwest_info *dsi_info = NULL;
int mipi_dsi_northwest_setup(u32 base_addr, u32 sim_addr)
/* Attach a LCD panel device */
int mipi_dsi_northwest_bridge_attach(struct mipi_dsi_bridge_driver *bridge_driver, struct mipi_dsi_client_dev *panel_dev)
{
if (dsi_info != NULL) {
printf("mipi_dsi_northwest has been initialized.\n");
return -EBUSY;
}
struct mipi_dsi_northwest_info *dsi_info = (struct mipi_dsi_northwest_info *)bridge_driver->driver_private;
dsi_info = (struct mipi_dsi_northwest_info *)malloc(sizeof(struct mipi_dsi_northwest_info));
if (!dsi_info) {
printf("failed to allocate mipi_dsi_northwest_info object.\n");
return -ENOMEM;
}
dsi_info->mmio_base = base_addr;
dsi_info->sim_base = sim_addr;
dsi_info->mipi_dsi_pkt_write = &mipi_dsi_pkt_write;
dsi_info->dsi_panel_dev = NULL;
dsi_info->dsi_panel_drv = NULL;
dsi_info->enabled = 0;
return 0;
}
/* Register a LCD panel device */
int mipi_dsi_northwest_register_panel_device(struct mipi_dsi_northwest_panel_device *panel_dev)
{
if (!panel_dev) {
printf("mipi_dsi_northwest_panel_device is NULL.\n");
return -EFAULT;
@ -506,11 +498,6 @@ int mipi_dsi_northwest_register_panel_device(struct mipi_dsi_northwest_panel_dev
return -EFAULT;
}
if (!dsi_info) {
printf("mipi_dsi_northwest is not initialized\n");
return -EFAULT;
}
if (dsi_info->dsi_panel_drv) {
if (strcmp(panel_dev->name, dsi_info->dsi_panel_drv->name)) {
printf("The panel device name %s is not for LCD driver %s\n",
@ -520,14 +507,17 @@ int mipi_dsi_northwest_register_panel_device(struct mipi_dsi_northwest_panel_dev
}
dsi_info->dsi_panel_dev = panel_dev;
panel_dev->host = dsi_info;
return 0;
}
/* Register a LCD panel driver, will search the panel device to bind with them */
int mipi_dsi_northwest_register_panel_driver(struct mipi_dsi_northwest_panel_driver *panel_drv)
/* Add a LCD panel driver, will search the panel device to bind with them */
int mipi_dsi_northwest_bridge_add_client_driver(struct mipi_dsi_bridge_driver *bridge_driver,
struct mipi_dsi_client_driver *panel_drv)
{
struct mipi_dsi_northwest_info *dsi_info = (struct mipi_dsi_northwest_info *)bridge_driver->driver_private;
if (!panel_drv) {
printf("mipi_dsi_northwest_panel_driver is NULL.\n");
return -EFAULT;
@ -538,11 +528,6 @@ int mipi_dsi_northwest_register_panel_driver(struct mipi_dsi_northwest_panel_dri
return -EFAULT;
}
if (!dsi_info) {
printf("mipi_dsi_northwest is not initialized\n");
return -EFAULT;
}
if (dsi_info->dsi_panel_dev) {
if (strcmp(panel_drv->name, dsi_info->dsi_panel_dev->name)) {
printf("The panel driver name %s is not for LCD device %s\n",
@ -557,8 +542,10 @@ int mipi_dsi_northwest_register_panel_driver(struct mipi_dsi_northwest_panel_dri
}
/* Enable the mipi dsi display */
int mipi_dsi_northwest_enable(void)
static int mipi_dsi_northwest_bridge_enable(struct mipi_dsi_bridge_driver *bridge_driver)
{
struct mipi_dsi_northwest_info *dsi_info = (struct mipi_dsi_northwest_info *)bridge_driver->driver_private;
if (!dsi_info->dsi_panel_dev || !dsi_info->dsi_panel_drv)
return -ENODEV;
@ -570,8 +557,10 @@ int mipi_dsi_northwest_enable(void)
}
/* Disable and shutdown the mipi dsi display */
int mipi_dsi_northwest_shutdown(void)
static int mipi_dsi_northwest_bridge_disable(struct mipi_dsi_bridge_driver *bridge_driver)
{
struct mipi_dsi_northwest_info *dsi_info = (struct mipi_dsi_northwest_info *)bridge_driver->driver_private;
if (!dsi_info->enabled)
return 0;
@ -582,3 +571,51 @@ int mipi_dsi_northwest_shutdown(void)
return 0;
}
static int mipi_dsi_northwest_bridge_mode_set(struct mipi_dsi_bridge_driver *bridge_driver,
struct fb_videomode *fbmode)
{
struct mipi_dsi_northwest_info *dsi_info = (struct mipi_dsi_northwest_info *)bridge_driver->driver_private;
dsi_info->mode = *fbmode;
return 0;
}
static int mipi_dsi_northwest_bridge_pkt_write(struct mipi_dsi_bridge_driver *bridge_driver,
u8 data_type, const u8 *buf, int len)
{
struct mipi_dsi_northwest_info *mipi_dsi = (struct mipi_dsi_northwest_info *)bridge_driver->driver_private;
return mipi_dsi_pkt_write(mipi_dsi, data_type, buf, len);
}
struct mipi_dsi_bridge_driver imx_northwest_dsi_driver = {
.attach = mipi_dsi_northwest_bridge_attach,
.enable = mipi_dsi_northwest_bridge_enable,
.disable = mipi_dsi_northwest_bridge_disable,
.mode_set = mipi_dsi_northwest_bridge_mode_set,
.pkt_write = mipi_dsi_northwest_bridge_pkt_write,
.add_client_driver = mipi_dsi_northwest_bridge_add_client_driver,
.name = "imx_northwest_mipi_dsi",
};
int mipi_dsi_northwest_setup(u32 base_addr, u32 sim_addr)
{
struct mipi_dsi_northwest_info *dsi_info;
dsi_info = (struct mipi_dsi_northwest_info *)malloc(sizeof(struct mipi_dsi_northwest_info));
if (!dsi_info) {
printf("failed to allocate mipi_dsi_northwest_info object.\n");
return -ENOMEM;
}
dsi_info->mmio_base = base_addr;
dsi_info->sim_base = sim_addr;
dsi_info->dsi_panel_dev = NULL;
dsi_info->dsi_panel_drv = NULL;
dsi_info->enabled = 0;
imx_northwest_dsi_driver.driver_private = dsi_info;
return imx_mipi_dsi_bridge_register_driver(&imx_northwest_dsi_driver);
}

View File

@ -11,78 +11,7 @@
#include <linux/fb.h>
#define DSI_CMD_BUF_MAXSIZE (128)
/*
* device structure for mipi-dsi based lcd panel.
*
* @name: name of the device to use with this device,
* the name will be used for binding driver.
* @mode: video mode parameters for the panel.
* @bpp: bits per pixel. only 24 bits is supported.
* @virtual_ch_id: virtual channel id for this dsi device.
* @data_lane_num: the data lane number, max is 2.
* @host: pointer to the host driver instance, will be setup
* during register device.
*/
struct mipi_dsi_northwest_panel_device {
const char *name;
struct fb_videomode mode;
int bpp;
u32 virtual_ch_id;
u32 data_lane_num;
struct mipi_dsi_northwest_info *host;
};
/*
* driver structure for mipi-dsi based lcd panel.
*
* this structure should be registered by lcd panel driver.
* mipi-dsi driver seeks lcd panel registered through name field
* and calls these callback functions in appropriate time.
*
* @name: name of the driver to use with this device, or an
* alias for that name.
* @mipi_panel_setup: callback pointer for initializing lcd panel based on mipi
* dsi interface.
*/
struct mipi_dsi_northwest_panel_driver {
const char *name;
int (*mipi_panel_setup)(struct mipi_dsi_northwest_panel_device *panel_dev);
};
/*
* mipi-dsi northwest driver information structure, holds useful data for the driver.
*/
struct mipi_dsi_northwest_info {
u32 mmio_base;
u32 sim_base;
int enabled;
struct mipi_dsi_northwest_panel_device *dsi_panel_dev;
struct mipi_dsi_northwest_panel_driver *dsi_panel_drv;
int (*mipi_dsi_pkt_write)(struct mipi_dsi_northwest_info *mipi_dsi,
u8 data_type, const u32 *buf, int len);
};
/* Setup mipi dsi host driver instance, with base address and SIM address provided */
int mipi_dsi_northwest_setup(u32 base_addr, u32 sim_addr);
/* Create a LCD panel device, will search the panel driver to bind with them */
int mipi_dsi_northwest_register_panel_device(struct mipi_dsi_northwest_panel_device *panel_dev);
/* Register a LCD panel driver, will search the panel device to bind with them */
int mipi_dsi_northwest_register_panel_driver(struct mipi_dsi_northwest_panel_driver *panel_drv);
/* Enable the mipi dsi display */
int mipi_dsi_northwest_enable(void);
/* Disable and shutdown the mipi dsi display */
int mipi_dsi_northwest_shutdown(void);
void hx8363_init(void);
#endif

View File

@ -1403,7 +1403,6 @@ CONFIG_MXC_KPD
CONFIG_MXC_KPD_COLMAX
CONFIG_MXC_KPD_ROWMAX
CONFIG_MXC_MCI_REGS_BASE
CONFIG_MXC_MIPI_DSI_NORTHWEST
CONFIG_MXC_NAND_HWECC
CONFIG_MXC_NAND_IP_REGS_BASE
CONFIG_MXC_NAND_REGS_BASE