diff options
author | Tomi Valkeinen <tomi.valkeinen@ti.com> | 2012-09-26 17:46:29 +0400 |
---|---|---|
committer | Tomi Valkeinen <tomi.valkeinen@ti.com> | 2012-09-26 17:46:29 +0400 |
commit | 866f0956cba7d28432f20f8a696e5c1a2b40b915 (patch) | |
tree | 87b1d203cef69785448a7b07611314c2a203ae23 | |
parent | e84dc1cc1503150e3bc37268a0b0f0bc0097622c (diff) | |
parent | 3c2995ac34eb559106504be962b162aef215895b (diff) | |
download | linux-866f0956cba7d28432f20f8a696e5c1a2b40b915.tar.xz |
Merge branch 'archit/outputs-for-3.7'
Merge omapdss output work, that creates a new entity "output" to represent the
outputs (DPI, DSI, HDMI, ...) from DSS. An output sits in between an overlay
manager and a panel, and helps us to remove references to panel devices from
the omapdss core.
* archit/outputs-for-3.7: (23 commits)
OMAPDSS: Remove old way of setting manager and device links
OMAPDSS: APPLY: Remove omap_dss_device references from dss_ovl_enable/disable
OMAPDSS: OVERLAY/MANAGER: Get device via output
OMAPDSS: MANAGER: Update display sysfs store
OMAPFB: Change dssdev->manager references
OMAPDSS: HDMI: Replace dssdev->manager with dssdev->output->manager references
OMAPDSS: VENC: Replace dssdev->manager with dssdev->output->manager references
OMAPDSS: RFBI: Replace dssdev->manager with dssdev->output->manager references
OMAPDSS: SDI: Replace dssdev->manager with dssdev->output->manager references
OMAPDSS: DSI: Replace dssdev->manager with dssdev->output->manager references
OMAPDSS: DSI: Remove dsi_pdev_map global struct
OMAPDSS: DPI: Replace dssdev->manager with dssdev->output->manager references
OMAPDSS: Create links between managers, outputs and devices
OMAPDRM: Remove manager->device references
OMAPFB: remove manager->device references
OMAP_VOUT: Remove manager->device references
OMAPDSS: Remove manager->device references
OMAPDSS: APPLY: Add manager set/unset output ops for omap_overlay_manager
OMAPDSS: output: Add set/unset device ops for omap_dss_output
OMAPDSS: outputs: Create and register output instances
...
23 files changed, 743 insertions, 198 deletions
diff --git a/drivers/media/video/omap/omap_vout.c b/drivers/media/video/omap/omap_vout.c index 88cf9d952631..f721fd2155f7 100644 --- a/drivers/media/video/omap/omap_vout.c +++ b/drivers/media/video/omap/omap_vout.c @@ -454,11 +454,15 @@ static int omapvid_init(struct omap_vout_device *vout, u32 addr) win = &vout->win; for (i = 0; i < ovid->num_overlays; i++) { + struct omap_dss_device *dssdev; + ovl = ovid->overlays[i]; - if (!ovl->manager || !ovl->manager->device) + dssdev = ovl->get_device(ovl); + + if (!dssdev) return -EINVAL; - timing = &ovl->manager->device->panel.timings; + timing = &dssdev->panel.timings; outw = win->w.width; outh = win->w.height; @@ -515,8 +519,11 @@ static int omapvid_apply_changes(struct omap_vout_device *vout) struct omapvideo_info *ovid = &vout->vid_info; for (i = 0; i < ovid->num_overlays; i++) { + struct omap_dss_device *dssdev; + ovl = ovid->overlays[i]; - if (!ovl->manager || !ovl->manager->device) + dssdev = ovl->get_device(ovl); + if (!dssdev) return -EINVAL; ovl->manager->apply(ovl->manager); } @@ -579,12 +586,14 @@ static void omap_vout_isr(void *arg, unsigned int irqstatus) ovid = &vout->vid_info; ovl = ovid->overlays[0]; - /* get the display device attached to the overlay */ - if (!ovl->manager || !ovl->manager->device) - return; mgr_id = ovl->manager->id; - cur_display = ovl->manager->device; + + /* get the display device attached to the overlay */ + cur_display = ovl->get_device(ovl); + + if (!cur_display) + return; spin_lock(&vout->vbq_lock); do_gettimeofday(&timevalue); @@ -948,7 +957,9 @@ static int omap_vout_release(struct file *file) /* Disable all the overlay managers connected with this interface */ for (i = 0; i < ovid->num_overlays; i++) { struct omap_overlay *ovl = ovid->overlays[i]; - if (ovl->manager && ovl->manager->device) + struct omap_dss_device *dssdev = ovl->get_device(ovl); + + if (dssdev) ovl->disable(ovl); } /* Turn off the pipeline */ @@ -1081,14 +1092,17 @@ static int vidioc_try_fmt_vid_out(struct file *file, void *fh, struct omapvideo_info *ovid; struct omap_video_timings *timing; struct omap_vout_device *vout = fh; + struct omap_dss_device *dssdev; ovid = &vout->vid_info; ovl = ovid->overlays[0]; + /* get the display device attached to the overlay */ + dssdev = ovl->get_device(ovl); - if (!ovl->manager || !ovl->manager->device) + if (!dssdev) return -EINVAL; - /* get the display device attached to the overlay */ - timing = &ovl->manager->device->panel.timings; + + timing = &dssdev->panel.timings; vout->fbuf.fmt.height = timing->y_res; vout->fbuf.fmt.width = timing->x_res; @@ -1105,6 +1119,7 @@ static int vidioc_s_fmt_vid_out(struct file *file, void *fh, struct omapvideo_info *ovid; struct omap_video_timings *timing; struct omap_vout_device *vout = fh; + struct omap_dss_device *dssdev; if (vout->streaming) return -EBUSY; @@ -1113,13 +1128,14 @@ static int vidioc_s_fmt_vid_out(struct file *file, void *fh, ovid = &vout->vid_info; ovl = ovid->overlays[0]; + dssdev = ovl->get_device(ovl); /* get the display device attached to the overlay */ - if (!ovl->manager || !ovl->manager->device) { + if (!dssdev) { ret = -EINVAL; goto s_fmt_vid_out_exit; } - timing = &ovl->manager->device->panel.timings; + timing = &dssdev->panel.timings; /* We dont support RGB24-packed mode if vrfb rotation * is enabled*/ @@ -1298,6 +1314,7 @@ static int vidioc_s_crop(struct file *file, void *fh, struct v4l2_crop *crop) struct omapvideo_info *ovid; struct omap_overlay *ovl; struct omap_video_timings *timing; + struct omap_dss_device *dssdev; if (vout->streaming) return -EBUSY; @@ -1305,13 +1322,15 @@ static int vidioc_s_crop(struct file *file, void *fh, struct v4l2_crop *crop) mutex_lock(&vout->lock); ovid = &vout->vid_info; ovl = ovid->overlays[0]; + /* get the display device attached to the overlay */ + dssdev = ovl->get_device(ovl); - if (!ovl->manager || !ovl->manager->device) { + if (!dssdev) { ret = -EINVAL; goto s_crop_err; } - /* get the display device attached to the overlay */ - timing = &ovl->manager->device->panel.timings; + + timing = &dssdev->panel.timings; if (is_rotation_90_or_270(vout)) { vout->fbuf.fmt.height = timing->x_res; @@ -1667,7 +1686,7 @@ static int vidioc_streamon(struct file *file, void *fh, enum v4l2_buf_type i) for (j = 0; j < ovid->num_overlays; j++) { struct omap_overlay *ovl = ovid->overlays[j]; - if (ovl->manager && ovl->manager->device) { + if (ovl->get_device(ovl)) { struct omap_overlay_info info; ovl->get_overlay_info(ovl, &info); info.paddr = addr; @@ -1690,8 +1709,9 @@ static int vidioc_streamon(struct file *file, void *fh, enum v4l2_buf_type i) for (j = 0; j < ovid->num_overlays; j++) { struct omap_overlay *ovl = ovid->overlays[j]; + struct omap_dss_device *dssdev = ovl->get_device(ovl); - if (ovl->manager && ovl->manager->device) { + if (dssdev) { ret = ovl->enable(ovl); if (ret) goto streamon_err1; @@ -1726,8 +1746,9 @@ static int vidioc_streamoff(struct file *file, void *fh, enum v4l2_buf_type i) for (j = 0; j < ovid->num_overlays; j++) { struct omap_overlay *ovl = ovid->overlays[j]; + struct omap_dss_device *dssdev = ovl->get_device(ovl); - if (ovl->manager && ovl->manager->device) + if (dssdev) ovl->disable(ovl); } @@ -1890,8 +1911,8 @@ static int __init omap_vout_setup_video_data(struct omap_vout_device *vout) struct video_device *vfd; struct v4l2_pix_format *pix; struct v4l2_control *control; - struct omap_dss_device *display = - vout->vid_info.overlays[0]->manager->device; + struct omap_overlay *ovl = vout->vid_info.overlays[0]; + struct omap_dss_device *display = ovl->get_device(ovl); /* set the default pix */ pix = &vout->pix; @@ -2205,8 +2226,10 @@ static int __init omap_vout_probe(struct platform_device *pdev) */ for (i = 1; i < vid_dev->num_overlays; i++) { ovl = omap_dss_get_overlay(i); - if (ovl->manager && ovl->manager->device) { - def_display = ovl->manager->device; + dssdev = ovl->get_device(ovl); + + if (dssdev) { + def_display = dssdev; } else { dev_warn(&pdev->dev, "cannot find display\n"); def_display = NULL; @@ -2253,8 +2276,10 @@ probe_err1: for (i = 1; i < vid_dev->num_overlays; i++) { def_display = NULL; ovl = omap_dss_get_overlay(i); - if (ovl->manager && ovl->manager->device) - def_display = ovl->manager->device; + dssdev = ovl->get_device(ovl); + + if (dssdev) + def_display = dssdev; if (def_display && def_display->driver) def_display->driver->disable(def_display); diff --git a/drivers/staging/omapdrm/omap_drv.c b/drivers/staging/omapdrm/omap_drv.c index 4beab9447ceb..64a354a54737 100644 --- a/drivers/staging/omapdrm/omap_drv.c +++ b/drivers/staging/omapdrm/omap_drv.c @@ -106,7 +106,8 @@ static void dump_video_chains(void) for (i = 0; i < omap_dss_get_num_overlays(); i++) { struct omap_overlay *ovl = omap_dss_get_overlay(i); struct omap_overlay_manager *mgr = ovl->manager; - struct omap_dss_device *dssdev = mgr ? mgr->device : NULL; + struct omap_dss_device *dssdev = mgr ? + mgr->get_device(mgr) : NULL; if (dssdev) { DBG("%d: %s -> %s -> %s", i, ovl->name, mgr->name, dssdev->name); @@ -185,7 +186,7 @@ static int create_connector(struct drm_device *dev, for (j = 0; j < priv->num_encoders; j++) { struct omap_overlay_manager *mgr = omap_encoder_get_manager(priv->encoders[j]); - if (mgr->device == dssdev) { + if (mgr->get_device(mgr) == dssdev) { drm_mode_connector_attach_encoder(connector, priv->encoders[j]); } diff --git a/drivers/video/omap2/dss/Makefile b/drivers/video/omap2/dss/Makefile index 00a6eb566bb6..4549869bfe1a 100644 --- a/drivers/video/omap2/dss/Makefile +++ b/drivers/video/omap2/dss/Makefile @@ -1,6 +1,6 @@ obj-$(CONFIG_OMAP2_DSS) += omapdss.o omapdss-y := core.o dss.o dss_features.o dispc.o dispc_coefs.o display.o \ - manager.o manager-sysfs.o overlay.o overlay-sysfs.o apply.o + manager.o manager-sysfs.o overlay.o overlay-sysfs.o output.o apply.o omapdss-$(CONFIG_OMAP2_DSS_DPI) += dpi.o omapdss-$(CONFIG_OMAP2_DSS_RFBI) += rfbi.o omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o venc_panel.o diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c index 6354bb842856..2b1fa851a8b9 100644 --- a/drivers/video/omap2/dss/apply.c +++ b/drivers/video/omap2/dss/apply.c @@ -421,17 +421,25 @@ static void wait_pending_extra_info_updates(void) int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr) { unsigned long timeout = msecs_to_jiffies(500); - struct mgr_priv_data *mp; + struct mgr_priv_data *mp = get_mgr_priv(mgr); u32 irq; + unsigned long flags; int r; int i; - struct omap_dss_device *dssdev = mgr->device; - if (!dssdev || dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) + spin_lock_irqsave(&data_lock, flags); + + if (mgr_manual_update(mgr)) { + spin_unlock_irqrestore(&data_lock, flags); return 0; + } - if (mgr_manual_update(mgr)) + if (!mp->enabled) { + spin_unlock_irqrestore(&data_lock, flags); return 0; + } + + spin_unlock_irqrestore(&data_lock, flags); r = dispc_runtime_get(); if (r) @@ -439,10 +447,8 @@ int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr) irq = dispc_mgr_get_vsync_irq(mgr->id); - mp = get_mgr_priv(mgr); i = 0; while (1) { - unsigned long flags; bool shadow_dirty, dirty; spin_lock_irqsave(&data_lock, flags); @@ -486,21 +492,30 @@ int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl) { unsigned long timeout = msecs_to_jiffies(500); struct ovl_priv_data *op; - struct omap_dss_device *dssdev; + struct mgr_priv_data *mp; u32 irq; + unsigned long flags; int r; int i; if (!ovl->manager) return 0; - dssdev = ovl->manager->device; + mp = get_mgr_priv(ovl->manager); + + spin_lock_irqsave(&data_lock, flags); - if (!dssdev || dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) + if (ovl_manual_update(ovl)) { + spin_unlock_irqrestore(&data_lock, flags); return 0; + } - if (ovl_manual_update(ovl)) + if (!mp->enabled) { + spin_unlock_irqrestore(&data_lock, flags); return 0; + } + + spin_unlock_irqrestore(&data_lock, flags); r = dispc_runtime_get(); if (r) @@ -511,7 +526,6 @@ int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl) op = get_ovl_priv(ovl); i = 0; while (1) { - unsigned long flags; bool shadow_dirty, dirty; spin_lock_irqsave(&data_lock, flags); @@ -1096,29 +1110,29 @@ void dss_mgr_get_info(struct omap_overlay_manager *mgr, spin_unlock_irqrestore(&data_lock, flags); } -int dss_mgr_set_device(struct omap_overlay_manager *mgr, - struct omap_dss_device *dssdev) +int dss_mgr_set_output(struct omap_overlay_manager *mgr, + struct omap_dss_output *output) { int r; mutex_lock(&apply_lock); - if (dssdev->manager) { - DSSERR("display '%s' already has a manager '%s'\n", - dssdev->name, dssdev->manager->name); + if (mgr->output) { + DSSERR("manager %s is already connected to an output\n", + mgr->name); r = -EINVAL; goto err; } - if ((mgr->supported_displays & dssdev->type) == 0) { - DSSERR("display '%s' does not support manager '%s'\n", - dssdev->name, mgr->name); + if ((mgr->supported_outputs & output->id) == 0) { + DSSERR("output does not support manager %s\n", + mgr->name); r = -EINVAL; goto err; } - dssdev->manager = mgr; - mgr->device = dssdev; + output->manager = mgr; + mgr->output = output; mutex_unlock(&apply_lock); @@ -1128,35 +1142,41 @@ err: return r; } -int dss_mgr_unset_device(struct omap_overlay_manager *mgr) +int dss_mgr_unset_output(struct omap_overlay_manager *mgr) { int r; + struct mgr_priv_data *mp = get_mgr_priv(mgr); + unsigned long flags; mutex_lock(&apply_lock); - if (!mgr->device) { - DSSERR("failed to unset display, display not set.\n"); + if (!mgr->output) { + DSSERR("failed to unset output, output not set\n"); r = -EINVAL; goto err; } - /* - * Don't allow currently enabled displays to have the overlay manager - * pulled out from underneath them - */ - if (mgr->device->state != OMAP_DSS_DISPLAY_DISABLED) { + spin_lock_irqsave(&data_lock, flags); + + if (mp->enabled) { + DSSERR("output can't be unset when manager is enabled\n"); r = -EINVAL; - goto err; + goto err1; } - mgr->device->manager = NULL; - mgr->device = NULL; + spin_unlock_irqrestore(&data_lock, flags); + + mgr->output->manager = NULL; + mgr->output = NULL; mutex_unlock(&apply_lock); return 0; +err1: + spin_unlock_irqrestore(&data_lock, flags); err: mutex_unlock(&apply_lock); + return r; } @@ -1380,7 +1400,7 @@ int dss_ovl_enable(struct omap_overlay *ovl) goto err1; } - if (ovl->manager == NULL || ovl->manager->device == NULL) { + if (ovl->manager == NULL || ovl->manager->output == NULL) { r = -EINVAL; goto err1; } @@ -1430,7 +1450,7 @@ int dss_ovl_disable(struct omap_overlay *ovl) goto err; } - if (ovl->manager == NULL || ovl->manager->device == NULL) { + if (ovl->manager == NULL || ovl->manager->output == NULL) { r = -EINVAL; goto err; } diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index 2137d2a2cc5d..811fe381aaea 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c @@ -3595,7 +3595,7 @@ static void dispc_error_worker(struct work_struct *work) bit = mgr_desc[i].sync_lost_irq; if (bit & errors) { - struct omap_dss_device *dssdev = mgr->device; + struct omap_dss_device *dssdev = mgr->get_device(mgr); bool enable; DSSERR("SYNC_LOST on channel %s, restarting the output " @@ -3626,9 +3626,13 @@ static void dispc_error_worker(struct work_struct *work) DSSERR("OCP_ERR\n"); for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) { struct omap_overlay_manager *mgr; + struct omap_dss_device *dssdev; + mgr = omap_dss_get_overlay_manager(i); - if (mgr->device && mgr->device->driver) - mgr->device->driver->disable(mgr->device); + dssdev = mgr->get_device(mgr); + + if (dssdev && dssdev->driver) + dssdev->driver->disable(dssdev); } } diff --git a/drivers/video/omap2/dss/display.c b/drivers/video/omap2/dss/display.c index db83ae81a713..ccf8550fafde 100644 --- a/drivers/video/omap2/dss/display.c +++ b/drivers/video/omap2/dss/display.c @@ -327,22 +327,35 @@ EXPORT_SYMBOL(omapdss_default_get_timings); */ static int dss_init_connections(struct omap_dss_device *dssdev, bool force) { + struct omap_dss_output *out; struct omap_overlay_manager *mgr; int i, r; - WARN_ON(dssdev->manager); + out = omapdss_get_output_from_dssdev(dssdev); + + WARN_ON(dssdev->output); + WARN_ON(out->device); + + r = omapdss_output_set_device(out, dssdev); + if (r) { + DSSERR("failed to connect output to new device\n"); + return r; + } mgr = omap_dss_get_overlay_manager(dssdev->channel); - if (mgr->device && !force) + if (mgr->output && !force) return 0; - if (mgr->device) - mgr->unset_device(mgr); + if (mgr->output) + mgr->unset_output(mgr); - r = mgr->set_device(mgr, dssdev); + r = mgr->set_output(mgr, out); if (r) { - DSSERR("failed to set initial manager\n"); + DSSERR("failed to connect manager to output of new device\n"); + + /* remove the output-device connection we just made */ + omapdss_output_unset_device(out); return r; } @@ -366,8 +379,14 @@ static int dss_init_connections(struct omap_dss_device *dssdev, bool force) static void dss_uninit_connections(struct omap_dss_device *dssdev) { - if (dssdev->manager) - dssdev->manager->unset_device(dssdev->manager); + if (dssdev->output) { + struct omap_overlay_manager *mgr = dssdev->output->manager; + + if (mgr) + mgr->unset_output(mgr); + + omapdss_output_unset_device(dssdev->output); + } } int dss_init_device(struct platform_device *pdev, diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c index f6800e19bbcb..d73a549050e4 100644 --- a/drivers/video/omap2/dss/dpi.c +++ b/drivers/video/omap2/dss/dpi.c @@ -44,6 +44,8 @@ static struct { struct omap_video_timings timings; struct dss_lcd_mgr_config mgr_config; int data_lines; + + struct omap_dss_output output; } dpi; static struct platform_device *dpi_get_dsidev(enum omap_dss_clk_source clk) @@ -126,6 +128,7 @@ static int dpi_set_dispc_clk(struct omap_dss_device *dssdev, static int dpi_set_mode(struct omap_dss_device *dssdev) { struct omap_video_timings *t = &dpi.timings; + struct omap_overlay_manager *mgr = dssdev->output->manager; int lck_div = 0, pck_div = 0; unsigned long fck = 0; unsigned long pck; @@ -150,13 +153,15 @@ static int dpi_set_mode(struct omap_dss_device *dssdev) t->pixel_clock = pck; } - dss_mgr_set_timings(dssdev->manager, t); + dss_mgr_set_timings(mgr, t); return 0; } static void dpi_config_lcd_manager(struct omap_dss_device *dssdev) { + struct omap_overlay_manager *mgr = dssdev->output->manager; + dpi.mgr_config.io_pad_mode = DSS_IO_PAD_MODE_BYPASS; dpi.mgr_config.stallmode = false; @@ -166,11 +171,12 @@ static void dpi_config_lcd_manager(struct omap_dss_device *dssdev) dpi.mgr_config.lcden_sig_polarity = 0; - dss_mgr_set_lcd_config(dssdev->manager, &dpi.mgr_config); + dss_mgr_set_lcd_config(mgr, &dpi.mgr_config); } int omapdss_dpi_display_enable(struct omap_dss_device *dssdev) { + struct omap_dss_output *out = dssdev->output; int r; mutex_lock(&dpi.lock); @@ -181,10 +187,10 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev) goto err_no_reg; } - if (dssdev->manager == NULL) { - DSSERR("failed to enable display: no manager\n"); + if (out == NULL || out->manager == NULL) { + DSSERR("failed to enable display: no output/manager\n"); r = -ENODEV; - goto err_no_mgr; + goto err_no_out_mgr; } r = omap_dss_start_device(dssdev); @@ -225,7 +231,7 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev) mdelay(2); - r = dss_mgr_enable(dssdev->manager); + r = dss_mgr_enable(out->manager); if (r) goto err_mgr_enable; @@ -249,7 +255,7 @@ err_get_dispc: err_reg_enable: omap_dss_stop_device(dssdev); err_start_dev: -err_no_mgr: +err_no_out_mgr: err_no_reg: mutex_unlock(&dpi.lock); return r; @@ -258,9 +264,11 @@ EXPORT_SYMBOL(omapdss_dpi_display_enable); void omapdss_dpi_display_disable(struct omap_dss_device *dssdev) { + struct omap_overlay_manager *mgr = dssdev->output->manager; + mutex_lock(&dpi.lock); - dss_mgr_disable(dssdev->manager); + dss_mgr_disable(mgr); if (dpi_use_dsi_pll(dssdev)) { dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK); @@ -296,12 +304,13 @@ int dpi_check_timings(struct omap_dss_device *dssdev, struct omap_video_timings *timings) { int r; + struct omap_overlay_manager *mgr = dssdev->output->manager; int lck_div, pck_div; unsigned long fck; unsigned long pck; struct dispc_clock_info dispc_cinfo; - if (dss_mgr_check_timings(dssdev->manager, timings)) + if (dss_mgr_check_timings(mgr, timings)) return -EINVAL; if (timings->pixel_clock == 0) @@ -436,10 +445,30 @@ static void __init dpi_probe_pdata(struct platform_device *dpidev) } } +static void __init dpi_init_output(struct platform_device *pdev) +{ + struct omap_dss_output *out = &dpi.output; + + out->pdev = pdev; + out->id = OMAP_DSS_OUTPUT_DPI; + out->type = OMAP_DISPLAY_TYPE_DPI; + + dss_register_output(out); +} + +static void __exit dpi_uninit_output(struct platform_device *pdev) +{ + struct omap_dss_output *out = &dpi.output; + + dss_unregister_output(out); +} + static int __init omap_dpi_probe(struct platform_device *pdev) { mutex_init(&dpi.lock); + dpi_init_output(pdev); + dpi_probe_pdata(pdev); return 0; @@ -449,6 +478,8 @@ static int __exit omap_dpi_remove(struct platform_device *pdev) { dss_unregister_child_devices(&pdev->dev); + dpi_uninit_output(pdev); + return 0; } diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index abe335abca53..e37e6d868acd 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -336,6 +336,8 @@ struct dsi_data { enum omap_dss_dsi_pixel_format pix_fmt; enum omap_dss_dsi_mode mode; struct omap_dss_dsi_videomode_timings vm_timings; + + struct omap_dss_output output; }; struct dsi_packet_sent_handler_data { @@ -343,8 +345,6 @@ struct dsi_packet_sent_handler_data { struct completion *completion; }; -static struct platform_device *dsi_pdev_map[MAX_NUM_DSI]; - #ifdef DEBUG static bool dsi_perf; module_param(dsi_perf, bool, 0644); @@ -357,12 +357,19 @@ static inline struct dsi_data *dsi_get_dsidrv_data(struct platform_device *dside static inline struct platform_device *dsi_get_dsidev_from_dssdev(struct omap_dss_device *dssdev) { - return dsi_pdev_map[dssdev->phy.dsi.module]; + return dssdev->output->pdev; } struct platform_device *dsi_get_dsidev_from_id(int module) { - return dsi_pdev_map[module]; + struct omap_dss_output *out; + enum omap_dss_output_id id; + + id = module == 0 ? OMAP_DSS_OUTPUT_DSI1 : OMAP_DSS_OUTPUT_DSI2; + + out = omap_dss_get_output(id); + + return out->pdev; } static inline void dsi_write_reg(struct platform_device *dsidev, @@ -2163,9 +2170,8 @@ static unsigned dsi_get_line_buf_size(struct platform_device *dsidev) } } -static int dsi_set_lane_config(struct omap_dss_device *dssdev) +static int dsi_set_lane_config(struct platform_device *dsidev) { - struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); static const u8 offsets[] = { 0, 4, 8, 12, 16 }; static const enum dsi_lane_function functions[] = { @@ -2307,10 +2313,9 @@ static void dsi_cio_timings(struct platform_device *dsidev) } /* lane masks have lane 0 at lsb. mask_p for positive lines, n for negative */ -static void dsi_cio_enable_lane_override(struct omap_dss_device *dssdev, +static void dsi_cio_enable_lane_override(struct platform_device *dsidev, unsigned mask_p, unsigned mask_n) { - struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); int i; u32 l; @@ -2357,9 +2362,8 @@ static void dsi_cio_disable_lane_override(struct platform_device *dsidev) REG_FLD_MOD(dsidev, DSI_DSIPHY_CFG10, 0, 22, 17); } -static int dsi_cio_wait_tx_clk_esc_reset(struct omap_dss_device *dssdev) +static int dsi_cio_wait_tx_clk_esc_reset(struct platform_device *dsidev) { - struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); int t, i; bool in_use[DSI_MAX_NR_LANES]; @@ -2407,9 +2411,8 @@ static int dsi_cio_wait_tx_clk_esc_reset(struct omap_dss_device *dssdev) } /* return bitmask of enabled lanes, lane0 being the lsb */ -static unsigned dsi_get_lane_mask(struct omap_dss_device *dssdev) +static unsigned dsi_get_lane_mask(struct platform_device *dsidev) { - struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); unsigned mask = 0; int i; @@ -2422,16 +2425,15 @@ static unsigned dsi_get_lane_mask(struct omap_dss_device *dssdev) return mask; } -static int dsi_cio_init(struct omap_dss_device *dssdev) +static int dsi_cio_init(struct platform_device *dsidev) { - struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); int r; u32 l; DSSDBGF(); - r = dss_dsi_enable_pads(dsi->module_id, dsi_get_lane_mask(dssdev)); + r = dss_dsi_enable_pads(dsi->module_id, dsi_get_lane_mask(dsidev)); if (r) return r; @@ -2448,7 +2450,7 @@ static int dsi_cio_init(struct omap_dss_device *dssdev) goto err_scp_clk_dom; } - r = dsi_set_lane_config(dssdev); + r = dsi_set_lane_config(dsidev); if (r) goto err_scp_clk_dom; @@ -2483,7 +2485,7 @@ static int dsi_cio_init(struct omap_dss_device *dssdev) mask_p |= 1 << i; } - dsi_cio_enable_lane_override(dssdev, mask_p, 0); + dsi_cio_enable_lane_override(dsidev, mask_p, 0); } r = dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_ON); @@ -2500,7 +2502,7 @@ static int dsi_cio_init(struct omap_dss_device *dssdev) dsi_if_enable(dsidev, false); REG_FLD_MOD(dsidev, DSI_CLK_CTRL, 1, 20, 20); /* LP_CLK_ENABLE */ - r = dsi_cio_wait_tx_clk_esc_reset(dssdev); + r = dsi_cio_wait_tx_clk_esc_reset(dsidev); if (r) goto err_tx_clk_esc_rst; @@ -2541,13 +2543,12 @@ err_cio_pwr: dsi_cio_disable_lane_override(dsidev); err_scp_clk_dom: dsi_disable_scp_clk(dsidev); - dss_dsi_disable_pads(dsi->module_id, dsi_get_lane_mask(dssdev)); + dss_dsi_disable_pads(dsi->module_id, dsi_get_lane_mask(dsidev)); return r; } -static void dsi_cio_uninit(struct omap_dss_device *dssdev) +static void dsi_cio_uninit(struct platform_device *dsidev) { - struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); /* DDR_CLK_ALWAYS_ON */ @@ -2555,7 +2556,7 @@ static void dsi_cio_uninit(struct omap_dss_device *dssdev) dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_OFF); dsi_disable_scp_clk(dsidev); - dss_dsi_disable_pads(dsi->module_id, dsi_get_lane_mask(dssdev)); + dss_dsi_disable_pads(dsi->module_id, dsi_get_lane_mask(dsidev)); } static void dsi_config_tx_fifo(struct platform_device *dsidev, @@ -3148,10 +3149,9 @@ int dsi_vc_send_null(struct omap_dss_device *dssdev, int channel) } EXPORT_SYMBOL(dsi_vc_send_null); -static int dsi_vc_write_nosync_common(struct omap_dss_device *dssdev, +static int dsi_vc_write_nosync_common(struct platform_device *dsidev, int channel, u8 *data, int len, enum dss_dsi_content_type type) { - struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); int r; if (len == 0) { @@ -3182,7 +3182,9 @@ static int dsi_vc_write_nosync_common(struct omap_dss_device *dssdev, int dsi_vc_dcs_write_nosync(struct omap_dss_device *dssdev, int channel, u8 *data, int len) { - return dsi_vc_write_nosync_common(dssdev, channel, data, len, + struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); + + return dsi_vc_write_nosync_common(dsidev, channel, data, len, DSS_DSI_CONTENT_DCS); } EXPORT_SYMBOL(dsi_vc_dcs_write_nosync); @@ -3190,7 +3192,9 @@ EXPORT_SYMBOL(dsi_vc_dcs_write_nosync); int dsi_vc_generic_write_nosync(struct omap_dss_device *dssdev, int channel, u8 *data, int len) { - return dsi_vc_write_nosync_common(dssdev, channel, data, len, + struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); + + return dsi_vc_write_nosync_common(dsidev, channel, data, len, DSS_DSI_CONTENT_GENERIC); } EXPORT_SYMBOL(dsi_vc_generic_write_nosync); @@ -3201,7 +3205,7 @@ static int dsi_vc_write_common(struct omap_dss_device *dssdev, int channel, struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); int r; - r = dsi_vc_write_nosync_common(dssdev, channel, data, len, type); + r = dsi_vc_write_nosync_common(dsidev, channel, data, len, type); if (r) goto err; @@ -3279,10 +3283,9 @@ int dsi_vc_generic_write_2(struct omap_dss_device *dssdev, int channel, } EXPORT_SYMBOL(dsi_vc_generic_write_2); -static int dsi_vc_dcs_send_read_request(struct omap_dss_device *dssdev, +static int dsi_vc_dcs_send_read_request(struct platform_device *dsidev, int channel, u8 dcs_cmd) { - struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); int r; @@ -3300,10 +3303,9 @@ static int dsi_vc_dcs_send_read_request(struct omap_dss_device *dssdev, return 0; } -static int dsi_vc_generic_send_read_request(struct omap_dss_device *dssdev, +static int dsi_vc_generic_send_read_request(struct platform_device *dsidev, int channel, u8 *reqdata, int reqlen) { - struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); u16 data; u8 data_type; @@ -3452,7 +3454,7 @@ int dsi_vc_dcs_read(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd, struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); int r; - r = dsi_vc_dcs_send_read_request(dssdev, channel, dcs_cmd); + r = dsi_vc_dcs_send_read_request(dsidev, channel, dcs_cmd); if (r) goto err; @@ -3483,7 +3485,7 @@ static int dsi_vc_generic_read(struct omap_dss_device *dssdev, int channel, struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); int r; - r = dsi_vc_generic_send_read_request(dssdev, channel, reqdata, reqlen); + r = dsi_vc_generic_send_read_request(dsidev, channel, reqdata, reqlen); if (r) return r; @@ -3765,14 +3767,12 @@ static void dsi_set_hs_tx_timeout(struct platform_device *dsidev, (total_ticks * 1000) / (fck / 1000 / 1000)); } -static void dsi_config_vp_num_line_buffers(struct omap_dss_device *dssdev) +static void dsi_config_vp_num_line_buffers(struct platform_device *dsidev) { - struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); int num_line_buffers; if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) { - struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); int bpp = dsi_get_pixel_size(dsi->pix_fmt); unsigned line_buf_size = dsi_get_line_buf_size(dsidev); struct omap_video_timings *timings = &dsi->timings; @@ -3793,9 +3793,8 @@ static void dsi_config_vp_num_line_buffers(struct omap_dss_device *dssdev) REG_FLD_MOD(dsidev, DSI_CTRL, num_line_buffers, 13, 12); } -static void dsi_config_vp_sync_events(struct omap_dss_device *dssdev) +static void dsi_config_vp_sync_events(struct platform_device *dsidev) { - struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); bool vsync_end = dsi->vm_timings.vp_vsync_end; bool hsync_end = dsi->vm_timings.vp_hsync_end; @@ -3812,9 +3811,8 @@ static void dsi_config_vp_sync_events(struct omap_dss_device *dssdev) dsi_write_reg(dsidev, DSI_CTRL, r); } -static void dsi_config_blanking_modes(struct omap_dss_device *dssdev) +static void dsi_config_blanking_modes(struct platform_device *dsidev) { - struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); int blanking_mode = dsi->vm_timings.blanking_mode; int hfp_blanking_mode = dsi->vm_timings.hfp_blanking_mode; @@ -4069,11 +4067,11 @@ static int dsi_proto_config(struct omap_dss_device *dssdev) dsi_write_reg(dsidev, DSI_CTRL, r); - dsi_config_vp_num_line_buffers(dssdev); + dsi_config_vp_num_line_buffers(dsidev); if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) { - dsi_config_vp_sync_events(dssdev); - dsi_config_blanking_modes(dssdev); + dsi_config_vp_sync_events(dsidev); + dsi_config_blanking_modes(dsidev); dsi_config_cmd_mode_interleaving(dssdev); } @@ -4085,9 +4083,8 @@ static int dsi_proto_config(struct omap_dss_device *dssdev) return 0; } -static void dsi_proto_timings(struct omap_dss_device *dssdev) +static void dsi_proto_timings(struct platform_device *dsidev) { - struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); unsigned tlpx, tclk_zero, tclk_prepare, tclk_trail; unsigned tclk_pre, tclk_post; @@ -4336,6 +4333,7 @@ int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel) { struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); + struct omap_overlay_manager *mgr = dssdev->output->manager; int bpp = dsi_get_pixel_size(dsi->pix_fmt); u8 data_type; u16 word_count; @@ -4375,7 +4373,7 @@ int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel) dsi_if_enable(dsidev, true); } - r = dss_mgr_enable(dssdev->manager); + r = dss_mgr_enable(mgr); if (r) { if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) { dsi_if_enable(dsidev, false); @@ -4393,6 +4391,7 @@ void dsi_disable_video_output(struct omap_dss_device *dssdev, int channel) { struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); + struct omap_overlay_manager *mgr = dssdev->output->manager; if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) { dsi_if_enable(dsidev, false); @@ -4405,7 +4404,7 @@ void dsi_disable_video_output(struct omap_dss_device *dssdev, int channel) dsi_if_enable(dsidev, true); } - dss_mgr_disable(dssdev->manager); + dss_mgr_disable(mgr); } EXPORT_SYMBOL(dsi_disable_video_output); @@ -4413,6 +4412,7 @@ static void dsi_update_screen_dispc(struct omap_dss_device *dssdev) { struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); + struct omap_overlay_manager *mgr = dssdev->output->manager; unsigned bytespp; unsigned bytespl; unsigned bytespf; @@ -4474,9 +4474,9 @@ static void dsi_update_screen_dispc(struct omap_dss_device *dssdev) msecs_to_jiffies(250)); BUG_ON(r == 0); - dss_mgr_set_timings(dssdev->manager, &dsi->timings); + dss_mgr_set_timings(mgr, &dsi->timings); - dss_mgr_start_update(dssdev->manager); + dss_mgr_start_update(mgr); if (dsi->te_enabled) { /* disable LP_RX_TO, so that we can receive TE. Time to wait @@ -4534,8 +4534,7 @@ static void dsi_framedone_timeout_work_callback(struct work_struct *work) static void dsi_framedone_irq_callback(void *data, u32 mask) { - struct omap_dss_device *dssdev = (struct omap_dss_device *) data; - struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); + struct platform_device *dsidev = (struct platform_device *) data; struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); /* Note: We get FRAMEDONE when DISPC has finished sending pixels and @@ -4605,6 +4604,7 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev) { struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); + struct omap_overlay_manager *mgr = dssdev->output->manager; int r; u32 irq = 0; @@ -4616,10 +4616,10 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev) dsi->timings.vfp = 0; dsi->timings.vbp = 0; - irq = dispc_mgr_get_framedone_irq(dssdev->manager->id); + irq = dispc_mgr_get_framedone_irq(mgr->id); r = omap_dispc_register_isr(dsi_framedone_irq_callback, - (void *) dssdev, irq); + (void *) dsidev, irq); if (r) { DSSERR("can't get FRAMEDONE irq\n"); goto err; @@ -4643,7 +4643,7 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev) dsi->timings.de_level = OMAPDSS_SIG_ACTIVE_HIGH; dsi->timings.sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES; - dss_mgr_set_timings(dssdev->manager, &dsi->timings); + dss_mgr_set_timings(mgr, &dsi->timings); r = dsi_configure_dispc_clocks(dssdev); if (r) @@ -4654,13 +4654,13 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev) dsi_get_pixel_size(dsi->pix_fmt); dsi->mgr_config.lcden_sig_polarity = 0; - dss_mgr_set_lcd_config(dssdev->manager, &dsi->mgr_config); + dss_mgr_set_lcd_config(mgr, &dsi->mgr_config); return 0; err1: if (dsi->mode == OMAP_DSS_DSI_CMD_MODE) omap_dispc_unregister_isr(dsi_framedone_irq_callback, - (void *) dssdev, irq); + (void *) dsidev, irq); err: return r; } @@ -4669,14 +4669,15 @@ static void dsi_display_uninit_dispc(struct omap_dss_device *dssdev) { struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); + struct omap_overlay_manager *mgr = dssdev->output->manager; if (dsi->mode == OMAP_DSS_DSI_CMD_MODE) { u32 irq; - irq = dispc_mgr_get_framedone_irq(dssdev->manager->id); + irq = dispc_mgr_get_framedone_irq(mgr->id); omap_dispc_unregister_isr(dsi_framedone_irq_callback, - (void *) dssdev, irq); + (void *) dsidev, irq); } } @@ -4709,6 +4710,7 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev) { struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); + struct omap_overlay_manager *mgr = dssdev->output->manager; int r; r = dsi_pll_init(dsidev, true, true); @@ -4721,18 +4723,18 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev) dss_select_dispc_clk_source(dssdev->clocks.dispc.dispc_fclk_src); dss_select_dsi_clk_source(dsi->module_id, dssdev->clocks.dsi.dsi_fclk_src); - dss_select_lcd_clk_source(dssdev->manager->id, + dss_select_lcd_clk_source(mgr->id, dssdev->clocks.dispc.channel.lcd_clk_src); DSSDBG("PLL OK\n"); - r = dsi_cio_init(dssdev); + r = dsi_cio_init(dsidev); if (r) goto err2; _dsi_print_reset_status(dsidev); - dsi_proto_timings(dssdev); + dsi_proto_timings(dsidev); dsi_set_lp_clk_divisor(dssdev); if (1) @@ -4752,11 +4754,11 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev) return 0; err3: - dsi_cio_uninit(dssdev); + dsi_cio_uninit(dsidev); err2: dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK); dss_select_dsi_clk_source(dsi->module_id, OMAP_DSS_CLK_SRC_FCK); - dss_select_lcd_clk_source(dssdev->manager->id, OMAP_DSS_CLK_SRC_FCK); + dss_select_lcd_clk_source(mgr->id, OMAP_DSS_CLK_SRC_FCK); err1: dsi_pll_uninit(dsidev, true); @@ -4769,6 +4771,7 @@ static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev, { struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); + struct omap_overlay_manager *mgr = dssdev->output->manager; if (enter_ulps && !dsi->ulps_enabled) dsi_enter_ulps(dsidev); @@ -4782,8 +4785,8 @@ static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev, dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK); dss_select_dsi_clk_source(dsi->module_id, OMAP_DSS_CLK_SRC_FCK); - dss_select_lcd_clk_source(dssdev->manager->id, OMAP_DSS_CLK_SRC_FCK); - dsi_cio_uninit(dssdev); + dss_select_lcd_clk_source(mgr->id, OMAP_DSS_CLK_SRC_FCK); + dsi_cio_uninit(dsidev); dsi_pll_uninit(dsidev, disconnect_lanes); } @@ -4791,6 +4794,7 @@ int omapdss_dsi_display_enable(struct omap_dss_device *dssdev) { struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); + struct omap_dss_output *out = dssdev->output; int r = 0; DSSDBG("dsi_display_enable\n"); @@ -4799,8 +4803,8 @@ int omapdss_dsi_display_enable(struct omap_dss_device *dssdev) mutex_lock(&dsi->lock); - if (dssdev->manager == NULL) { - DSSERR("failed to enable display: no manager\n"); + if (out == NULL || out->manager == NULL) { + DSSERR("failed to enable display: no output/manager\n"); r = -ENODEV; goto err_start_dev; } @@ -4957,7 +4961,8 @@ EXPORT_SYMBOL(omapdss_dsi_set_videomode_timings); static int __init dsi_init_display(struct omap_dss_device *dssdev) { - struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); + struct platform_device *dsidev = + dsi_get_dsidev_from_id(dssdev->phy.dsi.module); struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); DSSDBG("DSI init\n"); @@ -5167,6 +5172,28 @@ static void __init dsi_probe_pdata(struct platform_device *dsidev) } } +static void __init dsi_init_output(struct platform_device *dsidev) +{ + struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); + struct omap_dss_output *out = &dsi->output; + + out->pdev = dsidev; + out->id = dsi->module_id == 0 ? + OMAP_DSS_OUTPUT_DSI1 : OMAP_DSS_OUTPUT_DSI2; + + out->type = OMAP_DISPLAY_TYPE_DSI; + + dss_register_output(out); +} + +static void __exit dsi_uninit_output(struct platform_device *dsidev) +{ + struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); + struct omap_dss_output *out = &dsi->output; + + dss_unregister_output(out); +} + /* DSI1 HW IP initialisation */ static int __init omap_dsihw_probe(struct platform_device *dsidev) { @@ -5181,7 +5208,6 @@ static int __init omap_dsihw_probe(struct platform_device *dsidev) dsi->module_id = dsidev->id; dsi->pdev = dsidev; - dsi_pdev_map[dsi->module_id] = dsidev; dev_set_drvdata(&dsidev->dev, dsi); spin_lock_init(&dsi->irq_lock); @@ -5261,6 +5287,8 @@ static int __init omap_dsihw_probe(struct platform_device *dsidev) else dsi->num_lanes_supported = 3; + dsi_init_output(dsidev); + dsi_probe_pdata(dsidev); dsi_runtime_put(dsidev); @@ -5292,6 +5320,8 @@ static int __exit omap_dsihw_remove(struct platform_device *dsidev) dss_unregister_child_devices(&dsidev->dev); + dsi_uninit_output(dsidev); + pm_runtime_disable(&dsidev->dev); dsi_put_clocks(dsidev); diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h index 40c36cafec6e..a14528bcfeab 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h @@ -209,6 +209,9 @@ void dss_mgr_get_info(struct omap_overlay_manager *mgr, int dss_mgr_set_device(struct omap_overlay_manager *mgr, struct omap_dss_device *dssdev); int dss_mgr_unset_device(struct omap_overlay_manager *mgr); +int dss_mgr_set_output(struct omap_overlay_manager *mgr, + struct omap_dss_output *output); +int dss_mgr_unset_output(struct omap_overlay_manager *mgr); 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, @@ -226,6 +229,11 @@ int dss_ovl_set_manager(struct omap_overlay *ovl, struct omap_overlay_manager *mgr); int dss_ovl_unset_manager(struct omap_overlay *ovl); +/* output */ +void dss_register_output(struct omap_dss_output *out); +void dss_unregister_output(struct omap_dss_output *out); +struct omap_dss_output *omapdss_get_output_from_dssdev(struct omap_dss_device *dssdev); + /* display */ int dss_suspend_all_devices(void); int dss_resume_all_devices(void); diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c index 406913949e2c..bfe7fc7b8593 100644 --- a/drivers/video/omap2/dss/dss_features.c +++ b/drivers/video/omap2/dss/dss_features.c @@ -47,6 +47,7 @@ struct omap_dss_features { const int num_mgrs; const int num_ovls; const enum omap_display_type *supported_displays; + const enum omap_dss_output_id *supported_outputs; const enum omap_color_mode *supported_color_modes; const enum omap_overlay_caps *overlay_caps; const char * const *clksrc_names; @@ -172,6 +173,63 @@ static const enum omap_display_type omap5_dss_supported_displays[] = { OMAP_DISPLAY_TYPE_DSI, }; +static const enum omap_dss_output_id omap2_dss_supported_outputs[] = { + /* OMAP_DSS_CHANNEL_LCD */ + OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI, + + /* OMAP_DSS_CHANNEL_DIGIT */ + OMAP_DSS_OUTPUT_VENC, +}; + +static const enum omap_dss_output_id omap3430_dss_supported_outputs[] = { + /* OMAP_DSS_CHANNEL_LCD */ + OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI | + OMAP_DSS_OUTPUT_SDI | OMAP_DSS_OUTPUT_DSI1, + + /* OMAP_DSS_CHANNEL_DIGIT */ + OMAP_DSS_OUTPUT_VENC, +}; + +static const enum omap_dss_output_id omap3630_dss_supported_outputs[] = { + /* OMAP_DSS_CHANNEL_LCD */ + OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI | + OMAP_DSS_OUTPUT_DSI1, + + /* OMAP_DSS_CHANNEL_DIGIT */ + OMAP_DSS_OUTPUT_VENC, +}; + +static const enum omap_dss_output_id omap4_dss_supported_outputs[] = { + /* OMAP_DSS_CHANNEL_LCD */ + OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI | + OMAP_DSS_OUTPUT_DSI1, + + /* OMAP_DSS_CHANNEL_DIGIT */ + OMAP_DSS_OUTPUT_VENC | OMAP_DSS_OUTPUT_HDMI | + OMAP_DSS_OUTPUT_DPI, + + /* OMAP_DSS_CHANNEL_LCD2 */ + OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI | + OMAP_DSS_OUTPUT_DSI2, +}; + +static const enum omap_dss_output_id omap5_dss_supported_outputs[] = { + /* OMAP_DSS_CHANNEL_LCD */ + OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI | + OMAP_DSS_OUTPUT_DSI1 | OMAP_DSS_OUTPUT_DSI2, + + /* OMAP_DSS_CHANNEL_DIGIT */ + OMAP_DSS_OUTPUT_HDMI | OMAP_DSS_OUTPUT_DPI, + + /* OMAP_DSS_CHANNEL_LCD2 */ + OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI | + OMAP_DSS_OUTPUT_DSI1, + + /* OMAP_DSS_CHANNEL_LCD3 */ + OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI | + OMAP_DSS_OUTPUT_DSI2, +}; + static const enum omap_color_mode omap2_dss_supported_color_modes[] = { /* OMAP_DSS_GFX */ OMAP_DSS_COLOR_CLUT1 | OMAP_DSS_COLOR_CLUT2 | @@ -554,6 +612,7 @@ static const struct omap_dss_features omap2_dss_features = { .num_mgrs = 2, .num_ovls = 3, .supported_displays = omap2_dss_supported_displays, + .supported_outputs = omap2_dss_supported_outputs, .supported_color_modes = omap2_dss_supported_color_modes, .overlay_caps = omap2_dss_overlay_caps, .clksrc_names = omap2_dss_clk_source_names, @@ -574,6 +633,7 @@ static const struct omap_dss_features omap3430_dss_features = { .num_mgrs = 2, .num_ovls = 3, .supported_displays = omap3430_dss_supported_displays, + .supported_outputs = omap3430_dss_supported_outputs, .supported_color_modes = omap3_dss_supported_color_modes, .overlay_caps = omap3430_dss_overlay_caps, .clksrc_names = omap3_dss_clk_source_names, @@ -597,6 +657,7 @@ static const struct omap_dss_features am35xx_dss_features = { .num_mgrs = 2, .num_ovls = 3, .supported_displays = omap3430_dss_supported_displays, + .supported_outputs = omap3430_dss_supported_outputs, .supported_color_modes = omap3_dss_supported_color_modes, .overlay_caps = omap3430_dss_overlay_caps, .clksrc_names = omap3_dss_clk_source_names, @@ -616,6 +677,7 @@ static const struct omap_dss_features omap3630_dss_features = { .num_mgrs = 2, .num_ovls = 3, .supported_displays = omap3630_dss_supported_displays, + .supported_outputs = omap3630_dss_supported_outputs, .supported_color_modes = omap3_dss_supported_color_modes, .overlay_caps = omap3630_dss_overlay_caps, .clksrc_names = omap3_dss_clk_source_names, @@ -637,6 +699,7 @@ static const struct omap_dss_features omap4430_es1_0_dss_features = { .num_mgrs = 3, .num_ovls = 4, .supported_displays = omap4_dss_supported_displays, + .supported_outputs = omap4_dss_supported_outputs, .supported_color_modes = omap4_dss_supported_color_modes, .overlay_caps = omap4_dss_overlay_caps, .clksrc_names = omap4_dss_clk_source_names, @@ -657,6 +720,7 @@ static const struct omap_dss_features omap4430_es2_0_1_2_dss_features = { .num_mgrs = 3, .num_ovls = 4, .supported_displays = omap4_dss_supported_displays, + .supported_outputs = omap4_dss_supported_outputs, .supported_color_modes = omap4_dss_supported_color_modes, .overlay_caps = omap4_dss_overlay_caps, .clksrc_names = omap4_dss_clk_source_names, @@ -677,6 +741,7 @@ static const struct omap_dss_features omap4_dss_features = { .num_mgrs = 3, .num_ovls = 4, .supported_displays = omap4_dss_supported_displays, + .supported_outputs = omap4_dss_supported_outputs, .supported_color_modes = omap4_dss_supported_color_modes, .overlay_caps = omap4_dss_overlay_caps, .clksrc_names = omap4_dss_clk_source_names, @@ -697,6 +762,7 @@ static const struct omap_dss_features omap5_dss_features = { .num_mgrs = 3, .num_ovls = 4, .supported_displays = omap5_dss_supported_displays, + .supported_outputs = omap5_dss_supported_outputs, .supported_color_modes = omap4_dss_supported_color_modes, .overlay_caps = omap4_dss_overlay_caps, .clksrc_names = omap5_dss_clk_source_names, @@ -766,6 +832,11 @@ enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel return omap_current_dss_features->supported_displays[channel]; } +enum omap_dss_output_id dss_feat_get_supported_outputs(enum omap_channel channel) +{ + return omap_current_dss_features->supported_outputs[channel]; +} + enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane) { return omap_current_dss_features->supported_color_modes[plane]; diff --git a/drivers/video/omap2/dss/dss_features.h b/drivers/video/omap2/dss/dss_features.h index aacad863fa22..89df2aa860d4 100644 --- a/drivers/video/omap2/dss/dss_features.h +++ b/drivers/video/omap2/dss/dss_features.h @@ -108,6 +108,7 @@ int dss_feat_get_num_ovls(void); unsigned long dss_feat_get_param_min(enum dss_range_param param); unsigned long dss_feat_get_param_max(enum dss_range_param param); enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel); +enum omap_dss_output_id dss_feat_get_supported_outputs(enum omap_channel channel); enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane); enum omap_overlay_caps dss_feat_get_overlay_caps(enum omap_plane plane); bool dss_feat_color_mode_supported(enum omap_plane plane, diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c index 23daf7dcf54a..a48a7dd75b33 100644 --- a/drivers/video/omap2/dss/hdmi.c +++ b/drivers/video/omap2/dss/hdmi.c @@ -68,6 +68,8 @@ static struct { int ct_cp_hpd_gpio; int ls_oe_gpio; int hpd_gpio; + + struct omap_dss_output output; } hdmi; /* @@ -502,6 +504,7 @@ static int hdmi_power_on(struct omap_dss_device *dssdev) { int r; struct omap_video_timings *p; + struct omap_overlay_manager *mgr = dssdev->output->manager; unsigned long phy; gpio_set_value(hdmi.ct_cp_hpd_gpio, 1); @@ -518,7 +521,7 @@ static int hdmi_power_on(struct omap_dss_device *dssdev) if (r) goto err_runtime_get; - dss_mgr_disable(dssdev->manager); + dss_mgr_disable(mgr); p = &hdmi.ip_data.cfg.timings; @@ -560,13 +563,13 @@ static int hdmi_power_on(struct omap_dss_device *dssdev) dispc_enable_gamma_table(0); /* tv size */ - dss_mgr_set_timings(dssdev->manager, p); + dss_mgr_set_timings(mgr, p); r = hdmi.ip_data.ops->video_enable(&hdmi.ip_data); if (r) goto err_vid_enable; - r = dss_mgr_enable(dssdev->manager); + r = dss_mgr_enable(mgr); if (r) goto err_mgr_enable; @@ -590,7 +593,9 @@ err_vdac_enable: static void hdmi_power_off(struct omap_dss_device *dssdev) { - dss_mgr_disable(dssdev->manager); + struct omap_overlay_manager *mgr = dssdev->output->manager; + + dss_mgr_disable(mgr); hdmi.ip_data.ops->video_disable(&hdmi.ip_data); hdmi.ip_data.ops->phy_disable(&hdmi.ip_data); @@ -687,14 +692,15 @@ bool omapdss_hdmi_detect(void) int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev) { + struct omap_dss_output *out = dssdev->output; int r = 0; DSSDBG("ENTER hdmi_display_enable\n"); mutex_lock(&hdmi.lock); - if (dssdev->manager == NULL) { - DSSERR("failed to enable display: no manager\n"); + if (out == NULL || out->manager == NULL) { + DSSERR("failed to enable display: no output/manager\n"); r = -ENODEV; goto err0; } @@ -970,6 +976,24 @@ static void __init hdmi_probe_pdata(struct platform_device *pdev) } } +static void __init hdmi_init_output(struct platform_device *pdev) +{ + struct omap_dss_output *out = &hdmi.output; + + out->pdev = pdev; + out->id = OMAP_DSS_OUTPUT_HDMI; + out->type = OMAP_DISPLAY_TYPE_HDMI; + + dss_register_output(out); +} + +static void __exit hdmi_uninit_output(struct platform_device *pdev) +{ + struct omap_dss_output *out = &hdmi.output; + + dss_unregister_output(out); +} + /* HDMI HW IP initialisation */ static int __init omapdss_hdmihw_probe(struct platform_device *pdev) { @@ -1013,6 +1037,8 @@ static int __init omapdss_hdmihw_probe(struct platform_device *pdev) dss_debugfs_create_file("hdmi", hdmi_dump_regs); + hdmi_init_output(pdev); + hdmi_probe_pdata(pdev); return 0; @@ -1033,6 +1059,8 @@ static int __exit omapdss_hdmihw_remove(struct platform_device *pdev) hdmi_panel_exit(); + hdmi_uninit_output(pdev); + pm_runtime_disable(&pdev->dev); hdmi_put_clocks(); diff --git a/drivers/video/omap2/dss/manager-sysfs.c b/drivers/video/omap2/dss/manager-sysfs.c index 9b875fbe757e..9a2fb59b6f89 100644 --- a/drivers/video/omap2/dss/manager-sysfs.c +++ b/drivers/video/omap2/dss/manager-sysfs.c @@ -38,8 +38,10 @@ static ssize_t manager_name_show(struct omap_overlay_manager *mgr, char *buf) static ssize_t manager_display_show(struct omap_overlay_manager *mgr, char *buf) { - return snprintf(buf, PAGE_SIZE, "%s\n", - mgr->device ? mgr->device->name : "<none>"); + struct omap_dss_device *dssdev = mgr->get_device(mgr); + + return snprintf(buf, PAGE_SIZE, "%s\n", dssdev ? + dssdev->name : "<none>"); } static ssize_t manager_display_store(struct omap_overlay_manager *mgr, @@ -67,18 +69,29 @@ static ssize_t manager_display_store(struct omap_overlay_manager *mgr, if (dssdev) DSSDBG("display %s found\n", dssdev->name); - if (mgr->device) { - r = mgr->unset_device(mgr); + if (mgr->output) { + r = mgr->unset_output(mgr); if (r) { - DSSERR("failed to unset display\n"); + DSSERR("failed to unset current output\n"); goto put_device; } } if (dssdev) { - r = mgr->set_device(mgr, dssdev); + struct omap_dss_output *out = dssdev->output; + + /* + * a registered device should have an output connected to it + * already + */ + if (!out) { + DSSERR("device has no output connected to it\n"); + goto put_device; + } + + r = mgr->set_output(mgr, out); if (r) { - DSSERR("failed to set manager\n"); + DSSERR("failed to set manager output\n"); goto put_device; } diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c index 383314f222b0..c54d2f620ce3 100644 --- a/drivers/video/omap2/dss/manager.c +++ b/drivers/video/omap2/dss/manager.c @@ -36,9 +36,15 @@ static int num_managers; static struct omap_overlay_manager *managers; +static inline struct omap_dss_device *dss_mgr_get_device(struct omap_overlay_manager *mgr) +{ + return mgr->output ? mgr->output->device : NULL; +} + static int dss_mgr_wait_for_vsync(struct omap_overlay_manager *mgr) { unsigned long timeout = msecs_to_jiffies(500); + struct omap_dss_device *dssdev = mgr->get_device(mgr); u32 irq; int r; @@ -46,9 +52,9 @@ static int dss_mgr_wait_for_vsync(struct omap_overlay_manager *mgr) if (r) return r; - if (mgr->device->type == OMAP_DISPLAY_TYPE_VENC) + if (dssdev->type == OMAP_DISPLAY_TYPE_VENC) irq = DISPC_IRQ_EVSYNC_ODD; - else if (mgr->device->type == OMAP_DISPLAY_TYPE_HDMI) + else if (dssdev->type == OMAP_DISPLAY_TYPE_HDMI) irq = DISPC_IRQ_EVSYNC_EVEN; else irq = dispc_mgr_get_vsync_irq(mgr->id); @@ -93,17 +99,20 @@ int dss_init_overlay_managers(struct platform_device *pdev) break; } - mgr->set_device = &dss_mgr_set_device; - mgr->unset_device = &dss_mgr_unset_device; + mgr->set_output = &dss_mgr_set_output; + mgr->unset_output = &dss_mgr_unset_output; mgr->apply = &omap_dss_mgr_apply; mgr->set_manager_info = &dss_mgr_set_info; mgr->get_manager_info = &dss_mgr_get_info; mgr->wait_for_go = &dss_mgr_wait_for_go; mgr->wait_for_vsync = &dss_mgr_wait_for_vsync; + mgr->get_device = &dss_mgr_get_device; mgr->caps = 0; mgr->supported_displays = dss_feat_get_supported_displays(mgr->id); + mgr->supported_outputs = + dss_feat_get_supported_outputs(mgr->id); INIT_LIST_HEAD(&mgr->overlays); diff --git a/drivers/video/omap2/dss/output.c b/drivers/video/omap2/dss/output.c new file mode 100644 index 000000000000..813f26682b7a --- /dev/null +++ b/drivers/video/omap2/dss/output.c @@ -0,0 +1,148 @@ +/* + * Copyright (C) 2012 Texas Instruments Ltd + * Author: Archit Taneja <archit@ti.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. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/slab.h> + +#include <video/omapdss.h> + +#include "dss.h" + +static LIST_HEAD(output_list); +static DEFINE_MUTEX(output_lock); + +int omapdss_output_set_device(struct omap_dss_output *out, + struct omap_dss_device *dssdev) +{ + int r; + + mutex_lock(&output_lock); + + if (out->device) { + DSSERR("output already has device %s connected to it\n", + out->device->name); + r = -EINVAL; + goto err; + } + + if (out->type != dssdev->type) { + DSSERR("output type and display type don't match\n"); + r = -EINVAL; + goto err; + } + + out->device = dssdev; + dssdev->output = out; + + mutex_unlock(&output_lock); + + return 0; +err: + mutex_unlock(&output_lock); + + return r; +} +EXPORT_SYMBOL(omapdss_output_set_device); + +int omapdss_output_unset_device(struct omap_dss_output *out) +{ + int r; + + mutex_lock(&output_lock); + + if (!out->device) { + DSSERR("output doesn't have a device connected to it\n"); + r = -EINVAL; + goto err; + } + + if (out->device->state != OMAP_DSS_DISPLAY_DISABLED) { + DSSERR("device %s is not disabled, cannot unset device\n", + out->device->name); + r = -EINVAL; + goto err; + } + + out->device->output = NULL; + out->device = NULL; + + mutex_unlock(&output_lock); + + return 0; +err: + mutex_unlock(&output_lock); + + return r; +} +EXPORT_SYMBOL(omapdss_output_unset_device); + +void dss_register_output(struct omap_dss_output *out) +{ + list_add_tail(&out->list, &output_list); +} + +void dss_unregister_output(struct omap_dss_output *out) +{ + list_del(&out->list); +} + +struct omap_dss_output *omap_dss_get_output(enum omap_dss_output_id id) +{ + struct omap_dss_output *out; + + list_for_each_entry(out, &output_list, list) { + if (out->id == id) + return out; + } + + return NULL; +} + +struct omap_dss_output *omapdss_get_output_from_dssdev(struct omap_dss_device *dssdev) +{ + struct omap_dss_output *out = NULL; + enum omap_dss_output_id id; + + switch (dssdev->type) { + case OMAP_DISPLAY_TYPE_DPI: + out = omap_dss_get_output(OMAP_DSS_OUTPUT_DPI); + break; + case OMAP_DISPLAY_TYPE_DBI: + out = omap_dss_get_output(OMAP_DSS_OUTPUT_DBI); + break; + case OMAP_DISPLAY_TYPE_SDI: + out = omap_dss_get_output(OMAP_DSS_OUTPUT_SDI); + break; + case OMAP_DISPLAY_TYPE_VENC: + out = omap_dss_get_output(OMAP_DSS_OUTPUT_VENC); + break; + case OMAP_DISPLAY_TYPE_HDMI: + out = omap_dss_get_output(OMAP_DSS_OUTPUT_HDMI); + break; + case OMAP_DISPLAY_TYPE_DSI: + id = dssdev->phy.dsi.module == 0 ? OMAP_DSS_OUTPUT_DSI1 : + OMAP_DSS_OUTPUT_DSI2; + out = omap_dss_get_output(id); + break; + default: + break; + } + + return out; +} diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c index 52455a0609cb..45f4994bc6b0 100644 --- a/drivers/video/omap2/dss/overlay.c +++ b/drivers/video/omap2/dss/overlay.c @@ -38,6 +38,13 @@ static int num_overlays; static struct omap_overlay *overlays; +static inline struct omap_dss_device *dss_ovl_get_device(struct omap_overlay *ovl) +{ + return ovl->manager ? + (ovl->manager->output ? ovl->manager->output->device : NULL) : + NULL; +} + int omap_dss_get_num_overlays(void) { return num_overlays; @@ -94,6 +101,7 @@ void dss_init_overlays(struct platform_device *pdev) ovl->set_overlay_info = &dss_ovl_set_info; ovl->get_overlay_info = &dss_ovl_get_info; ovl->wait_for_go = &dss_mgr_wait_for_go_ovl; + ovl->get_device = &dss_ovl_get_device; ovl->caps = dss_feat_get_overlay_caps(ovl->id); ovl->supported_modes = diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c index 38d9b8ecbe3c..7282e5af3e1a 100644 --- a/drivers/video/omap2/dss/rfbi.c +++ b/drivers/video/omap2/dss/rfbi.c @@ -116,6 +116,8 @@ static struct { int pixel_size; int data_lines; struct rfbi_timings intf_timings; + + struct omap_dss_output output; } rfbi; static inline void rfbi_write_reg(const struct rfbi_reg idx, u32 val) @@ -310,6 +312,7 @@ static int rfbi_transfer_area(struct omap_dss_device *dssdev, { u32 l; int r; + struct omap_overlay_manager *mgr = dssdev->output->manager; u16 width = rfbi.timings.x_res; u16 height = rfbi.timings.y_res; @@ -318,9 +321,9 @@ static int rfbi_transfer_area(struct omap_dss_device *dssdev, DSSDBG("rfbi_transfer_area %dx%d\n", width, height); - dss_mgr_set_timings(dssdev->manager, &rfbi.timings); + dss_mgr_set_timings(mgr, &rfbi.timings); - r = dss_mgr_enable(dssdev->manager); + r = dss_mgr_enable(mgr); if (r) return r; @@ -849,6 +852,7 @@ static void rfbi_dump_regs(struct seq_file *s) static void rfbi_config_lcd_manager(struct omap_dss_device *dssdev) { + struct omap_overlay_manager *mgr = dssdev->output->manager; struct dss_lcd_mgr_config mgr_config; mgr_config.io_pad_mode = DSS_IO_PAD_MODE_RFBI; @@ -860,7 +864,7 @@ static void rfbi_config_lcd_manager(struct omap_dss_device *dssdev) mgr_config.video_port_width = rfbi.pixel_size; mgr_config.lcden_sig_polarity = 0; - dss_mgr_set_lcd_config(dssdev->manager, &mgr_config); + dss_mgr_set_lcd_config(mgr, &mgr_config); /* * Set rfbi.timings with default values, the x_res and y_res fields @@ -881,15 +885,16 @@ static void rfbi_config_lcd_manager(struct omap_dss_device *dssdev) rfbi.timings.de_level = OMAPDSS_SIG_ACTIVE_HIGH; rfbi.timings.sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES; - dss_mgr_set_timings(dssdev->manager, &rfbi.timings); + dss_mgr_set_timings(mgr, &rfbi.timings); } int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev) { + struct omap_dss_output *out = dssdev->output; int r; - if (dssdev->manager == NULL) { - DSSERR("failed to enable display: no manager\n"); + if (out == NULL || out->manager == NULL) { + DSSERR("failed to enable display: no output/manager\n"); return -ENODEV; } @@ -1002,6 +1007,24 @@ static void __init rfbi_probe_pdata(struct platform_device *rfbidev) } } +static void __init rfbi_init_output(struct platform_device *pdev) +{ + struct omap_dss_output *out = &rfbi.output; + + out->pdev = pdev; + out->id = OMAP_DSS_OUTPUT_DBI; + out->type = OMAP_DISPLAY_TYPE_DBI; + + dss_register_output(out); +} + +static void __exit rfbi_uninit_output(struct platform_device *pdev) +{ + struct omap_dss_output *out = &rfbi.output; + + dss_unregister_output(out); +} + /* RFBI HW IP initialisation */ static int __init omap_rfbihw_probe(struct platform_device *pdev) { @@ -1053,6 +1076,8 @@ static int __init omap_rfbihw_probe(struct platform_device *pdev) dss_debugfs_create_file("rfbi", rfbi_dump_regs); + rfbi_init_output(pdev); + rfbi_probe_pdata(pdev); return 0; @@ -1065,7 +1090,11 @@ err_runtime_get: static int __exit omap_rfbihw_remove(struct platform_device *pdev) { dss_unregister_child_devices(&pdev->dev); + + rfbi_uninit_output(pdev); + pm_runtime_disable(&pdev->dev); + return 0; } diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c index 919ff728c502..86f096aaf4fe 100644 --- a/drivers/video/omap2/dss/sdi.c +++ b/drivers/video/omap2/dss/sdi.c @@ -36,10 +36,14 @@ static struct { struct dss_lcd_mgr_config mgr_config; struct omap_video_timings timings; int datapairs; + + struct omap_dss_output output; } sdi; static void sdi_config_lcd_manager(struct omap_dss_device *dssdev) { + struct omap_overlay_manager *mgr = dssdev->output->manager; + sdi.mgr_config.io_pad_mode = DSS_IO_PAD_MODE_BYPASS; sdi.mgr_config.stallmode = false; @@ -48,19 +52,20 @@ static void sdi_config_lcd_manager(struct omap_dss_device *dssdev) sdi.mgr_config.video_port_width = 24; sdi.mgr_config.lcden_sig_polarity = 1; - dss_mgr_set_lcd_config(dssdev->manager, &sdi.mgr_config); + dss_mgr_set_lcd_config(mgr, &sdi.mgr_config); } int omapdss_sdi_display_enable(struct omap_dss_device *dssdev) { + struct omap_dss_output *out = dssdev->output; struct omap_video_timings *t = &sdi.timings; struct dss_clock_info dss_cinfo; struct dispc_clock_info dispc_cinfo; unsigned long pck; int r; - if (dssdev->manager == NULL) { - DSSERR("failed to enable display: no manager\n"); + if (out == NULL || out->manager == NULL) { + DSSERR("failed to enable display: no output/manager\n"); return -ENODEV; } @@ -99,7 +104,7 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev) } - dss_mgr_set_timings(dssdev->manager, t); + dss_mgr_set_timings(out->manager, t); r = dss_set_clock_div(&dss_cinfo); if (r) @@ -118,8 +123,7 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev) * need to care about the shadow register mechanism for pck-free. The * exact reason for this is unknown. */ - dispc_mgr_set_clock_div(dssdev->manager->id, - &sdi.mgr_config.clock_info); + dispc_mgr_set_clock_div(out->manager->id, &sdi.mgr_config.clock_info); dss_sdi_init(sdi.datapairs); r = dss_sdi_enable(); @@ -127,7 +131,7 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev) goto err_sdi_enable; mdelay(2); - r = dss_mgr_enable(dssdev->manager); + r = dss_mgr_enable(out->manager); if (r) goto err_mgr_enable; @@ -150,7 +154,9 @@ EXPORT_SYMBOL(omapdss_sdi_display_enable); void omapdss_sdi_display_disable(struct omap_dss_device *dssdev) { - dss_mgr_disable(dssdev->manager); + struct omap_overlay_manager *mgr = dssdev->output->manager; + + dss_mgr_disable(mgr); dss_sdi_disable(); @@ -255,8 +261,28 @@ static void __init sdi_probe_pdata(struct platform_device *sdidev) } } +static void __init sdi_init_output(struct platform_device *pdev) +{ + struct omap_dss_output *out = &sdi.output; + + out->pdev = pdev; + out->id = OMAP_DSS_OUTPUT_SDI; + out->type = OMAP_DISPLAY_TYPE_SDI; + + dss_register_output(out); +} + +static void __exit sdi_uninit_output(struct platform_device *pdev) +{ + struct omap_dss_output *out = &sdi.output; + + dss_unregister_output(out); +} + static int __init omap_sdi_probe(struct platform_device *pdev) { + sdi_init_output(pdev); + sdi_probe_pdata(pdev); return 0; @@ -266,6 +292,8 @@ static int __exit omap_sdi_remove(struct platform_device *pdev) { dss_unregister_child_devices(&pdev->dev); + sdi_uninit_output(pdev); + return 0; } diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c index 996779c0204c..56efa3bb465d 100644 --- a/drivers/video/omap2/dss/venc.c +++ b/drivers/video/omap2/dss/venc.c @@ -303,6 +303,8 @@ static struct { struct omap_video_timings timings; enum omap_dss_venc_type type; bool invert_polarity; + + struct omap_dss_output output; } venc; static inline void venc_write_reg(int idx, u32 val) @@ -427,6 +429,7 @@ static const struct venc_config *venc_timings_to_config( static int venc_power_on(struct omap_dss_device *dssdev) { + struct omap_overlay_manager *mgr = dssdev->output->manager; u32 l; int r; @@ -452,13 +455,13 @@ static int venc_power_on(struct omap_dss_device *dssdev) venc_write_reg(VENC_OUTPUT_CONTROL, l); - dss_mgr_set_timings(dssdev->manager, &venc.timings); + dss_mgr_set_timings(mgr, &venc.timings); r = regulator_enable(venc.vdda_dac_reg); if (r) goto err1; - r = dss_mgr_enable(dssdev->manager); + r = dss_mgr_enable(mgr); if (r) goto err2; @@ -477,10 +480,12 @@ err0: static void venc_power_off(struct omap_dss_device *dssdev) { + struct omap_overlay_manager *mgr = dssdev->output->manager; + venc_write_reg(VENC_OUTPUT_CONTROL, 0); dss_set_dac_pwrdn_bgz(0); - dss_mgr_disable(dssdev->manager); + dss_mgr_disable(mgr); regulator_disable(venc.vdda_dac_reg); @@ -495,14 +500,15 @@ unsigned long venc_get_pixel_clock(void) int omapdss_venc_display_enable(struct omap_dss_device *dssdev) { + struct omap_dss_output *out = dssdev->output; int r; DSSDBG("venc_display_enable\n"); mutex_lock(&venc.venc_lock); - if (dssdev->manager == NULL) { - DSSERR("Failed to enable display: no manager\n"); + if (out == NULL || out->manager == NULL) { + DSSERR("Failed to enable display: no output/manager\n"); r = -ENODEV; goto err0; } @@ -797,6 +803,24 @@ static void __init venc_probe_pdata(struct platform_device *vencdev) } } +static void __init venc_init_output(struct platform_device *pdev) +{ + struct omap_dss_output *out = &venc.output; + + out->pdev = pdev; + out->id = OMAP_DSS_OUTPUT_VENC; + out->type = OMAP_DISPLAY_TYPE_VENC; + + dss_register_output(out); +} + +static void __exit venc_uninit_output(struct platform_device *pdev) +{ + struct omap_dss_output *out = &venc.output; + + dss_unregister_output(out); +} + /* VENC HW IP initialisation */ static int __init omap_venchw_probe(struct platform_device *pdev) { @@ -844,6 +868,8 @@ static int __init omap_venchw_probe(struct platform_device *pdev) dss_debugfs_create_file("venc", venc_dump_regs); + venc_init_output(pdev); + venc_probe_pdata(pdev); return 0; @@ -866,6 +892,8 @@ static int __exit omap_venchw_remove(struct platform_device *pdev) venc_panel_exit(); + venc_uninit_output(pdev); + pm_runtime_disable(&pdev->dev); venc_put_clocks(); diff --git a/drivers/video/omap2/omapfb/omapfb-ioctl.c b/drivers/video/omap2/omapfb/omapfb-ioctl.c index c6cf372d22c5..606b89f12351 100644 --- a/drivers/video/omap2/omapfb/omapfb-ioctl.c +++ b/drivers/video/omap2/omapfb/omapfb-ioctl.c @@ -599,6 +599,7 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg) struct omapfb_info *ofbi = FB2OFB(fbi); struct omapfb2_device *fbdev = ofbi->fbdev; struct omap_dss_device *display = fb2display(fbi); + struct omap_overlay_manager *mgr; union { struct omapfb_update_window_old uwnd_o; @@ -786,12 +787,14 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg) case OMAPFB_WAITFORVSYNC: DBG("ioctl WAITFORVSYNC\n"); - if (!display) { + if (!display && !display->output && !display->output->manager) { r = -EINVAL; break; } - r = display->manager->wait_for_vsync(display->manager); + mgr = display->output->manager; + + r = mgr->wait_for_vsync(mgr); break; case OMAPFB_WAITFORGO: diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c index 77ae9edbf2cd..b103793516db 100644 --- a/drivers/video/omap2/omapfb/omapfb-main.c +++ b/drivers/video/omap2/omapfb/omapfb-main.c @@ -2379,6 +2379,7 @@ static int __init omapfb_probe(struct platform_device *pdev) struct omap_overlay *ovl; struct omap_dss_device *def_display; struct omap_dss_device *dssdev; + struct omap_dss_device *ovl_device; DBG("omapfb_probe\n"); @@ -2452,8 +2453,9 @@ static int __init omapfb_probe(struct platform_device *pdev) /* gfx overlay should be the default one. find a display * connected to that, and use it as default display */ ovl = omap_dss_get_overlay(0); - if (ovl->manager && ovl->manager->device) { - def_display = ovl->manager->device; + ovl_device = ovl->get_device(ovl); + if (ovl_device) { + def_display = ovl_device; } else { dev_warn(&pdev->dev, "cannot find default display\n"); def_display = NULL; diff --git a/drivers/video/omap2/omapfb/omapfb.h b/drivers/video/omap2/omapfb/omapfb.h index 30361a09aecd..5ced9b334d35 100644 --- a/drivers/video/omap2/omapfb/omapfb.h +++ b/drivers/video/omap2/omapfb/omapfb.h @@ -148,8 +148,9 @@ static inline struct omap_dss_device *fb2display(struct fb_info *fbi) /* XXX: returns the display connected to first attached overlay */ for (i = 0; i < ofbi->num_overlays; i++) { - if (ofbi->overlays[i]->manager) - return ofbi->overlays[i]->manager->device; + struct omap_overlay *ovl = ofbi->overlays[i]; + + return ovl->get_device(ovl); } return NULL; diff --git a/include/video/omapdss.h b/include/video/omapdss.h index ac2e4cca5a23..e65e2e9e16eb 100644 --- a/include/video/omapdss.h +++ b/include/video/omapdss.h @@ -208,6 +208,16 @@ enum omap_hdmi_flags { OMAP_HDMI_SDA_SCL_EXTERNAL_PULLUP = 1 << 0, }; +enum omap_dss_output_id { + OMAP_DSS_OUTPUT_DPI = 1 << 0, + OMAP_DSS_OUTPUT_DBI = 1 << 1, + OMAP_DSS_OUTPUT_SDI = 1 << 2, + OMAP_DSS_OUTPUT_DSI1 = 1 << 3, + OMAP_DSS_OUTPUT_DSI2 = 1 << 4, + OMAP_DSS_OUTPUT_VENC = 1 << 5, + OMAP_DSS_OUTPUT_HDMI = 1 << 6, +}; + /* RFBI */ struct rfbi_timings { @@ -425,6 +435,8 @@ struct omap_overlay { struct omap_overlay_info *info); int (*wait_for_go)(struct omap_overlay *ovl); + + struct omap_dss_device *(*get_device)(struct omap_overlay *ovl); }; struct omap_overlay_manager_info { @@ -449,9 +461,10 @@ struct omap_overlay_manager { enum omap_overlay_manager_caps caps; struct list_head overlays; enum omap_display_type supported_displays; + enum omap_dss_output_id supported_outputs; /* dynamic fields */ - struct omap_dss_device *device; + struct omap_dss_output *output; /* * The following functions do not block: @@ -464,9 +477,9 @@ struct omap_overlay_manager { * interrupt context */ - int (*set_device)(struct omap_overlay_manager *mgr, - struct omap_dss_device *dssdev); - int (*unset_device)(struct omap_overlay_manager *mgr); + int (*set_output)(struct omap_overlay_manager *mgr, + struct omap_dss_output *output); + int (*unset_output)(struct omap_overlay_manager *mgr); int (*set_manager_info)(struct omap_overlay_manager *mgr, struct omap_overlay_manager_info *info); @@ -476,6 +489,8 @@ struct omap_overlay_manager { int (*apply)(struct omap_overlay_manager *mgr); int (*wait_for_go)(struct omap_overlay_manager *mgr); int (*wait_for_vsync)(struct omap_overlay_manager *mgr); + + struct omap_dss_device *(*get_device)(struct omap_overlay_manager *mgr); }; /* 22 pins means 1 clk lane and 10 data lanes */ @@ -493,6 +508,24 @@ struct omap_dsi_pin_config { int pins[OMAP_DSS_MAX_DSI_PINS]; }; +struct omap_dss_output { + struct list_head list; + + /* display type supported by the output */ + enum omap_display_type type; + + /* output instance */ + enum omap_dss_output_id id; + + /* output's platform device pointer */ + struct platform_device *pdev; + + /* dynamic fields */ + struct omap_overlay_manager *manager; + + struct omap_dss_device *device; +}; + struct omap_dss_device { struct device dev; @@ -591,7 +624,7 @@ struct omap_dss_device { enum omap_display_caps caps; - struct omap_overlay_manager *manager; + struct omap_dss_output *output; enum omap_dss_display_state state; @@ -702,6 +735,11 @@ struct omap_overlay_manager *omap_dss_get_overlay_manager(int num); 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); +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); + 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); |