From 0a20012605033c8acd8b2c209c422d78880e2896 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Fri, 16 Nov 2012 14:59:56 +0200 Subject: OMAPDSS: add pdata->default_display_name We can currently set the default display (i.e. the initial display) in the omapdss platform data by using a pointer to the default omap_dss_device. Internally omapdss uses the device's name to resolve the default display. As it's difficult to get the omap_dss_device pointer in the future, after we've changed the omapdss device model, this patch adds a new way to define the default display, by using the name of the display. Signed-off-by: Tomi Valkeinen Reviewed-by: Archit Taneja --- include/video/omapdss.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include/video') diff --git a/include/video/omapdss.h b/include/video/omapdss.h index aeb4e9a0c5d1..6462f689a16d 100644 --- a/include/video/omapdss.h +++ b/include/video/omapdss.h @@ -365,6 +365,7 @@ struct omap_dss_board_info { int num_devices; struct omap_dss_device **devices; struct omap_dss_device *default_device; + const char *default_display_name; int (*dsi_enable_pads)(int dsi_id, unsigned lane_mask); void (*dsi_disable_pads)(int dsi_id, unsigned lane_mask); int (*set_min_bus_tput)(struct device *dev, unsigned long r); -- cgit v1.2.3 From 805cc2d19cce6bbd25fcefa24de7259508729e8a Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Wed, 13 Mar 2013 13:56:42 +0200 Subject: OMAPDSS: add omap_dss_find_output() Add a support function to find a DSS output by given name. This is used in later patches to link the panels to DSS outputs. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/output.c | 13 +++++++++++++ include/video/omapdss.h | 1 + 2 files changed, 14 insertions(+) (limited to 'include/video') diff --git a/drivers/video/omap2/dss/output.c b/drivers/video/omap2/dss/output.c index 5214df63e0a9..3274628e0ea1 100644 --- a/drivers/video/omap2/dss/output.c +++ b/drivers/video/omap2/dss/output.c @@ -115,6 +115,19 @@ struct omap_dss_output *omap_dss_get_output(enum omap_dss_output_id id) } EXPORT_SYMBOL(omap_dss_get_output); +struct omap_dss_output *omap_dss_find_output(const char *name) +{ + struct omap_dss_output *out; + + list_for_each_entry(out, &output_list, list) { + if (strcmp(out->name, name) == 0) + return out; + } + + return NULL; +} +EXPORT_SYMBOL(omap_dss_find_output); + static const struct dss_mgr_ops *dss_mgr_ops; int dss_install_mgr_ops(const struct dss_mgr_ops *mgr_ops) diff --git a/include/video/omapdss.h b/include/video/omapdss.h index 6462f689a16d..0b4f718a63c8 100644 --- a/include/video/omapdss.h +++ b/include/video/omapdss.h @@ -780,6 +780,7 @@ int omap_dss_get_num_overlays(void); struct omap_overlay *omap_dss_get_overlay(int num); struct omap_dss_output *omap_dss_get_output(enum omap_dss_output_id id); +struct omap_dss_output *omap_dss_find_output(const char *name); int omapdss_output_set_device(struct omap_dss_output *out, struct omap_dss_device *dssdev); int omapdss_output_unset_device(struct omap_dss_output *out); -- cgit v1.2.3 From 12ca755ba1c8714175f55ac069d8b51d9448778c Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Wed, 13 Mar 2013 14:22:30 +0200 Subject: OMAPDSS: add omap_dss_find_output_by_node() Add a support function to find a DSS output by given DT node. This is used in later patches to link the panels to DSS outputs. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/output.c | 13 +++++++++++++ include/video/omapdss.h | 1 + 2 files changed, 14 insertions(+) (limited to 'include/video') diff --git a/drivers/video/omap2/dss/output.c b/drivers/video/omap2/dss/output.c index 3274628e0ea1..4d01001497f4 100644 --- a/drivers/video/omap2/dss/output.c +++ b/drivers/video/omap2/dss/output.c @@ -128,6 +128,19 @@ struct omap_dss_output *omap_dss_find_output(const char *name) } EXPORT_SYMBOL(omap_dss_find_output); +struct omap_dss_output *omap_dss_find_output_by_node(struct device_node *node) +{ + struct omap_dss_output *out; + + list_for_each_entry(out, &output_list, list) { + if (out->pdev->dev.of_node == node) + return out; + } + + return NULL; +} +EXPORT_SYMBOL(omap_dss_find_output_by_node); + static const struct dss_mgr_ops *dss_mgr_ops; int dss_install_mgr_ops(const struct dss_mgr_ops *mgr_ops) diff --git a/include/video/omapdss.h b/include/video/omapdss.h index 0b4f718a63c8..25a944e080b4 100644 --- a/include/video/omapdss.h +++ b/include/video/omapdss.h @@ -781,6 +781,7 @@ struct omap_overlay *omap_dss_get_overlay(int num); struct omap_dss_output *omap_dss_get_output(enum omap_dss_output_id id); struct omap_dss_output *omap_dss_find_output(const char *name); +struct omap_dss_output *omap_dss_find_output_by_node(struct device_node *node); int omapdss_output_set_device(struct omap_dss_output *out, struct omap_dss_device *dssdev); int omapdss_output_unset_device(struct omap_dss_output *out); -- cgit v1.2.3 From be8e8e1c62678765868c0bc7b8b5209c38af105c Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Tue, 23 Apr 2013 15:35:35 +0300 Subject: OMAPDSS: add helpers to get mgr or output from display Add two helper functions that can be used to find either the DSS output or the overlay manager that is connected to the given display. This hides how the output and the manager are actually connected, making it easier to change the connections in the future. Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/omapdrm/omap_drv.c | 5 ++++- drivers/video/omap2/dss/manager-sysfs.c | 4 +++- drivers/video/omap2/dss/output.c | 19 +++++++++++++++++++ drivers/video/omap2/omapfb/omapfb-ioctl.c | 9 +++++++-- drivers/video/omap2/omapfb/omapfb-main.c | 16 +++++++--------- include/video/omapdss.h | 3 +++ 6 files changed, 43 insertions(+), 13 deletions(-) (limited to 'include/video') diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c index 826586ffbe83..b3577cb367af 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.c +++ b/drivers/gpu/drm/omapdrm/omap_drv.c @@ -247,6 +247,9 @@ static int omap_modeset_init(struct drm_device *dev) struct drm_encoder *encoder = priv->encoders[i]; struct omap_dss_device *dssdev = omap_encoder_get_dssdev(encoder); + struct omap_dss_output *output; + + output = omapdss_find_output_from_display(dssdev); /* figure out which crtc's we can connect the encoder to: */ encoder->possible_crtcs = 0; @@ -259,7 +262,7 @@ static int omap_modeset_init(struct drm_device *dev) supported_outputs = dss_feat_get_supported_outputs(crtc_channel); - if (supported_outputs & dssdev->output->id) + if (supported_outputs & output->id) encoder->possible_crtcs |= (1 << id); } } diff --git a/drivers/video/omap2/dss/manager-sysfs.c b/drivers/video/omap2/dss/manager-sysfs.c index 9a2fb59b6f89..51046819f33b 100644 --- a/drivers/video/omap2/dss/manager-sysfs.c +++ b/drivers/video/omap2/dss/manager-sysfs.c @@ -78,7 +78,9 @@ static ssize_t manager_display_store(struct omap_overlay_manager *mgr, } if (dssdev) { - struct omap_dss_output *out = dssdev->output; + struct omap_dss_output *out; + + out = omapdss_find_output_from_display(dssdev); /* * a registered device should have an output connected to it diff --git a/drivers/video/omap2/dss/output.c b/drivers/video/omap2/dss/output.c index 4d01001497f4..ab2c0f0ab244 100644 --- a/drivers/video/omap2/dss/output.c +++ b/drivers/video/omap2/dss/output.c @@ -141,6 +141,25 @@ struct omap_dss_output *omap_dss_find_output_by_node(struct device_node *node) } EXPORT_SYMBOL(omap_dss_find_output_by_node); +struct omap_dss_output *omapdss_find_output_from_display(struct omap_dss_device *dssdev) +{ + return dssdev->output; +} +EXPORT_SYMBOL(omapdss_find_output_from_display); + +struct omap_overlay_manager *omapdss_find_mgr_from_display(struct omap_dss_device *dssdev) +{ + struct omap_dss_output *out; + + out = omapdss_find_output_from_display(dssdev); + + if (out == NULL) + return NULL; + + return out->manager; +} +EXPORT_SYMBOL(omapdss_find_mgr_from_display); + static const struct dss_mgr_ops *dss_mgr_ops; int dss_install_mgr_ops(const struct dss_mgr_ops *mgr_ops) diff --git a/drivers/video/omap2/omapfb/omapfb-ioctl.c b/drivers/video/omap2/omapfb/omapfb-ioctl.c index d30b45d72649..146b6f5428db 100644 --- a/drivers/video/omap2/omapfb/omapfb-ioctl.c +++ b/drivers/video/omap2/omapfb/omapfb-ioctl.c @@ -770,12 +770,17 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg) case OMAPFB_WAITFORVSYNC: DBG("ioctl WAITFORVSYNC\n"); - if (!display || !display->output || !display->output->manager) { + + if (!display) { r = -EINVAL; break; } - mgr = display->output->manager; + mgr = omapdss_find_mgr_from_display(display); + if (!mgr) { + r = -EINVAL; + break; + } r = mgr->wait_for_vsync(mgr); break; diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c index 856917b33616..cc8953c4faa1 100644 --- a/drivers/video/omap2/omapfb/omapfb-main.c +++ b/drivers/video/omap2/omapfb/omapfb-main.c @@ -2363,18 +2363,16 @@ static int omapfb_init_connections(struct omapfb2_device *fbdev, int i, r; struct omap_overlay_manager *mgr; - if (!def_dssdev->output) { - dev_err(fbdev->dev, "no output for the default display\n"); - return -EINVAL; - } - for (i = 0; i < fbdev->num_displays; ++i) { struct omap_dss_device *dssdev = fbdev->displays[i].dssdev; - struct omap_dss_output *out = dssdev->output; + struct omap_dss_output *out; - mgr = omap_dss_get_overlay_manager(out->dispc_channel); + out = omapdss_find_output_from_display(dssdev); + if (!out) + continue; - if (!mgr || !out) + mgr = omap_dss_get_overlay_manager(out->dispc_channel); + if (!mgr) continue; if (mgr->output) @@ -2383,7 +2381,7 @@ static int omapfb_init_connections(struct omapfb2_device *fbdev, mgr->set_output(mgr, out); } - mgr = def_dssdev->output->manager; + mgr = omapdss_find_mgr_from_display(def_dssdev); if (!mgr) { dev_err(fbdev->dev, "no ovl manager for the default display\n"); diff --git a/include/video/omapdss.h b/include/video/omapdss.h index 25a944e080b4..898f81247859 100644 --- a/include/video/omapdss.h +++ b/include/video/omapdss.h @@ -786,6 +786,9 @@ int omapdss_output_set_device(struct omap_dss_output *out, struct omap_dss_device *dssdev); int omapdss_output_unset_device(struct omap_dss_output *out); +struct omap_dss_output *omapdss_find_output_from_display(struct omap_dss_device *dssdev); +struct omap_overlay_manager *omapdss_find_mgr_from_display(struct omap_dss_device *dssdev); + void omapdss_default_get_resolution(struct omap_dss_device *dssdev, u16 *xres, u16 *yres); int omapdss_default_get_recommended_bpp(struct omap_dss_device *dssdev); -- cgit v1.2.3 From a7e71e7f9fc7924921081aa55ceafca00d2c9f49 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Wed, 8 May 2013 16:23:32 +0300 Subject: OMAPDSS: Implement display (dis)connect support We currently have two steps in panel initialization and startup: probing and enabling. After the panel has been probed, it's ready and can be configured and later enabled. This model is not enough with more complex display pipelines, where we may have, for example, two panels, of which only one can be used at a time, connected to the same video output. To support that kind of scenarios, we need to add new step to the initialization: connect. This patch adds support for connecting and disconnecting panels. After probe, but before connect, no panel ops should be called. When the connect is called, a proper video pipeline is established, and the panel is ready for use. If some part in the video pipeline is already connected (by some other panel), the connect call fails. One key difference with the old style setup is that connect() handles also connecting to the overlay manager. This means that the omapfb (or omapdrm) no longer needs to figure out which overlay manager to use, but it can just call connect() on the panel, and the proper overlay manager is connected by omapdss. This also allows us to add back the support for dynamic switching between two exclusive panels. However, the current panel device model is not changed to support this, as the new device model is implemented in the following patches and the old model will be removed. The new device model supports dynamic switching. Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/omapdrm/omap_crtc.c | 24 +++++++++++++++++ drivers/gpu/drm/omapdrm/omap_drv.c | 12 ++++++++- drivers/video/omap2/dss/apply.c | 14 ++++++++++ drivers/video/omap2/dss/core.c | 44 +++++++++++++++++++++++++++++++ drivers/video/omap2/dss/display-sysfs.c | 28 +++++++++++--------- drivers/video/omap2/dss/manager-sysfs.c | 45 ++++++++++++++++++++------------ drivers/video/omap2/dss/output.c | 14 ++++++++++ drivers/video/omap2/omapfb/omapfb-main.c | 25 ++++++++++-------- include/video/omapdss.h | 23 ++++++++++++++++ 9 files changed, 188 insertions(+), 41 deletions(-) (limited to 'include/video') diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c index 02075bfcd8fd..b2ab2f5d3cb9 100644 --- a/drivers/gpu/drm/omapdrm/omap_crtc.c +++ b/drivers/gpu/drm/omapdrm/omap_crtc.c @@ -94,6 +94,28 @@ uint32_t pipe2vbl(struct drm_crtc *crtc) static struct omap_crtc *omap_crtcs[8]; /* we can probably ignore these until we support command-mode panels: */ +static int omap_crtc_connect(struct omap_overlay_manager *mgr, + struct omap_dss_output *dst) +{ + if (mgr->output) + return -EINVAL; + + if ((mgr->supported_outputs & dst->id) == 0) + return -EINVAL; + + dst->manager = mgr; + mgr->output = dst; + + return 0; +} + +static void omap_crtc_disconnect(struct omap_overlay_manager *mgr, + struct omap_dss_output *dst) +{ + mgr->output->manager = NULL; + mgr->output = NULL; +} + static void omap_crtc_start_update(struct omap_overlay_manager *mgr) { } @@ -138,6 +160,8 @@ static void omap_crtc_unregister_framedone_handler( } static const struct dss_mgr_ops mgr_ops = { + .connect = omap_crtc_connect, + .disconnect = omap_crtc_disconnect, .start_update = omap_crtc_start_update, .enable = omap_crtc_enable, .disable = omap_crtc_disable, diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c index ff9b49276b81..c65dd0d6b01d 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.c +++ b/drivers/gpu/drm/omapdrm/omap_drv.c @@ -97,6 +97,7 @@ static int omap_modeset_init(struct drm_device *dev) int num_mgrs = dss_feat_get_num_mgrs(); int num_crtcs; int i, id = 0; + int r; omap_crtc_pre_init(); @@ -118,6 +119,7 @@ static int omap_modeset_init(struct drm_device *dev) struct drm_connector *connector; struct drm_encoder *encoder; enum omap_channel channel; + struct omap_overlay_manager *mgr; if (!dssdev->driver) { dev_warn(dev->dev, "%s has no driver.. skipping it\n", @@ -133,6 +135,13 @@ static int omap_modeset_init(struct drm_device *dev) continue; } + r = dssdev->driver->connect(dssdev); + if (r) { + dev_err(dev->dev, "could not connect display: %s\n", + dssdev->name); + continue; + } + encoder = omap_encoder_init(dev, dssdev); if (!encoder) { @@ -174,8 +183,9 @@ static int omap_modeset_init(struct drm_device *dev) * other possible channels to which the encoder can connect are * not considered. */ - channel = dssdev->output->dispc_channel; + mgr = omapdss_find_mgr_from_display(dssdev); + channel = mgr->id; /* * if this channel hasn't already been taken by a previously * allocated crtc, we create a new crtc for it diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c index c844071e8e28..dbd3c2f28a83 100644 --- a/drivers/video/omap2/dss/apply.c +++ b/drivers/video/omap2/dss/apply.c @@ -790,6 +790,18 @@ static void mgr_clear_shadow_dirty(struct omap_overlay_manager *mgr) } } +static int dss_mgr_connect_compat(struct omap_overlay_manager *mgr, + struct omap_dss_output *dst) +{ + return mgr->set_output(mgr, dst); +} + +static void dss_mgr_disconnect_compat(struct omap_overlay_manager *mgr, + struct omap_dss_output *dst) +{ + mgr->unset_output(mgr); +} + static void dss_mgr_start_update_compat(struct omap_overlay_manager *mgr) { struct mgr_priv_data *mp = get_mgr_priv(mgr); @@ -1552,6 +1564,8 @@ static void dss_mgr_unregister_framedone_handler_compat(struct omap_overlay_mana } static const struct dss_mgr_ops apply_mgr_ops = { + .connect = dss_mgr_connect_compat, + .disconnect = dss_mgr_disconnect_compat, .start_update = dss_mgr_start_update_compat, .enable = dss_mgr_enable_compat, .disable = dss_mgr_disable_compat, diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c index 710e9f9a4436..831abec565f2 100644 --- a/drivers/video/omap2/dss/core.c +++ b/drivers/video/omap2/dss/core.c @@ -379,6 +379,46 @@ static int dss_driver_remove(struct device *dev) return 0; } +static int omapdss_default_connect(struct omap_dss_device *dssdev) +{ + struct omap_dss_output *out; + struct omap_overlay_manager *mgr; + int r; + + out = dssdev->output; + + if (out == NULL) + return -ENODEV; + + mgr = omap_dss_get_overlay_manager(out->dispc_channel); + if (!mgr) + return -ENODEV; + + r = dss_mgr_connect(mgr, out); + if (r) + return r; + + return 0; +} + +static void omapdss_default_disconnect(struct omap_dss_device *dssdev) +{ + struct omap_dss_output *out; + struct omap_overlay_manager *mgr; + + out = dssdev->output; + + if (out == NULL) + return; + + mgr = out->manager; + + if (mgr == NULL) + return; + + dss_mgr_disconnect(mgr, out); +} + int omap_dss_register_driver(struct omap_dss_driver *dssdriver) { dssdriver->driver.bus = &dss_bus_type; @@ -392,6 +432,10 @@ int omap_dss_register_driver(struct omap_dss_driver *dssdriver) omapdss_default_get_recommended_bpp; if (dssdriver->get_timings == NULL) dssdriver->get_timings = omapdss_default_get_timings; + if (dssdriver->connect == NULL) + dssdriver->connect = omapdss_default_connect; + if (dssdriver->disconnect == NULL) + dssdriver->disconnect = omapdss_default_disconnect; return driver_register(&dssdriver->driver); } diff --git a/drivers/video/omap2/dss/display-sysfs.c b/drivers/video/omap2/dss/display-sysfs.c index 18211a9ab354..81d5dc6e509f 100644 --- a/drivers/video/omap2/dss/display-sysfs.c +++ b/drivers/video/omap2/dss/display-sysfs.c @@ -33,9 +33,9 @@ static ssize_t display_enabled_show(struct device *dev, struct device_attribute *attr, char *buf) { struct omap_dss_device *dssdev = to_dss_device(dev); - bool enabled = dssdev->state != OMAP_DSS_DISPLAY_DISABLED; - return snprintf(buf, PAGE_SIZE, "%d\n", enabled); + return snprintf(buf, PAGE_SIZE, "%d\n", + omapdss_device_is_enabled(dssdev)); } static ssize_t display_enabled_store(struct device *dev, @@ -44,20 +44,24 @@ static ssize_t display_enabled_store(struct device *dev, { struct omap_dss_device *dssdev = to_dss_device(dev); int r; - bool enabled; + bool enable; - r = strtobool(buf, &enabled); + r = strtobool(buf, &enable); if (r) return r; - if (enabled != (dssdev->state != OMAP_DSS_DISPLAY_DISABLED)) { - if (enabled) { - r = dssdev->driver->enable(dssdev); - if (r) - return r; - } else { - dssdev->driver->disable(dssdev); - } + if (enable == omapdss_device_is_enabled(dssdev)) + return size; + + if (omapdss_device_is_connected(dssdev) == false) + return -ENODEV; + + if (enable) { + r = dssdev->driver->enable(dssdev); + if (r) + return r; + } else { + dssdev->driver->disable(dssdev); } return size; diff --git a/drivers/video/omap2/dss/manager-sysfs.c b/drivers/video/omap2/dss/manager-sysfs.c index 72784b3aad27..de7e7b5b1b7c 100644 --- a/drivers/video/omap2/dss/manager-sysfs.c +++ b/drivers/video/omap2/dss/manager-sysfs.c @@ -50,6 +50,7 @@ static ssize_t manager_display_store(struct omap_overlay_manager *mgr, int r = 0; size_t len = size; struct omap_dss_device *dssdev = NULL; + struct omap_dss_device *old_dssdev; int match(struct omap_dss_device *dssdev, void *data) { @@ -66,34 +67,44 @@ static ssize_t manager_display_store(struct omap_overlay_manager *mgr, if (len > 0 && dssdev == NULL) return -EINVAL; - if (dssdev) + if (dssdev) { DSSDBG("display %s found\n", dssdev->name); - if (mgr->output) { - r = mgr->unset_output(mgr); - if (r) { - DSSERR("failed to unset current output\n"); + if (omapdss_device_is_connected(dssdev)) { + DSSERR("new display is already connected\n"); + r = -EINVAL; + goto put_device; + } + + if (omapdss_device_is_enabled(dssdev)) { + DSSERR("new display is not disabled\n"); + r = -EINVAL; goto put_device; } } - if (dssdev) { - struct omap_dss_output *out; + old_dssdev = mgr->get_device(mgr); + if (old_dssdev) { + if (omapdss_device_is_enabled(old_dssdev)) { + DSSERR("old display is not disabled\n"); + r = -EINVAL; + goto put_device; + } - out = omapdss_find_output_from_display(dssdev); + old_dssdev->driver->disconnect(old_dssdev); + } - /* - * a registered device should have an output connected to it - * already - */ - if (!out) { - DSSERR("device has no output connected to it\n"); + if (dssdev) { + r = dssdev->driver->connect(dssdev); + if (r) { + DSSERR("failed to connect new device\n"); goto put_device; } - r = mgr->set_output(mgr, out); - if (r) { - DSSERR("failed to set manager output\n"); + old_dssdev = mgr->get_device(mgr); + if (old_dssdev != dssdev) { + DSSERR("failed to connect device to this manager\n"); + dssdev->driver->disconnect(dssdev); goto put_device; } diff --git a/drivers/video/omap2/dss/output.c b/drivers/video/omap2/dss/output.c index ab2c0f0ab244..a53b08b2249b 100644 --- a/drivers/video/omap2/dss/output.c +++ b/drivers/video/omap2/dss/output.c @@ -179,6 +179,20 @@ void dss_uninstall_mgr_ops(void) } EXPORT_SYMBOL(dss_uninstall_mgr_ops); +int dss_mgr_connect(struct omap_overlay_manager *mgr, + struct omap_dss_output *dst) +{ + return dss_mgr_ops->connect(mgr, dst); +} +EXPORT_SYMBOL(dss_mgr_connect); + +void dss_mgr_disconnect(struct omap_overlay_manager *mgr, + struct omap_dss_output *dst) +{ + dss_mgr_ops->disconnect(mgr, dst); +} +EXPORT_SYMBOL(dss_mgr_disconnect); + void dss_mgr_set_timings(struct omap_overlay_manager *mgr, const struct omap_video_timings *timings) { diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c index cc8953c4faa1..528e453e8e11 100644 --- a/drivers/video/omap2/omapfb/omapfb-main.c +++ b/drivers/video/omap2/omapfb/omapfb-main.c @@ -1853,6 +1853,8 @@ static void omapfb_free_resources(struct omapfb2_device *fbdev) if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) dssdev->driver->disable(dssdev); + dssdev->driver->disconnect(dssdev); + omap_dss_put_device(dssdev); } @@ -2363,22 +2365,23 @@ static int omapfb_init_connections(struct omapfb2_device *fbdev, int i, r; struct omap_overlay_manager *mgr; + r = def_dssdev->driver->connect(def_dssdev); + if (r) { + dev_err(fbdev->dev, "failed to connect default display\n"); + return r; + } + for (i = 0; i < fbdev->num_displays; ++i) { struct omap_dss_device *dssdev = fbdev->displays[i].dssdev; - struct omap_dss_output *out; - out = omapdss_find_output_from_display(dssdev); - if (!out) + if (dssdev == def_dssdev) continue; - mgr = omap_dss_get_overlay_manager(out->dispc_channel); - if (!mgr) - continue; - - if (mgr->output) - mgr->unset_output(mgr); - - mgr->set_output(mgr, out); + /* + * We don't care if the connect succeeds or not. We just want to + * connect as many displays as possible. + */ + dssdev->driver->connect(dssdev); } mgr = omapdss_find_mgr_from_display(def_dssdev); diff --git a/include/video/omapdss.h b/include/video/omapdss.h index 898f81247859..4f52f523fba4 100644 --- a/include/video/omapdss.h +++ b/include/video/omapdss.h @@ -689,6 +689,9 @@ struct omap_dss_driver { int (*probe)(struct omap_dss_device *); void (*remove)(struct omap_dss_device *); + int (*connect)(struct omap_dss_device *dssdev); + void (*disconnect)(struct omap_dss_device *dssdev); + int (*enable)(struct omap_dss_device *display); void (*disable)(struct omap_dss_device *display); int (*run_test)(struct omap_dss_device *display, int test); @@ -889,6 +892,11 @@ int omapdss_compat_init(void); void omapdss_compat_uninit(void); struct dss_mgr_ops { + int (*connect)(struct omap_overlay_manager *mgr, + struct omap_dss_output *dst); + void (*disconnect)(struct omap_overlay_manager *mgr, + struct omap_dss_output *dst); + void (*start_update)(struct omap_overlay_manager *mgr); int (*enable)(struct omap_overlay_manager *mgr); void (*disable)(struct omap_overlay_manager *mgr); @@ -905,6 +913,10 @@ struct dss_mgr_ops { int dss_install_mgr_ops(const struct dss_mgr_ops *mgr_ops); void dss_uninstall_mgr_ops(void); +int dss_mgr_connect(struct omap_overlay_manager *mgr, + struct omap_dss_output *dst); +void dss_mgr_disconnect(struct omap_overlay_manager *mgr, + struct omap_dss_output *dst); void dss_mgr_set_timings(struct omap_overlay_manager *mgr, const struct omap_video_timings *timings); void dss_mgr_set_lcd_config(struct omap_overlay_manager *mgr, @@ -916,4 +928,15 @@ int dss_mgr_register_framedone_handler(struct omap_overlay_manager *mgr, void (*handler)(void *), void *data); void dss_mgr_unregister_framedone_handler(struct omap_overlay_manager *mgr, void (*handler)(void *), void *data); + +static inline bool omapdss_device_is_connected(struct omap_dss_device *dssdev) +{ + return dssdev->output; +} + +static inline bool omapdss_device_is_enabled(struct omap_dss_device *dssdev) +{ + return dssdev->state == OMAP_DSS_DISPLAY_ACTIVE; +} + #endif -- cgit v1.2.3 From 6fcd485b04e67c370026b41a951e0dc410a8d47b Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Fri, 10 May 2013 13:02:32 +0300 Subject: OMAPDSS: add videomode conversion support Add helper functions to convert between omapdss specific video timings and the common videomode. Eventually omapdss will be changed to use only the common video timings, and these helper functions will make the transition easier. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/Kconfig | 1 + drivers/video/omap2/dss/display.c | 69 +++++++++++++++++++++++++++++++++++++++ include/video/omapdss.h | 7 ++++ 3 files changed, 77 insertions(+) (limited to 'include/video') diff --git a/drivers/video/omap2/dss/Kconfig b/drivers/video/omap2/dss/Kconfig index cb0f145c7077..8f70a8300b84 100644 --- a/drivers/video/omap2/dss/Kconfig +++ b/drivers/video/omap2/dss/Kconfig @@ -1,5 +1,6 @@ menuconfig OMAP2_DSS tristate "OMAP2+ Display Subsystem support" + select VIDEOMODE_HELPERS help OMAP2+ Display Subsystem support. diff --git a/drivers/video/omap2/dss/display.c b/drivers/video/omap2/dss/display.c index 0aa8ad8f9667..72ac058a56d3 100644 --- a/drivers/video/omap2/dss/display.c +++ b/drivers/video/omap2/dss/display.c @@ -219,3 +219,72 @@ void omap_dss_stop_device(struct omap_dss_device *dssdev) } EXPORT_SYMBOL(omap_dss_stop_device); +void videomode_to_omap_video_timings(const struct videomode *vm, + struct omap_video_timings *ovt) +{ + memset(ovt, 0, sizeof(*ovt)); + + ovt->pixel_clock = vm->pixelclock / 1000; + ovt->x_res = vm->hactive; + ovt->hbp = vm->hback_porch; + ovt->hfp = vm->hfront_porch; + ovt->hsw = vm->hsync_len; + ovt->y_res = vm->vactive; + ovt->vbp = vm->vback_porch; + ovt->vfp = vm->vfront_porch; + ovt->vsw = vm->vsync_len; + + ovt->vsync_level = vm->flags & DISPLAY_FLAGS_VSYNC_HIGH ? + OMAPDSS_SIG_ACTIVE_HIGH : + OMAPDSS_SIG_ACTIVE_LOW; + ovt->hsync_level = vm->flags & DISPLAY_FLAGS_HSYNC_HIGH ? + OMAPDSS_SIG_ACTIVE_HIGH : + OMAPDSS_SIG_ACTIVE_LOW; + ovt->de_level = vm->flags & DISPLAY_FLAGS_DE_HIGH ? + OMAPDSS_SIG_ACTIVE_HIGH : + OMAPDSS_SIG_ACTIVE_HIGH; + ovt->data_pclk_edge = vm->flags & DISPLAY_FLAGS_PIXDATA_POSEDGE ? + OMAPDSS_DRIVE_SIG_RISING_EDGE : + OMAPDSS_DRIVE_SIG_FALLING_EDGE; + + ovt->sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES; +} +EXPORT_SYMBOL(videomode_to_omap_video_timings); + +void omap_video_timings_to_videomode(const struct omap_video_timings *ovt, + struct videomode *vm) +{ + memset(vm, 0, sizeof(*vm)); + + vm->pixelclock = ovt->pixel_clock * 1000; + + vm->hactive = ovt->x_res; + vm->hback_porch = ovt->hbp; + vm->hfront_porch = ovt->hfp; + vm->hsync_len = ovt->hsw; + vm->vactive = ovt->y_res; + vm->vback_porch = ovt->vbp; + vm->vfront_porch = ovt->vfp; + vm->vsync_len = ovt->vsw; + + if (ovt->hsync_level == OMAPDSS_SIG_ACTIVE_HIGH) + vm->flags |= DISPLAY_FLAGS_HSYNC_HIGH; + else + vm->flags |= DISPLAY_FLAGS_HSYNC_LOW; + + if (ovt->vsync_level == OMAPDSS_SIG_ACTIVE_HIGH) + vm->flags |= DISPLAY_FLAGS_VSYNC_HIGH; + else + vm->flags |= DISPLAY_FLAGS_VSYNC_LOW; + + if (ovt->de_level == OMAPDSS_SIG_ACTIVE_HIGH) + vm->flags |= DISPLAY_FLAGS_DE_HIGH; + else + vm->flags |= DISPLAY_FLAGS_DE_LOW; + + if (ovt->data_pclk_edge == OMAPDSS_DRIVE_SIG_RISING_EDGE) + vm->flags |= DISPLAY_FLAGS_PIXDATA_POSEDGE; + else + vm->flags |= DISPLAY_FLAGS_PIXDATA_NEGEDGE; +} +EXPORT_SYMBOL(omap_video_timings_to_videomode); diff --git a/include/video/omapdss.h b/include/video/omapdss.h index 4f52f523fba4..0324c7b8a3e0 100644 --- a/include/video/omapdss.h +++ b/include/video/omapdss.h @@ -23,6 +23,8 @@ #include #include +#include