diff options
Diffstat (limited to 'drivers/video/omap2/dss')
-rw-r--r-- | drivers/video/omap2/dss/apply.c | 275 | ||||
-rw-r--r-- | drivers/video/omap2/dss/core.c | 135 | ||||
-rw-r--r-- | drivers/video/omap2/dss/dispc.c | 121 | ||||
-rw-r--r-- | drivers/video/omap2/dss/dispc_coefs.c | 9 | ||||
-rw-r--r-- | drivers/video/omap2/dss/display.c | 10 | ||||
-rw-r--r-- | drivers/video/omap2/dss/dsi.c | 65 | ||||
-rw-r--r-- | drivers/video/omap2/dss/dss.c | 17 | ||||
-rw-r--r-- | drivers/video/omap2/dss/dss.h | 10 | ||||
-rw-r--r-- | drivers/video/omap2/dss/dss_features.c | 181 | ||||
-rw-r--r-- | drivers/video/omap2/dss/dss_features.h | 54 | ||||
-rw-r--r-- | drivers/video/omap2/dss/hdmi.c | 278 | ||||
-rw-r--r-- | drivers/video/omap2/dss/manager.c | 12 | ||||
-rw-r--r-- | drivers/video/omap2/dss/rfbi.c | 36 | ||||
-rw-r--r-- | drivers/video/omap2/dss/ti_hdmi.h | 56 | ||||
-rw-r--r-- | drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c | 94 | ||||
-rw-r--r-- | drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h | 47 | ||||
-rw-r--r-- | drivers/video/omap2/dss/venc.c | 32 |
17 files changed, 846 insertions, 586 deletions
diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c index 87b3e25294cf..b10b3bc1931e 100644 --- a/drivers/video/omap2/dss/apply.c +++ b/drivers/video/omap2/dss/apply.c @@ -105,6 +105,9 @@ static struct { struct ovl_priv_data ovl_priv_data_array[MAX_DSS_OVERLAYS]; struct mgr_priv_data mgr_priv_data_array[MAX_DSS_MANAGERS]; + bool fifo_merge_dirty; + bool fifo_merge; + bool irq_enabled; } dss_data; @@ -351,6 +354,7 @@ static void wait_pending_extra_info_updates(void) bool updating; unsigned long flags; unsigned long t; + int r; spin_lock_irqsave(&data_lock, flags); @@ -366,11 +370,11 @@ static void wait_pending_extra_info_updates(void) spin_unlock_irqrestore(&data_lock, flags); t = msecs_to_jiffies(500); - wait_for_completion_timeout(&extra_updated_completion, t); - - updating = extra_info_update_ongoing(); - - WARN_ON(updating); + r = wait_for_completion_timeout(&extra_updated_completion, t); + if (r == 0) + DSSWARN("timeout in wait_pending_extra_info_updates\n"); + else if (r < 0) + DSSERR("wait_pending_extra_info_updates failed: %d\n", r); } int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr) @@ -388,6 +392,10 @@ int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr) if (mgr_manual_update(mgr)) return 0; + r = dispc_runtime_get(); + if (r) + return r; + irq = dispc_mgr_get_vsync_irq(mgr->id); mp = get_mgr_priv(mgr); @@ -428,6 +436,8 @@ int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr) } } + dispc_runtime_put(); + return r; } @@ -451,6 +461,10 @@ int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl) if (ovl_manual_update(ovl)) return 0; + r = dispc_runtime_get(); + if (r) + return r; + irq = dispc_mgr_get_vsync_irq(ovl->manager->id); op = get_ovl_priv(ovl); @@ -491,6 +505,8 @@ int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl) } } + dispc_runtime_put(); + return r; } @@ -585,11 +601,40 @@ static void dss_mgr_write_regs(struct omap_overlay_manager *mgr) } } +static void dss_write_regs_common(void) +{ + const int num_mgrs = omap_dss_get_num_overlay_managers(); + int i; + + if (!dss_data.fifo_merge_dirty) + return; + + for (i = 0; i < num_mgrs; ++i) { + struct omap_overlay_manager *mgr; + struct mgr_priv_data *mp; + + mgr = omap_dss_get_overlay_manager(i); + mp = get_mgr_priv(mgr); + + if (mp->enabled) { + if (dss_data.fifo_merge_dirty) { + dispc_enable_fifomerge(dss_data.fifo_merge); + dss_data.fifo_merge_dirty = false; + } + + if (mp->updating) + mp->shadow_info_dirty = true; + } + } +} + static void dss_write_regs(void) { const int num_mgrs = omap_dss_get_num_overlay_managers(); int i; + dss_write_regs_common(); + for (i = 0; i < num_mgrs; ++i) { struct omap_overlay_manager *mgr; struct mgr_priv_data *mp; @@ -640,6 +685,22 @@ static void dss_set_go_bits(void) } +static void mgr_clear_shadow_dirty(struct omap_overlay_manager *mgr) +{ + struct omap_overlay *ovl; + struct mgr_priv_data *mp; + struct ovl_priv_data *op; + + mp = get_mgr_priv(mgr); + mp->shadow_info_dirty = false; + + list_for_each_entry(ovl, &mgr->overlays, list) { + op = get_ovl_priv(ovl); + op->shadow_info_dirty = false; + op->shadow_extra_info_dirty = false; + } +} + void dss_mgr_start_update(struct omap_overlay_manager *mgr) { struct mgr_priv_data *mp = get_mgr_priv(mgr); @@ -659,6 +720,8 @@ void dss_mgr_start_update(struct omap_overlay_manager *mgr) dss_mgr_write_regs(mgr); + dss_write_regs_common(); + mp->updating = true; if (!dss_data.irq_enabled && need_isr()) @@ -666,6 +729,8 @@ void dss_mgr_start_update(struct omap_overlay_manager *mgr) dispc_mgr_enable(mgr->id, true); + mgr_clear_shadow_dirty(mgr); + spin_unlock_irqrestore(&data_lock, flags); } @@ -709,22 +774,6 @@ static void dss_unregister_vsync_isr(void) dss_data.irq_enabled = false; } -static void mgr_clear_shadow_dirty(struct omap_overlay_manager *mgr) -{ - struct omap_overlay *ovl; - struct mgr_priv_data *mp; - struct ovl_priv_data *op; - - mp = get_mgr_priv(mgr); - mp->shadow_info_dirty = false; - - list_for_each_entry(ovl, &mgr->overlays, list) { - op = get_ovl_priv(ovl); - op->shadow_info_dirty = false; - op->shadow_extra_info_dirty = false; - } -} - static void dss_apply_irq_handler(void *data, u32 mask) { const int num_mgrs = dss_feat_get_num_mgrs(); @@ -754,9 +803,6 @@ static void dss_apply_irq_handler(void *data, u32 mask) if (was_busy && !mp->busy) mgr_clear_shadow_dirty(mgr); - } else { - if (was_updating && !mp->updating) - mgr_clear_shadow_dirty(mgr); } } @@ -859,11 +905,20 @@ static void dss_apply_ovl_fifo_thresholds(struct omap_overlay *ovl, op->extra_info_dirty = true; } -static void dss_ovl_setup_fifo(struct omap_overlay *ovl) +static void dss_apply_fifo_merge(bool use_fifo_merge) +{ + if (dss_data.fifo_merge == use_fifo_merge) + return; + + dss_data.fifo_merge = use_fifo_merge; + dss_data.fifo_merge_dirty = true; +} + +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 size, burst_size; u32 fifo_low, fifo_high; if (!op->enabled && !op->enabling) @@ -871,33 +926,14 @@ static void dss_ovl_setup_fifo(struct omap_overlay *ovl) dssdev = ovl->manager->device; - size = dispc_ovl_get_fifo_size(ovl->id); - - burst_size = dispc_ovl_get_burst_size(ovl->id); - - switch (dssdev->type) { - case OMAP_DISPLAY_TYPE_DPI: - case OMAP_DISPLAY_TYPE_DBI: - case OMAP_DISPLAY_TYPE_SDI: - case OMAP_DISPLAY_TYPE_VENC: - case OMAP_DISPLAY_TYPE_HDMI: - default_get_overlay_fifo_thresholds(ovl->id, size, - burst_size, &fifo_low, &fifo_high); - break; -#ifdef CONFIG_OMAP2_DSS_DSI - case OMAP_DISPLAY_TYPE_DSI: - dsi_get_overlay_fifo_thresholds(ovl->id, size, - burst_size, &fifo_low, &fifo_high); - break; -#endif - default: - BUG(); - } + dispc_ovl_compute_fifo_thresholds(ovl->id, &fifo_low, &fifo_high, + use_fifo_merge); dss_apply_ovl_fifo_thresholds(ovl, fifo_low, fifo_high); } -static void dss_mgr_setup_fifos(struct omap_overlay_manager *mgr) +static void dss_mgr_setup_fifos(struct omap_overlay_manager *mgr, + bool use_fifo_merge) { struct omap_overlay *ovl; struct mgr_priv_data *mp; @@ -908,19 +944,94 @@ static void dss_mgr_setup_fifos(struct omap_overlay_manager *mgr) return; list_for_each_entry(ovl, &mgr->overlays, list) - dss_ovl_setup_fifo(ovl); + dss_ovl_setup_fifo(ovl, use_fifo_merge); +} + +static void dss_setup_fifos(bool use_fifo_merge) +{ + const int num_mgrs = omap_dss_get_num_overlay_managers(); + struct omap_overlay_manager *mgr; + int i; + + for (i = 0; i < num_mgrs; ++i) { + mgr = omap_dss_get_overlay_manager(i); + dss_mgr_setup_fifos(mgr, use_fifo_merge); + } } -static void dss_setup_fifos(void) +static int get_num_used_managers(void) { const int num_mgrs = omap_dss_get_num_overlay_managers(); struct omap_overlay_manager *mgr; + struct mgr_priv_data *mp; int i; + int enabled_mgrs; + + enabled_mgrs = 0; for (i = 0; i < num_mgrs; ++i) { mgr = omap_dss_get_overlay_manager(i); - dss_mgr_setup_fifos(mgr); + mp = get_mgr_priv(mgr); + + if (!mp->enabled) + continue; + + enabled_mgrs++; + } + + return enabled_mgrs; +} + +static int get_num_used_overlays(void) +{ + const int num_ovls = omap_dss_get_num_overlays(); + struct omap_overlay *ovl; + struct ovl_priv_data *op; + struct mgr_priv_data *mp; + int i; + int enabled_ovls; + + enabled_ovls = 0; + + for (i = 0; i < num_ovls; ++i) { + ovl = omap_dss_get_overlay(i); + op = get_ovl_priv(ovl); + + if (!op->enabled && !op->enabling) + continue; + + mp = get_mgr_priv(ovl->manager); + + if (!mp->enabled) + continue; + + enabled_ovls++; } + + return enabled_ovls; +} + +static bool get_use_fifo_merge(void) +{ + int enabled_mgrs = get_num_used_managers(); + int enabled_ovls = get_num_used_overlays(); + + if (!dss_has_feature(FEAT_FIFO_MERGE)) + return false; + + /* + * In theory the only requirement for fifomerge is enabled_ovls <= 1. + * However, if we have two managers enabled and set/unset the fifomerge, + * we need to set the GO bits in particular sequence for the managers, + * and wait in between. + * + * This is rather difficult as new apply calls can happen at any time, + * so we simplify the problem by requiring also that enabled_mgrs <= 1. + * In practice this shouldn't matter, because when only one overlay is + * enabled, most likely only one output is enabled. + */ + + return enabled_mgrs <= 1 && enabled_ovls <= 1; } int dss_mgr_enable(struct omap_overlay_manager *mgr) @@ -928,6 +1039,7 @@ int dss_mgr_enable(struct omap_overlay_manager *mgr) struct mgr_priv_data *mp = get_mgr_priv(mgr); unsigned long flags; int r; + bool fifo_merge; mutex_lock(&apply_lock); @@ -945,11 +1057,23 @@ int dss_mgr_enable(struct omap_overlay_manager *mgr) goto err; } - dss_setup_fifos(); + /* step 1: setup fifos/fifomerge before enabling the manager */ + + fifo_merge = get_use_fifo_merge(); + dss_setup_fifos(fifo_merge); + dss_apply_fifo_merge(fifo_merge); dss_write_regs(); dss_set_go_bits(); + spin_unlock_irqrestore(&data_lock, flags); + + /* wait until fifo config is in */ + wait_pending_extra_info_updates(); + + /* step 2: enable the manager */ + spin_lock_irqsave(&data_lock, flags); + if (!mgr_manual_update(mgr)) mp->updating = true; @@ -974,6 +1098,7 @@ void dss_mgr_disable(struct omap_overlay_manager *mgr) { struct mgr_priv_data *mp = get_mgr_priv(mgr); unsigned long flags; + bool fifo_merge; mutex_lock(&apply_lock); @@ -988,8 +1113,16 @@ void dss_mgr_disable(struct omap_overlay_manager *mgr) mp->updating = false; mp->enabled = false; + fifo_merge = get_use_fifo_merge(); + dss_setup_fifos(fifo_merge); + dss_apply_fifo_merge(fifo_merge); + + dss_write_regs(); + dss_set_go_bits(); + spin_unlock_irqrestore(&data_lock, flags); + wait_pending_extra_info_updates(); out: mutex_unlock(&apply_lock); } @@ -1241,6 +1374,7 @@ int dss_ovl_enable(struct omap_overlay *ovl) { struct ovl_priv_data *op = get_ovl_priv(ovl); unsigned long flags; + bool fifo_merge; int r; mutex_lock(&apply_lock); @@ -1266,7 +1400,22 @@ int dss_ovl_enable(struct omap_overlay *ovl) goto err2; } - dss_setup_fifos(); + /* step 1: configure fifos/fifomerge for currently enabled ovls */ + + fifo_merge = get_use_fifo_merge(); + dss_setup_fifos(fifo_merge); + dss_apply_fifo_merge(fifo_merge); + + dss_write_regs(); + dss_set_go_bits(); + + spin_unlock_irqrestore(&data_lock, flags); + + /* wait for fifo configs to go in */ + wait_pending_extra_info_updates(); + + /* step 2: enable the overlay */ + spin_lock_irqsave(&data_lock, flags); op->enabling = false; dss_apply_ovl_enable(ovl, true); @@ -1294,6 +1443,7 @@ int dss_ovl_disable(struct omap_overlay *ovl) { struct ovl_priv_data *op = get_ovl_priv(ovl); unsigned long flags; + bool fifo_merge; int r; mutex_lock(&apply_lock); @@ -1308,9 +1458,11 @@ int dss_ovl_disable(struct omap_overlay *ovl) goto err; } + /* step 1: disable the overlay */ spin_lock_irqsave(&data_lock, flags); dss_apply_ovl_enable(ovl, false); + dss_write_regs(); dss_set_go_bits(); @@ -1319,6 +1471,21 @@ int dss_ovl_disable(struct omap_overlay *ovl) /* wait for the overlay to be disabled */ wait_pending_extra_info_updates(); + /* step 2: configure fifos/fifomerge */ + spin_lock_irqsave(&data_lock, flags); + + fifo_merge = get_use_fifo_merge(); + dss_setup_fifos(fifo_merge); + dss_apply_fifo_merge(fifo_merge); + + dss_write_regs(); + dss_set_go_bits(); + + spin_unlock_irqrestore(&data_lock, flags); + + /* wait for fifo config to go in */ + wait_pending_extra_info_updates(); + mutex_unlock(&apply_lock); return 0; diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c index 8613f86fb56d..e8a120771ac6 100644 --- a/drivers/video/omap2/dss/core.c +++ b/drivers/video/omap2/dss/core.c @@ -183,42 +183,6 @@ static int omap_dss_probe(struct platform_device *pdev) dss_init_overlay_managers(pdev); dss_init_overlays(pdev); - r = dss_init_platform_driver(); - if (r) { - DSSERR("Failed to initialize DSS platform driver\n"); - goto err_dss; - } - - r = dispc_init_platform_driver(); - if (r) { - DSSERR("Failed to initialize dispc platform driver\n"); - goto err_dispc; - } - - r = rfbi_init_platform_driver(); - if (r) { - DSSERR("Failed to initialize rfbi platform driver\n"); - goto err_rfbi; - } - - r = venc_init_platform_driver(); - if (r) { - DSSERR("Failed to initialize venc platform driver\n"); - goto err_venc; - } - - r = dsi_init_platform_driver(); - if (r) { - DSSERR("Failed to initialize DSI platform driver\n"); - goto err_dsi; - } - - r = hdmi_init_platform_driver(); - if (r) { - DSSERR("Failed to initialize hdmi\n"); - goto err_hdmi; - } - r = dss_initialize_debugfs(); if (r) goto err_debugfs; @@ -246,18 +210,6 @@ static int omap_dss_probe(struct platform_device *pdev) err_register: dss_uninitialize_debugfs(); err_debugfs: - hdmi_uninit_platform_driver(); -err_hdmi: - dsi_uninit_platform_driver(); -err_dsi: - venc_uninit_platform_driver(); -err_venc: - dispc_uninit_platform_driver(); -err_dispc: - rfbi_uninit_platform_driver(); -err_rfbi: - dss_uninit_platform_driver(); -err_dss: return r; } @@ -269,13 +221,6 @@ static int omap_dss_remove(struct platform_device *pdev) dss_uninitialize_debugfs(); - hdmi_uninit_platform_driver(); - dsi_uninit_platform_driver(); - venc_uninit_platform_driver(); - rfbi_uninit_platform_driver(); - dispc_uninit_platform_driver(); - dss_uninit_platform_driver(); - dss_uninit_overlays(pdev); dss_uninit_overlay_managers(pdev); @@ -525,6 +470,80 @@ static int omap_dss_bus_register(void) /* INIT */ +static int __init omap_dss_register_drivers(void) +{ + int r; + + r = platform_driver_register(&omap_dss_driver); + if (r) + return r; + + r = dss_init_platform_driver(); + if (r) { + DSSERR("Failed to initialize DSS platform driver\n"); + goto err_dss; + } + + r = dispc_init_platform_driver(); + if (r) { + DSSERR("Failed to initialize dispc platform driver\n"); + goto err_dispc; + } + + r = rfbi_init_platform_driver(); + if (r) { + DSSERR("Failed to initialize rfbi platform driver\n"); + goto err_rfbi; + } + + r = venc_init_platform_driver(); + if (r) { + DSSERR("Failed to initialize venc platform driver\n"); + goto err_venc; + } + + r = dsi_init_platform_driver(); + if (r) { + DSSERR("Failed to initialize DSI platform driver\n"); + goto err_dsi; + } + + r = hdmi_init_platform_driver(); + if (r) { + DSSERR("Failed to initialize hdmi\n"); + goto err_hdmi; + } + + return 0; + +err_hdmi: + dsi_uninit_platform_driver(); +err_dsi: + venc_uninit_platform_driver(); +err_venc: + rfbi_uninit_platform_driver(); +err_rfbi: + dispc_uninit_platform_driver(); +err_dispc: + dss_uninit_platform_driver(); +err_dss: + platform_driver_unregister(&omap_dss_driver); + + return r; +} + +static void __exit omap_dss_unregister_drivers(void) +{ + hdmi_uninit_platform_driver(); + dsi_uninit_platform_driver(); + venc_uninit_platform_driver(); + rfbi_uninit_platform_driver(); + dispc_uninit_platform_driver(); + dss_uninit_platform_driver(); + + platform_driver_unregister(&omap_dss_driver); +} + #ifdef CONFIG_OMAP2_DSS_MODULE static void omap_dss_bus_unregister(void) { @@ -541,7 +560,7 @@ static int __init omap_dss_init(void) if (r) return r; - r = platform_driver_register(&omap_dss_driver); + r = omap_dss_register_drivers(); if (r) { omap_dss_bus_unregister(); return r; @@ -562,7 +581,7 @@ static void __exit omap_dss_exit(void) core.vdds_sdi_reg = NULL; } - platform_driver_unregister(&omap_dss_driver); + omap_dss_unregister_drivers(); omap_dss_bus_unregister(); } @@ -577,7 +596,7 @@ static int __init omap_dss_init(void) static int __init omap_dss_init2(void) { - return platform_driver_register(&omap_dss_driver); + return omap_dss_register_drivers(); } core_initcall(omap_dss_init); diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index e1626a1d5c45..bddd64b435b9 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c @@ -37,7 +37,6 @@ #include <linux/platform_device.h> #include <linux/pm_runtime.h> -#include <plat/sram.h> #include <plat/clock.h> #include <video/omapdss.h> @@ -736,11 +735,11 @@ static void dispc_ovl_set_color_mode(enum omap_plane plane, switch (color_mode) { case OMAP_DSS_COLOR_NV12: m = 0x0; break; - case OMAP_DSS_COLOR_RGB12U: + case OMAP_DSS_COLOR_RGBX16: m = 0x1; break; case OMAP_DSS_COLOR_RGBA16: m = 0x2; break; - case OMAP_DSS_COLOR_RGBX16: + case OMAP_DSS_COLOR_RGB12U: m = 0x4; break; case OMAP_DSS_COLOR_ARGB16: m = 0x5; break; @@ -789,9 +788,9 @@ static void dispc_ovl_set_color_mode(enum omap_plane plane, m = 0x8; break; case OMAP_DSS_COLOR_RGB24P: m = 0x9; break; - case OMAP_DSS_COLOR_YUV2: + case OMAP_DSS_COLOR_RGBX16: m = 0xa; break; - case OMAP_DSS_COLOR_UYVY: + case OMAP_DSS_COLOR_RGBA16: m = 0xb; break; case OMAP_DSS_COLOR_ARGB32: m = 0xc; break; @@ -909,7 +908,7 @@ static void dispc_configure_burst_sizes(void) dispc_ovl_set_burst_size(i, burst_size); } -u32 dispc_ovl_get_burst_size(enum omap_plane plane) +static u32 dispc_ovl_get_burst_size(enum omap_plane plane) { unsigned unit = dss_feat_get_burst_size_unit(); /* burst multiplier is always x8 (see dispc_configure_burst_sizes()) */ @@ -1018,7 +1017,7 @@ static void dispc_read_plane_fifo_sizes(void) } } -u32 dispc_ovl_get_fifo_size(enum omap_plane plane) +static u32 dispc_ovl_get_fifo_size(enum omap_plane plane) { return dispc.fifo_size[plane]; } @@ -1039,13 +1038,13 @@ void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high) dss_feat_get_reg_field(FEAT_REG_FIFOHIGHTHRESHOLD, &hi_start, &hi_end); dss_feat_get_reg_field(FEAT_REG_FIFOLOWTHRESHOLD, &lo_start, &lo_end); - DSSDBG("fifo(%d) low/high old %u/%u, new %u/%u\n", + DSSDBG("fifo(%d) threshold (bytes), old %u/%u, new %u/%u\n", plane, REG_GET(DISPC_OVL_FIFO_THRESHOLD(plane), - lo_start, lo_end), + lo_start, lo_end) * unit, REG_GET(DISPC_OVL_FIFO_THRESHOLD(plane), - hi_start, hi_end), - low, high); + hi_start, hi_end) * unit, + low * unit, high * unit); dispc_write_reg(DISPC_OVL_FIFO_THRESHOLD(plane), FLD_VAL(high, hi_start, hi_end) | @@ -1054,10 +1053,53 @@ void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high) void dispc_enable_fifomerge(bool enable) { + if (!dss_has_feature(FEAT_FIFO_MERGE)) { + WARN_ON(enable); + return; + } + DSSDBG("FIFO merge %s\n", enable ? "enabled" : "disabled"); REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 14, 14); } +void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane, + u32 *fifo_low, u32 *fifo_high, bool use_fifomerge) +{ + /* + * All sizes are in bytes. Both the buffer and burst are made of + * buffer_units, and the fifo thresholds must be buffer_unit aligned. + */ + + unsigned buf_unit = dss_feat_get_buffer_size_unit(); + unsigned ovl_fifo_size, total_fifo_size, burst_size; + int i; + + burst_size = dispc_ovl_get_burst_size(plane); + ovl_fifo_size = dispc_ovl_get_fifo_size(plane); + + if (use_fifomerge) { + total_fifo_size = 0; + for (i = 0; i < omap_dss_get_num_overlays(); ++i) + total_fifo_size += dispc_ovl_get_fifo_size(i); + } else { + total_fifo_size = ovl_fifo_size; + } + + /* + * We use the same low threshold for both fifomerge and non-fifomerge + * cases, but for fifomerge we calculate the high threshold using the + * combined fifo size + */ + + if (dss_has_feature(FEAT_OMAP3_DSI_FIFO_BUG)) { + *fifo_low = ovl_fifo_size - burst_size * 2; + *fifo_high = total_fifo_size - burst_size; + } else { + *fifo_low = ovl_fifo_size - burst_size; + *fifo_high = total_fifo_size - buf_unit; + } +} + static void dispc_ovl_set_fir(enum omap_plane plane, int hinc, int vinc, enum omap_color_component color_comp) @@ -1651,6 +1693,7 @@ static unsigned long calc_fclk(enum omap_channel channel, u16 width, u16 height, u16 out_width, u16 out_height) { unsigned int hf, vf; + unsigned long pclk = dispc_mgr_pclk_rate(channel); /* * FIXME how to determine the 'A' factor @@ -1673,13 +1716,16 @@ static unsigned long calc_fclk(enum omap_channel channel, u16 width, if (cpu_is_omap24xx()) { if (vf > 1 && hf > 1) - return dispc_mgr_pclk_rate(channel) * 4; + return pclk * 4; else - return dispc_mgr_pclk_rate(channel) * 2; + return pclk * 2; } else if (cpu_is_omap34xx()) { - return dispc_mgr_pclk_rate(channel) * vf * hf; + return pclk * vf * hf; } else { - return dispc_mgr_pclk_rate(channel) * hf; + if (hf > 1) + return DIV_ROUND_UP(pclk, out_width) * width; + else + return pclk; } } @@ -3298,15 +3344,6 @@ static int omap_dispchw_probe(struct platform_device *pdev) dispc.pdev = pdev; - clk = clk_get(&pdev->dev, "fck"); - if (IS_ERR(clk)) { - DSSERR("can't get fck\n"); - r = PTR_ERR(clk); - goto err_get_clk; - } - - dispc.dss_clk = clk; - spin_lock_init(&dispc.irq_lock); #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS @@ -3319,29 +3356,38 @@ static int omap_dispchw_probe(struct platform_device *pdev) dispc_mem = platform_get_resource(dispc.pdev, IORESOURCE_MEM, 0); if (!dispc_mem) { DSSERR("can't get IORESOURCE_MEM DISPC\n"); - r = -EINVAL; - goto err_ioremap; + return -EINVAL; } - dispc.base = ioremap(dispc_mem->start, resource_size(dispc_mem)); + + dispc.base = devm_ioremap(&pdev->dev, dispc_mem->start, + resource_size(dispc_mem)); if (!dispc.base) { DSSERR("can't ioremap DISPC\n"); - r = -ENOMEM; - goto err_ioremap; + return -ENOMEM; } + dispc.irq = platform_get_irq(dispc.pdev, 0); if (dispc.irq < 0) { DSSERR("platform_get_irq failed\n"); - r = -ENODEV; - goto err_irq; + return -ENODEV; } - r = request_irq(dispc.irq, omap_dispc_irq_handler, IRQF_SHARED, - "OMAP DISPC", dispc.pdev); + r = devm_request_irq(&pdev->dev, dispc.irq, omap_dispc_irq_handler, + IRQF_SHARED, "OMAP DISPC", dispc.pdev); if (r < 0) { DSSERR("request_irq failed\n"); - goto err_irq; + return r; + } + + clk = clk_get(&pdev->dev, "fck"); + if (IS_ERR(clk)) { + DSSERR("can't get fck\n"); + r = PTR_ERR(clk); + return r; } + dispc.dss_clk = clk; + pm_runtime_enable(&pdev->dev); r = dispc_runtime_get(); @@ -3362,12 +3408,7 @@ static int omap_dispchw_probe(struct platform_device *pdev) err_runtime_get: pm_runtime_disable(&pdev->dev); - free_irq(dispc.irq, dispc.pdev); -err_irq: - iounmap(dispc.base); -err_ioremap: clk_put(dispc.dss_clk); -err_get_clk: return r; } @@ -3377,8 +3418,6 @@ static int omap_dispchw_remove(struct platform_device *pdev) clk_put(dispc.dss_clk); - free_irq(dispc.irq, dispc.pdev); - iounmap(dispc.base); return 0; } diff --git a/drivers/video/omap2/dss/dispc_coefs.c b/drivers/video/omap2/dss/dispc_coefs.c index 069bccbb3f12..038c15b04215 100644 --- a/drivers/video/omap2/dss/dispc_coefs.c +++ b/drivers/video/omap2/dss/dispc_coefs.c @@ -19,14 +19,13 @@ #include <linux/kernel.h> #include <video/omapdss.h> -#include "dispc.h" -#define ARRAY_LEN(array) (sizeof(array) / sizeof(array[0])) +#include "dispc.h" static const struct dispc_coef coef3_M8[8] = { { 0, 0, 128, 0, 0 }, { 0, -4, 123, 9, 0 }, - { 0, -4, 108, 87, 0 }, + { 0, -4, 108, 24, 0 }, { 0, -2, 87, 43, 0 }, { 0, 64, 64, 0, 0 }, { 0, 43, 87, -2, 0 }, @@ -168,7 +167,7 @@ static const struct dispc_coef coef5_M8[8] = { static const struct dispc_coef coef5_M9[8] = { { -3, 10, 114, 10, -3 }, - { -6, 24, 110, 0, -1 }, + { -6, 24, 111, 0, -1 }, { -8, 40, 103, -7, 0 }, { -11, 58, 91, -11, 1 }, { 0, -12, 76, 76, -12 }, @@ -319,7 +318,7 @@ const struct dispc_coef *dispc_ovl_get_scale_coef(int inc, int five_taps) }; inc /= 128; - for (i = 0; i < ARRAY_LEN(coefs); ++i) + for (i = 0; i < ARRAY_SIZE(coefs); ++i) if (inc >= coefs[i].Mmin && inc <= coefs[i].Mmax) return five_taps ? coefs[i].coef_5 : coefs[i].coef_3; return NULL; diff --git a/drivers/video/omap2/dss/display.c b/drivers/video/omap2/dss/display.c index be331dc5a61b..4424c198dbcd 100644 --- a/drivers/video/omap2/dss/display.c +++ b/drivers/video/omap2/dss/display.c @@ -279,16 +279,6 @@ void omapdss_default_get_resolution(struct omap_dss_device *dssdev, } EXPORT_SYMBOL(omapdss_default_get_resolution); -void default_get_overlay_fifo_thresholds(enum omap_plane plane, - u32 fifo_size, u32 burst_size, - u32 *fifo_low, u32 *fifo_high) -{ - unsigned buf_unit = dss_feat_get_buffer_size_unit(); - - *fifo_high = fifo_size - buf_unit; - *fifo_low = fifo_size - burst_size; -} - int omapdss_default_get_recommended_bpp(struct omap_dss_device *dssdev) { switch (dssdev->type) { diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index 52f36ec1c8bb..662d14f8c2c3 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -4524,14 +4524,6 @@ int omapdss_dsi_enable_te(struct omap_dss_device *dssdev, bool enable) } EXPORT_SYMBOL(omapdss_dsi_enable_te); -void dsi_get_overlay_fifo_thresholds(enum omap_plane plane, - u32 fifo_size, u32 burst_size, - u32 *fifo_low, u32 *fifo_high) -{ - *fifo_high = fifo_size - burst_size; - *fifo_low = fifo_size - burst_size * 2; -} - int dsi_init_display(struct omap_dss_device *dssdev) { struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); @@ -4695,11 +4687,9 @@ static int omap_dsihw_probe(struct platform_device *dsidev) struct resource *dsi_mem; struct dsi_data *dsi; - dsi = kzalloc(sizeof(*dsi), GFP_KERNEL); - if (!dsi) { - r = -ENOMEM; - goto err_alloc; - } + dsi = devm_kzalloc(&dsidev->dev, sizeof(*dsi), GFP_KERNEL); + if (!dsi) + return -ENOMEM; dsi->pdev = dsidev; dsi_pdev_map[dsi_module] = dsidev; @@ -4722,12 +4712,6 @@ static int omap_dsihw_probe(struct platform_device *dsidev) mutex_init(&dsi->lock); sema_init(&dsi->bus_lock, 1); - r = dsi_get_clocks(dsidev); - if (r) - goto err_get_clk; - - pm_runtime_enable(&dsidev->dev); - INIT_DELAYED_WORK_DEFERRABLE(&dsi->framedone_timeout_work, dsi_framedone_timeout_work_callback); @@ -4739,27 +4723,27 @@ static int omap_dsihw_probe(struct platform_device *dsidev) dsi_mem = platform_get_resource(dsi->pdev, IORESOURCE_MEM, 0); if (!dsi_mem) { DSSERR("can't get IORESOURCE_MEM DSI\n"); - r = -EINVAL; - goto err_ioremap; + return -EINVAL; } - dsi->base = ioremap(dsi_mem->start, resource_size(dsi_mem)); + + dsi->base = devm_ioremap(&dsidev->dev, dsi_mem->start, + resource_size(dsi_mem)); if (!dsi->base) { DSSERR("can't ioremap DSI\n"); - r = -ENOMEM; - goto err_ioremap; + return -ENOMEM; } + dsi->irq = platform_get_irq(dsi->pdev, 0); if (dsi->irq < 0) { DSSERR("platform_get_irq failed\n"); - r = -ENODEV; - goto err_get_irq; + return -ENODEV; } - r = request_irq(dsi->irq, omap_dsi_irq_handler, IRQF_SHARED, - dev_name(&dsidev->dev), dsi->pdev); + r = devm_request_irq(&dsidev->dev, dsi->irq, omap_dsi_irq_handler, + IRQF_SHARED, dev_name(&dsidev->dev), dsi->pdev); if (r < 0) { DSSERR("request_irq failed\n"); - goto err_get_irq; + return r; } /* DSI VCs initialization */ @@ -4771,9 +4755,15 @@ static int omap_dsihw_probe(struct platform_device *dsidev) dsi_calc_clock_param_ranges(dsidev); + r = dsi_get_clocks(dsidev); + if (r) + return r; + + pm_runtime_enable(&dsidev->dev); + r = dsi_runtime_get(dsidev); if (r) - goto err_get_dsi; + goto err_runtime_get; rev = dsi_read_reg(dsidev, DSI_REVISION); dev_dbg(&dsidev->dev, "OMAP DSI rev %d.%d\n", @@ -4791,15 +4781,9 @@ static int omap_dsihw_probe(struct platform_device *dsidev) return 0; -err_get_dsi: |