Hi all,
Just a reminder of the BoF on Thursday at 4pm (pacific time) at ELC; in particular, it looks like we'll be in the Mission room of the Parc 55 Wyndham. Remember that you don't need to be registered for the conference to attend the BoF, so Bay Area folks are encouraged to join in. Also, if you know of colleagues that are coming to ELC and might not be on this list, please forward this along so they can attend.
Here's a rough agenda:
- Aims, goals, and non-goals. - CDFv3 overview. - Considerations for Android. - Future direction.
In particular, I think it would be good to call out non-goals, especially for the initial version of the framework so that we have a basis that is genuinely useful to build upon.
For reference, the thread on Laurent's report from the FOSDEM BoF
http://lists.freedesktop.org/archives/dri-devel/2013-February/034576.html
cheers, -- Jesse Barker Principal Software Engineer ARM +1 (408) 576-1423
-- IMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person, use it for any purpose, or store or copy the information in any medium. Thank you.
Hi Jesse,
On Tuesday 19 February 2013 09:54:35 Jesse Barker wrote:
Hi all,
Just a reminder of the BoF on Thursday at 4pm (pacific time) at ELC; in particular, it looks like we'll be in the Mission room of the Parc 55 Wyndham. Remember that you don't need to be registered for the conference to attend the BoF, so Bay Area folks are encouraged to join in. Also, if you know of colleagues that are coming to ELC and might not be on this list, please forward this along so they can attend.
Here's a rough agenda:
- Aims, goals, and non-goals.
- CDFv3 overview.
While not exactly CDFv3, the following patch should serve as a basis for the BoF discussions. It shows the general direction in which I'm going for v3. As I don't have the necessary hardware with me to test the new implementation, the real v3 will need to be postponed after the ELC.
Please note that not all comments received on v2 (including those discussed during the FOSDEM meeting) have been taken into account yet, I'll smooth the rough edges down in the real v3.
- Considerations for Android.
- Future direction.
In particular, I think it would be good to call out non-goals, especially for the initial version of the framework so that we have a basis that is genuinely useful to build upon.
For reference, the thread on Laurent's report from the FOSDEM BoF
http://lists.freedesktop.org/archives/dri-devel/2013-February/034576.html
Signed-off-by: Laurent Pinchart laurent.pinchart@ideasonboard.com --- drivers/video/Kconfig | 1 + drivers/video/Makefile | 1 + drivers/video/display/Kconfig | 4 + drivers/video/display/Makefile | 1 + drivers/video/display/display-core.c | 377 +++++++++++++++++++++++++++++++++++ include/video/display.h | 293 +++++++++++++++++++++++++++ 6 files changed, 677 insertions(+) create mode 100644 drivers/video/display/Kconfig create mode 100644 drivers/video/display/Makefile create mode 100644 drivers/video/display/display-core.c create mode 100644 include/video/display.h
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 807c7fa..62c3d1a 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -2444,6 +2444,7 @@ source "drivers/video/omap/Kconfig" source "drivers/video/omap2/Kconfig" source "drivers/video/exynos/Kconfig" source "drivers/video/backlight/Kconfig" +source "drivers/video/display/Kconfig"
if VT source "drivers/video/console/Kconfig" diff --git a/drivers/video/Makefile b/drivers/video/Makefile index f592f3b..4a091d4 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -14,6 +14,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 index 0000000..1d533e7 --- /dev/null +++ b/drivers/video/display/Kconfig @@ -0,0 +1,4 @@ +menuconfig DISPLAY_CORE + tristate "Display Core" + ---help--- + Support common display framework for graphics devices. diff --git a/drivers/video/display/Makefile b/drivers/video/display/Makefile new file mode 100644 index 0000000..bd93496 --- /dev/null +++ b/drivers/video/display/Makefile @@ -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 index 0000000..7950e35 --- /dev/null +++ b/drivers/video/display/display-core.c @@ -0,0 +1,377 @@ +/* + * 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/err.h> +#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 LIST_HEAD(display_entity_list); +static DEFINE_MUTEX(display_entity_mutex); + +/* ----------------------------------------------------------------------------- + * Control operations + */ + +/** + * display_entity_set_state - Set the display entity operation state + * @entity: The display entity + * @state: Display entity operation state + * + * See &enum display_entity_state for information regarding the entity states. + * + * Return 0 on success or a negative error code otherwise. + */ +int display_entity_set_state(struct display_entity *entity, + enum display_entity_state state) +{ + int ret; + + if (entity->state == state) + return 0; + + ret = display_entity_call(entity, set_state, state); + if (ret < 0) + return ret; + + entity->state = state; + return 0; +} +EXPORT_SYMBOL_GPL(display_entity_set_state); + +/** + * display_entity_update - Update the display + * @entity: The display entity + * + * Make the display entity ready to receive pixel data and start frame transfer. + * This operation can only be called if the display entity is in STANDBY or ON + * state. + * + * The display entity will call the upstream entity in the video chain to start + * the video stream. + * + * Return 0 on success or a negative error code otherwise. + */ +int display_entity_update(struct display_entity *entity) +{ + return display_entity_call(entity, update); +} +EXPORT_SYMBOL_GPL(display_entity_update); + +/** + * display_entity_get_modes - Get video modes supported by the display entity + * @entity The display entity + * @modes: Pointer to an array of modes + * + * Fill the modes argument with a pointer to an array of video modes. The array + * is owned by the display entity. + * + * Return the number of supported modes on success (including 0 if no mode is + * supported) or a negative error code otherwise. + */ +int display_entity_get_modes(struct display_entity *entity, + const struct videomode **modes) +{ + return display_entity_call(entity, get_modes, modes); +} +EXPORT_SYMBOL_GPL(display_entity_get_modes); + +/** + * display_entity_get_size - Get display entity physical size + * @entity: The display entity + * @width: Physical width in millimeters + * @height: Physical height in millimeters + * + * When applicable, for instance for display panels, retrieve the display + * physical size in millimeters. + * + * Return 0 on success or a negative error code otherwise. + */ +int display_entity_get_size(struct display_entity *entity, + unsigned int *width, unsigned int *height) +{ + return display_entity_call(entity, get_size, width, height); +} +EXPORT_SYMBOL_GPL(display_entity_get_size); + +/** + * display_entity_get_params - Get display entity interface parameters + * @entity: The display entity + * @params: Pointer to interface parameters + * + * Fill the parameters structure pointed to by the params argument with display + * entity interface parameters. + * + * Return 0 on success or a negative error code otherwise. + */ +int display_entity_get_params(struct display_entity *entity, + struct display_entity_interface_params *params) +{ + return display_entity_call(entity, get_params, params); +} +EXPORT_SYMBOL_GPL(display_entity_get_params); + +/* ----------------------------------------------------------------------------- + * Video operations + */ + +/** + * display_entity_set_stream - Control the video stream state + * @source: The video source port + * @state: Display video stream state + * + * Control the video stream state at the given entity video source port. + * + * See &enum display_entity_stream_state for information regarding the stream + * states. + * + * Return 0 on success or a negative error code otherwise. + */ +int display_entity_set_stream(struct display_entity_port *source, + enum display_entity_stream_state state) +{ + return display_entity_port_call(source, common, set_stream, state); +} +EXPORT_SYMBOL_GPL(display_entity_set_stream); + +/* ----------------------------------------------------------------------------- + * Connections + */ + +/* + * display_entity_get_source - Get the source port of the given entity + * @entity: the entity + * + * See display_entity_register() for information about how the source port is + * located. + * + * Return a pointer to the source port if found, NULL if the entity has no + * source port, or an error pointer otherwise. If the source port is validly + * specified but can't be located, return ERR_PTR(-EPROBE_DEFER). + */ +static struct display_entity_port * +display_entity_get_source(struct display_entity *entity) +{ + struct display_entity *source; + unsigned int source_port; + + if (entity->of_node) { + struct device_node *np; + const __be32 *prop; + int size; + + prop = of_get_property(entity->of_node, "video-source", &size); + if (prop == NULL) + return NULL; + + if (size < sizeof(*prop) * 2) + return ERR_PTR(-EINVAL); + + np = of_find_node_by_phandle(be32_to_cpup(prop)); + if (!np) + return ERR_PTR(-EINVAL); + + source_port = be32_to_cpup(&prop[1]); + } else if (entity->source_name) { + source_port = entity->source_port; + + list_for_each_entry(source, &display_entity_list, list) { + if (!strcmp(source->name, entity->source_name)) + break; + } + } else { + return NULL; + } + + if (&source->list == &display_entity_list) + return ERR_PTR(-EPROBE_DEFER); + + if (source_port >= source->num_ports) + return ERR_PTR(-EINVAL); + + return &source->ports[source_port]; +} + +/* + * display_entity_bind - Bind an entity to its source port + * @entity: the entity + */ +static int display_entity_bind(struct display_entity *entity) +{ + struct display_entity_port *source; + int ret; + + if (entity->source) + return 0; + + mutex_lock(&display_entity_mutex); + + source = display_entity_get_source(entity); + if (IS_ERR_OR_NULL(source)) { + /* NULL means that the entity has no source. This is a valid + * situation, return 0 in that case. + */ + ret = PTR_ERR(source); + goto done; + } + + ret = display_entity_port_call(source, common, bind, entity); + if (ret < 0 && ret != -ENOIOCTLCMD) + goto done; + + display_entity_get(source->entity); + + source->sink = entity; + entity->source = source; + + ret = 0; + +done: + mutex_unlock(&display_entity_mutex); + return ret; +} + +/* + * display_entity_bind - Unbind an entity from its source port + * @entity: the entity + */ +static void display_entity_unbind(struct display_entity *entity) +{ + struct display_entity_port *source = entity->source; + + if (!source) + return; + + display_entity_port_call(source, common, unbind, entity); + + source->sink = NULL; + entity->source = NULL; + + display_entity_put(source->entity); +} + +/* ----------------------------------------------------------------------------- + * Registration + */ + +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); +} + +/** + * display_entity_get - get a reference to a display entity + * @display_entity: the display entity + * + * Return the display entity pointer. + */ +struct display_entity *display_entity_get(struct display_entity *entity) +{ + if (entity == NULL) + return NULL; + + if (try_module_get(entity->owner)) + return NULL; + + kref_get(&entity->ref); + return entity; +} +EXPORT_SYMBOL_GPL(display_entity_get); + +/** + * display_entity_put - release a reference to a display entity + * @display_entity: the display entity + * + * Releasing the last reference to a display entity releases the display entity + * itself. + */ +void display_entity_put(struct display_entity *entity) +{ + module_put(entity->owner); + kref_put(&entity->ref, display_entity_release); +} +EXPORT_SYMBOL_GPL(display_entity_put); + +/** + * display_entity_register - register a display entity + * @display_entity: display entity to be registered + * + * This function initializes the display entity, binds it to its source port + * and registers it. + * + * When the entity has an associated OF node, the source port if located using + * the video-source property that contains a phandle to the source entity and a + * port number. If the video-source property is absent, the entity is considered + * as having no source port + * + * For non-OF entities, the source_name and source_port fields are used to match + * ports using their entity name and port index. If the source_name field is + * NULL, the entity is considered as having no source port. + * + * An entity that has no source port will not be bound. This isn't considered as + * an error. + * + * Return 0 on success and a negative error code otherwise. If the source port + * is validly specified but can't be located, return -EPROBE_DEFER. + */ +int __must_check __display_entity_register(struct display_entity *entity, + struct module *owner) +{ + int ret; + + kref_init(&entity->ref); + entity->owner = owner; + entity->state = DISPLAY_ENTITY_STATE_OFF; + + ret = display_entity_bind(entity); + if (ret < 0) + return ret; + + 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); + +/** + * display_entity_unregister - unregister a display entity + * @display_entity: display entity to be unregistered + * + * Unregister the display entity. If no other reference to the entity exists the + * entity will be released and destroyed. + */ +void display_entity_unregister(struct display_entity *entity) +{ + mutex_lock(&display_entity_mutex); + list_del(&entity->list); + mutex_unlock(&display_entity_mutex); + + display_entity_unbind(entity); + display_entity_put(entity); +} +EXPORT_SYMBOL_GPL(display_entity_unregister); + +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 index 0000000..a80154f --- /dev/null +++ b/include/video/display.h @@ -0,0 +1,293 @@ +/* + * 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> + +struct display_entity; +struct videomode; + +/* ----------------------------------------------------------------------------- + * DSI + */ + +/* 22 pins means 1 clk lane and 10 data lanes */ +#define MIPI_DSI_MAX_PINS 22 + +struct mipi_dsi_pin_config { + unsigned int num_pins; + /* + * pin numbers in the following order: + * clk+, clk- + * data1+, data1- + * data2+, data2- + * ... + */ + unsigned int pins[MIPI_DSI_MAX_PINS]; +}; + +#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; +}; + +/* ----------------------------------------------------------------------------- + * Display Entity Port + */ + +/** + * struct display_entity_port - A display entity port + * @entity: entity that the port belongs to + * @index: port index in the entity (0-based) + * @sink: sink entity this port is connected to + */ +struct display_entity_port { + struct display_entity *entity; + unsigned int index; + + struct display_entity *sink; +}; + +/* ----------------------------------------------------------------------------- + * Display Entity Video Operations + */ + +/** + * enum display_entity_stream_state - State of a video stream + * @DISPLAY_ENTITY_STREAM_STOPPED: The video stream is stopped, no frames are + * transferred. + * @DISPLAY_ENTITY_STREAM_SINGLE_SHOT: The video stream has been started for + * single shot operation. The source entity will transfer a single frame + * and then stop. + * @DISPLAY_ENTITY_STREAM_CONTINUOUS: The video stream is running, frames are + * transferred continuously by the source entity. + */ +enum display_entity_stream_state { + DISPLAY_ENTITY_STREAM_STOPPED, + DISPLAY_ENTITY_STREAM_SINGLE_SHOT, + DISPLAY_ENTITY_STREAM_CONTINUOUS, +}; + +struct display_entity_video_common_ops { + int (*set_stream)(struct display_entity_port *port, + enum display_entity_stream_state state); + int (*bind)(struct display_entity_port *source, + struct display_entity *sink); + int (*unbind)(struct display_entity_port *source, + struct display_entity *sink); +}; + +struct display_entity_video_dpi_ops { + int (*set_videomode)(struct display_entity_port *port, + const struct videomode *vm); + int (*set_data_lines)(struct display_entity_port *port, int lines); +}; + +struct display_entity_video_dsi_ops { + /* enable/disable dsi bus */ + int (*enable)(struct display_entity_port *port); + int (*disable)(struct display_entity_port *port); + + /* bus configuration */ + int (*configure_pins)(struct display_entity_port *port, + const struct mipi_dsi_pin_config *pins); + int (*set_clocks)(struct display_entity_port *port, + unsigned long ddr_clk, unsigned long lp_clk); + /* NOTE: Do we really need configure_pins and set_clocks here? */ + + void (*enable_hs)(struct display_entity_port *port, bool enable); + + /* data transfer */ + int (*dcs_write)(struct display_entity_port *port, int channel, + const u8 *data, size_t len); + int (*dcs_read)(struct display_entity_port *port, int channel, + u8 dcs_cmd, u8 *data, size_t len); + /* NOTE: Do we need more write and read types? */ + + int (*update)(struct display_entity_port *port, int channel, + void (*callback)(int, void *), void *data); +}; + +struct display_entity_video_dvi_ops { + int (*set_videomode)(struct display_entity_port *port, + const struct videomode *vm); +}; + +struct display_entity_video_ops { + const struct display_entity_video_common_ops *common; + union { + const struct display_entity_video_dpi_ops *dpi; + const struct display_entity_video_dsi_ops *dsi; + const struct display_entity_video_dvi_ops *dvi; + }; +}; + +/* ----------------------------------------------------------------------------- + * Display Entity Control + */ + +/** + * enum display_entity_state - State of a display entity + * @DISPLAY_ENTITY_STATE_OFF: The entity is turned off completely, possibly + * including its power supplies. Communication with a display entity in + * that state is not possible. + * @DISPLAY_ENTITY_STATE_STANDBY: The entity is in a low-power state. Full + * communication with the display entity is supported, including pixel data + * transfer, but the output is kept blanked. + * @DISPLAY_ENTITY_STATE_ON: The entity is fully operational. + */ +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, + DISPLAY_ENTITY_INTERFACE_DVI, +}; + +struct display_entity_interface_params { + enum display_entity_interface_type type; + union { + struct mipi_dsi_interface_params dsi; + } u; +}; + +struct display_entity_control_ops { + int (*set_state)(struct display_entity *entity, + enum display_entity_state state); + int (*update)(struct display_entity *entity); + int (*get_modes)(struct display_entity *entity, + const struct videomode **modes); + int (*get_params)(struct display_entity *entity, + struct display_entity_interface_params *params); + int (*get_size)(struct display_entity *entity, + unsigned int *width, unsigned int *height); +}; + +/* ----------------------------------------------------------------------------- + * Display Entity + */ + +/** + * struct display_entity - A display entity + * @list: list entry for entities list + * @dev: the owning device + * @owner: the owning module + * @name: the entity name + * @ref: reference count + * @release: entity refcount release function + * @port: array of data ports + * @num_ports: number of ports in the ports array + * @ops.ctrl: control operations, exposed to the entity user + * @ops.video: port-based video operations + * @source: video source port + * @state: display entity power state + */ +struct display_entity { + struct list_head list; + struct device *dev; + struct module *owner; + const char *name; + struct device_node *of_node; + + struct kref ref; + void(*release)(struct display_entity *ent); + + const char *source_name; + unsigned int source_port; + struct display_entity_port *source; + + struct display_entity_port *ports; + unsigned int num_ports; + + struct { + const struct display_entity_control_ops *ctrl; + const struct display_entity_video_ops *video; + } ops; + + enum display_entity_state state; +}; + +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) + +/* ----------------------------------------------------------------------------- + * Operation helpers + */ + +/* Call a display entity operation, checking for NULL pointers along the way. + * + * Return -ENODEV if the port or its entity is NULL, -ENOIOCTLCMD if the + * operation isn't implemented by the entity, or the entity return value + * otherwise. + */ +#define display_entity_port_call(port, o, f, args...) \ + (!(port) || !(port)->entity ? -ENODEV : \ + ((!(port)->entity->ops.video->o || \ + !(port)->entity->ops.video->o->f) ? -ENOIOCTLCMD : \ + (port)->entity->ops.video->o->f((port) , ##args))) + +#define display_entity_call(entity, f, args...) \ + (!(entity) ? -ENODEV : \ + (((entity)->ops.ctrl && (entity)->ops.ctrl->f) ? \ + (entity)->ops.ctrl->f((entity) , ##args) : -ENOIOCTLCMD)) + +int display_entity_set_state(struct display_entity *entity, + enum display_entity_state state); +int display_entity_update(struct display_entity *entity); +int display_entity_get_modes(struct display_entity *entity, + const struct videomode **modes); +int display_entity_get_params(struct display_entity *entity, + struct display_entity_interface_params *params); +int display_entity_get_size(struct display_entity *entity, + unsigned int *width, unsigned int *height); + +int display_entity_set_stream(struct display_entity_port *source, + enum display_entity_stream_state state); + +#endif /* __DISPLAY_H__ */
linaro-mm-sig@lists.linaro.org