Re: [RFC PATCH 1/4] mipi-dsi-bus: add MIPI DSI bus support

2013-10-11 Thread Andrzej Hajda
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

2013-10-07 Thread Bert Kenward
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

2013-09-25 Thread Andrzej Hajda
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