Re: [RFC PATCH 1/4] mipi-dsi-bus: add MIPI DSI bus support
On 10/07/2013 12:47 PM, Bert Kenward wrote: > On Tuesday September 24 2013 at 15:23, Andrzej Hajda wrote: >> MIPI DSI is a high-speed serial interface to transmit >> data from/to host to display module. >> >> Signed-off-by: Andrzej Hajda >> Signed-off-by: Kyungmin Park >> --- >> drivers/video/display/Kconfig| 4 + >> drivers/video/display/Makefile | 1 + >> drivers/video/display/mipi-dsi-bus.c | 332 >> +++ >> include/video/display.h | 3 + >> include/video/mipi-dsi-bus.h | 144 +++ >> 5 files changed, 484 insertions(+) > >> diff --git a/include/video/mipi-dsi-bus.h b/include/video/mipi-dsi-bus.h >> new file mode 100644 >> index 000..a78792d >> --- /dev/null >> +++ b/include/video/mipi-dsi-bus.h >> @@ -0,0 +1,144 @@ >> +/* >> + * MIPI DSI Bus >> + * >> + * Copyright (C) 2013, Samsung Electronics, Co., Ltd. >> + * Andrzej Hajda >> + * >> + * This program is free software; you can redistribute it and/or modify >> + * it under the terms of the GNU General Public License version 2 as >> + * published by the Free Software Foundation. >> + */ >> + >> +#ifndef __MIPI_DSI_BUS_H__ >> +#define __MIPI_DSI_BUS_H__ >> + >> +#include >> +#include >> + >> +struct mipi_dsi_bus; >> +struct mipi_dsi_device; >> + >> +struct mipi_dsi_bus_ops { >> +int (*set_power)(struct mipi_dsi_bus *bus, struct mipi_dsi_device >> *dev, >> + bool on); >> +int (*set_stream)(struct mipi_dsi_bus *bus, struct mipi_dsi_device >> *dev, >> + bool on); >> +int (*transfer)(struct mipi_dsi_bus *bus, struct mipi_dsi_device >> *dev, >> +u8 type, const u8 *tx_buf, size_t tx_len, u8 *rx_buf, >> +size_t rx_len); >> +}; >> + >> +#define DSI_MODE_VIDEO (1 << 0) >> +#define DSI_MODE_VIDEO_BURST(1 << 1) >> +#define DSI_MODE_VIDEO_SYNC_PULSE (1 << 2) >> +#define DSI_MODE_VIDEO_AUTO_VERT(1 << 3) >> +#define DSI_MODE_VIDEO_HSE (1 << 4) >> +#define DSI_MODE_VIDEO_HFP (1 << 5) >> +#define DSI_MODE_VIDEO_HBP (1 << 6) >> +#define DSI_MODE_VIDEO_HSA (1 << 7) >> +#define DSI_MODE_VSYNC_FLUSH(1 << 8) >> +#define DSI_MODE_EOT_PACKET (1 << 9) >> + >> +enum mipi_dsi_pixel_format { >> +DSI_FMT_RGB888, >> +DSI_FMT_RGB666, >> +DSI_FMT_RGB666_PACKED, >> +DSI_FMT_RGB565, >> +}; >> + >> +struct mipi_dsi_interface_params { >> +enum mipi_dsi_pixel_format format; >> +unsigned long mode; >> +unsigned long hs_clk_freq; >> +unsigned long esc_clk_freq; >> +unsigned char data_lanes; >> +unsigned char cmd_allow; >> +}; >> + >> +struct mipi_dsi_bus { >> +struct device *dev; >> +const struct mipi_dsi_bus_ops *ops; >> +}; >> + >> +#define MIPI_DSI_MODULE_PREFIX "mipi-dsi:" >> +#define MIPI_DSI_NAME_SIZE 32 >> + >> +struct mipi_dsi_device_id { >> +char name[MIPI_DSI_NAME_SIZE]; >> +__kernel_ulong_t driver_data/* Data private to the driver */ >> +__aligned(sizeof(__kernel_ulong_t)); >> +}; >> + >> +struct mipi_dsi_device { >> +char name[MIPI_DSI_NAME_SIZE]; >> +int id; >> +struct device dev; >> + >> +const struct mipi_dsi_device_id *id_entry; >> +struct mipi_dsi_bus *bus; >> +struct videomode vm; >> +struct mipi_dsi_interface_params params; >> +}; >> + >> +#define to_mipi_dsi_device(d) container_of(d, struct >> mipi_dsi_device, dev) >> + >> +int mipi_dsi_device_register(struct mipi_dsi_device *dev, >> + struct mipi_dsi_bus *bus); >> +void mipi_dsi_device_unregister(struct mipi_dsi_device *dev); >> + >> +struct mipi_dsi_driver { >> +int(*probe)(struct mipi_dsi_device *); >> +int(*remove)(struct mipi_dsi_device *); >> +struct device_driver driver; >> +const struct mipi_dsi_device_id *id_table; >> +}; >> + >> +#define to_mipi_dsi_driver(d) container_of(d, struct >> mipi_dsi_driver, driver) >> + >> +int mipi_dsi_driver_register(struct mipi_dsi_driver *drv); >> +void mipi_dsi_driver_unregister(struct mipi_dsi_driver *drv); >> + >> +static inline void *mipi_dsi_get_drvdata(const struct mipi_dsi_device >> *dev) >> +{ >> +return dev_get_drvdata(&dev->dev); >> +} >> + >> +static inline void mipi_dsi_set_drvdata(struct mipi_dsi_device *dev, >> +void *data) >> +{ >> +dev_set_drvdata(&dev->dev, data); >> +} >> + >> +int of_mipi_dsi_register_devices(struct mipi_dsi_bus *bus); >> +void mipi_dsi_unregister_devices(struct mipi_dsi_bus *bus); >> + >> +/* module_mipi_dsi_driver() - Helper macro for drivers that don't do >> + * anything special in module init/exit. This eliminates a lot of >> + * boilerplate. Each module may only use this macro once, and >> + * calling it replaces module_init() and module_exit() >> + */ >> +#define module_mipi_dsi_driver(__mipi_dsi_driver) \ >> +module_driver(__mi
RE: [RFC PATCH 1/4] mipi-dsi-bus: add MIPI DSI bus support
On Tuesday September 24 2013 at 15:23, Andrzej Hajda wrote: > MIPI DSI is a high-speed serial interface to transmit > data from/to host to display module. > > Signed-off-by: Andrzej Hajda > Signed-off-by: Kyungmin Park > --- > drivers/video/display/Kconfig| 4 + > drivers/video/display/Makefile | 1 + > drivers/video/display/mipi-dsi-bus.c | 332 > +++ > include/video/display.h | 3 + > include/video/mipi-dsi-bus.h | 144 +++ > 5 files changed, 484 insertions(+) diff --git a/include/video/mipi-dsi-bus.h b/include/video/mipi-dsi-bus.h > new file mode 100644 > index 000..a78792d > --- /dev/null > +++ b/include/video/mipi-dsi-bus.h > @@ -0,0 +1,144 @@ > +/* > + * MIPI DSI Bus > + * > + * Copyright (C) 2013, Samsung Electronics, Co., Ltd. > + * Andrzej Hajda > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License version 2 as > + * published by the Free Software Foundation. > + */ > + > +#ifndef __MIPI_DSI_BUS_H__ > +#define __MIPI_DSI_BUS_H__ > + > +#include > +#include > + > +struct mipi_dsi_bus; > +struct mipi_dsi_device; > + > +struct mipi_dsi_bus_ops { > + int (*set_power)(struct mipi_dsi_bus *bus, struct mipi_dsi_device > *dev, > + bool on); > + int (*set_stream)(struct mipi_dsi_bus *bus, struct mipi_dsi_device > *dev, > + bool on); > + int (*transfer)(struct mipi_dsi_bus *bus, struct mipi_dsi_device > *dev, > + u8 type, const u8 *tx_buf, size_t tx_len, u8 *rx_buf, > + size_t rx_len); > +}; > + > +#define DSI_MODE_VIDEO (1 << 0) > +#define DSI_MODE_VIDEO_BURST (1 << 1) > +#define DSI_MODE_VIDEO_SYNC_PULSE(1 << 2) > +#define DSI_MODE_VIDEO_AUTO_VERT (1 << 3) > +#define DSI_MODE_VIDEO_HSE (1 << 4) > +#define DSI_MODE_VIDEO_HFP (1 << 5) > +#define DSI_MODE_VIDEO_HBP (1 << 6) > +#define DSI_MODE_VIDEO_HSA (1 << 7) > +#define DSI_MODE_VSYNC_FLUSH (1 << 8) > +#define DSI_MODE_EOT_PACKET (1 << 9) > + > +enum mipi_dsi_pixel_format { > + DSI_FMT_RGB888, > + DSI_FMT_RGB666, > + DSI_FMT_RGB666_PACKED, > + DSI_FMT_RGB565, > +}; > + > +struct mipi_dsi_interface_params { > + enum mipi_dsi_pixel_format format; > + unsigned long mode; > + unsigned long hs_clk_freq; > + unsigned long esc_clk_freq; > + unsigned char data_lanes; > + unsigned char cmd_allow; > +}; > + > +struct mipi_dsi_bus { > + struct device *dev; > + const struct mipi_dsi_bus_ops *ops; > +}; > + > +#define MIPI_DSI_MODULE_PREFIX "mipi-dsi:" > +#define MIPI_DSI_NAME_SIZE 32 > + > +struct mipi_dsi_device_id { > + char name[MIPI_DSI_NAME_SIZE]; > + __kernel_ulong_t driver_data/* Data private to the driver */ > + __aligned(sizeof(__kernel_ulong_t)); > +}; > + > +struct mipi_dsi_device { > + char name[MIPI_DSI_NAME_SIZE]; > + int id; > + struct device dev; > + > + const struct mipi_dsi_device_id *id_entry; > + struct mipi_dsi_bus *bus; > + struct videomode vm; > + struct mipi_dsi_interface_params params; > +}; > + > +#define to_mipi_dsi_device(d)container_of(d, struct > mipi_dsi_device, dev) > + > +int mipi_dsi_device_register(struct mipi_dsi_device *dev, > + struct mipi_dsi_bus *bus); > +void mipi_dsi_device_unregister(struct mipi_dsi_device *dev); > + > +struct mipi_dsi_driver { > + int(*probe)(struct mipi_dsi_device *); > + int(*remove)(struct mipi_dsi_device *); > + struct device_driver driver; > + const struct mipi_dsi_device_id *id_table; > +}; > + > +#define to_mipi_dsi_driver(d)container_of(d, struct > mipi_dsi_driver, driver) > + > +int mipi_dsi_driver_register(struct mipi_dsi_driver *drv); > +void mipi_dsi_driver_unregister(struct mipi_dsi_driver *drv); > + > +static inline void *mipi_dsi_get_drvdata(const struct mipi_dsi_device > *dev) > +{ > + return dev_get_drvdata(&dev->dev); > +} > + > +static inline void mipi_dsi_set_drvdata(struct mipi_dsi_device *dev, > + void *data) > +{ > + dev_set_drvdata(&dev->dev, data); > +} > + > +int of_mipi_dsi_register_devices(struct mipi_dsi_bus *bus); > +void mipi_dsi_unregister_devices(struct mipi_dsi_bus *bus); > + > +/* module_mipi_dsi_driver() - Helper macro for drivers that don't do > + * anything special in module init/exit. This eliminates a lot of > + * boilerplate. Each module may only use this macro once, and > + * calling it replaces module_init() and module_exit() > + */ > +#define module_mipi_dsi_driver(__mipi_dsi_driver) \ > + module_driver(__mipi_dsi_driver, mipi_dsi_driver_register, \ > + mipi_dsi_driver_unregister) > + > +int mipi_dsi_set_power(struct mipi_dsi_device *dev, bool
[RFC PATCH 1/4] mipi-dsi-bus: add MIPI DSI bus support
MIPI DSI is a high-speed serial interface to transmit data from/to host to display module. Signed-off-by: Andrzej Hajda Signed-off-by: Kyungmin Park --- drivers/video/display/Kconfig| 4 + drivers/video/display/Makefile | 1 + drivers/video/display/mipi-dsi-bus.c | 332 +++ include/video/display.h | 3 + include/video/mipi-dsi-bus.h | 144 +++ 5 files changed, 484 insertions(+) create mode 100644 drivers/video/display/mipi-dsi-bus.c create mode 100644 include/video/mipi-dsi-bus.h diff --git a/drivers/video/display/Kconfig b/drivers/video/display/Kconfig index 9b482a8..619b05d 100644 --- a/drivers/video/display/Kconfig +++ b/drivers/video/display/Kconfig @@ -20,6 +20,10 @@ config DISPLAY_MIPI_DBI tristate default n +config DISPLAY_MIPI_DSI + tristate + default n + config DISPLAY_PANEL_DPI tristate "DPI (Parallel) Display Panels" ---help--- diff --git a/drivers/video/display/Makefile b/drivers/video/display/Makefile index d03c64a..b323fd4 100644 --- a/drivers/video/display/Makefile +++ b/drivers/video/display/Makefile @@ -3,6 +3,7 @@ display-y := display-core.o \ obj-$(CONFIG_DISPLAY_CORE) += display.o obj-$(CONFIG_DISPLAY_CONNECTOR_VGA)+= con-vga.o obj-$(CONFIG_DISPLAY_MIPI_DBI) += mipi-dbi-bus.o +obj-$(CONFIG_DISPLAY_MIPI_DSI) += mipi-dsi-bus.o obj-$(CONFIG_DISPLAY_PANEL_DPI)+= panel-dpi.o obj-$(CONFIG_DISPLAY_PANEL_R61505) += panel-r61505.o obj-$(CONFIG_DISPLAY_PANEL_R61517) += panel-r61517.o diff --git a/drivers/video/display/mipi-dsi-bus.c b/drivers/video/display/mipi-dsi-bus.c new file mode 100644 index 000..a194d92 --- /dev/null +++ b/drivers/video/display/mipi-dsi-bus.c @@ -0,0 +1,332 @@ +/* + * MIPI DSI Bus + * + * Copyright (C) 2012, Samsung Electronics, Co., Ltd. + * Andrzej Hajda + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* - + * Bus operations + */ + +int mipi_dsi_set_power(struct mipi_dsi_device *dev, bool on) +{ + const struct mipi_dsi_bus_ops *ops = dev->bus->ops; + + if (!ops->set_power) + return 0; + + return ops->set_power(dev->bus, dev, on); +} +EXPORT_SYMBOL_GPL(mipi_dsi_set_power); + +int mipi_dsi_set_stream(struct mipi_dsi_device *dev, bool on) +{ + const struct mipi_dsi_bus_ops *ops = dev->bus->ops; + + if (!ops->set_stream) + return 0; + + return ops->set_stream(dev->bus, dev, on); +} +EXPORT_SYMBOL_GPL(mipi_dsi_set_stream); + +int mipi_dsi_dcs_write(struct mipi_dsi_device *dev, int channel, const u8 *data, + size_t len) +{ + const struct mipi_dsi_bus_ops *ops = dev->bus->ops; + u8 type = channel << 6; + + if (!ops->transfer) + return -EINVAL; + + switch (len) { + case 0: + return -EINVAL; + case 1: + type |= MIPI_DSI_DCS_SHORT_WRITE; + break; + case 2: + type |= MIPI_DSI_DCS_SHORT_WRITE_PARAM; + break; + default: + type |= MIPI_DSI_DCS_LONG_WRITE; + } + + return ops->transfer(dev->bus, dev, type, data, len, NULL, 0); +} +EXPORT_SYMBOL_GPL(mipi_dsi_dcs_write); + +int mipi_dsi_dcs_read(struct mipi_dsi_device *dev, int channel, u8 cmd, + u8 *data, size_t len) +{ + const struct mipi_dsi_bus_ops *ops = dev->bus->ops; + u8 type = MIPI_DSI_DCS_READ | (channel << 6); + + if (!ops->transfer) + return -EINVAL; + + return ops->transfer(dev->bus, dev, type, &cmd, 1, data, len); +} +EXPORT_SYMBOL_GPL(mipi_dsi_dcs_read); + +/* - + * Bus type + */ + +static const struct mipi_dsi_device_id * +mipi_dsi_match_id(const struct mipi_dsi_device_id *id, + struct mipi_dsi_device *dev) +{ + while (id->name[0]) { + if (strcmp(dev->name, id->name) == 0) { + dev->id_entry = id; + return id; + } + id++; + } + return NULL; +} + +static int mipi_dsi_match(struct device *_dev, struct device_driver *_drv) +{ + struct mipi_dsi_device *dev = to_mipi_dsi_device(_dev); + struct mipi_dsi_driver *drv = to_mipi_dsi_driver(_drv); + + if (of_driver_match_device(_dev, _drv)) + return 1; + + if (drv->id_table) + return mipi_d