video: add display-core
authorTomasz Figa <t.figa@samsung.com>
Wed, 30 Jan 2013 10:07:46 +0000 (11:07 +0100)
committerChanho Park <chanho61.park@samsung.com>
Tue, 18 Nov 2014 02:42:31 +0000 (11:42 +0900)
Signed-off-by: Tomasz Figa <t.figa@samsung.com>
drivers/video/Kconfig
drivers/video/Makefile
drivers/video/display/Kconfig [new file with mode: 0644]
drivers/video/display/Makefile [new file with mode: 0644]
drivers/video/display/display-core.c [new file with mode: 0644]
include/video/display.h [new file with mode: 0644]

index 2e937bd..6d9788d 100644 (file)
@@ -2475,6 +2475,7 @@ source "drivers/video/omap2/Kconfig"
 source "drivers/video/exynos/Kconfig"
 source "drivers/video/mmp/Kconfig"
 source "drivers/video/backlight/Kconfig"
+source "drivers/video/display/Kconfig"
 
 if VT
        source "drivers/video/console/Kconfig"
index e8bae8d..d7fd4a2 100644 (file)
@@ -15,6 +15,7 @@ fb-objs                           := $(fb-y)
 obj-$(CONFIG_VT)                 += console/
 obj-$(CONFIG_LOGO)               += logo/
 obj-y                            += backlight/
+obj-y                            += display/
 
 obj-$(CONFIG_EXYNOS_VIDEO)     += exynos/
 
