summaryrefslogtreecommitdiffstats
path: root/drivers/video/omap2/dss
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/omap2/dss')
-rw-r--r--drivers/video/omap2/dss/apply.c275
-rw-r--r--drivers/video/omap2/dss/core.c135
-rw-r--r--drivers/video/omap2/dss/dispc.c121
-rw-r--r--drivers/video/omap2/dss/dispc_coefs.c9
-rw-r--r--drivers/video/omap2/dss/display.c10
-rw-r--r--drivers/video/omap2/dss/dsi.c65
-rw-r--r--drivers/video/omap2/dss/dss.c17
-rw-r--r--drivers/video/omap2/dss/dss.h10
-rw-r--r--drivers/video/omap2/dss/dss_features.c181
-rw-r--r--drivers/video/omap2/dss/dss_features.h54
-rw-r--r--drivers/video/omap2/dss/hdmi.c278
-rw-r--r--drivers/video/omap2/dss/manager.c12
-rw-r--r--drivers/video/omap2/dss/rfbi.c36
-rw-r--r--drivers/video/omap2/dss/ti_hdmi.h56
-rw-r--r--drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c94
-rw-r--r--drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h47
-rw-r--r--drivers/video/omap2/dss/venc.c32
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: