diff options
Diffstat (limited to 'drivers')
26 files changed, 799 insertions, 538 deletions
diff --git a/drivers/video/omap/Kconfig b/drivers/video/omap/Kconfig index 1e7536d9a8f..b48f95f0dfe 100644 --- a/drivers/video/omap/Kconfig +++ b/drivers/video/omap/Kconfig @@ -39,14 +39,6 @@ config FB_OMAP_LCD_MIPID the Mobile Industry Processor Interface DBI-C/DCS specification. (Supported LCDs: Philips LPH8923, Sharp LS041Y3) -config FB_OMAP_BOOTLOADER_INIT - bool "Check bootloader initialization" - depends on FB_OMAP - help - Say Y here if you want to enable checking if the bootloader has - already initialized the display controller. In this case the - driver will skip the initialization. - config FB_OMAP_CONSISTENT_DMA_SIZE int "Consistent DMA memory size (MB)" depends on FB_OMAP diff --git a/drivers/video/omap2/displays/panel-acx565akm.c b/drivers/video/omap2/displays/panel-acx565akm.c index d26f37ac69d..c98f2c16f74 100644 --- a/drivers/video/omap2/displays/panel-acx565akm.c +++ b/drivers/video/omap2/displays/panel-acx565akm.c @@ -738,12 +738,6 @@ static void acx_panel_set_timings(struct omap_dss_device *dssdev, } } -static void acx_panel_get_timings(struct omap_dss_device *dssdev, - struct omap_video_timings *timings) -{ - *timings = dssdev->panel.timings; -} - static int acx_panel_check_timings(struct omap_dss_device *dssdev, struct omap_video_timings *timings) { @@ -761,7 +755,6 @@ static struct omap_dss_driver acx_panel_driver = { .resume = acx_panel_resume, .set_timings = acx_panel_set_timings, - .get_timings = acx_panel_get_timings, .check_timings = acx_panel_check_timings, .get_recommended_bpp = acx_get_recommended_bpp, diff --git a/drivers/video/omap2/displays/panel-generic-dpi.c b/drivers/video/omap2/displays/panel-generic-dpi.c index 30fe4dfeb22..e42f9dc2212 100644 --- a/drivers/video/omap2/displays/panel-generic-dpi.c +++ b/drivers/video/omap2/displays/panel-generic-dpi.c @@ -386,6 +386,106 @@ static struct panel_config generic_dpi_panels[] = { .name = "innolux_at080tn52", }, + + /* Mitsubishi AA084SB01 */ + { + { + .x_res = 800, + .y_res = 600, + .pixel_clock = 40000, + + .hsw = 1, + .hfp = 254, + .hbp = 1, + + .vsw = 1, + .vfp = 26, + .vbp = 1, + }, + .config = OMAP_DSS_LCD_TFT, + .name = "mitsubishi_aa084sb01", + }, + /* EDT ET0500G0DH6 */ + { + { + .x_res = 800, + .y_res = 480, + .pixel_clock = 33260, + + .hsw = 128, + .hfp = 216, + .hbp = 40, + + .vsw = 2, + .vfp = 35, + .vbp = 10, + }, + .config = OMAP_DSS_LCD_TFT, + .name = "edt_et0500g0dh6", + }, + + /* Prime-View PD050VL1 */ + { + { + .x_res = 640, + .y_res = 480, + + .pixel_clock = 25000, + + .hsw = 96, + .hfp = 18, + .hbp = 46, + + .vsw = 2, + .vfp = 10, + .vbp = 33, + }, + .config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS | + OMAP_DSS_LCD_IHS | OMAP_DSS_LCD_IPC, + .name = "primeview_pd050vl1", + }, + + /* Prime-View PM070WL4 */ + { + { + .x_res = 800, + .y_res = 480, + + .pixel_clock = 32000, + + .hsw = 128, + .hfp = 42, + .hbp = 86, + + .vsw = 2, + .vfp = 10, + .vbp = 33, + }, + .config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS | + OMAP_DSS_LCD_IHS | OMAP_DSS_LCD_IPC, + .name = "primeview_pm070wl4", + }, + + /* Prime-View PD104SLF */ + { + { + .x_res = 800, + .y_res = 600, + + .pixel_clock = 40000, + + .hsw = 128, + .hfp = 42, + .hbp = 86, + + .vsw = 4, + .vfp = 1, + .vbp = 23, + }, + .config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS | + OMAP_DSS_LCD_IHS | OMAP_DSS_LCD_IPC, + .name = "primeview_pd104slf", + }, }; struct panel_drv_data { @@ -549,12 +649,6 @@ static void generic_dpi_panel_set_timings(struct omap_dss_device *dssdev, dpi_set_timings(dssdev, timings); } -static void generic_dpi_panel_get_timings(struct omap_dss_device *dssdev, - struct omap_video_timings *timings) -{ - *timings = dssdev->panel.timings; -} - static int generic_dpi_panel_check_timings(struct omap_dss_device *dssdev, struct omap_video_timings *timings) { @@ -571,7 +665,6 @@ static struct omap_dss_driver dpi_driver = { .resume = generic_dpi_panel_resume, .set_timings = generic_dpi_panel_set_timings, - .get_timings = generic_dpi_panel_get_timings, .check_timings = generic_dpi_panel_check_timings, .driver = { diff --git a/drivers/video/omap2/displays/panel-n8x0.c b/drivers/video/omap2/displays/panel-n8x0.c index dc9408dc93d..4a34cdc1371 100644 --- a/drivers/video/omap2/displays/panel-n8x0.c +++ b/drivers/video/omap2/displays/panel-n8x0.c @@ -610,12 +610,6 @@ static int n8x0_panel_resume(struct omap_dss_device *dssdev) return 0; } -static void n8x0_panel_get_timings(struct omap_dss_device *dssdev, - struct omap_video_timings *timings) -{ - *timings = dssdev->panel.timings; -} - static void n8x0_panel_get_resolution(struct omap_dss_device *dssdev, u16 *xres, u16 *yres) { @@ -678,8 +672,6 @@ static struct omap_dss_driver n8x0_panel_driver = { .get_resolution = n8x0_panel_get_resolution, .get_recommended_bpp = omapdss_default_get_recommended_bpp, - .get_timings = n8x0_panel_get_timings, - .driver = { .name = "n8x0_panel", .owner = THIS_MODULE, diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c index b2dd88b4842..2ce9992f403 100644 --- a/drivers/video/omap2/displays/panel-taal.c +++ b/drivers/video/omap2/displays/panel-taal.c @@ -30,7 +30,6 @@ #include <linux/gpio.h> #include <linux/workqueue.h> #include <linux/slab.h> -#include <linux/regulator/consumer.h> #include <linux/mutex.h> #include <video/omapdss.h> @@ -55,73 +54,6 @@ static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable); static int taal_panel_reset(struct omap_dss_device *dssdev); -struct panel_regulator { - struct regulator *regulator; - const char *name; - int min_uV; - int max_uV; -}; - -static void free_regulators(struct panel_regulator *regulators, int n) -{ - int i; - - for (i = 0; i < n; i++) { - /* disable/put in reverse order */ - regulator_disable(regulators[n - i - 1].regulator); - regulator_put(regulators[n - i - 1].regulator); - } -} - -static int init_regulators(struct omap_dss_device *dssdev, - struct panel_regulator *regulators, int n) -{ - int r, i, v; - - for (i = 0; i < n; i++) { - struct regulator *reg; - - reg = regulator_get(&dssdev->dev, regulators[i].name); - if (IS_ERR(reg)) { - dev_err(&dssdev->dev, "failed to get regulator %s\n", - regulators[i].name); - r = PTR_ERR(reg); - goto err; - } - - /* FIXME: better handling of fixed vs. variable regulators */ - v = regulator_get_voltage(reg); - if (v < regulators[i].min_uV || v > regulators[i].max_uV) { - r = regulator_set_voltage(reg, regulators[i].min_uV, - regulators[i].max_uV); - if (r) { - dev_err(&dssdev->dev, - "failed to set regulator %s voltage\n", - regulators[i].name); - regulator_put(reg); - goto err; - } - } - - r = regulator_enable(reg); - if (r) { - dev_err(&dssdev->dev, "failed to enable regulator %s\n", - regulators[i].name); - regulator_put(reg); - goto err; - } - - regulators[i].regulator = reg; - } - - return 0; - -err: - free_regulators(regulators, i); - - return r; -} - /** * struct panel_config - panel configuration * @name: panel name @@ -150,8 +82,6 @@ struct panel_config { unsigned int low; } reset_sequence; - struct panel_regulator *regulators; - int num_regulators; }; enum { @@ -577,12 +507,6 @@ static const struct backlight_ops taal_bl_ops = { .update_status = taal_bl_update_status, }; -static void taal_get_timings(struct omap_dss_device *dssdev, - struct omap_video_timings *timings) -{ - *timings = dssdev->panel.timings; -} - static void taal_get_resolution(struct omap_dss_device *dssdev, u16 *xres, u16 *yres) { @@ -977,11 +901,6 @@ static int taal_probe(struct omap_dss_device *dssdev) atomic_set(&td->do_update, 0); - r = init_regulators(dssdev, panel_config->regulators, - panel_config->num_regulators); - if (r) - goto err_reg; - td->workqueue = create_singlethread_workqueue("taal_esd"); if (td->workqueue == NULL) { dev_err(&dssdev->dev, "can't create ESD workqueue\n"); @@ -1087,8 +1006,6 @@ err_bl: err_rst_gpio: destroy_workqueue(td->workqueue); err_wq: - free_regulators(panel_config->regulators, panel_config->num_regulators); -err_reg: kfree(td); err: return r; @@ -1125,9 +1042,6 @@ static void __exit taal_remove(struct omap_dss_device *dssdev) /* reset, to be sure that the panel is in a valid state */ taal_hw_reset(dssdev); - free_regulators(td->panel_config->regulators, - td->panel_config->num_regulators); - if (gpio_is_valid(panel_data->reset_gpio)) gpio_free(panel_data->reset_gpio); @@ -1909,8 +1823,6 @@ static struct omap_dss_driver taal_driver = { .run_test = taal_run_test, .memory_read = taal_memory_read, - .get_timings = taal_get_timings, - .driver = { .name = "taal", .owner = THIS_MODULE, diff --git a/drivers/video/omap2/displays/panel-tpo-td043mtea1.c b/drivers/video/omap2/displays/panel-tpo-td043mtea1.c index 32f3fcd7f0f..4b6448b3c31 100644 --- a/drivers/video/omap2/displays/panel-tpo-td043mtea1.c +++ b/drivers/video/omap2/displays/panel-tpo-td043mtea1.c @@ -272,13 +272,16 @@ static const struct omap_video_timings tpo_td043_timings = { static int tpo_td043_power_on(struct tpo_td043_device *tpo_td043) { int nreset_gpio = tpo_td043->nreset_gpio; + int r; if (tpo_td043->powered_on) return 0; - regulator_enable(tpo_td043->vcc_reg); + r = regulator_enable(tpo_td043->vcc_reg); + if (r != 0) + return r; - /* wait for regulator to stabilize */ + /* wait for panel to stabilize */ msleep(160); if (gpio_is_valid(nreset_gpio)) @@ -470,6 +473,18 @@ static void tpo_td043_remove(struct omap_dss_device *dssdev) gpio_free(nreset_gpio); } +static void tpo_td043_set_timings(struct omap_dss_device *dssdev, + struct omap_video_timings *timings) +{ + dpi_set_timings(dssdev, timings); +} + +static int tpo_td043_check_timings(struct omap_dss_device *dssdev, + struct omap_video_timings *timings) +{ + return dpi_check_timings(dssdev, timings); +} + static struct omap_dss_driver tpo_td043_driver = { .probe = tpo_td043_probe, .remove = tpo_td043_remove, @@ -481,6 +496,9 @@ static struct omap_dss_driver tpo_td043_driver = { .set_mirror = tpo_td043_set_hmirror, .get_mirror = tpo_td043_get_hmirror, + .set_timings = tpo_td043_set_timings, + .check_timings = tpo_td043_check_timings, + .driver = { .name = "tpo_td043mtea1_panel", .owner = THIS_MODULE, diff --git a/drivers/video/omap2/dss/Kconfig b/drivers/video/omap2/dss/Kconfig index 7be7c06a249..9aaf3246f82 100644 --- a/drivers/video/omap2/dss/Kconfig +++ b/drivers/video/omap2/dss/Kconfig @@ -90,15 +90,6 @@ config OMAP2_DSS_DSI See http://www.mipi.org/ for DSI spesifications. -config OMAP2_DSS_FAKE_VSYNC - bool "Fake VSYNC irq from manual update displays" - default n - help - If this is selected, DSI will generate a fake DISPC VSYNC interrupt - when DSI has sent a frame. This is only needed with DSI or RFBI - displays using manual mode, and you want VSYNC to, for example, - time animation. - config OMAP2_DSS_MIN_FCK_PER_PCK int "Minimum FCK/PCK ratio (for scaling)" range 0 32 diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c index b10b3bc1931..dd88b8f936c 100644 --- a/drivers/video/omap2/dss/apply.c +++ b/drivers/video/omap2/dss/apply.c @@ -99,6 +99,11 @@ struct mgr_priv_data { /* If true, a display is enabled using this manager */ bool enabled; + + bool extra_info_dirty; + bool shadow_extra_info_dirty; + + struct omap_video_timings timings; }; static struct { @@ -176,7 +181,7 @@ static bool mgr_manual_update(struct omap_overlay_manager *mgr) } static int dss_check_settings_low(struct omap_overlay_manager *mgr, - struct omap_dss_device *dssdev, bool applying) + bool applying) { struct omap_overlay_info *oi; struct omap_overlay_manager_info *mi; @@ -187,6 +192,9 @@ static int dss_check_settings_low(struct omap_overlay_manager *mgr, mp = get_mgr_priv(mgr); + if (!mp->enabled) + return 0; + if (applying && mp->user_info_dirty) mi = &mp->user_info; else @@ -206,26 +214,24 @@ static int dss_check_settings_low(struct omap_overlay_manager *mgr, ois[ovl->id] = oi; } - return dss_mgr_check(mgr, dssdev, mi, ois); + return dss_mgr_check(mgr, mi, &mp->timings, ois); } /* * check manager and overlay settings using overlay_info from data->info */ -static int dss_check_settings(struct omap_overlay_manager *mgr, - struct omap_dss_device *dssdev) +static int dss_check_settings(struct omap_overlay_manager *mgr) { - return dss_check_settings_low(mgr, dssdev, false); + return dss_check_settings_low(mgr, false); } /* * check manager and overlay settings using overlay_info from ovl->info if * dirty and from data->info otherwise */ -static int dss_check_settings_apply(struct omap_overlay_manager *mgr, - struct omap_dss_device *dssdev) +static int dss_check_settings_apply(struct omap_overlay_manager *mgr) { - return dss_check_settings_low(mgr, dssdev, true); + return dss_check_settings_low(mgr, true); } static bool need_isr(void) @@ -261,6 +267,20 @@ static bool need_isr(void) if (mp->shadow_info_dirty) return true; + /* + * NOTE: we don't check extra_info flags for disabled + * managers, once the manager is enabled, the extra_info + * related manager changes will be taken in by HW. + */ + + /* to write new values to registers */ + if (mp->extra_info_dirty) + return true; + + /* to set GO bit */ + if (mp->shadow_extra_info_dirty) + return true; + list_for_each_entry(ovl, &mgr->overlays, list) { struct ovl_priv_data *op; @@ -305,7 +325,7 @@ static bool need_go(struct omap_overlay_manager *mgr) mp = get_mgr_priv(mgr); - if (mp->shadow_info_dirty) + if (mp->shadow_info_dirty || mp->shadow_extra_info_dirty) return true; list_for_each_entry(ovl, &mgr->overlays, list) { @@ -320,20 +340,16 @@ static bool need_go(struct omap_overlay_manager *mgr) /* returns true if an extra_info field is currently being updated */ static bool extra_info_update_ongoing(void) { - const int num_ovls = omap_dss_get_num_overlays(); - struct ovl_priv_data *op; - struct omap_overlay *ovl; - struct mgr_priv_data *mp; + const int num_mgrs = dss_feat_get_num_mgrs(); int i; - for (i = 0; i < num_ovls; ++i) { - ovl = omap_dss_get_overlay(i); - op = get_ovl_priv(ovl); - - if (!ovl->manager) - continue; + for (i = 0; i < num_mgrs; ++i) { + struct omap_overlay_manager *mgr; + struct omap_overlay *ovl; + struct mgr_priv_data *mp; - mp = get_mgr_priv(ovl->manager); + mgr = omap_dss_get_overlay_manager(i); + mp = get_mgr_priv(mgr); if (!mp->enabled) continue; @@ -341,8 +357,15 @@ static bool extra_info_update_ongoing(void) if (!mp->updating) continue; - if (op->extra_info_dirty || op->shadow_extra_info_dirty) + if (mp->extra_info_dirty || mp->shadow_extra_info_dirty) return true; + + list_for_each_entry(ovl, &mgr->overlays, list) { + struct ovl_priv_data *op = get_ovl_priv(ovl); + + if (op->extra_info_dirty || op->shadow_extra_info_dirty) + return true; + } } return false; @@ -525,11 +548,13 @@ static void dss_ovl_write_regs(struct omap_overlay *ovl) oi = &op->info; + mp = get_mgr_priv(ovl->manager); + replication = dss_use_replication(ovl->manager->device, oi->color_mode); ilace = ovl->manager->device->type == OMAP_DISPLAY_TYPE_VENC; - r = dispc_ovl_setup(ovl->id, oi, ilace, replication); + r = dispc_ovl_setup(ovl->id, oi, ilace, replication, &mp->timings); if (r) { /* * We can't do much here, as this function can be called from @@ -543,8 +568,6 @@ static void dss_ovl_write_regs(struct omap_overlay *ovl) return; } - mp = get_mgr_priv(ovl->manager); - op->info_dirty = false; if (mp->updating) op->shadow_info_dirty = true; @@ -601,6 +624,22 @@ static void dss_mgr_write_regs(struct omap_overlay_manager *mgr) } } +static void dss_mgr_write_regs_extra(struct omap_overlay_manager *mgr) +{ + struct mgr_priv_data *mp = get_mgr_priv(mgr); + + DSSDBGF("%d", mgr->id); + + if (!mp->extra_info_dirty) + return; + + dispc_mgr_set_timings(mgr->id, &mp->timings); + + mp->extra_info_dirty = false; + if (mp->updating) + mp->shadow_extra_info_dirty = true; +} + static void dss_write_regs_common(void) { const int num_mgrs = omap_dss_get_num_overlay_managers(); @@ -646,7 +685,7 @@ static void dss_write_regs(void) if (!mp->enabled || mgr_manual_update(mgr) || mp->busy) continue; - r = dss_check_settings(mgr, mgr->device); + r = dss_check_settings(mgr); if (r) { DSSERR("cannot write registers for manager %s: " "illegal configuration\n", mgr->name); @@ -654,6 +693,7 @@ static void dss_write_regs(void) } dss_mgr_write_regs(mgr); + dss_mgr_write_regs_extra(mgr); } } @@ -693,6 +733,7 @@ static void mgr_clear_shadow_dirty(struct omap_overlay_manager *mgr) mp = get_mgr_priv(mgr); mp->shadow_info_dirty = false; + mp->shadow_extra_info_dirty = false; list_for_each_entry(ovl, &mgr->overlays, list) { op = get_ovl_priv(ovl); @@ -711,7 +752,7 @@ void dss_mgr_start_update(struct omap_overlay_manager *mgr) WARN_ON(mp->updating); - r = dss_check_settings(mgr, mgr->device); + r = dss_check_settings(mgr); if (r) { DSSERR("cannot start manual update: illegal configuration\n"); spin_unlock_irqrestore(&data_lock, flags); @@ -719,6 +760,7 @@ void dss_mgr_start_update(struct omap_overlay_manager *mgr) } dss_mgr_write_regs(mgr); + dss_mgr_write_regs_extra(mgr); dss_write_regs_common(); @@ -857,7 +899,7 @@ int omap_dss_mgr_apply(struct omap_overlay_manager *mgr) spin_lock_irqsave(&data_lock, flags); - r = dss_check_settings_apply(mgr, mgr->device); + r = dss_check_settings_apply(mgr); if (r) { spin_unlock_irqrestore(&data_lock, flags); DSSERR("failed to apply settings: illegal configuration.\n"); @@ -918,14 +960,11 @@ static void dss_ovl_setup_fifo(struct omap_overlay *ovl, bool use_fifo_merge) { struct ovl_priv_data *op = get_ovl_priv(ovl); - struct omap_dss_device *dssdev; u32 fifo_low, fifo_high; if (!op->enabled && !op->enabling) return; - dssdev = ovl->manager->device; - dispc_ovl_compute_fifo_thresholds(ovl->id, &fifo_low, &fifo_high, use_fifo_merge); @@ -1050,7 +1089,7 @@ int dss_mgr_enable(struct omap_overlay_manager *mgr) mp->enabled = true; - r = dss_check_settings(mgr, mgr->device); + r = dss_check_settings(mgr); if (r) { DSSERR("failed to enable manager %d: check_settings failed\n", mgr->id); @@ -1225,6 +1264,35 @@ err: return r; } +static void dss_apply_mgr_timings(struct omap_overlay_manager *mgr, + struct omap_video_timings *timings) +{ + struct mgr_priv_data *mp = get_mgr_priv(mgr); + + mp->timings = *timings; + mp->extra_info_dirty = true; +} + +void dss_mgr_set_timings(struct omap_overlay_manager *mgr, + struct omap_video_timings *timings) +{ + unsigned long flags; + + mutex_lock(&apply_lock); + + spin_lock_irqsave(&data_lock, flags); + + dss_apply_mgr_timings(mgr, timings); + + dss_write_regs(); + dss_set_go_bits(); + + spin_unlock_irqrestore(&data_lock, flags); + + wait_pending_extra_info_updates(); + + mutex_unlock(&apply_lock); +} int dss_ovl_set_info(struct omap_overlay *ovl, struct omap_overlay_info *info) @@ -1393,7 +1461,7 @@ int dss_ovl_enable(struct omap_overlay *ovl) op->enabling = true; - r = dss_check_settings(ovl->manager, ovl->manager->device); + r = dss_check_settings(ovl->manager); if (r) { DSSERR("failed to enable overlay %d: check_settings failed\n", ovl->id); diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c index e8a120771ac..64cb8aa49b2 100644 --- a/drivers/video/omap2/dss/core.c +++ b/drivers/video/omap2/dss/core.c @@ -87,6 +87,16 @@ struct regulator *dss_get_vdds_sdi(void) return reg; } +int dss_set_min_bus_tput(struct device *dev, unsigned long tput) +{ + struct omap_dss_board_info *pdata = core.pdev->dev.platform_data; + + if (pdata->set_min_bus_tput) + return pdata->set_min_bus_tput(dev, tput); + else + return 0; +} + #if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) static int dss_debug_show(struct seq_file *s, void *unused) { @@ -381,6 +391,8 @@ int omap_dss_register_driver(struct omap_dss_driver *dssdriver) if (dssdriver->get_recommended_bpp == NULL) dssdriver->get_recommended_bpp = omapdss_default_get_recommended_bpp; + if (dssdriver->get_timings == NULL) + dssdriver->get_timings = omapdss_default_get_timings; return driver_register(&dssdriver->driver); } diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index ee30937482e..727e15b29a1 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c @@ -413,14 +413,6 @@ static inline bool dispc_mgr_is_lcd(enum omap_channel channel) return false; } -static struct omap_dss_device *dispc_mgr_get_device(enum omap_channel channel) -{ - struct omap_overlay_manager *mgr = - omap_dss_get_overlay_manager(channel); - - return mgr ? mgr->device : NULL; -} - u32 dispc_mgr_get_vsync_irq(enum omap_channel channel) { switch (channel) { @@ -983,20 +975,13 @@ static void dispc_ovl_enable_replication(enum omap_plane plane, bool enable) REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable, shift, shift); } -void dispc_mgr_set_lcd_size(enum omap_channel channel, u16 width, u16 height) +static void dispc_mgr_set_size(enum omap_channel channel, u16 width, + u16 height) { u32 val; - BUG_ON((width > (1 << 11)) || (height > (1 << 11))); - val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0); - dispc_write_reg(DISPC_SIZE_MGR(channel), val); -} -void dispc_set_digit_size(u16 width, u16 height) -{ - u32 val; - BUG_ON((width > (1 << 11)) || (height > (1 << 11))); val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0); - dispc_write_reg(DISPC_SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT), val); + dispc_write_reg(DISPC_SIZE_MGR(channel), val); } static void dispc_read_plane_fifo_sizes(void) @@ -1431,7 +1416,7 @@ static void calc_vrfb_rotation_offset(u8 rotation, bool mirror, enum omap_color_mode color_mode, bool fieldmode, unsigned int field_offset, unsigned *offset0, unsigned *offset1, - s32 *row_inc, s32 *pix_inc) + s32 *row_inc, s32 *pix_inc, int x_predecim, int y_predecim) { u8 ps; @@ -1477,10 +1462,10 @@ static void calc_vrfb_rotation_offset(u8 rotation, bool mirror, else *offset0 = 0; - *row_inc = pixinc(1 + (screen_width - width) + - (fieldmode ? screen_width : 0), - ps); - *pix_inc = pixinc(1, ps); + *row_inc = pixinc(1 + + (y_predecim * screen_width - x_predecim * width) + + (fieldmode ? screen_width : 0), ps); + *pix_inc = pixinc(x_predecim, ps); break; case OMAP_DSS_ROT_0 + 4: @@ -1498,10 +1483,10 @@ static void calc_vrfb_rotation_offset(u8 rotation, bool mirror, *offset0 = field_offset * screen_width * ps; else *offset0 = 0; - *row_inc = pixinc(1 - (screen_width + width) - - (fieldmode ? screen_width : 0), - ps); - *pix_inc = pixinc(1, ps); + *row_inc = pixinc(1 - + (y_predecim * screen_width + x_predecim * width) - + (fieldmode ? screen_width : 0), ps); + *pix_inc = pixinc(x_predecim, ps); break; default: @@ -1515,7 +1500,7 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror, enum omap_color_mode color_mode, bool fieldmode, unsigned int field_offset, unsigned *offset0, unsigned *offset1, - s32 *row_inc, s32 *pix_inc) + s32 *row_inc, s32 *pix_inc, int x_predecim, int y_predecim) { u8 ps; u16 fbw, fbh; @@ -1557,10 +1542,14 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror, *offset0 = *offset1 + field_offset * screen_width * ps; else *offset0 = *offset1; - *row_inc = pixinc(1 + (screen_width - fbw) + - (fieldmode ? screen_width : 0), - ps); - *pix_inc = pixinc(1, ps); + *row_inc = pixinc(1 + + (y_predecim * screen_width - fbw * x_predecim) + + (fieldmode ? screen_width : 0), ps); + if (color_mode == OMAP_DSS_COLOR_YUV2 || + color_mode == OMAP_DSS_COLOR_UYVY) + *pix_inc = pixinc(x_predecim, 2 * ps); + else + *pix_inc = pixinc(x_predecim, ps); break; case OMAP_DSS_ROT_90: *offset1 = screen_width * (fbh - 1) * ps; @@ -1568,9 +1557,9 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror, *offset0 = *offset1 + field_offset * ps; else *offset0 = *offset1; - *row_inc = pixinc(screen_width * (fbh - 1) + 1 + - (fieldmode ? 1 : 0), ps); - *pix_inc = pixinc(-screen_width, ps); + *row_inc = pixinc(screen_width * (fbh * x_predecim - 1) + + y_predecim + (fieldmode ? 1 : 0), ps); + *pix_inc = pixinc(-x_predecim * screen_width, ps); break; case OMAP_DSS_ROT_180: *offset1 = (screen_width * (fbh - 1) + fbw - 1) * ps; @@ -1579,10 +1568,13 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror, else *offset0 = *offset1; *row_inc = pixinc(-1 - - (screen_width - fbw) - - (fieldmode ? screen_width : 0), - ps); - *pix_inc = pixinc(-1, ps); + (y_predecim * screen_width - fbw * x_predecim) - + (fieldmode ? screen_width : 0), ps); + if (color_mode == OMAP_DSS_COLOR_YUV2 || + color_mode == OMAP_DSS_COLOR_UYVY) + *pix_inc = pixinc(-x_predecim, 2 * ps); + else + *pix_inc = pixinc(-x_predecim, ps); break; case OMAP_DSS_ROT_270: *offset1 = (fbw - 1) * ps; @@ -1590,9 +1582,9 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror, *offset0 = *offset1 - field_offset * ps; else *offset0 = *offset1; - *row_inc = pixinc(-screen_width * (fbh - 1) - 1 - - (fieldmode ? 1 : 0), ps); - *pix_inc = pixinc(screen_width, ps); + *row_inc = pixinc(-screen_width * (fbh * x_predecim - 1) - + y_predecim - (fieldmode ? 1 : 0), ps); + *pix_inc = pixinc(x_predecim * screen_width, ps); break; /* mirroring */ @@ -1602,10 +1594,14 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror, *offset0 = *offset1 + field_offset * screen_width * ps; else *offset0 = *offset1; - *row_inc = pixinc(screen_width * 2 - 1 + + *row_inc = pixinc(y_predecim * screen_width * 2 - 1 + (fieldmode ? screen_width : 0), ps); - *pix_inc = pixinc(-1, ps); + if (color_mode == OMAP_DSS_COLOR_YUV2 || + color_mode == OMAP_DSS_COLOR_UYVY) + *pix_inc = pixinc(-x_predecim, 2 * ps); + else + *pix_inc = pixinc(-x_predecim, ps); break; case OMAP_DSS_ROT_90 + 4: @@ -1614,10 +1610,10 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror, *offset0 = *offset1 + field_offset * ps; else *offset0 = *offset1; - *row_inc = pixinc(-screen_width * (fbh - 1) + 1 + - (fieldmode ? 1 : 0), + *row_inc = pixinc(-screen_width * (fbh * x_predecim - 1) + + y_predecim + (fieldmode ? 1 : 0), ps); - *pix_inc = pixinc(screen_width, ps); + *pix_inc = pixinc(x_predecim * screen_width, ps); break; case OMAP_DSS_ROT_180 + 4: @@ -1626,10 +1622,14 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror, *offset0 = *offset1 - field_offset * screen_width * ps; else *offset0 = *offset1; - *row_inc = pixinc(1 - screen_width * 2 - + *row_inc = pixinc(1 - y_predecim * screen_width * 2 - (fieldmode ? screen_width : 0), ps); - *pix_inc = pixinc(1, ps); + if (color_mode == OMAP_DSS_COLOR_YUV2 || + color_mode == OMAP_DSS_COLOR_UYVY) + *pix_inc = pixinc(x_predecim, 2 * ps); + else + *pix_inc = pixinc(x_predecim, ps); break; case OMAP_DSS_ROT_270 + 4: @@ -1638,10 +1638,10 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror, *offset0 = *offset1 - field_offset * ps; else *offset0 = *offset1; - *row_inc = pixinc(screen_width * (fbh - 1) - 1 - - (fieldmode ? 1 : 0), + *row_inc = pixinc(screen_width * (fbh * x_predecim - 1) - + y_predecim - (fieldmode ? 1 : 0), ps); - *pix_inc = pixinc(-screen_width, ps); + *pix_inc = pixinc(-x_predecim * screen_width, ps); break; default: @@ -1649,23 +1649,79 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror, } } -static unsigned long calc_fclk_five_taps(enum omap_channel channel, u16 width, +/* + * This function is used to avoid synclosts in OMAP3, because of some + * undocumented horizontal position and timing related limitations. + */ +static int check_horiz_timing_omap3(enum omap_channel channel, + const struct omap_video_timings *t, u16 pos_x, + u16 width, u16 height, u16 out_width, u16 out_height) +{ + int DS = DIV_ROUND_UP(height, out_height); + unsigned long nonactive, lclk, pclk; + static const u8 limits[3] = { 8, 10, 20 }; + u64 val, blank; + int i; + + nonactive = t->x_res + t->hfp + t->hsw + t->hbp - out_width; + pclk = dispc_mgr_pclk_rate(channel); + if (dispc_mgr_is_lcd(channel)) + lclk = dispc_mgr_lclk_rate(channel); + else + lclk = dispc_fclk_rate(); + + i = 0; + if (out_height < height) + i++; + if (out_width < width) + i++; + blank = div_u64((u64)(t->hbp + t->hsw + t->hfp) * lclk, pclk); + DSSDBG("blanking period + ppl = %llu (limit = %u)\n", blank, limits[i]); + if (blank <= limits[i]) + return -EINVAL; + + /* + * Pixel data should be prepared before visible display point starts. + * So, atleast DS-2 lines must have already been fetched by DISPC + * during nonactive - pos_x period. + */ + val = div_u64((u64)(nonactive - pos_x) * lclk, pclk); + DSSDBG("(nonactive - pos_x) * pcd = %llu max(0, DS - 2) * width = %d\n", + val, max(0, DS - 2) * width); + if (val < max(0, DS - 2) * width) + return -EINVAL; + + /* + * All lines need to be refilled during the nonactive period of which + * only one line can be loaded during the active period. So, atleast + * DS - 1 lines should be loaded during nonactive period. + */ + val = div_u64((u64)nonactive * lclk, pclk); + DSSDBG("nonactive * pcd = %llu, max(0, DS - 1) * width = %d\n", + val, max(0, DS - 1) * width); + if (val < max(0, DS - 1) * width) + return -EINVAL; + + return 0; +} + +static unsigned long calc_core_clk_five_taps(enum omap_channel channel, + const struct omap_video_timings *mgr_timings, u16 width, u16 height, u16 out_width, u16 out_height, enum omap_color_mode color_mode) { - u32 fclk = 0; + u32 core_clk = 0; u64 tmp, pclk = dispc_mgr_pclk_rate(channel); if (height <= out_height && width <= out_width) return (unsigned long) pclk; if (height > out_height) { - struct omap_dss_device *dssdev = dispc_mgr_get_device(channel); - unsigned int ppl = dssdev->panel.timings.x_res; + unsigned int ppl = mgr_timings->x_res; tmp = pclk * height * out_width; do_div(tmp, 2 * out_height * ppl); - fclk = tmp; + core_clk = tmp; if (height > 2 * out_height) { if (ppl == out_width) @@ -1673,23 +1729,23 @@ static unsigned long calc_fclk_five_taps(enum omap_channel channel, u16 width, tmp = pclk * (height - 2 * out_height) * out_width; do_div(tmp, 2 * out_height * (ppl - out_width)); - fclk = max(fclk, (u32) tmp); + core_clk = max_t(u32, core_clk, tmp); } } if (width > out_width) { tmp = pclk * width; do_div(tmp, out_width); - fclk = max(fclk, (u32) tmp); + core_clk = max_t(u32, core_clk, tmp); if (color_mode == OMAP_DSS_COLOR_RGB24U) - fclk <<= 1; + core_clk <<= 1; } - return fclk; + return core_clk; } -static unsigned long calc_fclk(enum omap_channel channel, u16 width, +static unsigned long calc_core_clk(enum omap_channel channel, u16 width, u16 height, u16 out_width, u16 out_height) { unsigned int hf, vf; @@ -1730,15 +1786,20 @@ static unsigned long calc_fclk(enum omap_channel channel, u16 width, } static int dispc_ovl_calc_scaling(enum omap_plane plane, - enum omap_channel channel, u16 width, u16 height, - u16 out_width, u16 out_height, - enum omap_color_mode color_mode, bool *five_taps) + enum omap_channel channel, + const struct omap_video_timings *mgr_timings, + u16 width, u16 height, u16 out_width, u16 out_height, + enum omap_color_mode color_mode, bool *five_taps, + int *x_predecim, int *y_predecim, u16 pos_x) { struct omap_overlay *ovl = omap_dss_get_overlay(plane); const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE); const int maxsinglelinewidth = dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH); - unsigned long fclk = 0; + const int max_decim_limit = 16; + unsigned long core_clk = 0; + int decim_x, decim_y, error, min_factor; + u16 in_width, in_height, in_width_max = 0; if (width == out_width && height == out_height) return 0; @@ -1746,64 +1807,154 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane, if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) return -EINVAL; - if (out_width < width / maxdownscale || - out_width > width * 8) + *x_predecim = max_decim_limit; + *y_predecim = max_decim_limit; + + if (color_mode == OMAP_DSS_COLOR_CLUT1 || + color_mode == OMAP_DSS_COLOR_CLUT2 || + color_mode == OMAP_DSS_COLOR_CLUT4 || + color_mode == OMAP_DSS_COLOR_CLUT8) { + *x_predecim = 1; + *y_predecim = 1; + *five_taps = false; + return 0; + } + + decim_x = DIV_ROUND_UP(DIV_ROUND_UP(width, out_width), maxdownscale); + decim_y = DIV_ROUND_UP(DIV_ROUND_UP(height, out_height), maxdownscale); + + min_factor = min(decim_x, decim_y); + + if (decim_x > *x_predecim || out_width > width * 8) return -EINVAL; - if (out_height < height / maxdownscale || - out_height > height * 8) + if (decim_y > *y_predecim || out_height > height * 8) return -EINVAL; if (cpu_is_omap24xx()) { - if (width > maxsinglelinewidth) - DSSERR("Cannot scale max input width exceeded"); *five_taps = false; - fclk = calc_fclk(channel, width, height, out_width, - out_height); + + do { + in_height = DIV_ROUND_UP(height, decim_y); + in_width = DIV_ROUND_UP(width, decim_x); + core_clk = calc_core_clk(channel, in_width, in_height, + out_width, out_height); + error = (in_width > maxsinglelinewidth || !core_clk || + core_clk > dispc_core_clk_rate()); + if (error) { + if (decim_x == decim_y) { + decim_x = min_factor; + decim_y++; + } else { + swap(decim_x, decim_y); + if (decim_x < decim_y) + decim_x++; + } + } + } while (decim_x <= *x_predecim && decim_y <= *y_predecim && + error); + + if (in_width > maxsinglelinewidth) { + DSSERR("Cannot scale max input width exceeded"); + return -EINVAL; + } } else if (cpu_is_omap34xx()) { - if (width > (maxsinglelinewidth * 2)) { + + do { + in_height = DIV_ROUND_UP(height, decim_y); + in_width = DIV_ROUND_UP(width, decim_x); + core_clk = calc_core_clk_five_taps(channel, mgr_timings, + in_width, in_height, out_width, out_height, + color_mode); + + error = check_horiz_timing_omap3(channel, mgr_timings, + pos_x, in_width, in_height, out_width, + out_height); + + if (in_width > maxsinglelinewidth) + if (in_height > out_height && + in_height < out_height * 2) + *five_taps = false; + if (!*five_taps) + core_clk = calc_core_clk(channel, in_width, + in_height, out_width, out_height); + error = (error || in_width > maxsinglelinewidth * 2 || + (in_width > maxsinglelinewidth && *five_taps) || + !core_clk || core_clk > dispc_core_clk_rate()); + if (error) { + if (decim_x == decim_y) { + decim_x = min_factor; + decim_y++; + } else { + swap(decim_x, decim_y); + if (decim_x < decim_y) + decim_x++; + } + } + } while (decim_x <= *x_predecim && decim_y <= *y_predecim + && error); + + if (check_horiz_timing_omap3(channel, mgr_timings, pos_x, width, + height, out_width, out_height)){ + DSSERR("horizontal timing too tight\n"); + return -EINVAL; + } + + if (in_width > (maxsinglelinewidth * 2)) { DSSERR("Cannot setup scaling"); DSSERR("width exceeds maximum width possible"); return -EINVAL; } - fclk = calc_fclk_five_taps(channel, width, height, out_width, - out_height, color_mode); - if (width > maxsinglelinewidth) { - if (height > out_height && height < out_height * 2) - *five_taps = false; - else { - DSSERR("cannot setup scaling with five taps"); - return -EINVAL; - } + + if (in_width > maxsinglelinewidth && *five_taps) { + DSSERR("cannot setup scaling with five taps"); + return -EINVAL; } - if (!*five_taps) - fclk = calc_fclk(channel, width, height, out_width, - out_height); } else { - if (width > maxsinglelinewidth) { + int decim_x_min = decim_x; + in_height = DIV_ROUND_UP(height, decim_y); + in_width_max = dispc_core_clk_rate() / + DIV_ROUND_UP(dispc_mgr_pclk_rate(channel), + out_width); + decim_x = DIV_ROUND_UP(width, in_width_max); + + decim_x = decim_x > decim_x_min ? decim_x : decim_x_min; + if (decim_x > *x_predecim) + return -EINVAL; + + do { + in_width = DIV_ROUND_UP(width, decim_x); + } while (decim_x <= *x_predecim && + in_width > maxsinglelinewidth && decim_x++); + + if (in_width > maxsinglelinewidth) { DSSERR("Cannot scale width exceeds max line width"); return -EINVAL; } - fclk = calc_fclk(channel, width, height, out_width, - out_height); + + core_clk = calc_core_clk(channel, in_width, in_height, + out_width, out_height); } - DSSDBG("required fclk rate = %lu Hz\n", fclk); - DSSDBG("current fclk rate = %lu Hz\n", dispc_fclk_rate()); + DSSDBG("required core clk rate = %lu Hz\n", core_clk); + DSSDBG("current core clk rate = %lu Hz\n", dispc_core_clk_rate()); - if (!fclk || fclk > dispc_fclk_rate()) { + if (!core_clk || core_clk > dispc_core_clk_rate()) { DSSERR("failed to set up scaling, " - "required fclk rate = %lu Hz, " - "current fclk rate = %lu Hz\n", - fclk, dispc_fclk_rate()); + "required core clk rate = %lu Hz, " + "current core clk rate = %lu Hz\n", + core_clk, dispc_core_clk_rate()); return -EINVAL; } + *x_predecim = decim_x; + *y_predecim = decim_y; return 0; } int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi, - bool ilace, bool replication) + bool ilace, bool replication, + const struct omap_video_timings *mgr_timings) { struct omap_overlay *ovl = omap_dss_get_overlay(plane); bool five_taps = true; @@ -1814,8 +1965,11 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi, s32 pix_inc; u16 frame_height = oi->height; unsigned int field_offset = 0; - u16 outw, outh; + u16 in_height = oi->height; + u16 in_width = oi->width; + u16 out_width, out_height; enum omap_channel channel; + int x_predecim = 1, y_predecim = 1; channel = dispc_ovl_get_channel_out(plane); @@ -1829,32 +1983,35 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi, if (oi->paddr == 0) return -EINVAL; - outw = oi->out_width == 0 ? oi->width : oi->out_width; - outh = oi->out_height == 0 ? oi->height : oi->out_height; + out_width = oi->out_width == 0 ? oi->width : oi->out_width; + out_height = oi->out_height == 0 ? oi->height : oi->out_height; - if (ilace && oi->height == outh) + if (ilace && oi->height == out_height) fieldmode = 1; if (ilace) { if (fieldmode) - oi->height /= 2; + in_height /= 2; oi->pos_y /= 2; - outh /= 2; + out_height /= 2; DSSDBG("adjusting for ilace: height %d, pos_y %d, " "out_height %d\n", - oi->height, oi->pos_y, outh); + in_height, oi->pos_y, out_height); } if (!dss_feat_color_mode_supported(plane, oi->color_mode)) return -EINVAL; - r = dispc_ovl_calc_scaling(plane, channel, oi->width, oi->height, - outw, outh, oi->color_mode, - &five_taps); + r = dispc_ovl_calc_scaling(plane, channel, mgr_timings, in_width, + in_height, out_width, out_height, oi->color_mode, + &five_taps, &x_predecim, &y_predecim, oi->pos_x); if (r) return r; + in_width = DIV_ROUND_UP(in_width, x_predecim); + in_height = DIV_ROUND_UP(in_height, y_predecim); + if (oi->color_mode == OMAP_DSS_COLOR_YUV2 || oi->color_mode == OMAP_DSS_COLOR_UYVY || oi->color_mode == OMAP_DSS_COLOR_NV12) @@ -1868,10 +2025,10 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi, * so the integer part must be added to the base address of the * bottom field. */ - if (!oi->height || oi->height == outh) + if (!in_height || in_height == out_height) field_offset = 0; else - field_offset = oi->height / outh / 2; + field_offset = in_height / out_height / 2; } /* Fields are independent but interleaved in memory. */ @@ -1880,14 +2037,16 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi, if (oi->rotation_type == OMAP_DSS_ROT_DMA) calc_dma_rotation_offset(oi->rotation, oi->mirror, - oi->screen_width, oi->width, frame_height, + oi->screen_width, in_width, frame_height, oi->color_mode, fieldmode, field_offset, - &offset0, &offset1, &row_inc, &pix_inc); + &offset0, &offset1, &row_inc, &pix_inc, + x_predecim, y_predecim); else calc_vrfb_rotation_offset(oi->rotation, oi->mirror, - oi->screen_width, oi->width, frame_height, + oi->screen_width, in_width, frame_height, oi->color_mode, fieldmode, field_offset, - &offset0, &offset1, &row_inc, &pix_inc); + &offset0, &offset1, &row_inc, &pix_inc, + x_predecim, y_predecim); DSSDBG("offset0 %u, offset1 %u, row_inc %d, pix_inc %d\n", offset0, offset1, row_inc, pix_inc); @@ -1906,19 +2065,18 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi, dispc_ovl_set_row_inc(plane, row_inc); dispc_ovl_set_pix_inc(plane, pix_inc); - DSSDBG("%d,%d %dx%d -> %dx%d\n", oi->pos_x, oi->pos_y, oi->width, - oi->height, outw, outh); + DSSDBG("%d,%d %dx%d -> %dx%d\n", oi->pos_x, oi->pos_y, in_width, + in_height, out_width, out_height); dispc_ovl_set_pos(plane, oi->pos_x, oi->pos_y); - dispc_ovl_set_pic_size(plane, oi->width, oi->height); + dispc_ovl_set_pic_size(plane, in_width, in_height); if (ovl->caps & OMAP_DSS_OVL_CAP_SCALE) { - dispc_ovl_set_scaling(plane, oi->width, oi->height, - outw, outh, - ilace, five_taps, fieldmode, + dispc_ovl_set_scaling(plane, in_width, in_height, out_width, + out_height, ilace, five_taps, fieldmode, oi->color_mode, oi->rotation); - dispc_ovl_set_vid_size(plane, outw, outh); + dispc_ovl_set_vid_size(plane, out_width, out_height); dispc_ovl_set_vid_color_conv(plane, cconv); } @@ -2285,6 +2443,12 @@ void dispc_mgr_enable_stallmode(enum omap_channel channel, bool enable) REG_FLD_MOD(DISPC_CONTROL, enable, 11, 11); } +static bool _dispc_mgr_size_ok(u16 width, u16 height) +{ + return width <= dss_feat_get_param_max(FEAT_PARAM_MGR_WIDTH) && + height <= dss_feat_get_param_max(FEAT_PARAM_MGR_HEIGHT); +} + static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp, int vsw, int vfp, int vbp) { @@ -2309,11 +2473,20 @@ static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp, return true; } -bool dispc_lcd_timings_ok(struct omap_video_timings *timings) +bool dispc_mgr_timings_ok(enum omap_channel channel, + const struct omap_video_timings *timings) { - return _dispc_lcd_timings_ok(timings->hsw, timings->hfp, - timings->hbp, timings->vsw, - timings->vfp, timings->vbp); + bool timings_ok; + + timings_ok = _dispc_mgr_size_ok(timings->x_res, timings->y_res); + + if (dispc_mgr_is_lcd(channel)) + timings_ok = timings_ok && _dispc_lcd_timings_ok(timings->hsw, + timings->hfp, timings->hbp, + timings->vsw, timings->vfp, + timings->vbp); + + return timings_ok; } static void _dispc_mgr_set_lcd_timings(enum omap_channel channel, int hsw, @@ -2340,37 +2513,40 @@ static void _dispc_mgr_set_lcd_timings(enum omap_channel channel, int hsw, } /* change name to mode? */ -void dispc_mgr_set_lcd_timings(enum omap_channel channel, +void dispc_mgr_set_timings(enum omap_channel channel, struct omap_video_timings *timings) { unsigned xtot, ytot; unsigned long ht, vt; - if (!_dispc_lcd_timings_ok(timings->hsw, timings->hfp, - timings->hbp, timings->vsw, - timings->vfp, timings->vbp)) - BUG(); + DSSDBG("channel %d xres %u yres %u\n", channel, timings->x_res, + timings->y_res); - _dispc_mgr_set_lcd_timings(channel, timings->hsw, timings->hfp, - timings->hbp, timings->vsw, timings->vfp, - timings->vbp); + if (!dispc_mgr_timings_ok(channel, timings)) + BUG(); - dispc_mgr_set_lcd_size(channel, timings->x_res, timings->y_res); + if (dispc_mgr_is_lcd(channel)) { + _dispc_mgr_set_lcd_timings(channel, timings->hsw, timings->hfp, + timings->hbp, timings->vsw, timings->vfp, + timings->vbp); - xtot = timings->x_res + timings->hfp + timings->hsw + timings->hbp; - ytot = timings->y_res + timings->vfp + timings->vsw + timings->vbp; + xtot = timings->x_res + timings->hfp + timings->hsw + + timings->hbp; + ytot = timings->y_res + timings->vfp + timings->vsw + + timings->vbp; - ht = (timings->pixel_clock * 1000) / xtot; - vt = (timings->pixel_clock * 1000) / xtot / ytot; + ht = (timings->pixel_clock * 1000) / xtot; + vt = (timings->pixel_clock * 1000) / xtot / ytot; - DSSDBG("channel %d xres %u yres %u\n", channel, timings->x_res, - timings->y_res); - DSSDBG("pck %u\n", timings->pixel_clock); - DSSDBG("hsw %d hfp %d hbp %d vsw %d vfp %d vbp %d\n", + DSSDBG("pck %u\n", timings->pixel_clock); + DSSDBG("hsw %d hfp %d hbp %d vsw %d vfp %d vbp %d\n", timings->hsw, timings->hfp, timings->hbp, timings->vsw, timings->vfp, timings->vbp); - DSSDBG("hsync %luHz, vsync %luHz\n", ht, vt); + DSSDBG("hsync %luHz, vsync %luHz\n", ht, vt); + } + + dispc_mgr_set_size(channel, timings->x_res, timings->y_res); } static void dispc_mgr_set_lcd_divisor(enum omap_channel channel, u16 lck_div, @@ -2462,13 +2638,14 @@ unsigned long dispc_mgr_pclk_rate(enum omap_channel channel) return r / pcd; } else { - struct omap_dss_device *dssdev = - dispc_mgr_get_device(channel); + enum dss_hdmi_venc_clk_source_select source; - switch (dssdev->type) { - case OMAP_DISPLAY_TYPE_VENC: + source = dss_get_hdmi_venc_clk_source(); + + switch (source) { + case DSS_VENC_TV_CLK: return venc_get_pixel_clock(); - case OMAP_DISPLAY_TYPE_HDMI: + case DSS_HDMI_M_PCLK: return hdmi_get_pixel_clock(); default: BUG(); @@ -2476,6 +2653,19 @@ unsigned long dispc_mgr_pclk_rate(enum omap_channel channel) } } +unsigned long dispc_core_clk_rate(void) +{ + int lcd; + unsigned long fclk = dispc_fclk_rate(); + + if (dss_has_feature(FEAT_CORE_CLK_DIV)) + lcd = REG_GET(DISPC_DIVISOR, 23, 16); + else + lcd = REG_GET(DISPC_DIVISORo(OMAP_DSS_CHANNEL_LCD), 23, 16); + + return fclk / lcd; +} + void dispc_dump_clocks(struct seq_file *s) { int lcd, pcd; @@ -3247,27 +3437,6 @@ int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask, return 0; } -#ifdef CONFIG_OMAP2_DSS_FAKE_VSYNC -void dispc_fake_vsync_irq(void) -{ - u32 irqstatus = DISPC_IRQ_VSYNC; - int i; - - WARN_ON(!in_interrupt()); - - for (i = 0; i < DISPC_MAX_NR_ISRS; i++) { - struct omap_dispc_isr_data *isr_data; - isr_data = &dispc.registered_isr[i]; - - if (!isr_data->isr) - continue; - - if (isr_data->mask & irqstatus) - isr_data->isr(isr_data->arg, irqstatus); - } -} -#endif - static void _omap_dispc_initialize_irq(void) { unsigned long flags; diff --git a/drivers/video/omap2/dss/display.c b/drivers/video/omap2/dss/display.c index 4424c198dbc..e688d10f061 100644 --- a/drivers/video/omap2/dss/display.c +++ b/drivers/video/omap2/dss/display.c @@ -308,6 +308,13 @@ int omapdss_default_get_recommended_bpp(struct omap_dss_device *dssdev) } EXPORT_SYMBOL(omapdss_default_get_recommended_bpp); +void omapdss_default_get_timings(struct omap_dss_device *dssdev, + struct omap_video_timings *timings) +{ + *timings = dssdev->panel.timings; +} +EXPORT_SYMBOL(omapdss_default_get_timings); + /* Checks if replication logic should be used. Only use for active matrix, * when overlay is in RGB12U or RGB16 mode, and LCD interface is * 18bpp or 24bpp */ diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c index faaf305fda2..d6e8fe77615 100644 --- a/drivers/video/omap2/dss/dpi.c +++ b/drivers/video/omap2/dss/dpi.c @@ -156,7 +156,7 @@ static int dpi_set_mode(struct omap_dss_device *dssdev) t->pixel_clock = pck; } - dispc_mgr_set_lcd_timings(dssdev->manager->id, t); + dss_mgr_set_timings(dssdev->manager, t); return 0; } @@ -294,10 +294,11 @@ void dpi_set_timings(struct omap_dss_device *dssdev, } dpi_set_mode(dssdev); - dispc_mgr_go(dssdev->manager->id); dispc_runtime_put(); dss_runtime_put(); + } else { + dss_mgr_set_timings(dssdev->manager, timings); } } EXPORT_SYMBOL(dpi_set_timings); @@ -312,7 +313,7 @@ int dpi_check_timings(struct omap_dss_device *dssdev, unsigned long pck; struct dispc_clock_info dispc_cinfo; - if (!dispc_lcd_timings_ok(timings)) + if (dss_mgr_check_timings(dssdev->manager, timings)) return -EINVAL; if (timings->pixel_clock == 0) diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index 210a3c4f615..446e1366747 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -1279,10 +1279,9 @@ static int dsi_pll_power(struct platform_device *dsidev, } /* calculate clock rates using dividers in cinfo */ -static int dsi_calc_clock_rates(struct omap_dss_device *dssdev, +static int dsi_calc_clock_rates(struct platform_device *dsidev, struct dsi_clock_info *cinfo) { - struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); if (cinfo->regn == 0 || cinfo->regn > dsi->regn_max) @@ -1297,21 +1296,8 @@ static int dsi_calc_clock_rates(struct omap_dss_device *dssdev, if (cinfo->regm_dsi > dsi->regm_dsi_max) return -EINVAL; - if (cinfo->use_sys_clk) { - cinfo->clkin = clk_get_rate(dsi->sys_clk); - /* XXX it is unclear if highfreq should be used - * with DSS_SYS_CLK source also */ - cinfo->highfreq = 0; - } else { - cinfo->clkin = dispc_mgr_pclk_rate(dssdev->manager->id); - - if (cinfo->clkin < 32000000) - cinfo->highfreq = 0; - else - cinfo->highfreq = 1; - } - - cinfo->fint = cinfo->clkin / (cinfo->regn * (cinfo->highfreq ? 2 : 1)); + cinfo->clkin = clk_get_rate(dsi->sys_clk); + cinfo->fint = cinfo->clkin / cinfo->regn; if (cinfo->fint > dsi->fint_max || cinfo->fint < dsi->fint_min) return -EINVAL; @@ -1378,27 +1364,21 @@ retry: memset(&cur, 0, sizeof(cur)); cur.clkin = dss_sys_clk; - cur.use_sys_clk = 1; - cur.highfreq = 0; - /* no highfreq: 0.75MHz < Fint = clkin / regn < 2.1MHz */ - /* highfreq: 0.75MHz < Fint = clkin / (2*regn) < 2.1MHz */ + /* 0.75MHz < Fint = clkin / regn < 2.1MHz */ /* To reduce PLL lock time, keep Fint high (around 2 MHz) */ for (cur.regn = 1; cur.regn < dsi->regn_max; ++cur.regn) { - if (cur.highfreq == 0) - cur.fint = cur.clkin / cur.regn; - else - cur.fint = cur.clkin / (2 * cur.regn); + cur.fint = cur.clkin / cur.regn; if (cur.fint > dsi->fint_max || cur.fint < dsi->fint_min) continue; - /* DSIPHY(MHz) = (2 * regm / regn) * (clkin / (highfreq + 1)) */ + /* DSIPHY(MHz) = (2 * regm / regn) * clkin */ for (cur.regm = 1; cur.regm < dsi->regm_max; ++cur.regm) { unsigned long a, b; a = 2 * cur.regm * (cur.clkin/1000); - b = cur.regn * (cur.highfreq + 1); + b = cur.regn; cur.clkin4ddr = a / b * 1000; if (cur.clkin4ddr > 1800 * 1000 * 1000) @@ -1486,9 +1466,7 @@ int dsi_pll_set_clock_div(struct platform_device *dsidev, DSSDBGF(); - dsi->current_cinfo.use_sys_clk = cinfo->use_sys_clk; - dsi->current_cinfo.highfreq = cinfo->highfreq; - + dsi->current_cinfo.clkin = cinfo->clkin; dsi->current_cinfo.fint = cinfo->fint; dsi->current_cinfo.clkin4ddr = cinfo->clkin4ddr; dsi->current_cinfo.dsi_pll_hsdiv_dispc_clk = @@ -1503,17 +1481,13 @@ int dsi_pll_set_clock_div(struct platform_device *dsidev, DSSDBG("DSI Fint %ld\n", cinfo->fint); - DSSDBG("clkin (%s) rate %ld, highfreq %d\n", - cinfo->use_sys_clk ? "dss_sys_clk" : "pclkfree", - cinfo->clkin, - cinfo->highfreq); + DSSDBG("clkin rate %ld\n", cinfo->clkin); /* DSIPHY == CLKIN4DDR */ - DSSDBG("CLKIN4DDR = 2 * %d / %d * %lu / %d = %lu\n", + DSSDBG("CLKIN4DDR = 2 * %d / %d * %lu = %lu\n", cinfo->regm, cinfo->regn, cinfo->clkin, - cinfo->highfreq + 1, cinfo->clkin4ddr); DSSDBG("Data rate on 1 DSI lane %ld Mbps\n", @@ -1568,10 +1542,6 @@ int dsi_pll_set_clock_div(struct platform_device *dsidev, if (dss_has_feature(FEAT_DSI_PLL_FREQSEL)) l = FLD_MOD(l, f, 4, 1); /* DSI_PLL_FREQSEL */ - l = FLD_MOD(l, cinfo->use_sys_clk ? 0 : 1, - 11, 11); /* DSI_PLL_CLKSEL */ - l = FLD_MOD(l, cinfo->highfreq, - 12, 12); /* DSI_PLL_HIGHFREQ */ l = FLD_MOD(l, 1, 13, 13); /* DSI_PLL_REFEN */ l = FLD_MOD(l, 0, 14, 14); /* DSIPHY_CLKINEN */ l = FLD_MOD(l, 1, 20, 20); /* DSI_HSDIVBYPASS */ @@ -1726,8 +1696,7 @@ static void dsi_dump_dsidev_clocks(struct platform_device *dsidev, seq_printf(s, "- DSI%d PLL -\n", dsi_module + 1); - seq_printf(s, "dsi pll source = %s\n", - cinfo->use_sys_clk ? "dss_sys_clk" : "pclkfree"); + seq_printf(s, "dsi pll clkin\t%lu\n", cinfo->clkin); seq_printf(s, "Fint\t\t%-16luregn %u\n", cinfo->fint, cinfo->regn); @@ -4192,10 +4161,6 @@ static void dsi_framedone_irq_callback(void *data, u32 mask) __cancel_delayed_work(&dsi->framedone_timeout_work); dsi_handle_framedone(dsidev, 0); - -#ifdef CONFIG_OMAP2_DSS_FAKE_VSYNC - dispc_fake_vsync_irq(); -#endif } int omap_dsi_update(struct omap_dss_device *dssdev, int channel, @@ -4259,13 +4224,12 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev) dispc_mgr_enable_stallmode(dssdev->manager->id, true); dispc_mgr_enable_fifohandcheck(dssdev->manager->id, 1); - dispc_mgr_set_lcd_timings(dssdev->manager->id, &timings); + dss_mgr_set_timings(dssdev->manager, &timings); } else { dispc_mgr_enable_stallmode(dssdev->manager->id, false); dispc_mgr_enable_fifohandcheck(dssdev->manager->id, 0); - dispc_mgr_set_lcd_timings(dssdev->manager->id, - &dssdev->panel.timings); + dss_mgr_set_timings(dssdev->manager, &dssdev->panel.timings); } dispc_mgr_set_lcd_display_type(dssdev->manager->id, @@ -4294,13 +4258,11 @@ static int dsi_configure_dsi_clocks(struct omap_dss_device *dssdev) struct dsi_clock_info cinfo; int r; - /* we always use DSS_CLK_SYSCK as input clock */ - cinfo.use_sys_clk = true; cinfo.regn = dssdev->clocks.dsi.regn; cinfo.regm = dssdev->clocks.dsi.regm; cinfo.regm_dispc = dssdev->clocks.dsi.regm_dispc; cinfo.regm_dsi = dssdev->clocks.dsi.regm_dsi; - r = dsi_calc_clock_rates(dssdev, &cinfo); + r = dsi_calc_clock_rates(dsidev, &cinfo); if (r) { DSSERR("Failed to calc dsi clocks\n"); return r; diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c index bd2d5e15946..e212acb1e7d 100644 --- a/drivers/video/omap2/dss/dss.c +++ b/drivers/video/omap2/dss/dss.c @@ -335,7 +335,7 @@ void dss_select_dsi_clk_source(int dsi_module, enum omap_dss_clk_source clk_src) { struct platform_device *dsidev; - int b; + int b, pos; switch (clk_src) { case OMAP_DSS_CLK_SRC_FCK: @@ -357,7 +357,8 @@ void dss_select_dsi_clk_source(int dsi_module, BUG(); } - REG_FLD_MOD(DSS_CONTROL, b, 1, 1); /* DSI_CLK_SWITCH */ + pos = dsi_module == 0 ? 1 : 10; + REG_FLD_MOD(DSS_CONTROL, b, pos, pos); /* DSIx_CLK_SWITCH */ dss.dsi_clk_source[dsi_module] = clk_src; } @@ -829,11 +830,24 @@ static int omap_dsshw_remove(struct platform_device *pdev) static int dss_runtime_suspend(struct device *dev) { dss_save_context(); + dss_set_min_bus_tput(dev, 0); return 0; } static int dss_runtime_resume(struct device *dev) { + int r; + /* + * Set an arbitrarily high tput request to ensure OPP100. + * What we should really do is to make a request to stay in OPP100, + * without any tput requirements, but that is not currently possible + * via the PM layer. + */ + + r = dss_set_min_bus_tput(dev, 1000000000); + if (r) + return r; + dss_restore_context(); return 0; } diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h index d4b3dff2ead..8e9e9a5765f 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h @@ -150,9 +150,6 @@ struct dsi_clock_info { u16 regm_dsi; /* OMAP3: REGM4 * OMAP4: REGM5 */ u16 lp_clk_div; - - u8 highfreq; - bool use_sys_clk; }; struct seq_file; @@ -162,6 +159,7 @@ struct platform_device; struct bus_type *dss_get_bus(void); struct regulator *dss_get_vdds_dsi(void); struct regulator *dss_get_vdds_sdi(void); +int dss_set_min_bus_tput(struct device *dev, unsigned long tput); /* apply */ void dss_apply_init(void); @@ -179,6 +177,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); +void dss_mgr_set_timings(struct omap_overlay_manager *mgr, + struct omap_video_timings *timings); +const struct omap_video_timings *dss_mgr_get_timings(struct omap_overlay_manager *mgr); bool dss_ovl_is_enabled(struct omap_overlay *ovl); int dss_ovl_enable(struct omap_overlay *ovl); @@ -208,9 +209,11 @@ int dss_init_overlay_managers(struct platform_device *pdev); void dss_uninit_overlay_managers(struct platform_device *pdev); int dss_mgr_simple_check(struct omap_overlay_manager *mgr, const struct omap_overlay_manager_info *info); +int dss_mgr_check_timings(struct omap_overlay_manager *mgr, + const struct omap_video_timings *timings); int dss_mgr_check(struct omap_overlay_manager *mgr, - struct omap_dss_device *dssdev, struct omap_overlay_manager_info *info, + const struct omap_video_timings *mgr_timings, struct omap_overlay_info **overlay_infos); /* overlay */ @@ -220,8 +223,8 @@ void dss_overlay_setup_dispc_manager(struct omap_overlay_manager *mgr); void dss_recheck_connections(struct omap_dss_device *dssdev, bool force); int dss_ovl_simple_check(struct omap_overlay *ovl, const struct omap_overlay_info *info); -int dss_ovl_check(struct omap_overlay *ovl, - struct omap_overlay_info *info, struct omap_dss_device *dssdev); +int dss_ovl_check(struct omap_overlay *ovl, struct omap_overlay_info *info, + const struct omap_video_timings *mgr_timings); /* DSS */ int dss_init_platform_driver(void); @@ -398,7 +401,6 @@ void dispc_dump_clocks(struct seq_file *s); void dispc_dump_irqs(struct seq_file *s); void dispc_dump_regs(struct seq_file *s); void dispc_irq_handler(void); -void dispc_fake_vsync_irq(void); int dispc_runtime_get(void); void dispc_runtime_put(void); @@ -409,12 +411,12 @@ void dispc_disable_sidle(void); void dispc_lcd_enable_signal_polarity(bool act_high); void dispc_lcd_enable_signal(bool enable); void dispc_pck_free_enable(bool enable); -void dispc_set_digit_size(u16 width, u16 height); void dispc_enable_fifomerge(bool enable); void dispc_enable_gamma_table(bool enable); void dispc_set_loadmode(enum omap_dss_load_mode mode); -bool dispc_lcd_timings_ok(struct omap_video_timings *timings); +bool dispc_mgr_timings_ok(enum omap_channel channel, + const struct omap_video_timings *timings); unsigned long dispc_fclk_rate(void); void dispc_find_clk_divs(bool is_tft, unsigned long req_pck, unsigned long fck, struct dispc_clock_info *cinfo); @@ -426,13 +428,13 @@ void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high); void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane, u32 *fifo_low, u32 *fifo_high, bool use_fifomerge); int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi, - bool ilace, bool replication); + bool ilace, bool replication, + const struct omap_video_timings *mgr_timings); int dispc_ovl_enable(enum omap_plane plane, bool enable); void dispc_ovl_set_channel_out(enum omap_plane plane, enum omap_channel channel); void dispc_mgr_enable_fifohandcheck(enum omap_channel channel, bool enable); -void dispc_mgr_set_lcd_size(enum omap_channel channel, u16 width, u16 height); u32 dispc_mgr_get_vsync_irq(enum omap_channel channel); u32 dispc_mgr_get_framedone_irq(enum omap_channel channel); bool dispc_mgr_go_busy(enum omap_channel channel); @@ -445,12 +447,13 @@ void dispc_mgr_enable_stallmode(enum omap_channel channel, bool enable); void dispc_mgr_set_tft_data_lines(enum omap_channel channel, u8 data_lines); void dispc_mgr_set_lcd_display_type(enum omap_channel channel, enum omap_lcd_display_type type); -void dispc_mgr_set_lcd_timings(enum omap_channel channel, +void dispc_mgr_set_timings(enum omap_channel channel, struct omap_video_timings *timings); void dispc_mgr_set_pol_freq(enum omap_channel channel, enum omap_panel_config config, u8 acbi, u8 acb); unsigned long dispc_mgr_lclk_rate(enum omap_channel channel); unsigned long dispc_mgr_pclk_rate(enum omap_channel channel); +unsigned long dispc_core_clk_rate(void); int dispc_mgr_set_clock_div(enum omap_channel channel, struct dispc_clock_info *cinfo); int dispc_mgr_get_clock_div(enum omap_channel channel, diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c index ce14aa6dd67..1d10a014bc5 100644 --- a/drivers/video/omap2/dss/dss_features.c +++ b/drivers/video/omap2/dss/dss_features.c @@ -311,6 +311,8 @@ static const struct dss_param_range omap2_dss_param_range[] = { * scaler cannot scale a image with width more than 768. */ [FEAT_PARAM_LINEWIDTH] = { 1, 768 }, + [FEAT_PARAM_MGR_WIDTH] = { 1, 2048 }, + [FEAT_PARAM_MGR_HEIGHT] = { 1, 2048 }, }; static const struct dss_param_range omap3_dss_param_range[] = { @@ -324,6 +326,8 @@ static const struct dss_param_range omap3_dss_param_range[] = { [FEAT_PARAM_DSIPLL_LPDIV] = { 1, (1 << 13) - 1}, [FEAT_PARAM_DOWNSCALE] = { 1, 4 }, [FEAT_PARAM_LINEWIDTH] = { 1, 1024 }, + [FEAT_PARAM_MGR_WIDTH] = { 1, 2048 }, + [FEAT_PARAM_MGR_HEIGHT] = { 1, 2048 }, }; static const struct dss_param_range omap4_dss_param_range[] = { @@ -337,6 +341,8 @@ static const struct dss_param_range omap4_dss_param_range[] = { [FEAT_PARAM_DSIPLL_LPDIV] = { 0, (1 << 13) - 1 }, [FEAT_PARAM_DOWNSCALE] = { 1, 4 }, [FEAT_PARAM_LINEWIDTH] = { 1, 2048 }, + [FEAT_PARAM_MGR_WIDTH] = { 1, 2048 }, + [FEAT_PARAM_MGR_HEIGHT] = { 1, 2048 }, }; static const enum dss_feat_id omap2_dss_feat_list[] = { diff --git a/drivers/video/omap2/dss/dss_features.h b/drivers/video/omap2/dss/dss_features.h index c332e7ddfce..3736367089a 100644 --- a/drivers/video/omap2/dss/dss_features.h +++ b/drivers/video/omap2/dss/dss_features.h @@ -91,6 +91,8 @@ enum dss_range_param { FEAT_PARAM_DSIPLL_LPDIV, FEAT_PARAM_DOWNSCALE, FEAT_PARAM_LINEWIDTH, + FEAT_PARAM_MGR_WIDTH, + FEAT_PARAM_MGR_HEIGHT, }; /* DSS Feature Functions */ diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c index c4b4f6950a9..32ad7124a95 100644 --- a/drivers/video/omap2/dss/hdmi.c +++ b/drivers/video/omap2/dss/hdmi.c @@ -376,8 +376,7 @@ static int hdmi_power_on(struct omap_dss_device *dssdev) dispc_enable_gamma_table(0); /* tv size */ - dispc_set_digit_size(dssdev->panel.timings.x_res, - dssdev->panel.timings.y_res); + dss_mgr_set_timings(dssdev->manager, &dssdev->panel.timings); hdmi.ip_data.ops->video_enable(&hdmi.ip_data, 1); @@ -436,6 +435,8 @@ void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev) r = hdmi_power_on(dssdev); if (r) DSSERR("failed to power on device\n"); + } else { + dss_mgr_set_timings(dssdev->manager, &dssdev->panel.timings); } } diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c index e7364603f6a..0cbcde4c688 100644 --- a/drivers/video/omap2/dss/manager.c +++ b/drivers/video/omap2/dss/manager.c @@ -654,9 +654,20 @@ static int dss_mgr_check_zorder(struct omap_overlay_manager *mgr, return 0; } +int dss_mgr_check_timings(struct omap_overlay_manager *mgr, + const struct omap_video_timings *timings) +{ + if (!dispc_mgr_timings_ok(mgr->id, timings)) { + DSSERR("check_manager: invalid timings\n"); + return -EINVAL; + } + + return 0; +} + int dss_mgr_check(struct omap_overlay_manager *mgr, - struct omap_dss_device *dssdev, struct omap_overlay_manager_info *info, + const struct omap_video_timings *mgr_timings, struct omap_overlay_info **overlay_infos) { struct omap_overlay *ovl; @@ -668,6 +679,10 @@ int dss_mgr_check(struct omap_overlay_manager *mgr, return r; } + r = dss_mgr_check_timings(mgr, mgr_timings); + if (r) + return r; + list_for_each_entry(ovl, &mgr->overlays, list) { struct omap_overlay_info *oi; int r; @@ -677,7 +692,7 @@ int dss_mgr_check(struct omap_overlay_manager *mgr, if (oi == NULL) continue; - r = dss_ovl_check(ovl, oi, dssdev); + r = dss_ovl_check(ovl, oi, mgr_timings); if (r) return r; } diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c index 6e821810dee..0da5eb654ae 100644 --- a/drivers/video/omap2/dss/overlay.c +++ b/drivers/video/omap2/dss/overlay.c @@ -631,16 +631,14 @@ int dss_ovl_simple_check(struct omap_overlay *ovl, return 0; } -int dss_ovl_check(struct omap_overlay *ovl, - struct omap_overlay_info *info, struct omap_dss_device *dssdev) +int dss_ovl_check(struct omap_overlay *ovl, struct omap_overlay_info *info, + const struct omap_video_timings *mgr_timings) { u16 outw, outh; u16 dw, dh; - if (dssdev == NULL) - return 0; - - dssdev->driver->get_resolution(dssdev, &dw, &dh); + dw = mgr_timings->x_res; + dh = mgr_timings->y_res; if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) { outw = info->width; diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c index 788a0ef6323..feadfab27ec 100644 --- a/drivers/video/omap2/dss/rfbi.c +++ b/drivers/video/omap2/dss/rfbi.c @@ -304,13 +304,23 @@ static void rfbi_transfer_area(struct omap_dss_device *dssdev, u16 width, u16 height, void (*callback)(void *data), void *data) { u32 l; + struct omap_video_timings timings = { + .hsw = 1, + .hfp = 1, + .hbp = 1, + .vsw = 1, + .vfp = 0, + .vbp = 0, + .x_res = width, + .y_res = height, + }; /*BUG_ON(callback == 0);*/ BUG_ON(rfbi.framedone_callback != NULL); DSSDBG("rfbi_transfer_area %dx%d\n", width, height); - dispc_mgr_set_lcd_size(dssdev->manager->id, width, height); + dss_mgr_set_timings(dssdev->manager, &timings); dispc_mgr_enable(dssdev->manager->id, true); @@ -766,6 +776,16 @@ int omap_rfbi_prepare_update(struct omap_dss_device *dssdev, u16 *x, u16 *y, u16 *w, u16 *h) { u16 dw, dh; + struct omap_video_timings timings = { + .hsw = 1, + .hfp = 1, + .hbp = 1, + .vsw = 1, + .vfp = 0, + .vbp = 0, + .x_res = *w, + .y_res = *h, + }; dssdev->driver->get_resolution(dssdev, &dw, &dh); @@ -784,7 +804,7 @@ int omap_rfbi_prepare_update(struct omap_dss_device *dssdev, if (*w == 0 || *h == 0) return -EINVAL; - dispc_mgr_set_lcd_size(dssdev->manager->id, *w, *h); + dss_mgr_set_timings(dssdev->manager, &timings); return 0; } diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c index 8266ca0d666..67fbe7cee41 100644 --- a/drivers/video/omap2/dss/sdi.c +++ b/drivers/video/omap2/dss/sdi.c @@ -107,7 +107,7 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev) } - dispc_mgr_set_lcd_timings(dssdev->manager->id, t); + dss_mgr_set_timings(dssdev->manager, t); r = dss_set_clock_div(&dss_cinfo); if (r) diff --git a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c index bfe6fe65c8b..35f59e47d7f 100644 --- a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c +++ b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c @@ -886,10 +886,12 @@ void ti_hdmi_4xxx_core_dump(struct hdmi_ip_data *ip_data, struct seq_file *s) #define CORE_REG(i, name) name(i) #define DUMPCORE(r) seq_printf(s, "%-35s %08x\n", #r,\ - hdmi_read_reg(hdmi_pll_base(ip_data), r)) -#define DUMPCOREAV(i, r) seq_printf(s, "%s[%d]%*s %08x\n", #r, i, \ + hdmi_read_reg(hdmi_core_sys_base(ip_data), r)) +#define DUMPCOREAV(r) seq_printf(s, "%-35s %08x\n", #r,\ + hdmi_read_reg(hdmi_av_base(ip_data), r)) +#define DUMPCOREAV2(i, r) seq_printf(s, "%s[%d]%*s %08x\n", #r, i, \ (i < 10) ? 32 - strlen(#r) : 31 - strlen(#r), " ", \ - hdmi_read_reg(hdmi_pll_base(ip_data), CORE_REG(i, r))) + hdmi_read_reg(hdmi_av_base(ip_data), CORE_REG(i, r))) DUMPCORE(HDMI_CORE_SYS_VND_IDL); DUMPCORE(HDMI_CORE_SYS_DEV_IDL); @@ -898,6 +900,13 @@ void ti_hdmi_4xxx_core_dump(struct hdmi_ip_data *ip_data, struct seq_file *s) DUMPCORE(HDMI_CORE_SYS_SRST); DUMPCORE(HDMI_CORE_CTRL1); DUMPCORE(HDMI_CORE_SYS_SYS_STAT); + DUMPCORE(HDMI_CORE_SYS_DE_DLY); + DUMPCORE(HDMI_CORE_SYS_DE_CTRL); + DUMPCORE(HDMI_CORE_SYS_DE_TOP); + DUMPCORE(HDMI_CORE_SYS_DE_CNTL); + DUMPCORE(HDMI_CORE_SYS_DE_CNTH); + DUMPCORE(HDMI_CORE_SYS_DE_LINL); + DUMPCORE(HDMI_CORE_SYS_DE_LINH_1); DUMPCORE(HDMI_CORE_SYS_VID_ACEN); DUMPCORE(HDMI_CORE_SYS_VID_MODE); DUMPCORE(HDMI_CORE_SYS_INTR_STATE); @@ -907,102 +916,91 @@ void ti_hdmi_4xxx_core_dump(struct hdmi_ip_data *ip_data, struct seq_file *s) DUMPCORE(HDMI_CORE_SYS_INTR4); DUMPCORE(HDMI_CORE_SYS_UMASK1); DUMPCORE(HDMI_CORE_SYS_TMDS_CTRL); - DUMPCORE(HDMI_CORE_SYS_DE_DLY); - DUMPCORE(HDMI_CORE_SYS_DE_CTRL); - DUMPCORE(HDMI_CORE_SYS_DE_TOP); - DUMPCORE(HDMI_CORE_SYS_DE_CNTL); - DUMPCORE(HDMI_CORE_SYS_DE_CNTH); - DUMPCORE(HDMI_CORE_SYS_DE_LINL); - DUMPCORE(HDMI_CORE_SYS_DE_LINH_1); - DUMPCORE(HDMI_CORE_DDC_CMD); - DUMPCORE(HDMI_CORE_DDC_STATUS); DUMPCORE(HDMI_CORE_DDC_ADDR); + DUMPCORE(HDMI_CORE_DDC_SEGM); DUMPCORE(HDMI_CORE_DDC_OFFSET); DUMPCORE(HDMI_CORE_DDC_COUNT1); DUMPCORE(HDMI_CORE_DDC_COUNT2); + DUMPCORE(HDMI_CORE_DDC_STATUS); + DUMPCORE(HDMI_CORE_DDC_CMD); DUMPCORE(HDMI_CORE_DDC_DATA); - DUMPCORE(HDMI_CORE_DDC_SEGM); - DUMPCORE(HDMI_CORE_AV_HDMI_CTRL); - DUMPCORE(HDMI_CORE_AV_DPD); - DUMPCORE(HDMI_CORE_AV_PB_CTRL1); - DUMPCORE(HDMI_CORE_AV_PB_CTRL2); - DUMPCORE(HDMI_CORE_AV_AVI_TYPE); - DUMPCORE(HDMI_CORE_AV_AVI_VERS); - DUMPCORE(HDMI_CORE_AV_AVI_LEN); - DUMPCORE(HDMI_CORE_AV_AVI_CHSUM); + DUMPCOREAV(HDMI_CORE_AV_ACR_CTRL); + DUMPCOREAV(HDMI_CORE_AV_FREQ_SVAL); + DUMPCOREAV(HDMI_CORE_AV_N_SVAL1); + DUMPCOREAV(HDMI_CORE_AV_N_SVAL2); + DUMPCOREAV(HDMI_CORE_AV_N_SVAL3); + DUMPCOREAV(HDMI_CORE_AV_CTS_SVAL1); + DUMPCOREAV(HDMI_CORE_AV_CTS_SVAL2); + DUMPCOREAV(HDMI_CORE_AV_CTS_SVAL3); + DUMPCOREAV(HDMI_CORE_AV_CTS_HVAL1); + DUMPCOREAV(HDMI_CORE_AV_CTS_HVAL2); + DUMPCOREAV(HDMI_CORE_AV_CTS_HVAL3); + DUMPCOREAV(HDMI_CORE_AV_AUD_MODE); + DUMPCOREAV(HDMI_CORE_AV_SPDIF_CTRL); + DUMPCOREAV(HDMI_CORE_AV_HW_SPDIF_FS); + DUMPCOREAV(HDMI_CORE_AV_SWAP_I2S); + DUMPCOREAV(HDMI_CORE_AV_SPDIF_ERTH); + DUMPCOREAV(HDMI_CORE_AV_I2S_IN_MAP); + DUMPCOREAV(HDMI_CORE_AV_I2S_IN_CTRL); + DUMPCOREAV(HDMI_CORE_AV_I2S_CHST0); + DUMPCOREAV(HDMI_CORE_AV_I2S_CHST1); + DUMPCOREAV(HDMI_CORE_AV_I2S_CHST2); + DUMPCOREAV(HDMI_CORE_AV_I2S_CHST4); + DUMPCOREAV(HDMI_CORE_AV_I2S_CHST5); + DUMPCOREAV(HDMI_CORE_AV_ASRC); + DUMPCOREAV(HDMI_CORE_AV_I2S_IN_LEN); + DUMPCOREAV(HDMI_CORE_AV_HDMI_CTRL); + DUMPCOREAV(HDMI_CORE_AV_AUDO_TXSTAT); + DUMPCOREAV(HDMI_CORE_AV_AUD_PAR_BUSCLK_1); + DUMPCOREAV(HDMI_CORE_AV_AUD_PAR_BUSCLK_2); + DUMPCOREAV(HDMI_CORE_AV_AUD_PAR_BUSCLK_3); + DUMPCOREAV(HDMI_CORE_AV_TEST_TXCTRL); + DUMPCOREAV(HDMI_CORE_AV_DPD); + DUMPCOREAV(HDMI_CORE_AV_PB_CTRL1); + DUMPCOREAV(HDMI_CORE_AV_PB_CTRL2); + DUMPCOREAV(HDMI_CORE_AV_AVI_TYPE); + DUMPCOREAV(HDMI_CORE_AV_AVI_VERS); + DUMPCOREAV(HDMI_CORE_AV_AVI_LEN); + DUMPCOREAV(HDMI_CORE_AV_AVI_CHSUM); for (i = 0; i < HDMI_CORE_AV_AVI_DBYTE_NELEMS; i++) - DUMPCOREAV(i, HDMI_CORE_AV_AVI_DBYTE); + DUMPCOREAV2(i, HDMI_CORE_AV_AVI_DBYTE); + + DUMPCOREAV(HDMI_CORE_AV_SPD_TYPE); + DUMPCOREAV(HDMI_CORE_AV_SPD_VERS); + DUMPCOREAV(HDMI_CORE_AV_SPD_LEN); + DUMPCOREAV(HDMI_CORE_AV_SPD_CHSUM); for (i = 0; i < HDMI_CORE_AV_SPD_DBYTE_NELEMS; i++) - DUMPCOREAV(i, HDMI_CORE_AV_SPD_DBYTE); + DUMPCOREAV2(i, HDMI_CORE_AV_SPD_DBYTE); + + DUMPCOREAV(HDMI_CORE_AV_AUDIO_TYPE); + DUMPCOREAV(HDMI_CORE_AV_AUDIO_VERS); + DUMPCOREAV(HDMI_CORE_AV_AUDIO_LEN); + DUMPCOREAV(HDMI_CORE_AV_AUDIO_CHSUM); for (i = 0; i < HDMI_CORE_AV_AUD_DBYTE_NELEMS; i++) - DUMPCOREAV(i, HDMI_CORE_AV_AUD_DBYTE); + DUMPCOREAV2(i, HDMI_CORE_AV_AUD_DBYTE); + + DUMPCOREAV(HDMI_CORE_AV_MPEG_TYPE); + DUMPCOREAV(HDMI_CORE_AV_MPEG_VERS); + DUMPCOREAV(HDMI_CORE_AV_MPEG_LEN); + DUMPCOREAV(HDMI_CORE_AV_MPEG_CHSUM); for (i = 0; i < HDMI_CORE_AV_MPEG_DBYTE_NELEMS; i++) - DUMPCOREAV(i, HDMI_CORE_AV_MPEG_DBYTE); + DUMPCOREAV2(i, HDMI_CORE_AV_MPEG_DBYTE); for (i = 0; i < HDMI_CORE_AV_GEN_DBYTE_NELEMS; i++) - DUMPCOREAV(i, HDMI_CORE_AV_GEN_DBYTE); + DUMPCOREAV2(i, HDMI_CORE_AV_GEN_DBYTE); + + DUMPCOREAV(HDMI_CORE_AV_CP_BYTE1); for (i = 0; i < HDMI_CORE_AV_GEN2_DBYTE_NELEMS; i++) - DUMPCOREAV(i, HDMI_CORE_AV_GEN2_DBYTE); - - DUMPCORE(HDMI_CORE_AV_ACR_CTRL); - DUMPCORE(HDMI_CORE_AV_FREQ_SVAL); - DUMPCORE(HDMI_CORE_AV_N_SVAL1); - DUMPCORE(HDMI_CORE_AV_N_SVAL2); - DUMPCORE(HDMI_CORE_AV_N_SVAL3); - DUMPCORE(HDMI_CORE_AV_CTS_SVAL1); - DUMPCORE(HDMI_CORE_AV_CTS_SVAL2); - DUMPCORE(HDMI_CORE_AV_CTS_SVAL3); - DUMPCORE(HDMI_CORE_AV_CTS_HVAL1); - DUMPCORE(HDMI_CORE_AV_CTS_HVAL2); - DUMPCORE(HDMI_CORE_AV_CTS_HVAL3); - DUMPCORE(HDMI_CORE_AV_AUD_MODE); - DUMPCORE(HDMI_CORE_AV_SPDIF_CTRL); - DUMPCORE(HDMI_CORE_AV_HW_SPDIF_FS); - DUMPCORE(HDMI_CORE_AV_SWAP_I2S); - DUMPCORE(HDMI_CORE_AV_SPDIF_ERTH); - DUMPCORE(HDMI_CORE_AV_I2S_IN_MAP); - DUMPCORE(HDMI_CORE_AV_I2S_IN_CTRL); - DUMPCORE(HDMI_CORE_AV_I2S_CHST0); - DUMPCORE(HDMI_CORE_AV_I2S_CHST1); - DUMPCORE(HDMI_CORE_AV_I2S_CHST2); - DUMPCORE(HDMI_CORE_AV_I2S_CHST4); - DUMPCORE(HDMI_CORE_AV_I2S_CHST5); - DUMPCORE(HDMI_CORE_AV_ASRC); - DUMPCORE(HDMI_CORE_AV_I2S_IN_LEN); - DUMPCORE(HDMI_CORE_AV_HDMI_CTRL); - DUMPCORE(HDMI_CORE_AV_AUDO_TXSTAT); - DUMPCORE(HDMI_CORE_AV_AUD_PAR_BUSCLK_1); - DUMPCORE(HDMI_CORE_AV_AUD_PAR_BUSCLK_2); - DUMPCORE(HDMI_CORE_AV_AUD_PAR_BUSCLK_3); - DUMPCORE(HDMI_CORE_AV_TEST_TXCTRL); - DUMPCORE(HDMI_CORE_AV_DPD); - DUMPCORE(HDMI_CORE_AV_PB_CTRL1); - DUMPCORE(HDMI_CORE_AV_PB_CTRL2); - DUMPCORE(HDMI_CORE_AV_AVI_TYPE); - DUMPCORE(HDMI_CORE_AV_AVI_VERS); - DUMPCORE(HDMI_CORE_AV_AVI_LEN); - DUMPCORE(HDMI_CORE_AV_AVI_CHSUM); - DUMPCORE(HDMI_CORE_AV_SPD_TYPE); - DUMPCORE(HDMI_CORE_AV_SPD_VERS); - DUMPCORE(HDMI_CORE_AV_SPD_LEN); - DUMPCORE(HDMI_CORE_AV_SPD_CHSUM); - DUMPCORE(HDMI_CORE_AV_AUDIO_TYPE); - DUMPCORE(HDMI_CORE_AV_AUDIO_VERS); - DUMPCORE(HDMI_CORE_AV_AUDIO_LEN); - DUMPCORE(HDMI_CORE_AV_AUDIO_CHSUM); - DUMPCORE(HDMI_CORE_AV_MPEG_TYPE); - DUMPCORE(HDMI_CORE_AV_MPEG_VERS); - DUMPCORE(HDMI_CORE_AV_MPEG_LEN); - DUMPCORE(HDMI_CORE_AV_MPEG_CHSUM); - DUMPCORE(HDMI_CORE_AV_CP_BYTE1); - DUMPCORE(HDMI_CORE_AV_CEC_ADDR_ID); + DUMPCOREAV2(i, HDMI_CORE_AV_GEN2_DBYTE); + + DUMPCOREAV(HDMI_CORE_AV_CEC_ADDR_ID); } void ti_hdmi_4xxx_phy_dump(struct hdmi_ip_data *ip_data, struct seq_file *s) diff --git a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h index a14d1a0e6e4..b724bc68307 100644 --- a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h +++ b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h @@ -57,6 +57,13 @@ #define HDMI_CORE_SYS_SRST 0x14 #define HDMI_CORE_CTRL1 0x20 #define HDMI_CORE_SYS_SYS_STAT 0x24 +#define HDMI_CORE_SYS_DE_DLY 0xC8 +#define HDMI_CORE_SYS_DE_CTRL 0xCC +#define HDMI_CORE_SYS_DE_TOP 0xD0 +#define HDMI_CORE_SYS_DE_CNTL 0xD8 +#define HDMI_CORE_SYS_DE_CNTH 0xDC +#define HDMI_CORE_SYS_DE_LINL 0xE0 +#define HDMI_CORE_SYS_DE_LINH_1 0xE4 #define HDMI_CORE_SYS_VID_ACEN 0x124 #define HDMI_CORE_SYS_VID_MODE 0x128 #define HDMI_CORE_SYS_INTR_STATE 0x1C0 @@ -66,50 +73,24 @@ #define HDMI_CORE_SYS_INTR4 0x1D0 #define HDMI_CORE_SYS_UMASK1 0x1D4 #define HDMI_CORE_SYS_TMDS_CTRL 0x208 -#define HDMI_CORE_SYS_DE_DLY 0xC8 -#define HDMI_CORE_SYS_DE_CTRL 0xCC -#define HDMI_CORE_SYS_DE_TOP 0xD0 -#define HDMI_CORE_SYS_DE_CNTL 0xD8 -#define HDMI_CORE_SYS_DE_CNTH 0xDC -#define HDMI_CORE_SYS_DE_LINL 0xE0 -#define HDMI_CORE_SYS_DE_LINH_1 0xE4 + #define HDMI_CORE_CTRL1_VEN_FOLLOWVSYNC 0x1 #define HDMI_CORE_CTRL1_HEN_FOLLOWHSYNC 0x1 -#define HDMI_CORE_CTRL1_BSEL_24BITBUS 0x1 +#define HDMI_CORE_CTRL1_BSEL_24BITBUS 0x1 #define HDMI_CORE_CTRL1_EDGE_RISINGEDGE 0x1 /* HDMI DDC E-DID */ -#define HDMI_CORE_DDC_CMD 0x3CC -#define HDMI_CORE_DDC_STATUS 0x3C8 #define HDMI_CORE_DDC_ADDR 0x3B4 +#define HDMI_CORE_DDC_SEGM 0x3B8 #define HDMI_CORE_DDC_OFFSET 0x3BC #define HDMI_CORE_DDC_COUNT1 0x3C0 #define HDMI_CORE_DDC_COUNT2 0x3C4 +#define HDMI_CORE_DDC_STATUS 0x3C8 +#define HDMI_CORE_DDC_CMD 0x3CC #define HDMI_CORE_DDC_DATA 0x3D0 -#define HDMI_CORE_DDC_SEGM 0x3B8 /* HDMI IP Core Audio Video */ -#define HDMI_CORE_AV_HDMI_CTRL 0xBC -#define HDMI_CORE_AV_DPD 0xF4 -#define HDMI_CORE_AV_PB_CTRL1 0xF8 -#define HDMI_CORE_AV_PB_CTRL2 0xFC -#define HDMI_CORE_AV_AVI_TYPE 0x100 -#define HDMI_CORE_AV_AVI_VERS 0x104 -#define HDMI_CORE_AV_AVI_LEN 0x108 -#define HDMI_CORE_AV_AVI_CHSUM 0x10C -#define HDMI_CORE_AV_AVI_DBYTE(n) (n * 4 + 0x110) -#define HDMI_CORE_AV_AVI_DBYTE_NELEMS 15 -#define HDMI_CORE_AV_SPD_DBYTE(n) (n * 4 + 0x190) -#define HDMI_CORE_AV_SPD_DBYTE_NELEMS 27 -#define HDMI_CORE_AV_AUD_DBYTE(n) (n * 4 + 0x210) -#define HDMI_CORE_AV_AUD_DBYTE_NELEMS 10 -#define HDMI_CORE_AV_MPEG_DBYTE(n) (n * 4 + 0x290) -#define HDMI_CORE_AV_MPEG_DBYTE_NELEMS 27 -#define HDMI_CORE_AV_GEN_DBYTE(n) (n * 4 + 0x300) -#define HDMI_CORE_AV_GEN_DBYTE_NELEMS 31 -#define HDMI_CORE_AV_GEN2_DBYTE(n) (n * 4 + 0x380) -#define HDMI_CORE_AV_GEN2_DBYTE_NELEMS 31 #define HDMI_CORE_AV_ACR_CTRL 0x4 #define HDMI_CORE_AV_FREQ_SVAL 0x8 #define HDMI_CORE_AV_N_SVAL1 0xC @@ -148,25 +129,39 @@ #define HDMI_CORE_AV_AVI_VERS 0x104 #define HDMI_CORE_AV_AVI_LEN 0x108 #define HDMI_CORE_AV_AVI_CHSUM 0x10C +#define HDMI_CORE_AV_AVI_DBYTE(n) (n * 4 + 0x110) #define HDMI_CORE_AV_SPD_TYPE 0x180 #define HDMI_CORE_AV_SPD_VERS 0x184 #define HDMI_CORE_AV_SPD_LEN 0x188 #define HDMI_CORE_AV_SPD_CHSUM 0x18C +#define HDMI_CORE_AV_SPD_DBYTE(n) (n * 4 + 0x190) #define HDMI_CORE_AV_AUDIO_TYPE 0x200 #define HDMI_CORE_AV_AUDIO_VERS 0x204 #define HDMI_CORE_AV_AUDIO_LEN 0x208 #define HDMI_CORE_AV_AUDIO_CHSUM 0x20C +#define HDMI_CORE_AV_AUD_DBYTE(n) (n * 4 + 0x210) #define HDMI_CORE_AV_MPEG_TYPE 0x280 #define HDMI_CORE_AV_MPEG_VERS 0x284 #define HDMI_CORE_AV_MPEG_LEN 0x288 #define HDMI_CORE_AV_MPEG_CHSUM 0x28C +#define HDMI_CORE_AV_MPEG_DBYTE(n) (n * 4 + 0x290) +#define HDMI_CORE_AV_GEN_DBYTE(n) (n * 4 + 0x300) #define HDMI_CORE_AV_CP_BYTE1 0x37C +#define HDMI_CORE_AV_GEN2_DBYTE(n) (n * 4 + 0x380) #define HDMI_CORE_AV_CEC_ADDR_ID 0x3FC + #define HDMI_CORE_AV_SPD_DBYTE_ELSIZE 0x4 #define HDMI_CORE_AV_GEN2_DBYTE_ELSIZE 0x4 #define HDMI_CORE_AV_MPEG_DBYTE_ELSIZE 0x4 #define HDMI_CORE_AV_GEN_DBYTE_ELSIZE 0x4 +#define HDMI_CORE_AV_AVI_DBYTE_NELEMS 15 +#define HDMI_CORE_AV_SPD_DBYTE_NELEMS 27 +#define HDMI_CORE_AV_AUD_DBYTE_NELEMS 10 +#define HDMI_CORE_AV_MPEG_DBYTE_NELEMS 27 +#define HDMI_CORE_AV_GEN_DBYTE_NELEMS 31 +#define HDMI_CORE_AV_GEN2_DBYTE_NELEMS 31 + /* PLL */ #define PLLCTRL_PLL_CONTROL 0x0 diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c index 9c3daf71750..e2374645a44 100644 --- a/drivers/video/omap2/dss/venc.c +++ b/drivers/video/omap2/dss/venc.c @@ -421,6 +421,7 @@ static int venc_power_on(struct omap_dss_device *dssdev) { u32 l; int r; + struct omap_video_timings timings; venc_reset(); venc_write_config(venc_timings_to_config(&dssdev->panel.timings)); @@ -440,10 +441,14 @@ static int venc_power_on(struct omap_dss_device *dssdev) venc_write_reg(VENC_OUTPUT_CONTROL, l); - dispc_set_digit_size(dssdev->panel.timings.x_res, - dssdev->panel.timings.y_res/2); + timings = dssdev->panel.timings; + timings.y_res /= 2; - regulator_enable(venc.vdda_dac_reg); + dss_mgr_set_timings(dssdev->manager, &timings); + + r = regulator_enable(venc.vdda_dac_reg); + if (r) + goto err; if (dssdev->platform_enable) dssdev->platform_enable(dssdev); @@ -577,12 +582,6 @@ static int venc_panel_resume(struct omap_dss_device *dssdev) return venc_panel_enable(dssdev); } -static void venc_get_timings(struct omap_dss_device *dssdev, - struct omap_video_timings *timings) -{ - *timings = dssdev->panel.timings; -} - static void venc_set_timings(struct omap_dss_device *dssdev, struct omap_video_timings *timings) { @@ -661,7 +660,6 @@ static struct omap_dss_driver venc_driver = { .get_resolution = omapdss_default_get_resolution, .get_recommended_bpp = omapdss_default_get_recommended_bpp, - .get_timings = venc_get_timings, .set_timings = venc_set_timings, .check_timings = venc_check_timings, diff --git a/drivers/video/omap2/omapfb/omapfb-ioctl.c b/drivers/video/omap2/omapfb/omapfb-ioctl.c index 6a09ef87e14..27a85813c60 100644 --- a/drivers/video/omap2/omapfb/omapfb-ioctl.c +++ b/drivers/video/omap2/omapfb/omapfb-ioctl.c @@ -225,6 +225,9 @@ static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi) down_write_nested(&rg->lock, rg->id); atomic_inc(&rg->lock_count); + if (rg->size == size && rg->type == mi->type) + goto out; + if (atomic_read(&rg->map_count)) { r = -EBUSY; goto out; @@ -247,12 +250,10 @@ static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi) } } - if (rg->size != size || rg->type != mi->type) { - r = omapfb_realloc_fbmem(fbi, size, mi->type); - if (r) { - dev_err(fbdev->dev, "realloc fbmem failed\n"); - goto out; - } + r = omapfb_realloc_fbmem(fbi, size, mi->type); + if (r) { + dev_err(fbdev->dev, "realloc fbmem failed\n"); + goto out; } out: |