diff --git a/drivers/video/display/Kconfig b/drivers/video/display/Kconfig
new file mode 100644 (file)
index 0000000..477192d
--- /dev/null
@@ -0,0 +1,10 @@
+menuconfig DISPLAY_CORE
+       tristate "Display Core"
+       ---help---
+         Support common display framework for graphics devices.
+
+if DISPLAY_CORE
+
+
+
+endif # DISPLAY_CORE
diff --git a/drivers/video/display/Makefile b/drivers/video/display/Makefile
new file mode 100644 (file)
index 0000000..bd93496
--- /dev/null
@@ -0,0 +1 @@
+obj-$(CONFIG_DISPLAY_CORE) += display-core.o
diff --git a/drivers/video/display/display-core.c b/drivers/video/display/display-core.c
new file mode 100644 (file)
index 0000000..9c93aae
--- /dev/null
@@ -0,0 +1,295 @@
+/*
+ * Display Core
+ *
+ * Copyright (C) 2012 Renesas Solutions Corp.
+ *
+ * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *
+ * 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 <linux/export.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+
+#include <video/display.h>
+#include <video/videomode.h>
+
+static struct video_source *video_source_bind(struct display_entity *entity);
+static void video_source_unbind(struct display_entity *entity);
+
+/* -----------------------------------------------------------------------------
+ * Display Entity
+ */
+
+static LIST_HEAD(display_entity_list);
+static DEFINE_MUTEX(display_entity_mutex);
+
+struct display_entity *display_entity_get_first(void)
+{
+       /* FIXME: Don't we need some locking here? */
+
+       if (list_empty(&display_entity_list))
+               return NULL;
+
+       return list_first_entry(&display_entity_list, struct display_entity,
+                       list);
+}
+EXPORT_SYMBOL(display_entity_get_first);
+
+int display_entity_set_state(struct display_entity *entity,
+                            enum display_entity_state state)
+{
+       int ret;
+
+       if (entity->state == state)
+               return 0;
+
+       if (!entity->ops || !entity->ops->set_state)
+               return 0;
+
+       ret = entity->ops->set_state(entity, state);
+       if (ret < 0)
+               return ret;
+
+       entity->state = state;
+       return 0;
+}
+EXPORT_SYMBOL_GPL(display_entity_set_state);
+
+int display_entity_get_modes(struct display_entity *entity,
+                            const struct videomode **modes)
+{
+       if (!entity->ops || !entity->ops->get_modes)
+               return 0;
+
+       return entity->ops->get_modes(entity, modes);
+}
+EXPORT_SYMBOL_GPL(display_entity_get_modes);
+
+int display_entity_get_size(struct display_entity *entity,
+                           unsigned int *width, unsigned int *height)
+{
+       if (!entity->ops || !entity->ops->get_size)
+               return -EOPNOTSUPP;
+
+       return entity->ops->get_size(entity, width, height);
+}
+EXPORT_SYMBOL_GPL(display_entity_get_size);
+
+int display_entity_get_params(struct display_entity *entity,
+                             struct display_entity_interface_params *params)
+{
+       if (!entity->ops || !entity->ops->get_params)
+               return -EOPNOTSUPP;
+
+       return entity->ops->get_params(entity, params);
+}
+EXPORT_SYMBOL_GPL(display_entity_get_params);
+
+static void display_entity_release(struct kref *ref)
+{
+       struct display_entity *entity =
+               container_of(ref, struct display_entity, ref);
+
+       if (entity->release)
+               entity->release(entity);
+}
+
+struct display_entity *display_entity_get(struct display_entity *entity)
+{
+       if (entity == NULL)
+               return NULL;
+
+       kref_get(&entity->ref);
+       return entity;
+}
+EXPORT_SYMBOL_GPL(display_entity_get);
+
+void display_entity_put(struct display_entity *entity)
+{
+       kref_put(&entity->ref, display_entity_release);
+}
+EXPORT_SYMBOL_GPL(display_entity_put);
+
+int __must_check __display_entity_register(struct display_entity *entity,
+                                          struct module *owner)
+{
+       struct video_source *src;
+
+       kref_init(&entity->ref);
+       entity->owner = owner;
+       entity->state = DISPLAY_ENTITY_STATE_OFF;
+       entity->source = NULL;
+
+       src = video_source_bind(entity);
+       if (!src)
+               return -EPROBE_DEFER;
+
+       mutex_lock(&display_entity_mutex);
+       list_add(&entity->list, &display_entity_list);
+       mutex_unlock(&display_entity_mutex);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(__display_entity_register);
+
+void display_entity_unregister(struct display_entity *entity)
+{
+       video_source_unbind(entity);
+
+       mutex_lock(&display_entity_mutex);
+
+       list_del(&entity->list);
+       mutex_unlock(&display_entity_mutex);
+
+       display_entity_put(entity);
+}
+EXPORT_SYMBOL_GPL(display_entity_unregister);
+
+/* -----------------------------------------------------------------------------
+ * Video Source
+ */
+
+static LIST_HEAD(video_source_list);
+static DEFINE_MUTEX(video_source_mutex);
+
+static void video_source_release(struct kref *ref)
+{
+       struct video_source *src =
+               container_of(ref, struct video_source, ref);
+
+       if (src->release)
+               src->release(src);
+}
+
+static struct video_source *video_source_get(struct video_source *src)
+{
+       if (src == NULL)
+               return NULL;
+
+       kref_get(&src->ref);
+       if (!try_module_get(src->owner)) {
+               kref_put(&src->ref, video_source_release);
+               return NULL;
+       }
+
+       return src;
+}
+
+static void video_source_put(struct video_source *src)
+{
+       module_put(src->owner);
+       kref_put(&src->ref, video_source_release);
+}
+
+int __must_check __video_source_register(struct video_source *src,
+                                                       struct module *owner)
+{
+       kref_init(&src->ref);
+       src->owner = owner;
+
+       mutex_lock(&video_source_mutex);
+       list_add(&src->list, &video_source_list);
+
+       mutex_unlock(&video_source_mutex);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(__video_source_register);
+
+void video_source_unregister(struct video_source *src)
+{
+       mutex_lock(&video_source_mutex);
+
+       list_del(&src->list);
+       mutex_unlock(&video_source_mutex);
+
+       kref_put(&src->ref, video_source_release);
+}
+EXPORT_SYMBOL_GPL(video_source_unregister);
+
+static struct video_source *video_source_bind(struct display_entity *entity)
+{
+       struct video_source *src = NULL;
+       int ret;
+
+       if (entity->source)
+               return entity->source;
+
+       mutex_lock(&video_source_mutex);
+
+       if (entity->of_node) {
+               struct device_node *np;
+
+               np = of_parse_phandle(entity->of_node, "video-source", 0);
+               if (!np)
+                       goto unlock;
+
+               list_for_each_entry(src, &video_source_list, list) {
+                       if (src->of_node == np)
+                               goto found;
+               }
+
+               src = NULL;
+               goto unlock;
+       }
+
+       if (!entity->src_name)
+               goto unlock;
+
+       list_for_each_entry(src, &video_source_list, list) {
+               if (src->id != entity->src_id)
+                       continue;
+               if (!strcmp(src->name, entity->src_name))
+                       goto found;
+       }
+
+       src = NULL;
+       goto unlock;
+
+found:
+       video_source_get(src);
+
+       if (src->common_ops->bind) {
+               ret = src->common_ops->bind(src, entity);
+               if (ret != 0) {
+                       video_source_put(src);
+                       src = NULL;
+                       goto unlock;
+               }
+       }
+
+       src->sink = entity;
+       entity->source = src;
+
+unlock:
+       mutex_unlock(&video_source_mutex);
+
+       return src;
+}
+
+static void video_source_unbind(struct display_entity *entity)
+{
+       struct video_source *src = entity->source;
+
+       if (!src)
+               return;
+
+       if (src->common_ops && src->common_ops->unbind)
+               src->common_ops->unbind(src, entity);
+
+       src->sink = NULL;
+       entity->source = NULL;
+
+       video_source_put(src);
+}
+
+MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
+MODULE_DESCRIPTION("Display Core");
+MODULE_LICENSE("GPL");
diff --git a/include/video/display.h b/include/video/display.h
new file mode 100644 (file)
index 0000000..11d7032
--- /dev/null
@@ -0,0 +1,230 @@
+/*
+ * Display Core
+ *
+ * Copyright (C) 2012 Renesas Solutions Corp.
+ *
+ * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *
+ * 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 __DISPLAY_H__
+#define __DISPLAY_H__
+
+#include <linux/kref.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <video/omapdss.h>
+
+struct display_entity;
+struct video_source;
+struct videomode;
+
+/* -----------------------------------------------------------------------------
+ * Display Entity
+ */
+
+/* Hack to get the first registered display entity */
+struct display_entity *display_entity_get_first(void);
+
+enum display_entity_state {
+       DISPLAY_ENTITY_STATE_OFF,
+       DISPLAY_ENTITY_STATE_STANDBY,
+       DISPLAY_ENTITY_STATE_ON,
+};
+
+enum display_entity_interface_type {
+       DISPLAY_ENTITY_INTERFACE_DPI,
+       DISPLAY_ENTITY_INTERFACE_DSI,
+};
+
+#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 display_entity_interface_params {
+       enum display_entity_interface_type type;
+       union {
+               struct mipi_dsi_interface_params dsi;
+       } p;
+};
+
+struct display_entity_control_ops {
+       int (*set_state)(struct display_entity *ent,
+                        enum display_entity_state state);
+       int (*update)(struct display_entity *ent,
+                       void (*callback)(int, void *), void *data);
+       int (*get_modes)(struct display_entity *ent,
+                        const struct videomode **modes);
+       int (*get_params)(struct display_entity *ent,
+                         struct display_entity_interface_params *params);
+       int (*get_size)(struct display_entity *ent,
+                       unsigned int *width, unsigned int *height);
+};
+
+struct display_entity {
+       struct list_head list;
+       struct device *dev;
+       struct device_node *of_node;
+       struct module *owner;
+       struct kref ref;
+
+       const char *src_name;
+       int src_id;
+       struct video_source *source;
+
+       const struct display_entity_control_ops *ops;
+
+       void(*release)(struct display_entity *ent);
+
+       enum display_entity_state state;
+};
+
+int display_entity_set_state(struct display_entity *entity,
+                            enum display_entity_state state);
+int display_entity_get_params(struct display_entity *entity,
+                             struct display_entity_interface_params *params);
+int display_entity_get_modes(struct display_entity *entity,
+                            const struct videomode **modes);
+int display_entity_get_size(struct display_entity *entity,
+                           unsigned int *width, unsigned int *height);
+
+struct display_entity *display_entity_get(struct display_entity *entity);
+void display_entity_put(struct display_entity *entity);
+
+int __must_check __display_entity_register(struct display_entity *entity,
+                                          struct module *owner);
+void display_entity_unregister(struct display_entity *entity);
+
+#define display_entity_register(display_entity) \
+       __display_entity_register(display_entity, THIS_MODULE)
+
+
+/* -----------------------------------------------------------------------------
+ * Video Source
+ */
+
+enum video_source_stream_state {
+       DISPLAY_ENTITY_STREAM_STOPPED,
+       DISPLAY_ENTITY_STREAM_CONTINUOUS,
+};
+
+struct common_video_source_ops {
+       int (*set_stream)(struct video_source *src,
+                        enum video_source_stream_state state);
+       int (*bind)(struct video_source *src, struct display_entity *sink);
+       int (*unbind)(struct video_source *src, struct display_entity *sink);
+};
+
+struct dpi_video_source_ops {
+       int (*set_videomode)(struct video_source *src,
+                       const struct videomode *vm);
+       int (*set_data_lines)(struct video_source *src, int lines);
+};
+
+struct dsi_video_source_ops {
+       /* enable/disable dsi bus */
+       int (*enable)(struct video_source *src);
+       int (*disable)(struct video_source *src);
+
+       /* bus configuration */
+       int (*configure_pins)(struct video_source *src,
+                       const struct omap_dsi_pin_config *pins);
+       int (*set_clocks)(struct video_source *src,
+                       unsigned long ddr_clk,
+                       unsigned long lp_clk);
+       /* NOTE: Do we really need configure_pins and set_clocks here? */
+
+       void (*enable_hs)(struct video_source *src, bool enable);
+
+       /* data transfer */
+       int (*dcs_write)(struct video_source *src, int channel,
+                       const u8 *data, size_t len);
+       int (*dcs_read)(struct video_source *src, int channel, u8 dcs_cmd,
+                       u8 *data, size_t len);
+       /* NOTE: Do we need more write and read types? */
+
+       int (*update)(struct video_source *src, int channel,
+                       void (*callback)(int, void *), void *data);
+};
+
+struct dvi_video_source_ops {
+       int (*set_videomode)(struct video_source *src,
+                       const struct videomode *vm);
+};
+
+struct video_source {
+       struct list_head list;
+       struct device *dev;
+       struct device_node *of_node;
+       struct module *owner;
+       struct kref ref;
+
+       struct display_entity *sink;
+
+       const char *name;
+       int id;
+
+       const struct common_video_source_ops *common_ops;
+
+       union {
+               const struct dpi_video_source_ops *dpi;
+               const struct dsi_video_source_ops *dsi;
+               const struct dvi_video_source_ops *dvi;
+       } ops;
+
+       void(*release)(struct video_source *src);
+};
+
+static inline int dsi_dcs_write(struct video_source *src, int channel,
+                                               const u8 *data, size_t len)
+{
+       if (!src->ops.dsi || !src->ops.dsi->dcs_write)
+               return -EINVAL;
+
+       return src->ops.dsi->dcs_write(src, channel, data, len);
+}
+
+static inline int dsi_dcs_read(struct video_source *src, int channel,
+                                       u8 dcs_cmd, u8 *data, size_t len)
+{
+       if (!src->ops.dsi || !src->ops.dsi->dcs_read)
+               return -EINVAL;
+
+       return src->ops.dsi->dcs_read(src, channel, dcs_cmd, data, len);
+}
+
+
+#define video_source_register(video_source) \
+       __video_source_register(video_source, THIS_MODULE)
+
+int __must_check __video_source_register(struct video_source *entity,
+                                                       struct module *owner);
+void video_source_unregister(struct video_source *entity);
+
+#endif /* __DISPLAY_H__ */