From e6b0f884520e604408ebda3b60605cabe0a8d162 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Fri, 13 Jan 2012 13:24:04 +0200 Subject: OMAPDSS: FEAT: Add FIFO_MERGE feature Add feature flag for fifo merge. OMAP2 doesn't contain fifo merge, later OMAPs do. dispc_enable_fifomerge() checks for the flag when called, and gives a WARN if fifo merge is being enabled when it is not supported. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dispc.c | 5 +++++ drivers/video/omap2/dss/dss_features.c | 9 +++++---- drivers/video/omap2/dss/dss_features.h | 1 + 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index a5ec7f37c18..d711518f9f1 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c @@ -1054,6 +1054,11 @@ 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); } diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c index afcb59301c3..c2456c5bcd3 100644 --- a/drivers/video/omap2/dss/dss_features.c +++ b/drivers/video/omap2/dss/dss_features.c @@ -370,7 +370,7 @@ static const struct omap_dss_features omap3430_dss_features = { FEAT_LINEBUFFERSPLIT | FEAT_RESIZECONF | FEAT_DSI_PLL_FREQSEL | FEAT_DSI_REVERSE_TXCLKESC | FEAT_VENC_REQUIRES_TV_DAC_CLK | FEAT_CPR | FEAT_PRELOAD | - FEAT_FIR_COEF_V | FEAT_ALPHA_FIXED_ZORDER, + FEAT_FIR_COEF_V | FEAT_ALPHA_FIXED_ZORDER | FEAT_FIFO_MERGE, .num_mgrs = 2, .num_ovls = 3, @@ -394,7 +394,7 @@ static const struct omap_dss_features omap3630_dss_features = { FEAT_ROWREPEATENABLE | FEAT_LINEBUFFERSPLIT | FEAT_RESIZECONF | FEAT_DSI_PLL_PWR_BUG | FEAT_DSI_PLL_FREQSEL | FEAT_CPR | FEAT_PRELOAD | - FEAT_FIR_COEF_V | FEAT_ALPHA_FIXED_ZORDER, + FEAT_FIR_COEF_V | FEAT_ALPHA_FIXED_ZORDER | FEAT_FIFO_MERGE, .num_mgrs = 2, .num_ovls = 3, @@ -419,7 +419,7 @@ static const struct omap_dss_features omap4430_es1_0_dss_features = { FEAT_DSI_DCS_CMD_CONFIG_VC | FEAT_DSI_VC_OCP_WIDTH | FEAT_DSI_GNQ | FEAT_HANDLE_UV_SEPARATE | FEAT_ATTR2 | FEAT_CPR | FEAT_PRELOAD | FEAT_FIR_COEF_V | - FEAT_ALPHA_FREE_ZORDER, + FEAT_ALPHA_FREE_ZORDER | FEAT_FIFO_MERGE, .num_mgrs = 3, .num_ovls = 4, @@ -443,7 +443,8 @@ static const struct omap_dss_features omap4_dss_features = { FEAT_DSI_DCS_CMD_CONFIG_VC | FEAT_DSI_VC_OCP_WIDTH | FEAT_DSI_GNQ | FEAT_HDMI_CTS_SWMODE | FEAT_HANDLE_UV_SEPARATE | FEAT_ATTR2 | FEAT_CPR | - FEAT_PRELOAD | FEAT_FIR_COEF_V | FEAT_ALPHA_FREE_ZORDER, + FEAT_PRELOAD | FEAT_FIR_COEF_V | FEAT_ALPHA_FREE_ZORDER | + FEAT_FIFO_MERGE, .num_mgrs = 3, .num_ovls = 4, diff --git a/drivers/video/omap2/dss/dss_features.h b/drivers/video/omap2/dss/dss_features.h index cd833bbaac3..50caee9192a 100644 --- a/drivers/video/omap2/dss/dss_features.h +++ b/drivers/video/omap2/dss/dss_features.h @@ -58,6 +58,7 @@ enum dss_feat_id { FEAT_FIR_COEF_V = 1 << 25, FEAT_ALPHA_FIXED_ZORDER = 1 << 26, FEAT_ALPHA_FREE_ZORDER = 1 << 27, + FEAT_FIFO_MERGE = 1 << 28, }; /* DSS register field id */ -- cgit v1.2.3 From fb0119742291b6f30cd97026ee137b2d3d1f4de8 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Wed, 16 Nov 2011 15:00:22 +0200 Subject: OMAPDSS: APPLY: add fifo merge support funcs Add mechanism to set/unset the DISPC fifo-merge: Add new fields to dss_data, fifo_merge and fifo_merge_dirty. These are similar to the other info/dirty flags in ovl_priv_data and ovl_mgr_data, but fifo merge is a common attribute to all managers and thus outside the ovl_mgr_data. The fifo-merge field is used in the dss_write_regs_common, which handles writing the register. dss_apply_fifo_merge() can be used to set/unset the fifo merge field in the dss_data. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/apply.c | 43 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c index 052dc874cd3..604737f1187 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; @@ -585,11 +588,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; @@ -659,6 +691,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()) @@ -859,6 +893,15 @@ static void dss_apply_ovl_fifo_thresholds(struct omap_overlay *ovl, op->extra_info_dirty = true; } +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) { struct ovl_priv_data *op = get_ovl_priv(ovl); -- cgit v1.2.3 From 1d71f42b35ed66d90a9a39bc515bb16cfe2d4a46 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Wed, 16 Nov 2011 16:44:08 +0200 Subject: OMAPDSS: APPLY: add fifo-merge support Add fifo-merge support. This is done mainly in four functions: mgr_enable/disable and ovl_enable/disable. These are the functions where overlays are taken into and out of active use. The process to enable and disable fifo-merge is not simple. We need to do it in steps, waiting in between for certain settings to be taken into use, and continuing after that. The reason for this is that fifo-merge is a common thing for all managers/overlays, and its use must be synchronized. As an example, when we disable an overlay, we first set the overlay as disabled, then wait until the overlay is actually disabled in the HW, and only after that we may re-configure the fifos, possibly taking fifo-merge into use. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/apply.c | 164 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 156 insertions(+), 8 deletions(-) diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c index 604737f1187..6f7b213e096 100644 --- a/drivers/video/omap2/dss/apply.c +++ b/drivers/video/omap2/dss/apply.c @@ -902,7 +902,8 @@ static void dss_apply_fifo_merge(bool use_fifo_merge) dss_data.fifo_merge_dirty = true; } -static void dss_ovl_setup_fifo(struct omap_overlay *ovl) +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; @@ -914,7 +915,16 @@ static void dss_ovl_setup_fifo(struct omap_overlay *ovl) dssdev = ovl->manager->device; - size = dispc_ovl_get_fifo_size(ovl->id); + if (use_fifo_merge) { + int i; + + size = 0; + + for (i = 0; i < omap_dss_get_num_overlays(); ++i) + size += dispc_ovl_get_fifo_size(i); + } else { + size = dispc_ovl_get_fifo_size(ovl->id); + } burst_size = dispc_ovl_get_burst_size(ovl->id); @@ -940,7 +950,8 @@ static void dss_ovl_setup_fifo(struct omap_overlay *ovl) 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; @@ -951,10 +962,10 @@ 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(void) +static void dss_setup_fifos(bool use_fifo_merge) { const int num_mgrs = omap_dss_get_num_overlay_managers(); struct omap_overlay_manager *mgr; @@ -962,15 +973,91 @@ static void dss_setup_fifos(void) for (i = 0; i < num_mgrs; ++i) { mgr = omap_dss_get_overlay_manager(i); - dss_mgr_setup_fifos(mgr); + dss_mgr_setup_fifos(mgr, use_fifo_merge); } } +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); + 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) { struct mgr_priv_data *mp = get_mgr_priv(mgr); unsigned long flags; int r; + bool fifo_merge; mutex_lock(&apply_lock); @@ -988,11 +1075,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; @@ -1017,6 +1116,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); @@ -1031,8 +1131,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); } @@ -1284,6 +1392,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); @@ -1309,7 +1418,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); @@ -1319,6 +1443,9 @@ int dss_ovl_enable(struct omap_overlay *ovl) spin_unlock_irqrestore(&data_lock, flags); + /* wait for overlay to be enabled */ + wait_pending_extra_info_updates(); + mutex_unlock(&apply_lock); return 0; @@ -1334,6 +1461,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); @@ -1348,14 +1476,34 @@ 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(); spin_unlock_irqrestore(&data_lock, flags); + /* 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; -- cgit v1.2.3 From 3cb5d966e233167fcbeb7c7d7a66294e13ee9d90 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Fri, 13 Jan 2012 13:14:57 +0200 Subject: OMAPDSS: DISPC: print fifo threshold values in bytes Fifo thresholds are calculated using bytes, but the debug print prints values in buffer units. Change the prints to use bytes to be in line with the calculations, and also to print in the same units on all OMAPs. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dispc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index d711518f9f1..ba907bd6009 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c @@ -1039,13 +1039,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) | -- cgit v1.2.3 From 83fa2f2e940dc21a204cff697d84d37214a91708 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Fri, 13 Jan 2012 13:17:01 +0200 Subject: OMAPDSS: DISPC: move fifo threhold calc to dispc.c Move fifo threshold calculation into dispc.c, as the thresholds are really dispc internal thing. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/apply.c | 34 ++-------------------------------- drivers/video/omap2/dss/dispc.c | 22 ++++++++++++++++++++-- drivers/video/omap2/dss/display.c | 10 ---------- drivers/video/omap2/dss/dsi.c | 8 -------- drivers/video/omap2/dss/dss.h | 10 ++-------- 5 files changed, 24 insertions(+), 60 deletions(-) diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c index 6f7b213e096..b0264a16465 100644 --- a/drivers/video/omap2/dss/apply.c +++ b/drivers/video/omap2/dss/apply.c @@ -907,7 +907,6 @@ static void dss_ovl_setup_fifo(struct omap_overlay *ovl, { 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) @@ -915,37 +914,8 @@ static void dss_ovl_setup_fifo(struct omap_overlay *ovl, dssdev = ovl->manager->device; - if (use_fifo_merge) { - int i; - - size = 0; - - for (i = 0; i < omap_dss_get_num_overlays(); ++i) - size += dispc_ovl_get_fifo_size(i); - } else { - 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); } diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index ba907bd6009..a75972250a2 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c @@ -909,7 +909,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 +1018,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]; } @@ -1063,6 +1063,24 @@ void dispc_enable_fifomerge(bool enable) 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 fifo_size, burst_size; + + burst_size = dispc_ovl_get_burst_size(plane); + fifo_size = dispc_ovl_get_fifo_size(plane); + + *fifo_low = fifo_size - burst_size; + *fifo_high = fifo_size - buf_unit; +} + static void dispc_ovl_set_fir(enum omap_plane plane, int hinc, int vinc, enum omap_color_component color_comp) diff --git a/drivers/video/omap2/dss/display.c b/drivers/video/omap2/dss/display.c index be331dc5a61..4424c198dbc 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 d4d676c82c1..a4b9d58e8b4 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); diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h index 32ff69fb333..d4b3dff2ead 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h @@ -202,9 +202,6 @@ void dss_uninit_device(struct platform_device *pdev, struct omap_dss_device *dssdev); bool dss_use_replication(struct omap_dss_device *dssdev, enum omap_color_mode mode); -void default_get_overlay_fifo_thresholds(enum omap_plane plane, - u32 fifo_size, u32 burst_size, - u32 *fifo_low, u32 *fifo_high); /* manager */ int dss_init_overlay_managers(struct platform_device *pdev); @@ -313,9 +310,6 @@ int dsi_pll_calc_clock_div_pck(struct platform_device *dsidev, bool is_tft, int dsi_pll_init(struct platform_device *dsidev, bool enable_hsclk, bool enable_hsdiv); void dsi_pll_uninit(struct platform_device *dsidev, bool disconnect_lanes); -void dsi_get_overlay_fifo_thresholds(enum omap_plane plane, - u32 fifo_size, u32 burst_size, - u32 *fifo_low, u32 *fifo_high); void dsi_wait_pll_hsdiv_dispc_active(struct platform_device *dsidev); void dsi_wait_pll_hsdiv_dsi_active(struct platform_device *dsidev); struct platform_device *dsi_get_dsidev_from_id(int module); @@ -429,8 +423,8 @@ int dispc_calc_clock_rates(unsigned long dispc_fclk_rate, void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high); -u32 dispc_ovl_get_fifo_size(enum omap_plane plane); -u32 dispc_ovl_get_burst_size(enum omap_plane plane); +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); int dispc_ovl_enable(enum omap_plane plane, bool enable); -- cgit v1.2.3 From e0e405b9252e5e8926786d796e0d4293bc90cd56 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Fri, 13 Jan 2012 13:18:11 +0200 Subject: OMAPDSS: DISPC: Add naive threshold calc for fifomerge Take fifo merge into use by implementing a rather naive fifo merge threshold calculation: keep the low threshold always the same, but increase the high threshold when fifo merge is used. This should greatly increase the time between pixel data fetches from SDRAM, as the usable fifo size is much larger. However, it probably won't help for fifo underflows, as the low threshols is kept the same. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dispc.c | 28 ++++++++++++++++++++++++---- drivers/video/omap2/dss/dss_features.c | 6 ++++-- drivers/video/omap2/dss/dss_features.h | 2 ++ 3 files changed, 30 insertions(+), 6 deletions(-) diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index a75972250a2..374c987038a 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c @@ -1072,13 +1072,33 @@ void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane, */ unsigned buf_unit = dss_feat_get_buffer_size_unit(); - unsigned fifo_size, burst_size; + unsigned ovl_fifo_size, total_fifo_size, burst_size; + int i; burst_size = dispc_ovl_get_burst_size(plane); - fifo_size = dispc_ovl_get_fifo_size(plane); + ovl_fifo_size = dispc_ovl_get_fifo_size(plane); - *fifo_low = fifo_size - burst_size; - *fifo_high = fifo_size - buf_unit; + 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, diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c index c2456c5bcd3..419419ad049 100644 --- a/drivers/video/omap2/dss/dss_features.c +++ b/drivers/video/omap2/dss/dss_features.c @@ -370,7 +370,8 @@ static const struct omap_dss_features omap3430_dss_features = { FEAT_LINEBUFFERSPLIT | FEAT_RESIZECONF | FEAT_DSI_PLL_FREQSEL | FEAT_DSI_REVERSE_TXCLKESC | FEAT_VENC_REQUIRES_TV_DAC_CLK | FEAT_CPR | FEAT_PRELOAD | - FEAT_FIR_COEF_V | FEAT_ALPHA_FIXED_ZORDER | FEAT_FIFO_MERGE, + FEAT_FIR_COEF_V | FEAT_ALPHA_FIXED_ZORDER | FEAT_FIFO_MERGE | + FEAT_OMAP3_DSI_FIFO_BUG, .num_mgrs = 2, .num_ovls = 3, @@ -394,7 +395,8 @@ static const struct omap_dss_features omap3630_dss_features = { FEAT_ROWREPEATENABLE | FEAT_LINEBUFFERSPLIT | FEAT_RESIZECONF | FEAT_DSI_PLL_PWR_BUG | FEAT_DSI_PLL_FREQSEL | FEAT_CPR | FEAT_PRELOAD | - FEAT_FIR_COEF_V | FEAT_ALPHA_FIXED_ZORDER | FEAT_FIFO_MERGE, + FEAT_FIR_COEF_V | FEAT_ALPHA_FIXED_ZORDER | FEAT_FIFO_MERGE | + FEAT_OMAP3_DSI_FIFO_BUG, .num_mgrs = 2, .num_ovls = 3, diff --git a/drivers/video/omap2/dss/dss_features.h b/drivers/video/omap2/dss/dss_features.h index 50caee9192a..5f9b8215677 100644 --- a/drivers/video/omap2/dss/dss_features.h +++ b/drivers/video/omap2/dss/dss_features.h @@ -59,6 +59,8 @@ enum dss_feat_id { FEAT_ALPHA_FIXED_ZORDER = 1 << 26, FEAT_ALPHA_FREE_ZORDER = 1 << 27, FEAT_FIFO_MERGE = 1 << 28, + /* An unknown HW bug causing the normal FIFO thresholds not to work */ + FEAT_OMAP3_DSI_FIFO_BUG = 1 << 29, }; /* DSS register field id */ -- cgit v1.2.3 From aeec1a6ccbe28c2cea5f19803394f99859566552 Mon Sep 17 00:00:00 2001 From: Mythri P K Date: Fri, 6 Jan 2012 17:52:07 +0530 Subject: OMAPDSS: HDMI: remove duplicate video interface code video interface structure is a duplicate structure with parameters which are already present in ip_data config structure, Thus removing the structure and modifying corresponding code. Signed-off-by: Mythri P K Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c | 31 ++++++++----------------------- drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h | 7 ------- 2 files changed, 8 insertions(+), 30 deletions(-) diff --git a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c index 9af81f18f16..bafbd9fad4b 100644 --- a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c +++ b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c @@ -629,8 +629,7 @@ static void hdmi_core_av_packet_config(struct hdmi_ip_data *ip_data, } static void hdmi_wp_init(struct omap_video_timings *timings, - struct hdmi_video_format *video_fmt, - struct hdmi_video_interface *video_int) + struct hdmi_video_format *video_fmt) { pr_debug("Enter hdmi_wp_init\n"); @@ -645,12 +644,6 @@ static void hdmi_wp_init(struct omap_video_timings *timings, video_fmt->y_res = 0; video_fmt->x_res = 0; - video_int->vsp = 0; - video_int->hsp = 0; - - video_int->interlacing = 0; - video_int->tm = 0; /* HDMI_TIMING_SLAVE */ - } void ti_hdmi_4xxx_wp_video_start(struct hdmi_ip_data *ip_data, bool start) @@ -687,17 +680,16 @@ static void hdmi_wp_video_config_format(struct hdmi_ip_data *ip_data, hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_SIZE, l); } -static void hdmi_wp_video_config_interface(struct hdmi_ip_data *ip_data, - struct hdmi_video_interface *video_int) +static void hdmi_wp_video_config_interface(struct hdmi_ip_data *ip_data) { u32 r; pr_debug("Enter hdmi_wp_video_config_interface\n"); r = hdmi_read_reg(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_CFG); - r = FLD_MOD(r, video_int->vsp, 7, 7); - r = FLD_MOD(r, video_int->hsp, 6, 6); - r = FLD_MOD(r, video_int->interlacing, 3, 3); - r = FLD_MOD(r, video_int->tm, 1, 0); + r = FLD_MOD(r, ip_data->cfg.timings.vsync_pol, 7, 7); + r = FLD_MOD(r, ip_data->cfg.timings.hsync_pol, 6, 6); + r = FLD_MOD(r, ip_data->cfg.interlace, 3, 3); + r = FLD_MOD(r, 1, 1, 0); /* HDMI_TIMING_MASTER_24BIT */ hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_CFG, r); } @@ -725,15 +717,13 @@ void ti_hdmi_4xxx_basic_configure(struct hdmi_ip_data *ip_data) /* HDMI */ struct omap_video_timings video_timing; struct hdmi_video_format video_format; - struct hdmi_video_interface video_interface; /* HDMI core */ struct hdmi_core_infoframe_avi avi_cfg; struct hdmi_core_video_config v_core_cfg; struct hdmi_core_packet_enable_repeat repeat_cfg; struct hdmi_config *cfg = &ip_data->cfg; - hdmi_wp_init(&video_timing, &video_format, - &video_interface); + hdmi_wp_init(&video_timing, &video_format); hdmi_core_init(&v_core_cfg, &avi_cfg, @@ -748,12 +738,7 @@ void ti_hdmi_4xxx_basic_configure(struct hdmi_ip_data *ip_data) hdmi_wp_video_config_format(ip_data, &video_format); - video_interface.vsp = cfg->timings.vsync_pol; - video_interface.hsp = cfg->timings.hsync_pol; - video_interface.interlacing = cfg->interlace; - video_interface.tm = 1 ; /* HDMI_TIMING_MASTER_24BIT */ - - hdmi_wp_video_config_interface(ip_data, &video_interface); + hdmi_wp_video_config_interface(ip_data); /* * configure core video part diff --git a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h index a442998980f..004b4182bdd 100644 --- a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h +++ b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h @@ -517,13 +517,6 @@ struct hdmi_video_format { u32 x_res; /* pixel per line */ }; -struct hdmi_video_interface { - int vsp; /* Vsync polarity */ - int hsp; /* Hsync polarity */ - int interlacing; - int tm; /* Timing mode */ -}; - struct hdmi_audio_format { enum hdmi_stereo_channels stereo_channels; u8 active_chnnls_msk; -- cgit v1.2.3 From a05ce78f308fa22b6254995c25ff79e82a27de75 Mon Sep 17 00:00:00 2001 From: Mythri P K Date: Fri, 6 Jan 2012 17:52:08 +0530 Subject: OMAPDSS: HDMI: update static timing table Add the vsync polarity, hsync polarity, interlace to hdmi_video_timings. Remove the now duplicate structure hdmi_timings. update the static table structure in HDMI with CEA/VESA code and mode. Signed-off-by: Mythri P K Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/hdmi.c | 96 +++++++++++++++---------------- drivers/video/omap2/dss/ti_hdmi.h | 14 ++--- drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c | 20 +++---- 3 files changed, 63 insertions(+), 67 deletions(-) diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c index b4c270edb91..266af264eb9 100644 --- a/drivers/video/omap2/dss/hdmi.c +++ b/drivers/video/omap2/dss/hdmi.c @@ -88,42 +88,42 @@ static struct { * map it to corresponding CEA or VESA index. */ -static const struct hdmi_timings cea_vesa_timings[OMAP_HDMI_TIMINGS_NB] = { - { {640, 480, 25200, 96, 16, 48, 2, 10, 33} , 0 , 0}, - { {1280, 720, 74250, 40, 440, 220, 5, 5, 20}, 1, 1}, - { {1280, 720, 74250, 40, 110, 220, 5, 5, 20}, 1, 1}, - { {720, 480, 27027, 62, 16, 60, 6, 9, 30}, 0, 0}, - { {2880, 576, 108000, 256, 48, 272, 5, 5, 39}, 0, 0}, - { {1440, 240, 27027, 124, 38, 114, 3, 4, 15}, 0, 0}, - { {1440, 288, 27000, 126, 24, 138, 3, 2, 19}, 0, 0}, - { {1920, 540, 74250, 44, 528, 148, 5, 2, 15}, 1, 1}, - { {1920, 540, 74250, 44, 88, 148, 5, 2, 15}, 1, 1}, - { {1920, 1080, 148500, 44, 88, 148, 5, 4, 36}, 1, 1}, - { {720, 576, 27000, 64, 12, 68, 5, 5, 39}, 0, 0}, - { {1440, 576, 54000, 128, 24, 136, 5, 5, 39}, 0, 0}, - { {1920, 1080, 148500, 44, 528, 148, 5, 4, 36}, 1, 1}, - { {2880, 480, 108108, 248, 64, 240, 6, 9, 30}, 0, 0}, - { {1920, 1080, 74250, 44, 638, 148, 5, 4, 36}, 1, 1}, - /* VESA From Here */ - { {640, 480, 25175, 96, 16, 48, 2 , 11, 31}, 0, 0}, - { {800, 600, 40000, 128, 40, 88, 4 , 1, 23}, 1, 1}, - { {848, 480, 33750, 112, 16, 112, 8 , 6, 23}, 1, 1}, - { {1280, 768, 79500, 128, 64, 192, 7 , 3, 20}, 1, 0}, - { {1280, 800, 83500, 128, 72, 200, 6 , 3, 22}, 1, 0}, - { {1360, 768, 85500, 112, 64, 256, 6 , 3, 18}, 1, 1}, - { {1280, 960, 108000, 112, 96, 312, 3 , 1, 36}, 1, 1}, - { {1280, 1024, 108000, 112, 48, 248, 3 , 1, 38}, 1, 1}, - { {1024, 768, 65000, 136, 24, 160, 6, 3, 29}, 0, 0}, - { {1400, 1050, 121750, 144, 88, 232, 4, 3, 32}, 1, 0}, - { {1440, 900, 106500, 152, 80, 232, 6, 3, 25}, 1, 0}, - { {1680, 1050, 146250, 176 , 104, 280, 6, 3, 30}, 1, 0}, - { {1366, 768, 85500, 143, 70, 213, 3, 3, 24}, 1, 1}, - { {1920, 1080, 148500, 44, 148, 80, 5, 4, 36}, 1, 1}, - { {1280, 768, 68250, 32, 48, 80, 7, 3, 12}, 0, 1}, - { {1400, 1050, 101000, 32, 48, 80, 4, 3, 23}, 0, 1}, - { {1680, 1050, 119000, 32, 48, 80, 6, 3, 21}, 0, 1}, - { {1280, 800, 79500, 32, 48, 80, 6, 3, 14}, 0, 1}, - { {1280, 720, 74250, 40, 110, 220, 5, 5, 20}, 1, 1} +static const struct hdmi_config cea_vesa_timings[OMAP_HDMI_TIMINGS_NB] = { +{ {640, 480, 25200, 96, 16, 48, 2, 10, 33, 0, 0, 0}, {1, HDMI_HDMI} }, +{ {720, 480, 27027, 62, 16, 60, 6, 9, 30, 0, 0, 0}, {2, HDMI_HDMI} }, +{ {1280, 720, 74250, 40, 110, 220, 5, 5, 20, 1, 1, 0}, {4, HDMI_HDMI} }, +{ {1920, 540, 74250, 44, 88, 148, 5, 2, 15, 1, 1, 1}, {5, HDMI_HDMI} }, +{ {1440, 240, 27027, 124, 38, 114, 3, 4, 15, 0, 0, 1}, {6, HDMI_HDMI} }, +{ {1920, 1080, 148500, 44, 88, 148, 5, 4, 36, 1, 1, 0}, {16, HDMI_HDMI} }, +{ {720, 576, 27000, 64, 12, 68, 5, 5, 39, 0, 0, 0}, {17, HDMI_HDMI} }, +{ {1280, 720, 74250, 40, 440, 220, 5, 5, 20, 1, 1, 0}, {19, HDMI_HDMI} }, +{ {1920, 540, 74250, 44, 528, 148, 5, 2, 15, 1, 1, 1}, {20, HDMI_HDMI} }, +{ {1440, 288, 27000, 126, 24, 138, 3, 2, 19, 0, 0, 1}, {21, HDMI_HDMI} }, +{ {1440, 576, 54000, 128, 24, 136, 5, 5, 39, 0, 0, 0}, {29, HDMI_HDMI} }, +{ {1920, 1080, 148500, 44, 528, 148, 5, 4, 36, 1, 1, 0}, {31, HDMI_HDMI} }, +{ {1920, 1080, 74250, 44, 638, 148, 5, 4, 36, 1, 1, 0}, {32, HDMI_HDMI} }, +{ {2880, 480, 108108, 248, 64, 240, 6, 9, 30, 0, 0, 0}, {35, HDMI_HDMI} }, +{ {2880, 576, 108000, 256, 48, 272, 5, 5, 39, 0, 0, 0}, {37, HDMI_HDMI} }, +/* VESA From Here */ +{ {640, 480, 25175, 96, 16, 48, 2 , 11, 31, 0, 0, 0}, {4, HDMI_DVI} }, +{ {800, 600, 40000, 128, 40, 88, 4 , 1, 23, 1, 1, 0}, {9, HDMI_DVI} }, +{ {848, 480, 33750, 112, 16, 112, 8 , 6, 23, 1, 1, 0}, {0xE, HDMI_DVI} }, +{ {1280, 768, 79500, 128, 64, 192, 7 , 3, 20, 1, 0, 0}, {0x17, HDMI_DVI} }, +{ {1280, 800, 83500, 128, 72, 200, 6 , 3, 22, 1, 0, 0}, {0x1C, HDMI_DVI} }, +{ {1360, 768, 85500, 112, 64, 256, 6 , 3, 18, 1, 1, 0}, {0x27, HDMI_DVI} }, +{ {1280, 960, 108000, 112, 96, 312, 3 , 1, 36, 1, 1, 0}, {0x20, HDMI_DVI} }, +{ {1280, 1024, 108000, 112, 48, 248, 3 , 1, 38, 1, 1, 0}, {0x23, HDMI_DVI} }, +{ {1024, 768, 65000, 136, 24, 160, 6, 3, 29, 0, 0, 0}, {0x10, HDMI_DVI} }, +{ {1400, 1050, 121750, 144, 88, 232, 4, 3, 32, 1, 0, 0}, {0x2A, HDMI_DVI} }, +{ {1440, 900, 106500, 152, 80, 232, 6, 3, 25, 1, 0, 0}, {0x2F, HDMI_DVI} }, +{ {1680, 1050, 146250, 176 , 104, 280, 6, 3, 30, 1, 0, 0}, {0x3A, HDMI_DVI} }, +{ {1366, 768, 85500, 143, 70, 213, 3, 3, 24, 1, 1, 0}, {0x51, HDMI_DVI} }, +{ {1920, 1080, 148500, 44, 148, 80, 5, 4, 36, 1, 1, 0}, {0x52, HDMI_DVI} }, +{ {1280, 768, 68250, 32, 48, 80, 7, 3, 12, 0, 1, 0}, {0x16, HDMI_DVI} }, +{ {1400, 1050, 101000, 32, 48, 80, 4, 3, 23, 0, 1, 0}, {0x29, HDMI_DVI} }, +{ {1680, 1050, 119000, 32, 48, 80, 6, 3, 21, 0, 1, 0}, {0x39, HDMI_DVI} }, +{ {1280, 800, 79500, 32, 48, 80, 6, 3, 14, 0, 1, 0}, {0x1B, HDMI_DVI} }, +{ {1280, 720, 74250, 40, 110, 220, 5, 5, 20, 1, 1, 0}, {0x55, HDMI_DVI} } }; /* @@ -253,23 +253,23 @@ static struct hdmi_cm hdmi_get_code(struct omap_video_timings *timing) static void update_hdmi_timings(struct hdmi_config *cfg, struct omap_video_timings *timings, int code) { - cfg->timings.timings.x_res = timings->x_res; - cfg->timings.timings.y_res = timings->y_res; - cfg->timings.timings.hbp = timings->hbp; - cfg->timings.timings.hfp = timings->hfp; - cfg->timings.timings.hsw = timings->hsw; - cfg->timings.timings.vbp = timings->vbp; - cfg->timings.timings.vfp = timings->vfp; - cfg->timings.timings.vsw = timings->vsw; - cfg->timings.timings.pixel_clock = timings->pixel_clock; - cfg->timings.vsync_pol = cea_vesa_timings[code].vsync_pol; - cfg->timings.hsync_pol = cea_vesa_timings[code].hsync_pol; + cfg->timings.x_res = timings->x_res; + cfg->timings.y_res = timings->y_res; + cfg->timings.hbp = timings->hbp; + cfg->timings.hfp = timings->hfp; + cfg->timings.hsw = timings->hsw; + cfg->timings.vbp = timings->vbp; + cfg->timings.vfp = timings->vfp; + cfg->timings.vsw = timings->vsw; + cfg->timings.pixel_clock = timings->pixel_clock; + cfg->timings.vsync_pol = cea_vesa_timings[code].timings.vsync_pol; + cfg->timings.hsync_pol = cea_vesa_timings[code].timings.hsync_pol; } unsigned long hdmi_get_pixel_clock(void) { /* HDMI Pixel Clock in Mhz */ - return hdmi.ip_data.cfg.timings.timings.pixel_clock * 1000; + return hdmi.ip_data.cfg.timings.pixel_clock * 1000; } static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy, diff --git a/drivers/video/omap2/dss/ti_hdmi.h b/drivers/video/omap2/dss/ti_hdmi.h index 7503f7f619a..26ec6d1162f 100644 --- a/drivers/video/omap2/dss/ti_hdmi.h +++ b/drivers/video/omap2/dss/ti_hdmi.h @@ -42,6 +42,7 @@ enum hdmi_clk_refsel { HDMI_REFSEL_SYSCLK = 3 }; +/* HDMI timing structure */ struct hdmi_video_timings { u16 x_res; u16 y_res; @@ -53,13 +54,9 @@ struct hdmi_video_timings { u16 vsw; u16 vfp; u16 vbp; -}; - -/* HDMI timing structure */ -struct hdmi_timings { - struct hdmi_video_timings timings; - int vsync_pol; - int hsync_pol; + bool vsync_pol; + bool hsync_pol; + bool interlace; }; struct hdmi_cm { @@ -68,8 +65,7 @@ struct hdmi_cm { }; struct hdmi_config { - struct hdmi_timings timings; - u16 interlace; + struct hdmi_video_timings timings; struct hdmi_cm cm; }; diff --git a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c index bafbd9fad4b..a229ae71be7 100644 --- a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c +++ b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c @@ -656,15 +656,15 @@ static void hdmi_wp_video_init_format(struct hdmi_video_format *video_fmt, { pr_debug("Enter hdmi_wp_video_init_format\n"); - video_fmt->y_res = param->timings.timings.y_res; - video_fmt->x_res = param->timings.timings.x_res; - - timings->hbp = param->timings.timings.hbp; - timings->hfp = param->timings.timings.hfp; - timings->hsw = param->timings.timings.hsw; - timings->vbp = param->timings.timings.vbp; - timings->vfp = param->timings.timings.vfp; - timings->vsw = param->timings.timings.vsw; + video_fmt->y_res = param->timings.y_res; + video_fmt->x_res = param->timings.x_res; + + timings->hbp = param->timings.hbp; + timings->hfp = param->timings.hfp; + timings->hsw = param->timings.hsw; + timings->vbp = param->timings.vbp; + timings->vfp = param->timings.vfp; + timings->vsw = param->timings.vsw; } static void hdmi_wp_video_config_format(struct hdmi_ip_data *ip_data, @@ -688,7 +688,7 @@ static void hdmi_wp_video_config_interface(struct hdmi_ip_data *ip_data) r = hdmi_read_reg(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_CFG); r = FLD_MOD(r, ip_data->cfg.timings.vsync_pol, 7, 7); r = FLD_MOD(r, ip_data->cfg.timings.hsync_pol, 6, 6); - r = FLD_MOD(r, ip_data->cfg.interlace, 3, 3); + r = FLD_MOD(r, ip_data->cfg.timings.interlace, 3, 3); r = FLD_MOD(r, 1, 1, 0); /* HDMI_TIMING_MASTER_24BIT */ hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_CFG, r); } -- cgit v1.2.3 From 46095b2d96bac92c2cc5ca557ec7de73e13311ab Mon Sep 17 00:00:00 2001 From: Mythri P K Date: Fri, 6 Jan 2012 17:52:09 +0530 Subject: OMAPDSS: HDMI: change the timing match logic Change the timing match logic, Instead of the statically mapped method to get the corresponding timings for a given code and mode, move to a simpler array indexed method. It will help to scale up to add more timings when needed. Signed-off-by: Mythri P K Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/hdmi.c | 176 ++++++++++++++++++----------------------- 1 file changed, 76 insertions(+), 100 deletions(-) diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c index 266af264eb9..6f027d30d5d 100644 --- a/drivers/video/omap2/dss/hdmi.c +++ b/drivers/video/omap2/dss/hdmi.c @@ -58,8 +58,6 @@ #define EDID_SIZE_BLOCK0_TIMING_DESCRIPTOR 4 #define EDID_SIZE_BLOCK1_TIMING_DESCRIPTOR 4 -#define OMAP_HDMI_TIMINGS_NB 34 - #define HDMI_DEFAULT_REGN 16 #define HDMI_DEFAULT_REGM2 1 @@ -88,7 +86,7 @@ static struct { * map it to corresponding CEA or VESA index. */ -static const struct hdmi_config cea_vesa_timings[OMAP_HDMI_TIMINGS_NB] = { +static const struct hdmi_config cea_timings[] = { { {640, 480, 25200, 96, 16, 48, 2, 10, 33, 0, 0, 0}, {1, HDMI_HDMI} }, { {720, 480, 27027, 62, 16, 60, 6, 9, 30, 0, 0, 0}, {2, HDMI_HDMI} }, { {1280, 720, 74250, 40, 110, 220, 5, 5, 20, 1, 1, 0}, {4, HDMI_HDMI} }, @@ -104,6 +102,8 @@ static const struct hdmi_config cea_vesa_timings[OMAP_HDMI_TIMINGS_NB] = { { {1920, 1080, 74250, 44, 638, 148, 5, 4, 36, 1, 1, 0}, {32, HDMI_HDMI} }, { {2880, 480, 108108, 248, 64, 240, 6, 9, 30, 0, 0, 0}, {35, HDMI_HDMI} }, { {2880, 576, 108000, 256, 48, 272, 5, 5, 39, 0, 0, 0}, {37, HDMI_HDMI} }, +}; +static const struct hdmi_config vesa_timings[] = { /* VESA From Here */ { {640, 480, 25175, 96, 16, 48, 2 , 11, 31, 0, 0, 0}, {4, HDMI_DVI} }, { {800, 600, 40000, 128, 40, 88, 4 , 1, 23, 1, 1, 0}, {9, HDMI_DVI} }, @@ -126,39 +126,6 @@ static const struct hdmi_config cea_vesa_timings[OMAP_HDMI_TIMINGS_NB] = { { {1280, 720, 74250, 40, 110, 220, 5, 5, 20, 1, 1, 0}, {0x55, HDMI_DVI} } }; -/* - * This is a static mapping array which maps the timing values - * with corresponding CEA / VESA code - */ -static const int code_index[OMAP_HDMI_TIMINGS_NB] = { - 1, 19, 4, 2, 37, 6, 21, 20, 5, 16, 17, 29, 31, 35, 32, - /* <--15 CEA 17--> vesa*/ - 4, 9, 0xE, 0x17, 0x1C, 0x27, 0x20, 0x23, 0x10, 0x2A, - 0X2F, 0x3A, 0X51, 0X52, 0x16, 0x29, 0x39, 0x1B -}; - -/* - * This is reverse static mapping which maps the CEA / VESA code - * to the corresponding timing values - */ -static const int code_cea[39] = { - -1, 0, 3, 3, 2, 8, 5, 5, -1, -1, - -1, -1, -1, -1, -1, -1, 9, 10, 10, 1, - 7, 6, 6, -1, -1, -1, -1, -1, -1, 11, - 11, 12, 14, -1, -1, 13, 13, 4, 4 -}; - -static const int code_vesa[85] = { - -1, -1, -1, -1, 15, -1, -1, -1, -1, 16, - -1, -1, -1, -1, 17, -1, 23, -1, -1, -1, - -1, -1, 29, 18, -1, -1, -1, 32, 19, -1, - -1, -1, 21, -1, -1, 22, -1, -1, -1, 20, - -1, 30, 24, -1, -1, -1, -1, 25, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 31, 26, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 27, 28, -1, 33}; - static int hdmi_runtime_get(void) { int r; @@ -188,82 +155,83 @@ int hdmi_init_display(struct omap_dss_device *dssdev) return 0; } -static int get_timings_index(void) +static const struct hdmi_config *hdmi_find_timing( + const struct hdmi_config *timings_arr, + int len) { - int code; + int i; - if (hdmi.mode == 0) - code = code_vesa[hdmi.code]; - else - code = code_cea[hdmi.code]; + for (i = 0; i < len; i++) { + if (timings_arr[i].cm.code == hdmi.code) + return &timings_arr[i]; + } + return NULL; +} - if (code == -1) { - /* HDMI code 4 corresponds to 640 * 480 VGA */ - hdmi.code = 4; - /* DVI mode 1 corresponds to HDMI 0 to DVI */ - hdmi.mode = HDMI_DVI; +static const struct hdmi_config *hdmi_get_timings(void) +{ + const struct hdmi_config *arr; + int len; + + if (hdmi.mode == HDMI_DVI) { + arr = vesa_timings; + len = ARRAY_SIZE(vesa_timings); + } else { + arr = cea_timings; + len = ARRAY_SIZE(cea_timings); + } + + return hdmi_find_timing(arr, len); +} + +static bool hdmi_timings_compare(struct omap_video_timings *timing1, + const struct hdmi_video_timings *timing2) +{ + int timing1_vsync, timing1_hsync, timing2_vsync, timing2_hsync; + + if ((timing2->pixel_clock == timing1->pixel_clock) && + (timing2->x_res == timing1->x_res) && + (timing2->y_res == timing1->y_res)) { + + timing2_hsync = timing2->hfp + timing2->hsw + timing2->hbp; + timing1_hsync = timing1->hfp + timing1->hsw + timing1->hbp; + timing2_vsync = timing2->vfp + timing2->vsw + timing2->vbp; + timing1_vsync = timing2->vfp + timing2->vsw + timing2->vbp; - code = code_vesa[hdmi.code]; + DSSDBG("timing1_hsync = %d timing1_vsync = %d"\ + "timing2_hsync = %d timing2_vsync = %d\n", + timing1_hsync, timing1_vsync, + timing2_hsync, timing2_vsync); + + if ((timing1_hsync == timing2_hsync) && + (timing1_vsync == timing2_vsync)) { + return true; + } } - return code; + return false; } static struct hdmi_cm hdmi_get_code(struct omap_video_timings *timing) { - int i = 0, code = -1, temp_vsync = 0, temp_hsync = 0; - int timing_vsync = 0, timing_hsync = 0; - struct hdmi_video_timings temp; + int i; struct hdmi_cm cm = {-1}; DSSDBG("hdmi_get_code\n"); - for (i = 0; i < OMAP_HDMI_TIMINGS_NB; i++) { - temp = cea_vesa_timings[i].timings; - if ((temp.pixel_clock == timing->pixel_clock) && - (temp.x_res == timing->x_res) && - (temp.y_res == timing->y_res)) { - - temp_hsync = temp.hfp + temp.hsw + temp.hbp; - timing_hsync = timing->hfp + timing->hsw + timing->hbp; - temp_vsync = temp.vfp + temp.vsw + temp.vbp; - timing_vsync = timing->vfp + timing->vsw + timing->vbp; - - DSSDBG("temp_hsync = %d , temp_vsync = %d" - "timing_hsync = %d, timing_vsync = %d\n", - temp_hsync, temp_hsync, - timing_hsync, timing_vsync); - - if ((temp_hsync == timing_hsync) && - (temp_vsync == timing_vsync)) { - code = i; - cm.code = code_index[i]; - if (code < 14) - cm.mode = HDMI_HDMI; - else - cm.mode = HDMI_DVI; - DSSDBG("Hdmi_code = %d mode = %d\n", - cm.code, cm.mode); - break; - } + for (i = 0; i < ARRAY_SIZE(cea_timings); i++) { + if (hdmi_timings_compare(timing, &cea_timings[i].timings)) { + cm = cea_timings[i].cm; + goto end; + } + } + for (i = 0; i < ARRAY_SIZE(vesa_timings); i++) { + if (hdmi_timings_compare(timing, &vesa_timings[i].timings)) { + cm = vesa_timings[i].cm; + goto end; } } - return cm; -} +end: return cm; -static void update_hdmi_timings(struct hdmi_config *cfg, - struct omap_video_timings *timings, int code) -{ - cfg->timings.x_res = timings->x_res; - cfg->timings.y_res = timings->y_res; - cfg->timings.hbp = timings->hbp; - cfg->timings.hfp = timings->hfp; - cfg->timings.hsw = timings->hsw; - cfg->timings.vbp = timings->vbp; - cfg->timings.vfp = timings->vfp; - cfg->timings.vsw = timings->vsw; - cfg->timings.pixel_clock = timings->pixel_clock; - cfg->timings.vsync_pol = cea_vesa_timings[code].timings.vsync_pol; - cfg->timings.hsync_pol = cea_vesa_timings[code].timings.hsync_pol; } unsigned long hdmi_get_pixel_clock(void) @@ -325,7 +293,8 @@ static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy, static int hdmi_power_on(struct omap_dss_device *dssdev) { - int r, code = 0; + int r; + const struct hdmi_config *timing; struct omap_video_timings *p; unsigned long phy; @@ -341,9 +310,16 @@ static int hdmi_power_on(struct omap_dss_device *dssdev) dssdev->panel.timings.x_res, dssdev->panel.timings.y_res); - code = get_timings_index(); - update_hdmi_timings(&hdmi.ip_data.cfg, p, code); - + timing = hdmi_get_timings(); + if (timing == NULL) { + /* HDMI code 4 corresponds to 640 * 480 VGA */ + hdmi.code = 4; + /* DVI mode 1 corresponds to HDMI 0 to DVI */ + hdmi.mode = HDMI_DVI; + hdmi.ip_data.cfg = vesa_timings[0]; + } else { + hdmi.ip_data.cfg = *timing; + } phy = p->pixel_clock; hdmi_compute_pll(dssdev, phy, &hdmi.ip_data.pll_data); -- cgit v1.2.3 From 9e4ed603e6ec71da9e0a7484a694f98dff869068 Mon Sep 17 00:00:00 2001 From: Mythri P K Date: Fri, 6 Jan 2012 17:52:10 +0530 Subject: OMAPDSS: HDMI: remove duplicate code and mode parameter code and mode parameters are already a part of the ip_data structure so no need to keep the same parameters again in hdmi global structure. Signed-off-by: Mythri P K Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/hdmi.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c index 6f027d30d5d..92a66798f67 100644 --- a/drivers/video/omap2/dss/hdmi.c +++ b/drivers/video/omap2/dss/hdmi.c @@ -66,8 +66,6 @@ static struct { struct omap_display_platform_data *pdata; struct platform_device *pdev; struct hdmi_ip_data ip_data; - int code; - int mode; struct clk *sys_clk; } hdmi; @@ -162,7 +160,7 @@ static const struct hdmi_config *hdmi_find_timing( int i; for (i = 0; i < len; i++) { - if (timings_arr[i].cm.code == hdmi.code) + if (timings_arr[i].cm.code == hdmi.ip_data.cfg.cm.code) return &timings_arr[i]; } return NULL; @@ -173,7 +171,7 @@ static const struct hdmi_config *hdmi_get_timings(void) const struct hdmi_config *arr; int len; - if (hdmi.mode == HDMI_DVI) { + if (hdmi.ip_data.cfg.cm.mode == HDMI_DVI) { arr = vesa_timings; len = ARRAY_SIZE(vesa_timings); } else { @@ -313,9 +311,9 @@ static int hdmi_power_on(struct omap_dss_device *dssdev) timing = hdmi_get_timings(); if (timing == NULL) { /* HDMI code 4 corresponds to 640 * 480 VGA */ - hdmi.code = 4; + hdmi.ip_data.cfg.cm.code = 4; /* DVI mode 1 corresponds to HDMI 0 to DVI */ - hdmi.mode = HDMI_DVI; + hdmi.ip_data.cfg.cm.mode = HDMI_DVI; hdmi.ip_data.cfg = vesa_timings[0]; } else { hdmi.ip_data.cfg = *timing; @@ -339,8 +337,6 @@ static int hdmi_power_on(struct omap_dss_device *dssdev) goto err; } - hdmi.ip_data.cfg.cm.mode = hdmi.mode; - hdmi.ip_data.cfg.cm.code = hdmi.code; hdmi.ip_data.ops->video_configure(&hdmi.ip_data); /* Make selection of HDMI in DSS */ @@ -407,8 +403,8 @@ void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev) struct hdmi_cm cm; cm = hdmi_get_code(&dssdev->panel.timings); - hdmi.code = cm.code; - hdmi.mode = cm.mode; + hdmi.ip_data.cfg.cm.code = cm.code; + hdmi.ip_data.cfg.cm.mode = cm.mode; if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) { int r; @@ -707,7 +703,7 @@ static int hdmi_audio_hw_params(struct snd_pcm_substream *substream, static int hdmi_audio_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - if (!hdmi.mode) { + if (!hdmi.ip_data.cfg.cm.mode) { pr_err("Current video settings do not support audio.\n"); return -EIO; } -- cgit v1.2.3 From 1149c74419179d57fdcd506424da2444755e65d9 Mon Sep 17 00:00:00 2001 From: Ricardo Neri Date: Thu, 19 Jan 2012 12:21:41 -0600 Subject: OMAPDSS: HDMI: Correct source of the pixel clock in ACR calculation Due to changes in struct hdmi_config, the pixel clock has to be obtained differently. The pixel clock is needed to calculate the CTS value as defined in the HDMI specification. Signed-off-by: Ricardo Neri Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c index a229ae71be7..9bbf9614fe0 100644 --- a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c +++ b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c @@ -1137,7 +1137,7 @@ int hdmi_config_audio_acr(struct hdmi_ip_data *ip_data, { u32 r; u32 deep_color = 0; - u32 pclk = ip_data->cfg.timings.timings.pixel_clock; + u32 pclk = ip_data->cfg.timings.pixel_clock; if (n == NULL || cts == NULL) return -EINVAL; -- cgit v1.2.3 From cc1d3e032df53d83d0ca4d537d8eb67eb5b3e808 Mon Sep 17 00:00:00 2001 From: Danny Kukawka Date: Tue, 24 Jan 2012 16:44:42 +0100 Subject: OMAPDSS: VENC: fix NULL pointer dereference in DSS2 VENC sysfs debug attr on OMAP4 Commit ba02fa37de80bea10d706f39f076dd848348320a disabled the venc driver registration on OMAP4. Since the driver never gets probed/initialised your get a dereferenceed NULL pointer if you try to get info from /sys/kernel/debug/omapdss/venc Return info message about disabled venc if venc_dump_regs() gets called. Signed-off-by: Danny Kukawka Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/venc.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c index b3e9f909158..82865bec945 100644 --- a/drivers/video/omap2/dss/venc.c +++ b/drivers/video/omap2/dss/venc.c @@ -699,6 +699,11 @@ void venc_dump_regs(struct seq_file *s) { #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, venc_read_reg(r)) + if (cpu_is_omap44xx()) { + seq_printf(s, "VENC currently disabled on OMAP44xx\n"); + return; + } + if (venc_runtime_get()) return; -- cgit v1.2.3 From 6e2a14d2c59f6208310eeb6b031e9d1c22b38c6a Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Tue, 24 Jan 2012 14:00:45 +0100 Subject: OMAPDSS: use devm_ functions The various devm_ functions allocate memory that is released when a driver detaches. This patch uses these functions for data that is allocated in the probe function of a platform device and is only freed in the remove function. Signed-off-by: Julia Lawall Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dispc.c | 16 ++++++---------- drivers/video/omap2/dss/dsi.c | 28 +++++++++------------------- drivers/video/omap2/dss/dss.c | 9 +++------ drivers/video/omap2/dss/rfbi.c | 5 ++--- drivers/video/omap2/dss/venc.c | 8 +++----- 5 files changed, 23 insertions(+), 43 deletions(-) diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index a5ec7f37c18..6fa866a83f1 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c @@ -3322,7 +3322,8 @@ static int omap_dispchw_probe(struct platform_device *pdev) r = -EINVAL; goto err_ioremap; } - 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; @@ -3332,14 +3333,14 @@ static int omap_dispchw_probe(struct platform_device *pdev) if (dispc.irq < 0) { DSSERR("platform_get_irq failed\n"); r = -ENODEV; - goto err_irq; + goto err_ioremap; } - 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; + goto err_ioremap; } pm_runtime_enable(&pdev->dev); @@ -3362,9 +3363,6 @@ 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: @@ -3377,8 +3375,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/dsi.c b/drivers/video/omap2/dss/dsi.c index d4d676c82c1..52b93597730 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -4695,7 +4695,7 @@ static int omap_dsihw_probe(struct platform_device *dsidev) struct resource *dsi_mem; struct dsi_data *dsi; - dsi = kzalloc(sizeof(*dsi), GFP_KERNEL); + dsi = devm_kzalloc(&dsidev->dev, sizeof(*dsi), GFP_KERNEL); if (!dsi) { r = -ENOMEM; goto err_alloc; @@ -4724,7 +4724,7 @@ static int omap_dsihw_probe(struct platform_device *dsidev) r = dsi_get_clocks(dsidev); if (r) - goto err_get_clk; + goto err_alloc; pm_runtime_enable(&dsidev->dev); @@ -4742,7 +4742,8 @@ static int omap_dsihw_probe(struct platform_device *dsidev) r = -EINVAL; goto err_ioremap; } - 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; @@ -4752,14 +4753,14 @@ static int omap_dsihw_probe(struct platform_device *dsidev) if (dsi->irq < 0) { DSSERR("platform_get_irq failed\n"); r = -ENODEV; - goto err_get_irq; + goto err_ioremap; } - 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; + goto err_ioremap; } /* DSI VCs initialization */ @@ -4773,7 +4774,7 @@ static int omap_dsihw_probe(struct platform_device *dsidev) r = dsi_runtime_get(dsidev); if (r) - goto err_get_dsi; + goto err_ioremap; rev = dsi_read_reg(dsidev, DSI_REVISION); dev_dbg(&dsidev->dev, "OMAP DSI rev %d.%d\n", @@ -4791,14 +4792,8 @@ static int omap_dsihw_probe(struct platform_device *dsidev) return 0; -err_get_dsi: - free_irq(dsi->irq, dsi->pdev); -err_get_irq: - iounmap(dsi->base); err_ioremap: pm_runtime_disable(&dsidev->dev); -err_get_clk: - kfree(dsi); err_alloc: return r; } @@ -4823,11 +4818,6 @@ static int omap_dsihw_remove(struct platform_device *dsidev) dsi->vdds_dsi_reg = NULL; } - free_irq(dsi->irq, dsi->pdev); - iounmap(dsi->base); - - kfree(dsi); - return 0; } diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c index 17033457ee8..e75f837c766 100644 --- a/drivers/video/omap2/dss/dss.c +++ b/drivers/video/omap2/dss/dss.c @@ -751,7 +751,8 @@ static int omap_dsshw_probe(struct platform_device *pdev) r = -EINVAL; goto err_ioremap; } - dss.base = ioremap(dss_mem->start, resource_size(dss_mem)); + dss.base = devm_ioremap(&pdev->dev, dss_mem->start, + resource_size(dss_mem)); if (!dss.base) { DSSERR("can't ioremap DSS\n"); r = -ENOMEM; @@ -760,7 +761,7 @@ static int omap_dsshw_probe(struct platform_device *pdev) r = dss_get_clocks(); if (r) - goto err_clocks; + goto err_ioremap; pm_runtime_enable(&pdev->dev); @@ -808,8 +809,6 @@ err_dpi: err_runtime_get: pm_runtime_disable(&pdev->dev); dss_put_clocks(); -err_clocks: - iounmap(dss.base); err_ioremap: return r; } @@ -819,8 +818,6 @@ static int omap_dsshw_remove(struct platform_device *pdev) dpi_exit(); sdi_exit(); - iounmap(dss.base); - pm_runtime_disable(&pdev->dev); dss_put_clocks(); diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c index 814bb9500dc..159e914063c 100644 --- a/drivers/video/omap2/dss/rfbi.c +++ b/drivers/video/omap2/dss/rfbi.c @@ -925,7 +925,8 @@ static int omap_rfbihw_probe(struct platform_device *pdev) r = -EINVAL; goto err_ioremap; } - rfbi.base = ioremap(rfbi_mem->start, resource_size(rfbi_mem)); + rfbi.base = devm_ioremap(&pdev->dev, rfbi_mem->start, + resource_size(rfbi_mem)); if (!rfbi.base) { DSSERR("can't ioremap RFBI\n"); r = -ENOMEM; @@ -963,7 +964,6 @@ err_get_ick: rfbi_runtime_put(); err_get_rfbi: pm_runtime_disable(&pdev->dev); - iounmap(rfbi.base); err_ioremap: return r; } @@ -971,7 +971,6 @@ err_ioremap: static int omap_rfbihw_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); - iounmap(rfbi.base); return 0; } diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c index 82865bec945..4172232cdec 100644 --- a/drivers/video/omap2/dss/venc.c +++ b/drivers/video/omap2/dss/venc.c @@ -798,7 +798,8 @@ static int omap_venchw_probe(struct platform_device *pdev) r = -EINVAL; goto err_ioremap; } - venc.base = ioremap(venc_mem->start, resource_size(venc_mem)); + venc.base = devm_ioremap(&pdev->dev, venc_mem->start, + resource_size(venc_mem)); if (!venc.base) { DSSERR("can't ioremap VENC\n"); r = -ENOMEM; @@ -807,7 +808,7 @@ static int omap_venchw_probe(struct platform_device *pdev) r = venc_get_clocks(pdev); if (r) - goto err_get_clk; + goto err_ioremap; pm_runtime_enable(&pdev->dev); @@ -825,8 +826,6 @@ static int omap_venchw_probe(struct platform_device *pdev) err_get_venc: pm_runtime_disable(&pdev->dev); venc_put_clocks(); -err_get_clk: - iounmap(venc.base); err_ioremap: return r; } @@ -842,7 +841,6 @@ static int omap_venchw_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); venc_put_clocks(); - iounmap(venc.base); return 0; } -- cgit v1.2.3 From cd3b34493f9b5de1d617e0be39f6cb5c59c9889c Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Wed, 25 Jan 2012 13:31:04 +0200 Subject: OMAPDSS: cleanup probe functions Now that dss is using devm_ functions for allocation in probe functions, small reordering of the allocations allows us to clean up the probe functions more. This patch moves "unmanaged" allocations after the managed ones, and uses plain returns instead of gotos where possible. This lets us remove a bunch of goto labels, simplifying the probe's error handling. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dispc.c | 33 +++++++++++++++------------------ drivers/video/omap2/dss/dsi.c | 37 +++++++++++++++++-------------------- drivers/video/omap2/dss/dss.c | 10 ++++------ drivers/video/omap2/dss/rfbi.c | 31 +++++++++++++------------------ drivers/video/omap2/dss/venc.c | 21 ++++++++++++--------- 5 files changed, 61 insertions(+), 71 deletions(-) diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index f235798a7ba..d8e044df3d4 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c @@ -3341,15 +3341,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 @@ -3362,30 +3353,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 = 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_ioremap; + return -ENODEV; } 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_ioremap; + 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(); @@ -3406,9 +3405,7 @@ static int omap_dispchw_probe(struct platform_device *pdev) err_runtime_get: pm_runtime_disable(&pdev->dev); -err_ioremap: clk_put(dispc.dss_clk); -err_get_clk: return r; } diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index 0330216bd4e..662d14f8c2c 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -4688,10 +4688,8 @@ static int omap_dsihw_probe(struct platform_device *dsidev) struct dsi_data *dsi; dsi = devm_kzalloc(&dsidev->dev, sizeof(*dsi), GFP_KERNEL); - if (!dsi) { - r = -ENOMEM; - goto err_alloc; - } + if (!dsi) + return -ENOMEM; dsi->pdev = dsidev; dsi_pdev_map[dsi_module] = dsidev; @@ -4714,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_alloc; - - pm_runtime_enable(&dsidev->dev); - INIT_DELAYED_WORK_DEFERRABLE(&dsi->framedone_timeout_work, dsi_framedone_timeout_work_callback); @@ -4731,28 +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 = 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_ioremap; + return -ENODEV; } 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_ioremap; + return r; } /* DSI VCs initialization */ @@ -4764,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_ioremap; + goto err_runtime_get; rev = dsi_read_reg(dsidev, DSI_REVISION); dev_dbg(&dsidev->dev, "OMAP DSI rev %d.%d\n", @@ -4784,9 +4781,9 @@ static int omap_dsihw_probe(struct platform_device *dsidev) return 0; -err_ioremap: +err_runtime_get: pm_runtime_disable(&dsidev->dev); -err_alloc: + dsi_put_clocks(dsidev); return r; } diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c index aa2e0896864..4a6b5eeef6a 100644 --- a/drivers/video/omap2/dss/dss.c +++ b/drivers/video/omap2/dss/dss.c @@ -748,20 +748,19 @@ static int omap_dsshw_probe(struct platform_device *pdev) dss_mem = platform_get_resource(dss.pdev, IORESOURCE_MEM, 0); if (!dss_mem) { DSSERR("can't get IORESOURCE_MEM DSS\n"); - r = -EINVAL; - goto err_ioremap; + return -EINVAL; } + dss.base = devm_ioremap(&pdev->dev, dss_mem->start, resource_size(dss_mem)); if (!dss.base) { DSSERR("can't ioremap DSS\n"); - r = -ENOMEM; - goto err_ioremap; + return -ENOMEM; } r = dss_get_clocks(); if (r) - goto err_ioremap; + return r; pm_runtime_enable(&pdev->dev); @@ -809,7 +808,6 @@ err_dpi: err_runtime_get: pm_runtime_disable(&pdev->dev); dss_put_clocks(); -err_ioremap: return r; } diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c index 7370482b726..788a0ef6323 100644 --- a/drivers/video/omap2/dss/rfbi.c +++ b/drivers/video/omap2/dss/rfbi.c @@ -922,36 +922,34 @@ static int omap_rfbihw_probe(struct platform_device *pdev) rfbi_mem = platform_get_resource(rfbi.pdev, IORESOURCE_MEM, 0); if (!rfbi_mem) { DSSERR("can't get IORESOURCE_MEM RFBI\n"); - r = -EINVAL; - goto err_ioremap; + return -EINVAL; } + rfbi.base = devm_ioremap(&pdev->dev, rfbi_mem->start, resource_size(rfbi_mem)); if (!rfbi.base) { DSSERR("can't ioremap RFBI\n"); - r = -ENOMEM; - goto err_ioremap; + return -ENOMEM; } - pm_runtime_enable(&pdev->dev); - - r = rfbi_runtime_get(); - if (r) - goto err_get_rfbi; - - msleep(10); - clk = clk_get(&pdev->dev, "ick"); if (IS_ERR(clk)) { DSSERR("can't get ick\n"); - r = PTR_ERR(clk); - goto err_get_ick; + return PTR_ERR(clk); } rfbi.l4_khz = clk_get_rate(clk) / 1000; clk_put(clk); + pm_runtime_enable(&pdev->dev); + + r = rfbi_runtime_get(); + if (r) + goto err_runtime_get; + + msleep(10); + rev = rfbi_read_reg(RFBI_REVISION); dev_dbg(&pdev->dev, "OMAP RFBI rev %d.%d\n", FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); @@ -960,11 +958,8 @@ static int omap_rfbihw_probe(struct platform_device *pdev) return 0; -err_get_ick: - rfbi_runtime_put(); -err_get_rfbi: +err_runtime_get: pm_runtime_disable(&pdev->dev); -err_ioremap: return r; } diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c index 967d4432c67..9c3daf71750 100644 --- a/drivers/video/omap2/dss/venc.c +++ b/drivers/video/omap2/dss/venc.c @@ -795,38 +795,41 @@ static int omap_venchw_probe(struct platform_device *pdev) venc_mem = platform_get_resource(venc.pdev, IORESOURCE_MEM, 0); if (!venc_mem) { DSSERR("can't get IORESOURCE_MEM VENC\n"); - r = -EINVAL; - goto err_ioremap; + return -EINVAL; } + venc.base = devm_ioremap(&pdev->dev, venc_mem->start, resource_size(venc_mem)); if (!venc.base) { DSSERR("can't ioremap VENC\n"); - r = -ENOMEM; - goto err_ioremap; + return -ENOMEM; } r = venc_get_clocks(pdev); if (r) - goto err_ioremap; + return r; pm_runtime_enable(&pdev->dev); r = venc_runtime_get(); if (r) - goto err_get_venc; + goto err_runtime_get; rev_id = (u8)(venc_read_reg(VENC_REV_ID) & 0xff); dev_dbg(&pdev->dev, "OMAP VENC rev %d\n", rev_id); venc_runtime_put(); - return omap_dss_register_driver(&venc_driver); + r = omap_dss_register_driver(&venc_driver); + if (r) + goto err_reg_panel_driver; + + return 0; -err_get_venc: +err_reg_panel_driver: +err_runtime_get: pm_runtime_disable(&pdev->dev); venc_put_clocks(); -err_ioremap: return r; } -- cgit v1.2.3 From c124f23dfdf7da890405dfa0efbeb015cab27b56 Mon Sep 17 00:00:00 2001 From: Archit Taneja Date: Mon, 30 Jan 2012 10:52:39 +0530 Subject: OMAPDSS: Features: Maintain dss_feats as a list The number of dss_feat_id members has increased to a large value, the current way of assigning a subset of these features (for a particular OMAP) as a mask is no longer feasible. Maintain the subset of features supported as lists. Make the function dss_has_feature() traverse through this list. Signed-off-by: Archit Taneja Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dss_features.c | 140 ++++++++++++++++++++++++--------- drivers/video/omap2/dss/dss_features.h | 54 ++++++------- 2 files changed, 128 insertions(+), 66 deletions(-) diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c index 419419ad049..656cb69f464 100644 --- a/drivers/video/omap2/dss/dss_features.c +++ b/drivers/video/omap2/dss/dss_features.c @@ -41,7 +41,8 @@ struct omap_dss_features { const struct dss_reg_field *reg_fields; const int num_reg_fields; - const u32 has_feature; + const enum dss_feat_id *features; + const int num_features; const int num_mgrs; const int num_ovls; @@ -337,15 +338,92 @@ static const struct dss_param_range omap4_dss_param_range[] = { [FEAT_PARAM_LINEWIDTH] = { 1, 2048 }, }; +static const enum dss_feat_id omap2_dss_feat_list[] = { + FEAT_LCDENABLEPOL, + FEAT_LCDENABLESIGNAL, + FEAT_PCKFREEENABLE, + FEAT_FUNCGATED, + FEAT_ROWREPEATENABLE, + FEAT_RESIZECONF, +}; + +static const enum dss_feat_id omap3430_dss_feat_list[] = { + FEAT_LCDENABLEPOL, + FEAT_LCDENABLESIGNAL, + FEAT_PCKFREEENABLE, + FEAT_FUNCGATED, + FEAT_LINEBUFFERSPLIT, + FEAT_ROWREPEATENABLE, + FEAT_RESIZECONF, + FEAT_DSI_PLL_FREQSEL, + FEAT_DSI_REVERSE_TXCLKESC, + FEAT_VENC_REQUIRES_TV_DAC_CLK, + FEAT_CPR, + FEAT_PRELOAD, + FEAT_FIR_COEF_V, + FEAT_ALPHA_FIXED_ZORDER, + FEAT_FIFO_MERGE, + FEAT_OMAP3_DSI_FIFO_BUG, +}; + +static const enum dss_feat_id omap3630_dss_feat_list[] = { + FEAT_LCDENABLEPOL, + FEAT_LCDENABLESIGNAL, + FEAT_PCKFREEENABLE, + FEAT_FUNCGATED, + FEAT_LINEBUFFERSPLIT, + FEAT_ROWREPEATENABLE, + FEAT_RESIZECONF, + FEAT_DSI_PLL_PWR_BUG, + FEAT_DSI_PLL_FREQSEL, + FEAT_CPR, + FEAT_PRELOAD, + FEAT_FIR_COEF_V, + FEAT_ALPHA_FIXED_ZORDER, + FEAT_FIFO_MERGE, + FEAT_OMAP3_DSI_FIFO_BUG, +}; + +static const enum dss_feat_id omap4430_es1_0_dss_feat_list[] = { + FEAT_MGR_LCD2, + FEAT_CORE_CLK_DIV, + FEAT_LCD_CLK_SRC, + FEAT_DSI_DCS_CMD_CONFIG_VC, + FEAT_DSI_VC_OCP_WIDTH, + FEAT_DSI_GNQ, + FEAT_HANDLE_UV_SEPARATE, + FEAT_ATTR2, + FEAT_CPR, + FEAT_PRELOAD, + FEAT_FIR_COEF_V, + FEAT_ALPHA_FREE_ZORDER, + FEAT_FIFO_MERGE, +}; + +static const enum dss_feat_id omap4_dss_feat_list[] = { + FEAT_MGR_LCD2, + FEAT_CORE_CLK_DIV, + FEAT_LCD_CLK_SRC, + FEAT_DSI_DCS_CMD_CONFIG_VC, + FEAT_DSI_VC_OCP_WIDTH, + FEAT_DSI_GNQ, + FEAT_HDMI_CTS_SWMODE, + FEAT_HANDLE_UV_SEPARATE, + FEAT_ATTR2, + FEAT_CPR, + FEAT_PRELOAD, + FEAT_FIR_COEF_V, + FEAT_ALPHA_FREE_ZORDER, + FEAT_FIFO_MERGE, +}; + /* OMAP2 DSS Features */ static const struct omap_dss_features omap2_dss_features = { .reg_fields = omap2_dss_reg_fields, .num_reg_fields = ARRAY_SIZE(omap2_dss_reg_fields), - .has_feature = - FEAT_LCDENABLEPOL | FEAT_LCDENABLESIGNAL | - FEAT_PCKFREEENABLE | FEAT_FUNCGATED | - FEAT_ROWREPEATENABLE | FEAT_RESIZECONF, + .features = omap2_dss_feat_list, + .num_features = ARRAY_SIZE(omap2_dss_feat_list), .num_mgrs = 2, .num_ovls = 3, @@ -363,15 +441,8 @@ static const struct omap_dss_features omap3430_dss_features = { .reg_fields = omap3_dss_reg_fields, .num_reg_fields = ARRAY_SIZE(omap3_dss_reg_fields), - .has_feature = - FEAT_LCDENABLEPOL | - FEAT_LCDENABLESIGNAL | FEAT_PCKFREEENABLE | - FEAT_FUNCGATED | FEAT_ROWREPEATENABLE | - FEAT_LINEBUFFERSPLIT | FEAT_RESIZECONF | - FEAT_DSI_PLL_FREQSEL | FEAT_DSI_REVERSE_TXCLKESC | - FEAT_VENC_REQUIRES_TV_DAC_CLK | FEAT_CPR | FEAT_PRELOAD | - FEAT_FIR_COEF_V | FEAT_ALPHA_FIXED_ZORDER | FEAT_FIFO_MERGE | - FEAT_OMAP3_DSI_FIFO_BUG, + .features = omap3430_dss_feat_list, + .num_features = ARRAY_SIZE(omap3430_dss_feat_list), .num_mgrs = 2, .num_ovls = 3, @@ -388,15 +459,8 @@ static const struct omap_dss_features omap3630_dss_features = { .reg_fields = omap3_dss_reg_fields, .num_reg_fields = ARRAY_SIZE(omap3_dss_reg_fields), - .has_feature = - FEAT_LCDENABLEPOL | - FEAT_LCDENABLESIGNAL | FEAT_PCKFREEENABLE | - FEAT_FUNCGATED | - FEAT_ROWREPEATENABLE | FEAT_LINEBUFFERSPLIT | - FEAT_RESIZECONF | FEAT_DSI_PLL_PWR_BUG | - FEAT_DSI_PLL_FREQSEL | FEAT_CPR | FEAT_PRELOAD | - FEAT_FIR_COEF_V | FEAT_ALPHA_FIXED_ZORDER | FEAT_FIFO_MERGE | - FEAT_OMAP3_DSI_FIFO_BUG, + .features = omap3630_dss_feat_list, + .num_features = ARRAY_SIZE(omap3630_dss_feat_list), .num_mgrs = 2, .num_ovls = 3, @@ -415,13 +479,8 @@ static const struct omap_dss_features omap4430_es1_0_dss_features = { .reg_fields = omap4_dss_reg_fields, .num_reg_fields = ARRAY_SIZE(omap4_dss_reg_fields), - .has_feature = - FEAT_MGR_LCD2 | - FEAT_CORE_CLK_DIV | FEAT_LCD_CLK_SRC | - FEAT_DSI_DCS_CMD_CONFIG_VC | FEAT_DSI_VC_OCP_WIDTH | - FEAT_DSI_GNQ | FEAT_HANDLE_UV_SEPARATE | FEAT_ATTR2 | - FEAT_CPR | FEAT_PRELOAD | FEAT_FIR_COEF_V | - FEAT_ALPHA_FREE_ZORDER | FEAT_FIFO_MERGE, + .features = omap4430_es1_0_dss_feat_list, + .num_features = ARRAY_SIZE(omap4430_es1_0_dss_feat_list), .num_mgrs = 3, .num_ovls = 4, @@ -439,14 +498,8 @@ static const struct omap_dss_features omap4_dss_features = { .reg_fields = omap4_dss_reg_fields, .num_reg_fields = ARRAY_SIZE(omap4_dss_reg_fields), - .has_feature = - FEAT_MGR_LCD2 | - FEAT_CORE_CLK_DIV | FEAT_LCD_CLK_SRC | - FEAT_DSI_DCS_CMD_CONFIG_VC | FEAT_DSI_VC_OCP_WIDTH | - FEAT_DSI_GNQ | FEAT_HDMI_CTS_SWMODE | - FEAT_HANDLE_UV_SEPARATE | FEAT_ATTR2 | FEAT_CPR | - FEAT_PRELOAD | FEAT_FIR_COEF_V | FEAT_ALPHA_FREE_ZORDER | - FEAT_FIFO_MERGE, + .features = omap4_dss_feat_list, + .num_features = ARRAY_SIZE(omap4_dss_feat_list), .num_mgrs = 3, .num_ovls = 4, @@ -550,7 +603,16 @@ u32 dss_feat_get_burst_size_unit(void) /* DSS has_feature check */ bool dss_has_feature(enum dss_feat_id id) { - return omap_current_dss_features->has_feature & id; + int i; + const enum dss_feat_id *features = omap_current_dss_features->features; + const int num_features = omap_current_dss_features->num_features; + + for (i = 0; i < num_features; i++) { + if (features[i] == id) + return true; + } + + return false; } void dss_feat_get_reg_field(enum dss_feat_reg_field id, u8 *start, u8 *end) diff --git a/drivers/video/omap2/dss/dss_features.h b/drivers/video/omap2/dss/dss_features.h index 5f9b8215677..682f091cf02 100644 --- a/drivers/video/omap2/dss/dss_features.h +++ b/drivers/video/omap2/dss/dss_features.h @@ -31,36 +31,36 @@ /* DSS has feature id */ enum dss_feat_id { - FEAT_LCDENABLEPOL = 1 << 3, - FEAT_LCDENABLESIGNAL = 1 << 4, - FEAT_PCKFREEENABLE = 1 << 5, - FEAT_FUNCGATED = 1 << 6, - FEAT_MGR_LCD2 = 1 << 7, - FEAT_LINEBUFFERSPLIT = 1 << 8, - FEAT_ROWREPEATENABLE = 1 << 9, - FEAT_RESIZECONF = 1 << 10, + FEAT_LCDENABLEPOL, + FEAT_LCDENABLESIGNAL, + FEAT_PCKFREEENABLE, + FEAT_FUNCGATED, + FEAT_MGR_LCD2, + FEAT_LINEBUFFERSPLIT, + FEAT_ROWREPEATENABLE, + FEAT_RESIZECONF, /* Independent core clk divider */ - FEAT_CORE_CLK_DIV = 1 << 11, - FEAT_LCD_CLK_SRC = 1 << 12, + FEAT_CORE_CLK_DIV, + FEAT_LCD_CLK_SRC, /* DSI-PLL power command 0x3 is not working */ - FEAT_DSI_PLL_PWR_BUG = 1 << 13, - FEAT_DSI_PLL_FREQSEL = 1 << 14, - FEAT_DSI_DCS_CMD_CONFIG_VC = 1 << 15, - FEAT_DSI_VC_OCP_WIDTH = 1 << 16, - FEAT_DSI_REVERSE_TXCLKESC = 1 << 17, - FEAT_DSI_GNQ = 1 << 18, - FEAT_HDMI_CTS_SWMODE = 1 << 19, - FEAT_HANDLE_UV_SEPARATE = 1 << 20, - FEAT_ATTR2 = 1 << 21, - FEAT_VENC_REQUIRES_TV_DAC_CLK = 1 << 22, - FEAT_CPR = 1 << 23, - FEAT_PRELOAD = 1 << 24, - FEAT_FIR_COEF_V = 1 << 25, - FEAT_ALPHA_FIXED_ZORDER = 1 << 26, - FEAT_ALPHA_FREE_ZORDER = 1 << 27, - FEAT_FIFO_MERGE = 1 << 28, + FEAT_DSI_PLL_PWR_BUG, + FEAT_DSI_PLL_FREQSEL, + FEAT_DSI_DCS_CMD_CONFIG_VC, + FEAT_DSI_VC_OCP_WIDTH, + FEAT_DSI_REVERSE_TXCLKESC, + FEAT_DSI_GNQ, + FEAT_HDMI_CTS_SWMODE, + FEAT_HANDLE_UV_SEPARATE, + FEAT_ATTR2, + FEAT_VENC_REQUIRES_TV_DAC_CLK, + FEAT_CPR, + FEAT_PRELOAD, + FEAT_FIR_COEF_V, + FEAT_ALPHA_FIXED_ZORDER, + FEAT_ALPHA_FREE_ZORDER, + FEAT_FIFO_MERGE, /* An unknown HW bug causing the normal FIFO thresholds not to work */ - FEAT_OMAP3_DSI_FIFO_BUG = 1 << 29, + FEAT_OMAP3_DSI_FIFO_BUG, }; /* DSS register field id */ -- cgit v1.2.3 From 79ee89cdbd9a58baa079d019574d11aa864b7842 Mon Sep 17 00:00:00 2001 From: Archit Taneja Date: Mon, 30 Jan 2012 10:54:17 +0530 Subject: OMAPDSS: DISPC: Fix scaling constraints for OMAP4 The calculation of required DISPC_FCLK for downscaling is done by multplying the pixel clock with an integer factor. This isn't true for OMAP4 where the required clock is calculated using the exact ratio of downscaling done. Fix this calculation for OMAP4. Also, do a minor clean up of calc_fclk(). Signed-off-by: Archit Taneja Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dispc.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index d8e044df3d4..22023bba63e 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c @@ -1694,6 +1694,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 @@ -1716,13 +1717,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; } } -- cgit v1.2.3 From 992ee64af66f05e16aa70b475f9ad3047f801185 Mon Sep 17 00:00:00 2001 From: Yegor Yefremov Date: Wed, 8 Feb 2012 11:11:08 +0100 Subject: OMAPDSS: add Innolux AT080TN52 display support This patch adds support for Innolux AT080TN52 800x600 panel. Tested with AM3517 based board. Signed-off-by: Yegor Yefremov Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/displays/panel-generic-dpi.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/drivers/video/omap2/displays/panel-generic-dpi.c b/drivers/video/omap2/displays/panel-generic-dpi.c index 28b9a6d61b0..30fe4dfeb22 100644 --- a/drivers/video/omap2/displays/panel-generic-dpi.c +++ b/drivers/video/omap2/displays/panel-generic-dpi.c @@ -363,6 +363,29 @@ static struct panel_config generic_dpi_panels[] = { .name = "ortustech_com43h4m10xtc", }, + + /* Innolux AT080TN52 */ + { + { + .x_res = 800, + .y_res = 600, + + .pixel_clock = 41142, + + .hsw = 20, + .hfp = 210, + .hbp = 46, + + .vsw = 10, + .vfp = 12, + .vbp = 23, + }, + .acb = 0x0, + .config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS | + OMAP_DSS_LCD_IHS | OMAP_DSS_LCD_IEO, + + .name = "innolux_at080tn52", + }, }; struct panel_drv_data { -- cgit v1.2.3 From da8f14fc3bb054081c90abc9dd38679bb9308dbb Mon Sep 17 00:00:00 2001 From: Mythri P K Date: Wed, 8 Feb 2012 11:54:19 +0530 Subject: OMAPDSS: HDMI: Move Avi-infoframe struct to hdmi_ip_data With AVI infoframe various parameters of video stream such as aspect ratio, quantization range, videocode etc will be indicated from source to sink.Thus AVI information needs to be set/accessed by the middle ware based on the video content. Thus this parameter is now moved to the ip_data structure. Signed-off-by: Mythri P K Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/ti_hdmi.h | 42 +++++++++++++++++++++++++++++++ drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c | 8 +++--- drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h | 40 ----------------------------- 3 files changed, 46 insertions(+), 44 deletions(-) diff --git a/drivers/video/omap2/dss/ti_hdmi.h b/drivers/video/omap2/dss/ti_hdmi.h index cb6f0f20f45..1f58b84d690 100644 --- a/drivers/video/omap2/dss/ti_hdmi.h +++ b/drivers/video/omap2/dss/ti_hdmi.h @@ -113,6 +113,47 @@ struct ti_hdmi_ip_ops { }; +/* + * Refer to section 8.2 in HDMI 1.3 specification for + * details about infoframe databytes + */ +struct hdmi_core_infoframe_avi { + /* Y0, Y1 rgb,yCbCr */ + u8 db1_format; + /* A0 Active information Present */ + u8 db1_active_info; + /* B0, B1 Bar info data valid */ + u8 db1_bar_info_dv; + /* S0, S1 scan information */ + u8 db1_scan_info; + /* C0, C1 colorimetry */ + u8 db2_colorimetry; + /* M0, M1 Aspect ratio (4:3, 16:9) */ + u8 db2_aspect_ratio; + /* R0...R3 Active format aspect ratio */ + u8 db2_active_fmt_ar; + /* ITC IT content. */ + u8 db3_itc; + /* EC0, EC1, EC2 Extended colorimetry */ + u8 db3_ec; + /* Q1, Q0 Quantization range */ + u8 db3_q_range; + /* SC1, SC0 Non-uniform picture scaling */ + u8 db3_nup_scaling; + /* VIC0..6 Video format identification */ + u8 db4_videocode; + /* PR0..PR3 Pixel repetition factor */ + u8 db5_pixel_repeat; + /* Line number end of top bar */ + u16 db6_7_line_eoftop; + /* Line number start of bottom bar */ + u16 db8_9_line_sofbottom; + /* Pixel number end of left bar */ + u16 db10_11_pixel_eofleft; + /* Pixel number start of right bar */ + u16 db12_13_pixel_sofright; +}; + struct hdmi_ip_data { void __iomem *base_wp; /* HDMI wrapper */ unsigned long core_sys_offset; @@ -122,6 +163,7 @@ struct hdmi_ip_data { const struct ti_hdmi_ip_ops *ops; struct hdmi_config cfg; struct hdmi_pll_info pll_data; + struct hdmi_core_infoframe_avi avi_cfg; /* ti_hdmi_4xxx_ip private data. These should be in a separate struct */ int hpd_gpio; diff --git a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c index c05eacd4444..b9b97f172cd 100644 --- a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c +++ b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c @@ -594,12 +594,12 @@ static void hdmi_core_video_config(struct hdmi_ip_data *ip_data, HDMI_CORE_SYS_TMDS_CTRL, cfg->tclk_sel_clkmult, 6, 5); } -static void hdmi_core_aux_infoframe_avi_config(struct hdmi_ip_data *ip_data, - struct hdmi_core_infoframe_avi info_avi) +static void hdmi_core_aux_infoframe_avi_config(struct hdmi_ip_data *ip_data) { u32 val; char sum = 0, checksum = 0; void __iomem *av_base = hdmi_av_base(ip_data); + struct hdmi_core_infoframe_avi info_avi = ip_data->avi_cfg; sum += 0x82 + 0x002 + 0x00D; hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_TYPE, 0x082); @@ -778,7 +778,7 @@ void ti_hdmi_4xxx_basic_configure(struct hdmi_ip_data *ip_data) struct omap_video_timings video_timing; struct hdmi_video_format video_format; /* HDMI core */ - struct hdmi_core_infoframe_avi avi_cfg; + struct hdmi_core_infoframe_avi avi_cfg = ip_data->avi_cfg; struct hdmi_core_video_config v_core_cfg; struct hdmi_core_packet_enable_repeat repeat_cfg; struct hdmi_config *cfg = &ip_data->cfg; @@ -840,7 +840,7 @@ void ti_hdmi_4xxx_basic_configure(struct hdmi_ip_data *ip_data) avi_cfg.db10_11_pixel_eofleft = 0; avi_cfg.db12_13_pixel_sofright = 0; - hdmi_core_aux_infoframe_avi_config(ip_data, avi_cfg); + hdmi_core_aux_infoframe_avi_config(ip_data); /* enable/repeat the infoframe */ repeat_cfg.avi_infoframe = HDMI_PACKETENABLE; diff --git a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h index 004b4182bdd..a14d1a0e6e4 100644 --- a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h +++ b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h @@ -446,46 +446,6 @@ struct hdmi_core_video_config { enum hdmi_core_tclkselclkmult tclk_sel_clkmult; }; -/* - * Refer to section 8.2 in HDMI 1.3 specification for - * details about infoframe databytes - */ -struct hdmi_core_infoframe_avi { - /* Y0, Y1 rgb,yCbCr */ - u8 db1_format; - /* A0 Active information Present */ - u8 db1_active_info; - /* B0, B1 Bar info data valid */ - u8 db1_bar_info_dv; - /* S0, S1 scan information */ - u8 db1_scan_info; - /* C0, C1 colorimetry */ - u8 db2_colorimetry; - /* M0, M1 Aspect ratio (4:3, 16:9) */ - u8 db2_aspect_ratio; - /* R0...R3 Active format aspect ratio */ - u8 db2_active_fmt_ar; - /* ITC IT content. */ - u8 db3_itc; - /* EC0, EC1, EC2 Extended colorimetry */ - u8 db3_ec; - /* Q1, Q0 Quantization range */ - u8 db3_q_range; - /* SC1, SC0 Non-uniform picture scaling */ - u8 db3_nup_scaling; - /* VIC0..6 Video format identification */ - u8 db4_videocode; - /* PR0..PR3 Pixel repetition factor */ - u8 db5_pixel_repeat; - /* Line number end of top bar */ - u16 db6_7_line_eoftop; - /* Line number start of bottom bar */ - u16 db8_9_line_sofbottom; - /* Pixel number end of left bar */ - u16 db10_11_pixel_eofleft; - /* Pixel number start of right bar */ - u16 db12_13_pixel_sofright; -}; /* * Refer to section 8.2 in HDMI 1.3 specification for * details about infoframe databytes -- cgit v1.2.3 From 8df4f5ce64e9dc986570799f94c8850f57f8ced9 Mon Sep 17 00:00:00 2001 From: Grazvydas Ignotas Date: Tue, 7 Feb 2012 02:13:49 +0200 Subject: OMAPDSS: TPO-TD03MTEA1: fix suspend hang During system suspend, at the time DSS is being suspended, SPI is already suspended and it's clocks are cut. Because of this trying to communicate with the LCD controller results in a deadlock. To fix this, split out LCD programming parts of display enable/disable functions and perform them from SPI PM callbacks instead when system is being suspended. If the display is just being enabled/disabled, do it from DSS callbacks as before. Signed-off-by: Grazvydas Ignotas Signed-off-by: Tomi Valkeinen --- .../video/omap2/displays/panel-tpo-td043mtea1.c | 151 +++++++++++++++------ 1 file changed, 108 insertions(+), 43 deletions(-) diff --git a/drivers/video/omap2/displays/panel-tpo-td043mtea1.c b/drivers/video/omap2/displays/panel-tpo-td043mtea1.c index e6649aa8959..741e9d7cec1 100644 --- a/drivers/video/omap2/displays/panel-tpo-td043mtea1.c +++ b/drivers/video/omap2/displays/panel-tpo-td043mtea1.c @@ -53,10 +53,14 @@ static const u16 tpo_td043_def_gamma[12] = { struct tpo_td043_device { struct spi_device *spi; struct regulator *vcc_reg; + int nreset_gpio; u16 gamma[12]; u32 mode; u32 hmirror:1; u32 vmirror:1; + u32 powered_on:1; + u32 spi_suspended:1; + u32 power_on_resume:1; }; static int tpo_td043_write(struct spi_device *spi, u8 addr, u8 data) @@ -265,28 +269,16 @@ static const struct omap_video_timings tpo_td043_timings = { .vbp = 34, }; -static int tpo_td043_power_on(struct omap_dss_device *dssdev) +static int tpo_td043_power_on(struct tpo_td043_device *tpo_td043) { - struct tpo_td043_device *tpo_td043 = dev_get_drvdata(&dssdev->dev); - int nreset_gpio = dssdev->reset_gpio; - int r; + int nreset_gpio = tpo_td043->nreset_gpio; - if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) + if (tpo_td043->powered_on) return 0; - r = omapdss_dpi_display_enable(dssdev); - if (r) - goto err0; - - if (dssdev->platform_enable) { - r = dssdev->platform_enable(dssdev); - if (r) - goto err1; - } - regulator_enable(tpo_td043->vcc_reg); - /* wait for power up */ + /* wait for regulator to stabilize */ msleep(160); if (gpio_is_valid(nreset_gpio)) @@ -301,19 +293,15 @@ static int tpo_td043_power_on(struct omap_dss_device *dssdev) tpo_td043->vmirror); tpo_td043_write_gamma(tpo_td043->spi, tpo_td043->gamma); + tpo_td043->powered_on = 1; return 0; -err1: - omapdss_dpi_display_disable(dssdev); -err0: - return r; } -static void tpo_td043_power_off(struct omap_dss_device *dssdev) +static void tpo_td043_power_off(struct tpo_td043_device *tpo_td043) { - struct tpo_td043_device *tpo_td043 = dev_get_drvdata(&dssdev->dev); - int nreset_gpio = dssdev->reset_gpio; + int nreset_gpio = tpo_td043->nreset_gpio; - if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) + if (!tpo_td043->powered_on) return; tpo_td043_write(tpo_td043->spi, 3, @@ -329,54 +317,94 @@ static void tpo_td043_power_off(struct omap_dss_device *dssdev) regulator_disable(tpo_td043->vcc_reg); + tpo_td043->powered_on = 0; +} + +static int tpo_td043_enable_dss(struct omap_dss_device *dssdev) +{ + struct tpo_td043_device *tpo_td043 = dev_get_drvdata(&dssdev->dev); + int r; + + if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) + return 0; + + r = omapdss_dpi_display_enable(dssdev); + if (r) + goto err0; + + if (dssdev->platform_enable) { + r = dssdev->platform_enable(dssdev); + if (r) + goto err1; + } + + /* + * If we are resuming from system suspend, SPI clocks might not be + * enabled yet, so we'll program the LCD from SPI PM resume callback. + */ + if (!tpo_td043->spi_suspended) { + r = tpo_td043_power_on(tpo_td043); + if (r) + goto err1; + } + + dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; + + return 0; +err1: + omapdss_dpi_display_disable(dssdev); +err0: + return r; +} + +static void tpo_td043_disable_dss(struct omap_dss_device *dssdev) +{ + struct tpo_td043_device *tpo_td043 = dev_get_drvdata(&dssdev->dev); + + if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) + return; + if (dssdev->platform_disable) dssdev->platform_disable(dssdev); omapdss_dpi_display_disable(dssdev); + + if (!tpo_td043->spi_suspended) + tpo_td043_power_off(tpo_td043); } static int tpo_td043_enable(struct omap_dss_device *dssdev) { - int ret; - dev_dbg(&dssdev->dev, "enable\n"); - ret = tpo_td043_power_on(dssdev); - if (ret) - return ret; - - dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; - - return 0; + return tpo_td043_enable_dss(dssdev); } static void tpo_td043_disable(struct omap_dss_device *dssdev) { dev_dbg(&dssdev->dev, "disable\n"); - tpo_td043_power_off(dssdev); + tpo_td043_disable_dss(dssdev); dssdev->state = OMAP_DSS_DISPLAY_DISABLED; } static int tpo_td043_suspend(struct omap_dss_device *dssdev) { - tpo_td043_power_off(dssdev); + dev_dbg(&dssdev->dev, "suspend\n"); + + tpo_td043_disable_dss(dssdev); + dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED; + return 0; } static int tpo_td043_resume(struct omap_dss_device *dssdev) { - int r = 0; - - r = tpo_td043_power_on(dssdev); - if (r) - return r; - - dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; + dev_dbg(&dssdev->dev, "resume\n"); - return 0; + return tpo_td043_enable_dss(dssdev); } static int tpo_td043_probe(struct omap_dss_device *dssdev) @@ -491,6 +519,7 @@ static int tpo_td043_spi_probe(struct spi_device *spi) return -ENOMEM; tpo_td043->spi = spi; + tpo_td043->nreset_gpio = dssdev->reset_gpio; dev_set_drvdata(&spi->dev, tpo_td043); dev_set_drvdata(&dssdev->dev, tpo_td043); @@ -509,10 +538,46 @@ static int __devexit tpo_td043_spi_remove(struct spi_device *spi) return 0; } +#ifdef CONFIG_PM_SLEEP +static int tpo_td043_spi_suspend(struct device *dev) +{ + struct tpo_td043_device *tpo_td043 = dev_get_drvdata(dev); + + dev_dbg(dev, "tpo_td043_spi_suspend, tpo %p\n", tpo_td043); + + tpo_td043->power_on_resume = tpo_td043->powered_on; + tpo_td043_power_off(tpo_td043); + tpo_td043->spi_suspended = 1; + + return 0; +} + +static int tpo_td043_spi_resume(struct device *dev) +{ + struct tpo_td043_device *tpo_td043 = dev_get_drvdata(dev); + int ret; + + dev_dbg(dev, "tpo_td043_spi_resume\n"); + + if (tpo_td043->power_on_resume) { + ret = tpo_td043_power_on(tpo_td043); + if (ret) + return ret; + } + tpo_td043->spi_suspended = 0; + + return 0; +} +#endif + +static SIMPLE_DEV_PM_OPS(tpo_td043_spi_pm, + tpo_td043_spi_suspend, tpo_td043_spi_resume); + static struct spi_driver tpo_td043_spi_driver = { .driver = { .name = "tpo_td043mtea1_panel_spi", .owner = THIS_MODULE, + .pm = &tpo_td043_spi_pm, }, .probe = tpo_td043_spi_probe, .remove = __devexit_p(tpo_td043_spi_remove), -- cgit v1.2.3 From 4306b721ac1e8b79858b38537f0fb5a940a792be Mon Sep 17 00:00:00 2001 From: Grazvydas Ignotas Date: Tue, 7 Feb 2012 02:13:50 +0200 Subject: OMAPDSS: TPO-TD03MTEA1: update default gamma Over time better gamma has been determined and tuned with some equipment so update the defaults. From subjective point of view dark shades should be better visible. Signed-off-by: Grazvydas Ignotas Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/displays/panel-tpo-td043mtea1.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/omap2/displays/panel-tpo-td043mtea1.c b/drivers/video/omap2/displays/panel-tpo-td043mtea1.c index 741e9d7cec1..d63e5e5dbbf 100644 --- a/drivers/video/omap2/displays/panel-tpo-td043mtea1.c +++ b/drivers/video/omap2/displays/panel-tpo-td043mtea1.c @@ -47,7 +47,7 @@ TPO_R03_EN_PRE_CHARGE | TPO_R03_SOFTWARE_CTL) static const u16 tpo_td043_def_gamma[12] = { - 106, 200, 289, 375, 460, 543, 625, 705, 785, 864, 942, 1020 + 105, 315, 381, 431, 490, 537, 579, 686, 780, 837, 880, 1023 }; struct tpo_td043_device { -- cgit v1.2.3 From 709881942d2af6944a59d1b90e73ba8f4d76bd82 Mon Sep 17 00:00:00 2001 From: Ricardo Neri Date: Thu, 16 Feb 2012 09:20:57 -0600 Subject: OMAPDSS: Add DSS feature for HDMI MCLK for audio Certain OMAP4 revisions (i.e., 4430 ES2.3, 4460, and 4470) use a pseudo clock (generated from the TMDS clock), MCLK, to drive the generation of Audio Clock Regeneration packets. Other devices (i.e., 4430 ES2.[0,2]) use the TMDS clock directly. This patch adds a new DSS feature for MCLK support. It also rearranges the omap_dss_features structures to reflect the devices supporting it. Signed-off-by: Ricardo Neri Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dss_features.c | 41 ++++++++++++++++++++++++++++++++++ drivers/video/omap2/dss/dss_features.h | 1 + 2 files changed, 42 insertions(+) diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c index 656cb69f464..0a926432ccd 100644 --- a/drivers/video/omap2/dss/dss_features.c +++ b/drivers/video/omap2/dss/dss_features.c @@ -400,6 +400,23 @@ static const enum dss_feat_id omap4430_es1_0_dss_feat_list[] = { FEAT_FIFO_MERGE, }; +static const enum dss_feat_id omap4430_es2_0_1_2_dss_feat_list[] = { + FEAT_MGR_LCD2, + FEAT_CORE_CLK_DIV, + FEAT_LCD_CLK_SRC, + FEAT_DSI_DCS_CMD_CONFIG_VC, + FEAT_DSI_VC_OCP_WIDTH, + FEAT_DSI_GNQ, + FEAT_HDMI_CTS_SWMODE, + FEAT_HANDLE_UV_SEPARATE, + FEAT_ATTR2, + FEAT_CPR, + FEAT_PRELOAD, + FEAT_FIR_COEF_V, + FEAT_ALPHA_FREE_ZORDER, + FEAT_FIFO_MERGE, +}; + static const enum dss_feat_id omap4_dss_feat_list[] = { FEAT_MGR_LCD2, FEAT_CORE_CLK_DIV, @@ -408,6 +425,7 @@ static const enum dss_feat_id omap4_dss_feat_list[] = { FEAT_DSI_VC_OCP_WIDTH, FEAT_DSI_GNQ, FEAT_HDMI_CTS_SWMODE, + FEAT_HDMI_AUDIO_USE_MCLK, FEAT_HANDLE_UV_SEPARATE, FEAT_ATTR2, FEAT_CPR, @@ -493,6 +511,25 @@ static const struct omap_dss_features omap4430_es1_0_dss_features = { .burst_size_unit = 16, }; +/* For OMAP4430 ES 2.0, 2.1 and 2.2 revisions */ +static const struct omap_dss_features omap4430_es2_0_1_2_dss_features = { + .reg_fields = omap4_dss_reg_fields, + .num_reg_fields = ARRAY_SIZE(omap4_dss_reg_fields), + + .features = omap4430_es2_0_1_2_dss_feat_list, + .num_features = ARRAY_SIZE(omap4430_es2_0_1_2_dss_feat_list), + + .num_mgrs = 3, + .num_ovls = 4, + .supported_displays = omap4_dss_supported_displays, + .supported_color_modes = omap4_dss_supported_color_modes, + .overlay_caps = omap4_dss_overlay_caps, + .clksrc_names = omap4_dss_clk_source_names, + .dss_params = omap4_dss_param_range, + .buffer_size_unit = 16, + .burst_size_unit = 16, +}; + /* For all the other OMAP4 versions */ static const struct omap_dss_features omap4_dss_features = { .reg_fields = omap4_dss_reg_fields, @@ -634,6 +671,10 @@ void dss_features_init(void) omap_current_dss_features = &omap3430_dss_features; else if (omap_rev() == OMAP4430_REV_ES1_0) omap_current_dss_features = &omap4430_es1_0_dss_features; + else if (omap_rev() == OMAP4430_REV_ES2_0 || + omap_rev() == OMAP4430_REV_ES2_1 || + omap_rev() == OMAP4430_REV_ES2_2) + omap_current_dss_features = &omap4430_es2_0_1_2_dss_features; else if (cpu_is_omap44xx()) omap_current_dss_features = &omap4_dss_features; else diff --git a/drivers/video/omap2/dss/dss_features.h b/drivers/video/omap2/dss/dss_features.h index 682f091cf02..c332e7ddfce 100644 --- a/drivers/video/omap2/dss/dss_features.h +++ b/drivers/video/omap2/dss/dss_features.h @@ -50,6 +50,7 @@ enum dss_feat_id { FEAT_DSI_REVERSE_TXCLKESC, FEAT_DSI_GNQ, FEAT_HDMI_CTS_SWMODE, + FEAT_HDMI_AUDIO_USE_MCLK, FEAT_HANDLE_UV_SEPARATE, FEAT_ATTR2, FEAT_VENC_REQUIRES_TV_DAC_CLK, -- cgit v1.2.3 From d8989d96eb35335e4e464369da7bdb28e8c84a9f Mon Sep 17 00:00:00 2001 From: Ricardo Neri Date: Tue, 31 Jan 2012 13:36:06 -0600 Subject: OMAPDSS: HDMI: Implement initialization of MCLK When the MCLK is used to drive the Audio Clock Regeneration packets, the initialization procedure is to set ACR_CTRL[2] to 0 and then back again to 1. Also, devices that do not support the MCLK, use the TMDS clock directly by leaving ACR_CTRL[2] set to 0. The MLCK clock divisor, mclk_mode, is configured only if MLCK is used. Such configuration is no longer related to the CTS mode as in some silicon revisions CTS SW-mode is used along with the MCLK. Signed-off-by: Ricardo Neri Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c | 37 ++++++++++++++++++------------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c index b9b97f172cd..bb784d2329b 100644 --- a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c +++ b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c @@ -1068,13 +1068,9 @@ void hdmi_core_audio_config(struct hdmi_ip_data *ip_data, u32 r; void __iomem *av_base = hdmi_av_base(ip_data); - /* audio clock recovery parameters */ - r = hdmi_read_reg(av_base, HDMI_CORE_AV_ACR_CTRL); - r = FLD_MOD(r, cfg->use_mclk, 2, 2); - r = FLD_MOD(r, cfg->en_acr_pkt, 1, 1); - r = FLD_MOD(r, cfg->cts_mode, 0, 0); - hdmi_write_reg(av_base, HDMI_CORE_AV_ACR_CTRL, r); - + /* + * Parameters for generation of Audio Clock Recovery packets + */ REG_FLD_MOD(av_base, HDMI_CORE_AV_N_SVAL1, cfg->n, 7, 0); REG_FLD_MOD(av_base, HDMI_CORE_AV_N_SVAL2, cfg->n >> 8, 7, 0); REG_FLD_MOD(av_base, HDMI_CORE_AV_N_SVAL3, cfg->n >> 16, 7, 0); @@ -1086,14 +1082,6 @@ void hdmi_core_audio_config(struct hdmi_ip_data *ip_data, REG_FLD_MOD(av_base, HDMI_CORE_AV_CTS_SVAL3, cfg->cts >> 16, 7, 0); } else { - /* - * HDMI IP uses this configuration to divide the MCLK to - * update CTS value. - */ - REG_FLD_MOD(av_base, - HDMI_CORE_AV_FREQ_SVAL, cfg->mclk_mode, 2, 0); - - /* Configure clock for audio packets */ REG_FLD_MOD(av_base, HDMI_CORE_AV_AUD_PAR_BUSCLK_1, cfg->aud_par_busclk, 7, 0); REG_FLD_MOD(av_base, HDMI_CORE_AV_AUD_PAR_BUSCLK_2, @@ -1102,6 +1090,25 @@ void hdmi_core_audio_config(struct hdmi_ip_data *ip_data, (cfg->aud_par_busclk >> 16), 7, 0); } + /* Set ACR clock divisor */ + REG_FLD_MOD(av_base, + HDMI_CORE_AV_FREQ_SVAL, cfg->mclk_mode, 2, 0); + + r = hdmi_read_reg(av_base, HDMI_CORE_AV_ACR_CTRL); + /* + * Use TMDS clock for ACR packets. For devices that use + * the MCLK, this is the first part of the MCLK initialization. + */ + r = FLD_MOD(r, 0, 2, 2); + + r = FLD_MOD(r, cfg->en_acr_pkt, 1, 1); + r = FLD_MOD(r, cfg->cts_mode, 0, 0); + hdmi_write_reg(av_base, HDMI_CORE_AV_ACR_CTRL, r); + + /* For devices using MCLK, this completes its initialization. */ + if (cfg->use_mclk) + REG_FLD_MOD(av_base, HDMI_CORE_AV_ACR_CTRL, 1, 2, 2); + /* Override of SPDIF sample frequency with value in I2S_CHST4 */ REG_FLD_MOD(av_base, HDMI_CORE_AV_SPDIF_CTRL, cfg->fs_override, 1, 1); -- cgit v1.2.3 From f15511e23db4e1deb6bf6a3c88c04ba85434e142 Mon Sep 17 00:00:00 2001 From: Ricardo Neri Date: Tue, 31 Jan 2012 15:56:16 -0600 Subject: OMAPDSS: HDMI: Modify logic to configure MCLK The MCLK mode defines a factor to divide the clock that is used to generate the Audio Clock Regeneration packets, MCLK. The divisor is not used when the CTS value is calculated by HW. When the value is calculated by SW, it depends on the silicon revision. Signed-off-by: Ricardo Neri Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/hdmi.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c index ec902b3c2de..012ee49c78d 100644 --- a/drivers/video/omap2/dss/hdmi.c +++ b/drivers/video/omap2/dss/hdmi.c @@ -667,13 +667,15 @@ static int hdmi_audio_hw_params(struct snd_pcm_substream *substream, if (dss_has_feature(FEAT_HDMI_CTS_SWMODE)) { core_cfg.aud_par_busclk = 0; core_cfg.cts_mode = HDMI_AUDIO_CTS_MODE_SW; - core_cfg.use_mclk = false; + core_cfg.use_mclk = dss_has_feature(FEAT_HDMI_AUDIO_USE_MCLK); } else { core_cfg.aud_par_busclk = (((128 * 31) - 1) << 8); core_cfg.cts_mode = HDMI_AUDIO_CTS_MODE_HW; core_cfg.use_mclk = true; - core_cfg.mclk_mode = HDMI_AUDIO_MCLK_128FS; } + + if (core_cfg.use_mclk) + core_cfg.mclk_mode = HDMI_AUDIO_MCLK_128FS; core_cfg.layout = HDMI_AUDIO_LAYOUT_2CH; core_cfg.en_spdif = false; /* Use sample frequency from channel status word */ -- cgit v1.2.3 From fdcb68884b3b0def9cc410d07adbafe7c3a9e537 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Tue, 10 May 2011 17:31:20 +0300 Subject: OMAPFB: remove old blizzard driver N8x0's blizzard driver has been ported to new omapdss driver, so we can now remove the old blizzard driver. Signed-off-by: Tomi Valkeinen --- arch/arm/plat-omap/include/plat/blizzard.h | 12 - drivers/video/omap/Kconfig | 7 - drivers/video/omap/Makefile | 1 - drivers/video/omap/blizzard.c | 1648 ---------------------------- drivers/video/omap/omapfb_main.c | 4 - 5 files changed, 1672 deletions(-) delete mode 100644 arch/arm/plat-omap/include/plat/blizzard.h delete mode 100644 drivers/video/omap/blizzard.c diff --git a/arch/arm/plat-omap/include/plat/blizzard.h b/arch/arm/plat-omap/include/plat/blizzard.h deleted file mode 100644 index 56e7f2e7d12..00000000000 --- a/arch/arm/plat-omap/include/plat/blizzard.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef _BLIZZARD_H -#define _BLIZZARD_H - -struct blizzard_platform_data { - void (*power_up)(struct device *dev); - void (*power_down)(struct device *dev); - unsigned long (*get_clock_rate)(struct device *dev); - - unsigned te_connected:1; -}; - -#endif diff --git a/drivers/video/omap/Kconfig b/drivers/video/omap/Kconfig index 84ff23208c2..ab234d59711 100644 --- a/drivers/video/omap/Kconfig +++ b/drivers/video/omap/Kconfig @@ -23,13 +23,6 @@ config FB_OMAP_LCDC_HWA742 Say Y here if you want to have support for the external Epson HWA742 LCD controller. -config FB_OMAP_LCDC_BLIZZARD - bool "Epson Blizzard LCD controller support" - depends on FB_OMAP && FB_OMAP_LCDC_EXTERNAL - help - Say Y here if you want to have support for the external - Epson Blizzard LCD controller. - config FB_OMAP_MANUAL_UPDATE bool "Default to manual update mode" depends on FB_OMAP && FB_OMAP_LCDC_EXTERNAL diff --git a/drivers/video/omap/Makefile b/drivers/video/omap/Makefile index ef78550917f..7042a4ac707 100644 --- a/drivers/video/omap/Makefile +++ b/drivers/video/omap/Makefile @@ -14,7 +14,6 @@ objs-$(CONFIG_ARCH_OMAP1)$(CONFIG_FB_OMAP_LCDC_EXTERNAL) += sossi.o objs-$(CONFIG_ARCH_OMAP2)$(CONFIG_FB_OMAP_LCDC_EXTERNAL) += rfbi.o objs-y$(CONFIG_FB_OMAP_LCDC_HWA742) += hwa742.o -objs-y$(CONFIG_FB_OMAP_LCDC_BLIZZARD) += blizzard.o objs-y$(CONFIG_MACH_AMS_DELTA) += lcd_ams_delta.o objs-y$(CONFIG_MACH_OMAP_H3) += lcd_h3.o diff --git a/drivers/video/omap/blizzard.c b/drivers/video/omap/blizzard.c deleted file mode 100644 index c0504a8a507..00000000000 --- a/drivers/video/omap/blizzard.c +++ /dev/null @@ -1,1648 +0,0 @@ -/* - * Epson Blizzard LCD controller driver - * - * Copyright (C) 2004-2005 Nokia Corporation - * Authors: Juha Yrjola - * Imre Deak - * YUV support: Jussi Laako - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ -#include -#include -#include -#include -#include - -#include -#include - -#include "omapfb.h" -#include "dispc.h" - -#define MODULE_NAME "blizzard" - -#define BLIZZARD_REV_CODE 0x00 -#define BLIZZARD_CONFIG 0x02 -#define BLIZZARD_PLL_DIV 0x04 -#define BLIZZARD_PLL_LOCK_RANGE 0x06 -#define BLIZZARD_PLL_CLOCK_SYNTH_0 0x08 -#define BLIZZARD_PLL_CLOCK_SYNTH_1 0x0a -#define BLIZZARD_PLL_MODE 0x0c -#define BLIZZARD_CLK_SRC 0x0e -#define BLIZZARD_MEM_BANK0_ACTIVATE 0x10 -#define BLIZZARD_MEM_BANK0_STATUS 0x14 -#define BLIZZARD_PANEL_CONFIGURATION 0x28 -#define BLIZZARD_HDISP 0x2a -#define BLIZZARD_HNDP 0x2c -#define BLIZZARD_VDISP0 0x2e -#define BLIZZARD_VDISP1 0x30 -#define BLIZZARD_VNDP 0x32 -#define BLIZZARD_HSW 0x34 -#define BLIZZARD_VSW 0x38 -#define BLIZZARD_DISPLAY_MODE 0x68 -#define BLIZZARD_INPUT_WIN_X_START_0 0x6c -#define BLIZZARD_DATA_SOURCE_SELECT 0x8e -#define BLIZZARD_DISP_MEM_DATA_PORT 0x90 -#define BLIZZARD_DISP_MEM_READ_ADDR0 0x92 -#define BLIZZARD_POWER_SAVE 0xE6 -#define BLIZZARD_NDISP_CTRL_STATUS 0xE8 - -/* Data source select */ -/* For S1D13745 */ -#define BLIZZARD_SRC_WRITE_LCD_BACKGROUND 0x00 -#define BLIZZARD_SRC_WRITE_LCD_DESTRUCTIVE 0x01 -#define BLIZZARD_SRC_WRITE_OVERLAY_ENABLE 0x04 -#define BLIZZARD_SRC_DISABLE_OVERLAY 0x05 -/* For S1D13744 */ -#define BLIZZARD_SRC_WRITE_LCD 0x00 -#define BLIZZARD_SRC_BLT_LCD 0x06 - -#define BLIZZARD_COLOR_RGB565 0x01 -#define BLIZZARD_COLOR_YUV420 0x09 - -#define BLIZZARD_VERSION_S1D13745 0x01 /* Hailstorm */ -#define BLIZZARD_VERSION_S1D13744 0x02 /* Blizzard */ - -#define BLIZZARD_AUTO_UPDATE_TIME (HZ / 20) - -/* Reserve 4 request slots for requests in irq context */ -#define REQ_POOL_SIZE 24 -#define IRQ_REQ_POOL_SIZE 4 - -#define REQ_FROM_IRQ_POOL 0x01 - -#define REQ_COMPLETE 0 -#define REQ_PENDING 1 - -struct blizzard_reg_list { - int start; - int end; -}; - -/* These need to be saved / restored separately from the rest. */ -static const struct blizzard_reg_list blizzard_pll_regs[] = { - { - .start = 0x04, /* Don't save PLL ctrl (0x0C) */ - .end = 0x0a, - }, - { - .start = 0x0e, /* Clock configuration */ - .end = 0x0e, - }, -}; - -static const struct blizzard_reg_list blizzard_gen_regs[] = { - { - .start = 0x18, /* SDRAM control */ - .end = 0x20, - }, - { - .start = 0x28, /* LCD Panel configuration */ - .end = 0x5a, /* HSSI interface, TV configuration */ - }, -}; - -static u8 blizzard_reg_cache[0x5a / 2]; - -struct update_param { - int plane; - int x, y, width, height; - int out_x, out_y; - int out_width, out_height; - int color_mode; - int bpp; - int flags; -}; - -struct blizzard_request { - struct list_head entry; - unsigned int flags; - - int (*handler)(struct blizzard_request *req); - void (*complete)(void *data); - void *complete_data; - - union { - struct update_param update; - struct completion *sync; - } par; -}; - -struct plane_info { - unsigned long offset; - int pos_x, pos_y; - int width, height; - int out_width, out_height; - int scr_width; - int color_mode; - int bpp; -}; - -struct blizzard_struct { - enum omapfb_update_mode update_mode; - enum omapfb_update_mode update_mode_before_suspend; - - struct timer_list auto_update_timer; - int stop_auto_update; - struct omapfb_update_window auto_update_window; - int enabled_planes; - int vid_nonstd_color; - int vid_scaled; - int last_color_mode; - int zoom_on; - int zoom_area_gx1; - int zoom_area_gx2; - int zoom_area_gy1; - int zoom_area_gy2; - int screen_width; - int screen_height; - unsigned te_connected:1; - unsigned vsync_only:1; - - struct plane_info plane[OMAPFB_PLANE_NUM]; - - struct blizzard_request req_pool[REQ_POOL_SIZE]; - struct list_head pending_req_list; - struct list_head free_req_list; - struct semaphore req_sema; - spinlock_t req_lock; - - unsigned long sys_ck_rate; - struct extif_timings reg_timings, lut_timings; - - u32 max_transmit_size; - u32 extif_clk_period; - int extif_clk_div; - unsigned long pix_tx_time; - unsigned long line_upd_time; - - struct omapfb_device *fbdev; - struct lcd_ctrl_extif *extif; - const struct lcd_ctrl *int_ctrl; - - void (*power_up)(struct device *dev); - void (*power_down)(struct device *dev); - - int version; -} blizzard; - -struct lcd_ctrl blizzard_ctrl; - -static u8 blizzard_read_reg(u8 reg) -{ - u8 data; - - blizzard.extif->set_bits_per_cycle(8); - blizzard.extif->write_command(®, 1); - blizzard.extif->read_data(&data, 1); - - return data; -} - -static void blizzard_write_reg(u8 reg, u8 val) -{ - blizzard.extif->set_bits_per_cycle(8); - blizzard.extif->write_command(®, 1); - blizzard.extif->write_data(&val, 1); -} - -static void blizzard_restart_sdram(void) -{ - unsigned long tmo; - - blizzard_write_reg(BLIZZARD_MEM_BANK0_ACTIVATE, 0); - udelay(50); - blizzard_write_reg(BLIZZARD_MEM_BANK0_ACTIVATE, 1); - tmo = jiffies + msecs_to_jiffies(200); - while (!(blizzard_read_reg(BLIZZARD_MEM_BANK0_STATUS) & 0x01)) { - if (time_after(jiffies, tmo)) { - dev_err(blizzard.fbdev->dev, - "s1d1374x: SDRAM not ready\n"); - break; - } - msleep(1); - } -} - -static void blizzard_stop_sdram(void) -{ - blizzard_write_reg(BLIZZARD_MEM_BANK0_ACTIVATE, 0); -} - -/* Wait until the last window was completely written into the controllers - * SDRAM and we can start transferring the next window. - */ -static void blizzard_wait_line_buffer(void) -{ - unsigned long tmo = jiffies + msecs_to_jiffies(30); - - while (blizzard_read_reg(BLIZZARD_NDISP_CTRL_STATUS) & (1 << 7)) { - if (time_after(jiffies, tmo)) { - if (printk_ratelimit()) - dev_err(blizzard.fbdev->dev, - "s1d1374x: line buffer not ready\n"); - break; - } - } -} - -/* Wait until the YYC color space converter is idle. */ -static void blizzard_wait_yyc(void) -{ - unsigned long tmo = jiffies + msecs_to_jiffies(30); - - while (blizzard_read_reg(BLIZZARD_NDISP_CTRL_STATUS) & (1 << 4)) { - if (time_after(jiffies, tmo)) { - if (printk_ratelimit()) - dev_err(blizzard.fbdev->dev, - "s1d1374x: YYC not ready\n"); - break; - } - } -} - -static void disable_overlay(void) -{ - blizzard_write_reg(BLIZZARD_DATA_SOURCE_SELECT, - BLIZZARD_SRC_DISABLE_OVERLAY); -} - -static void set_window_regs(int x_start, int y_start, int x_end, int y_end, - int x_out_start, int y_out_start, - int x_out_end, int y_out_end, int color_mode, - int zoom_off, int flags) -{ - u8 tmp[18]; - u8 cmd; - - x_end--; - y_end--; - tmp[0] = x_start; - tmp[1] = x_start >> 8; - tmp[2] = y_start; - tmp[3] = y_start >> 8; - tmp[4] = x_end; - tmp[5] = x_end >> 8; - tmp[6] = y_end; - tmp[7] = y_end >> 8; - - x_out_end--; - y_out_end--; - tmp[8] = x_out_start; - tmp[9] = x_out_start >> 8; - tmp[10] = y_out_start; - tmp[11] = y_out_start >> 8; - tmp[12] = x_out_end; - tmp[13] = x_out_end >> 8; - tmp[14] = y_out_end; - tmp[15] = y_out_end >> 8; - - tmp[16] = color_mode; - if (zoom_off && blizzard.version == BLIZZARD_VERSION_S1D13745) - tmp[17] = BLIZZARD_SRC_WRITE_LCD_BACKGROUND; - else if (flags & OMAPFB_FORMAT_FLAG_ENABLE_OVERLAY) - tmp[17] = BLIZZARD_SRC_WRITE_OVERLAY_ENABLE; - else - tmp[17] = blizzard.version == BLIZZARD_VERSION_S1D13744 ? - BLIZZARD_SRC_WRITE_LCD : - BLIZZARD_SRC_WRITE_LCD_DESTRUCTIVE; - - blizzard.extif->set_bits_per_cycle(8); - cmd = BLIZZARD_INPUT_WIN_X_START_0; - blizzard.extif->write_command(&cmd, 1); - blizzard.extif->write_data(tmp, 18); -} - -static void enable_tearsync(int y, int width, int height, int screen_height, - int out_height, int force_vsync) -{ - u8 b; - - b = blizzard_read_reg(BLIZZARD_NDISP_CTRL_STATUS); - b |= 1 << 3; - blizzard_write_reg(BLIZZARD_NDISP_CTRL_STATUS, b); - - if (likely(blizzard.vsync_only || force_vsync)) { - blizzard.extif->enable_tearsync(1, 0); - return; - } - - if (width * blizzard.pix_tx_time < blizzard.line_upd_time) { - blizzard.extif->enable_tearsync(1, 0); - return; - } - - if ((width * blizzard.pix_tx_time / 1000) * height < - (y + out_height) * (blizzard.line_upd_time / 1000)) { - blizzard.extif->enable_tearsync(1, 0); - return; - } - - blizzard.extif->enable_tearsync(1, y + 1); -} - -static void disable_tearsync(void) -{ - u8 b; - - blizzard.extif->enable_tearsync(0, 0); - b = blizzard_read_reg(BLIZZARD_NDISP_CTRL_STATUS); - b &= ~(1 << 3); - blizzard_write_reg(BLIZZARD_NDISP_CTRL_STATUS, b); - b = blizzard_read_reg(BLIZZARD_NDISP_CTRL_STATUS); -} - -static inline void set_extif_timings(const struct extif_timings *t); - -static inline struct blizzard_request *alloc_req(void) -{ - unsigned long flags; - struct blizzard_request *req; - int req_flags = 0; - - if (!in_interrupt()) - down(&blizzard.req_sema); - else - req_flags = REQ_FROM_IRQ_POOL; - - spin_lock_irqsave(&blizzard.req_lock, flags); - BUG_ON(list_empty(&blizzard.free_req_list)); - req = list_entry(blizzard.free_req_list.next, - struct blizzard_request, entry); - list_del(&req->entry); - spin_unlock_irqrestore(&blizzard.req_lock, flags); - - INIT_LIST_HEAD(&req->entry); - req->flags = req_flags; - - return req; -} - -static inline void free_req(struct blizzard_request *req) -{ - unsigned long flags; - - spin_lock_irqsave(&blizzard.req_lock, flags); - - list_move(&req->entry, &blizzard.free_req_list); - if (!(req->flags & REQ_FROM_IRQ_POOL)) - up(&blizzard.req_sema); - - spin_unlock_irqrestore(&blizzard.req_lock, flags); -} - -static void process_pending_requests(void) -{ - unsigned long flags; - - spin_lock_irqsave(&blizzard.req_lock, flags); - - while (!list_empty(&blizzard.pending_req_list)) { - struct blizzard_request *req; - void (*complete)(void *); - void *complete_data; - - req = list_entry(blizzard.pending_req_list.next, - struct blizzard_request, entry); - spin_unlock_irqrestore(&blizzard.req_lock, flags); - - if (req->handler(req) == REQ_PENDING) - return; - - complete = req->complete; - complete_data = req->complete_data; - free_req(req); - - if (complete) - complete(complete_data); - - spin_lock_irqsave(&blizzard.req_lock, flags); - } - - spin_unlock_irqrestore(&blizzard.req_lock, flags); -} - -static void submit_req_list(struct list_head *head) -{ - unsigned long flags; - int process = 1; - - spin_lock_irqsave(&blizzard.req_lock, flags); - if (likely(!list_empty(&blizzard.pending_req_list))) - process = 0; - list_splice_init(head, blizzard.pending_req_list.prev); - spin_unlock_irqrestore(&blizzard.req_lock, flags); - - if (process) - process_pending_requests(); -} - -static void request_complete(void *data) -{ - struct blizzard_request *req = (struct blizzard_request *)data; - void (*complete)(void *); - void *complete_data; - - complete = req->complete; - complete_data = req->complete_data; - - free_req(req); - - if (complete) - complete(complete_data); - - process_pending_requests(); -} - - -static int do_full_screen_update(struct blizzard_request *req) -{ - int i; - int flags; - - for (i = 0; i < 3; i++) { - struct plane_info *p = &blizzard.plane[i]; - if (!(blizzard.enabled_planes & (1 << i))) { - blizzard.int_ctrl->enable_plane(i, 0); - continue; - } - dev_dbg(blizzard.fbdev->dev, "pw %d ph %d\n", - p->width, p->height); - blizzard.int_ctrl->setup_plane(i, - OMAPFB_CHANNEL_OUT_LCD, p->offset, - p->scr_width, p->pos_x, p->pos_y, - p->width, p->height, - p->color_mode); - blizzard.int_ctrl->enable_plane(i, 1); - } - - dev_dbg(blizzard.fbdev->dev, "sw %d sh %d\n", - blizzard.screen_width, blizzard.screen_height); - blizzard_wait_line_buffer(); - flags = req->par.update.flags; - if (flags & OMAPFB_FORMAT_FLAG_TEARSYNC) - enable_tearsync(0, blizzard.screen_width, - blizzard.screen_height, - blizzard.screen_height, - blizzard.screen_height, - flags & OMAPFB_FORMAT_FLAG_FORCE_VSYNC); - else - disable_tearsync(); - - set_window_regs(0, 0, blizzard.screen_width, blizzard.screen_height, - 0, 0, blizzard.screen_width, blizzard.screen_height, - BLIZZARD_COLOR_RGB565, blizzard.zoom_on, flags); - blizzard.zoom_on = 0; - - blizzard.extif->set_bits_per_cycle(16); - /* set_window_regs has left the register index at the right - * place, so no need to set it here. - */ - blizzard.extif->transfer_area(blizzard.screen_width, - blizzard.screen_height, - request_complete, req); - return REQ_PENDING; -} - -static int check_1d_intersect(int a1, int a2, int b1, int b2) -{ - if (a2 <= b1 || b2 <= a1) - return 0; - return 1; -} - -/* Setup all planes with an overlapping area with the update window. */ -static int do_partial_update(struct blizzard_request *req, int plane, - int x, int y, int w, int h, - int x_out, int y_out, int w_out, int h_out, - int wnd_color_mode, int bpp) -{ - int i; - int gx1, gy1, gx2, gy2; - int gx1_out, gy1_out, gx2_out, gy2_out; - int color_mode; - int flags; - int zoom_off; - int have_zoom_for_this_update = 0; - - /* Global coordinates, relative to pixel 0,0 of the LCD */ - gx1 = x + blizzard.plane[plane].pos_x; - gy1 = y + blizzard.plane[plane].pos_y; - gx2 = gx1 + w; - gy2 = gy1 + h; - - flags = req->par.update.flags; - if (flags & OMAPFB_FORMAT_FLAG_DOUBLE) { - gx1_out = gx1; - gy1_out = gy1; - gx2_out = gx1 + w * 2; - gy2_out = gy1 + h * 2; - } else { - gx1_out = x_out + blizzard.plane[plane].pos_x; - gy1_out = y_out + blizzard.plane[plane].pos_y; - gx2_out = gx1_out + w_out; - gy2_out = gy1_out + h_out; - } - - for (i = 0; i < OMAPFB_PLANE_NUM; i++) { - struct plane_info *p = &blizzard.plane[i]; - int px1, py1; - int px2, py2; - int pw, ph; - int pposx, pposy; - unsigned long offset; - - if (!(blizzard.enabled_planes & (1 << i)) || - (wnd_color_mode && i != plane)) { - blizzard.int_ctrl->enable_plane(i, 0); - continue; - } - /* Plane coordinates */ - if (i == plane) { - /* Plane in which we are doing the update. - * Local coordinates are the one in the update - * request. - */ - px1 = x; - py1 = y; - px2 = x + w; - py2 = y + h; - pposx = 0; - pposy = 0; - } else { - /* Check if this plane has an overlapping part */ - px1 = gx1 - p->pos_x; - py1 = gy1 - p->pos_y; - px2 = gx2 - p->pos_x; - py2 = gy2 - p->pos_y; - if (px1 >= p->width || py1 >= p->height || - px2 <= 0 || py2 <= 0) { - blizzard.int_ctrl->enable_plane(i, 0); - continue; - } - /* Calculate the coordinates for the overlapping - * part in the plane's local coordinates. - */ - pposx = -px1; - pposy = -py1; - if (px1 < 0) - px1 = 0; - if (py1 < 0) - py1 = 0; - if (px2 > p->width) - px2 = p->width; - if (py2 > p->height) - py2 = p->height; - if (pposx < 0) - pposx = 0; - if (pposy < 0) - pposy = 0; - } - pw = px2 - px1; - ph = py2 - py1; - offset = p->offset + (p->scr_width * py1 + px1) * p->bpp / 8; - if (wnd_color_mode) - /* Window embedded in the plane with a differing - * color mode / bpp. Calculate the number of DMA - * transfer elements in terms of the plane's bpp. - */ - pw = (pw + 1) * bpp / p->bpp; -#ifdef VERBOSE - dev_dbg(blizzard.fbdev->dev, - "plane %d offset %#08lx pposx %d pposy %d " - "px1 %d py1 %d pw %d ph %d\n", - i, offset, pposx, pposy, px1, py1, pw, ph); -#endif - blizzard.int_ctrl->setup_plane(i, - OMAPFB_CHANNEL_OUT_LCD, offset, - p->scr_width, - pposx, pposy, pw, ph, - p->color_mode); - - blizzard.int_ctrl->enable_plane(i, 1); - } - - switch (wnd_color_mode) { - case OMAPFB_COLOR_YUV420: - color_mode = BLIZZARD_COLOR_YUV420; - /* Currently only the 16 bits/pixel cycle format is - * supported on the external interface. Adjust the number - * of transfer elements per line for 12bpp format. - */ - w = (w + 1) * 3 / 4; - break; - default: - color_mode = BLIZZARD_COLOR_RGB565; - break; - } - - blizzard_wait_line_buffer(); - if (blizzard.last_color_mode == BLIZZARD_COLOR_YUV420) - blizzard_wait_yyc(); - blizzard.last_color_mode = color_mode; - if (flags & OMAPFB_FORMAT_FLAG_TEARSYNC) - enable_tearsync(gy1, w, h, - blizzard.screen_height, - h_out, - flags & OMAPFB_FORMAT_FLAG_FORCE_VSYNC); - else - disable_tearsync(); - - if ((gx2_out - gx1_out) != (gx2 - gx1) || - (gy2_out - gy1_out) != (gy2 - gy1)) - have_zoom_for_this_update = 1; - - /* 'background' type of screen update (as opposed to 'destructive') - can be used to disable scaling if scaling is active */ - zoom_off = blizzard.zoom_on && !have_zoom_for_this_update && - (gx1_out == 0) && (gx2_out == blizzard.screen_width) && - (gy1_out == 0) && (gy2_out == blizzard.screen_height) && - (gx1 == 0) && (gy1 == 0); - - if (blizzard.zoom_on && !have_zoom_for_this_update && !zoom_off && - check_1d_intersect(blizzard.zoom_area_gx1, blizzard.zoom_area_gx2, - gx1_out, gx2_out) && - check_1d_intersect(blizzard.zoom_area_gy1, blizzard.zoom_area_gy2, - gy1_out, gy2_out)) { - /* Previous screen update was using scaling, current update - * is not using it. Additionally, current screen update is - * going to overlap with the scaled area. Scaling needs to be - * disabled in order to avoid 'magnifying glass' effect. - * Dummy setup of background window can be used for this. - */ - set_window_regs(0, 0, blizzard.screen_width, - blizzard.screen_height, - 0, 0, blizzard.screen_width, - blizzard.screen_height, - BLIZZARD_COLOR_RGB565, 1, flags); - blizzard.zoom_on = 0; - } - - /* remember scaling settings if we have scaled update */ - if (have_zoom_for_this_update) { - blizzard.zoom_on = 1; - blizzard.zoom_area_gx1 = gx1_out; - blizzard.zoom_area_gx2 = gx2_out; - blizzard.zoom_area_gy1 = gy1_out; - blizzard.zoom_area_gy2 = gy2_out; - } - - set_window_regs(gx1, gy1, gx2, gy2, gx1_out, gy1_out, gx2_out, gy2_out, - color_mode, zoom_off, flags); - if (zoom_off) - blizzard.zoom_on = 0; - - blizzard.extif->set_bits_per_cycle(16); - /* set_window_regs has left the register index at the right - * place, so no need to set it here. - */ - blizzard.extif->transfer_area(w, h, request_complete, req); - - return REQ_PENDING; -} - -static int send_frame_handler(struct blizzard_request *req) -{ - struct update_param *par = &req->par.update; - int plane = par->plane; - -#ifdef VERBOSE - dev_dbg(blizzard.fbdev->dev, - "send_frame: x %d y %d w %d h %d " - "x_out %d y_out %d w_out %d h_out %d " - "color_mode %04x flags %04x planes %01x\n", - par->x, par->y, par->width, par->height, - par->out_x, par->out_y, par->out_width, par->out_height, - par->color_mode, par->flags, blizzard.enabled_planes); -#endif - if (par->flags & OMAPFB_FORMAT_FLAG_DISABLE_OVERLAY) - disable_overlay(); - - if ((blizzard.enabled_planes & blizzard.vid_nonstd_color) || - (blizzard.enabled_planes & blizzard.vid_scaled)) - return do_full_screen_update(req); - - return do_partial_update(req, plane, par->x, par->y, - par->width, par->height, - par->out_x, par->out_y, - par->out_width, par->out_height, - par->color_mode, par->bpp); -} - -static void send_frame_complete(void *data) -{ -} - -#define ADD_PREQ(_x, _y, _w, _h, _x_out, _y_out, _w_out, _h_out) do { \ - req = alloc_req(); \ - req->handler = send_frame_handler; \ - req->complete = send_frame_complete; \ - req->par.update.plane = plane_idx; \ - req->par.update.x = _x; \ - req->par.update.y = _y; \ - req->par.update.width = _w; \ - req->par.update.height = _h; \ - req->par.update.out_x = _x_out; \ - req->par.update.out_y = _y_out; \ - req->par.update.out_width = _w_out; \ - req->par.update.out_height = _h_out; \ - req->par.update.bpp = bpp; \ - req->par.update.color_mode = color_mode;\ - req->par.update.flags = flags; \ - list_add_tail(&req->entry, req_head); \ -} while(0) - -static void create_req_list(int plane_idx, - struct omapfb_update_window *win, - struct list_head *req_head) -{ - struct blizzard_request *req; - int x = win->x; - int y = win->y; - int width = win->width; - int height = win->height; - int x_out = win->out_x; - int y_out = win->out_y; - int width_out = win->out_width; - int height_out = win->out_height; - int color_mode; - int bpp; - int flags; - unsigned int ystart = y; - unsigned int yspan = height; - unsigned int ystart_out = y_out; - unsigned int yspan_out = height_out; - - flags = win->format & ~OMAPFB_FORMAT_MASK; - color_mode = win->format & OMAPFB_FORMAT_MASK; - switch (color_mode) { - case OMAPFB_COLOR_YUV420: - /* Embedded window with different color mode */ - bpp = 12; - /* X, Y, height must be aligned at 2, width at 4 pixels */ - x &= ~1; - y &= ~1; - height = yspan = height & ~1; - width = width & ~3; - break; - default: - /* Same as the plane color mode */ - bpp = blizzard.plane[plane_idx].bpp; - break; - } - if (width * height * bpp / 8 > blizzard.max_transmit_size) { - yspan = blizzard.max_transmit_size / (width * bpp / 8); - yspan_out = yspan * height_out / height; - ADD_PREQ(x, ystart, width, yspan, x_out, ystart_out, - width_out, yspan_out); - ystart += yspan; - ystart_out += yspan_out; - yspan = height - yspan; - yspan_out = height_out - yspan_out; - flags &= ~OMAPFB_FORMAT_FLAG_TEARSYNC; - } - - ADD_PREQ(x, ystart, width, yspan, x_out, ystart_out, - width_out, yspan_out); -} - -static void auto_update_complete(void *data) -{ - if (!blizzard.stop_auto_update) - mod_timer(&blizzard.auto_update_timer, - jiffies + BLIZZARD_AUTO_UPDATE_TIME); -} - -static void blizzard_update_window_auto(unsigned long arg) -{ - LIST_HEAD(req_list); - struct blizzard_request *last; - struct omapfb_plane_struct *plane; - - plane = blizzard.fbdev->fb_info[0]->par; - create_req_list(plane->idx, - &blizzard.auto_update_window, &req_list); - last = list_entry(req_list.prev, struct blizzard_request, entry); - - last->complete = auto_update_complete; - last->complete_data = NULL; - - submit_req_list(&req_list); -} - -int blizzard_update_window_async(struct fb_info *fbi, - struct omapfb_update_window *win, - void (*complete_callback)(void *arg), - void *complete_callback_data) -{ - LIST_HEAD(req_list); - struct blizzard_request *last; - struct omapfb_plane_struct *plane = fbi->par; - - if (unlikely(blizzard.update_mode != OMAPFB_MANUAL_UPDATE)) - return -EINVAL; - if (unlikely(!blizzard.te_connected && - (win->format & OMAPFB_FORMAT_FLAG_TEARSYNC))) - return -EINVAL; - - create_req_list(plane->idx, win, &req_list); - last = list_entry(req_list.prev, struct blizzard_request, entry); - - last->complete = complete_callback; - last->complete_data = (void *)complete_callback_data; - - submit_req_list(&req_list); - - return 0; -} -EXPORT_SYMBOL(blizzard_update_window_async); - -static int update_full_screen(void) -{ - return blizzard_update_window_async(blizzard.fbdev->fb_info[0], - &blizzard.auto_update_window, NULL, NULL); - -} - -static int blizzard_setup_plane(int plane, int channel_out, - unsigned long offset, int screen_width, - int pos_x, int pos_y, int width, int height, - int color_mode) -{ - struct plane_info *p; - -#ifdef VERBOSE - dev_dbg(blizzard.fbdev->dev, - "plane %d ch_out %d offset %#08lx scr_width %d " - "pos_x %d pos_y %d width %d height %d color_mode %d\n", - plane, channel_out, offset, screen_width, - pos_x, pos_y, width, height, color_mode); -#endif - if ((unsigned)plane > OMAPFB_PLANE_NUM) - return -EINVAL; - p = &blizzard.plane[plane]; - - switch (color_mode) { - case OMAPFB_COLOR_YUV422: - case OMAPFB_COLOR_YUY422: - p->bpp = 16; - blizzard.vid_nonstd_color &= ~(1 << plane); - break; - case OMAPFB_COLOR_YUV420: - p->bpp = 12; - blizzard.vid_nonstd_color |= 1 << plane; - break; - case OMAPFB_COLOR_RGB565: - p->bpp = 16; - blizzard.vid_nonstd_color &= ~(1 << plane); - break; - default: - return -EINVAL; - } - - p->offset = offset; - p->pos_x = pos_x; - p->pos_y = pos_y; - p->width = width; - p->height = height; - p->scr_width = screen_width; - if (!p->out_width) - p->out_width = width; - if (!p->out_height) - p->out_height = height; - - p->color_mode = color_mode; - - return 0; -} - -static int blizzard_set_scale(int plane, int orig_w, int orig_h, - int out_w, int out_h) -{ - struct plane_info *p = &blizzard.plane[plane]; - int r; - - dev_dbg(blizzard.fbdev->dev, - "plane %d orig_w %d orig_h %d out_w %d out_h %d\n", - plane, orig_w, orig_h, out_w, out_h); - if ((unsigned)plane > OMAPFB_PLANE_NUM) - return -ENODEV; - - r = blizzard.int_ctrl->set_scale(plane, orig_w, orig_h, out_w, out_h); - if (r < 0) - return r; - - p->width = orig_w; - p->height = orig_h; - p->out_width = out_w; - p->out_height = out_h; - if (orig_w == out_w && orig_h == out_h) - blizzard.vid_scaled &= ~(1 << plane); - else - blizzard.vid_scaled |= 1 << plane; - - return 0; -} - -static int blizzard_set_rotate(int angle) -{ - u32 l; - - l = blizzard_read_reg(BLIZZARD_PANEL_CONFIGURATION); - l &= ~0x03; - - switch (angle) { - case 0: - l = l | 0x00; - break; - case 90: - l = l | 0x03; - break; - case 180: - l = l | 0x02; - break; - case 270: - l = l | 0x01; - break; - default: - return -EINVAL; - } - - blizzard_write_reg(BLIZZARD_PANEL_CONFIGURATION, l); - - return 0; -} - -static int blizzard_enable_plane(int plane, int enable) -{ - if (enable) - blizzard.enabled_planes |= 1 << plane; - else - blizzard.enabled_planes &= ~(1 << plane); - - return 0; -} - -static int sync_handler(struct blizzard_request *req) -{ - complete(req->par.sync); - return REQ_COMPLETE; -} - -static void blizzard_sync(void) -{ - LIST_HEAD(req_list); - struct blizzard_request *req; - struct completion comp; - - req = alloc_req(); - - req->handler = sync_handler; - req->complete = NULL; - init_completion(&comp); - req->par.sync = ∁ - - list_add(&req->entry, &req_list); - submit_req_list(&req_list); - - wait_for_completion(&comp); -} - - -static void blizzard_bind_client(struct omapfb_notifier_block *nb) -{ - if (blizzard.update_mode == OMAPFB_MANUAL_UPDATE) { - omapfb_notify_clients(blizzard.fbdev, OMAPFB_EVENT_READY); - } -} - -static int blizzard_set_update_mode(enum omapfb_update_mode mode) -{ - if (unlikely(mode != OMAPFB_MANUAL_UPDATE && - mode != OMAPFB_AUTO_UPDATE && - mode != OMAPFB_UPDATE_DISABLED)) - return -EINVAL; - - if (mode == blizzard.update_mode) - return 0; - - dev_info(blizzard.fbdev->dev, "s1d1374x: setting update mode to %s\n", - mode == OMAPFB_UPDATE_DISABLED ? "disabled" : - (mode == OMAPFB_AUTO_UPDATE ? "auto" : "manual")); - - switch (blizzard.update_mode) { - case OMAPFB_MANUAL_UPDATE: - omapfb_notify_clients(blizzard.fbdev, OMAPFB_EVENT_DISABLED); - break; - case OMAPFB_AUTO_UPDATE: - blizzard.stop_auto_update = 1; - del_timer_sync(&blizzard.auto_update_timer); - break; - case OMAPFB_UPDATE_DISABLED: - break; - } - - blizzard.update_mode = mode; - blizzard_sync(); - blizzard.stop_auto_update = 0; - - switch (mode) { - case OMAPFB_MANUAL_UPDATE: - omapfb_notify_clients(blizzard.fbdev, OMAPFB_EVENT_READY); - break; - case OMAPFB_AUTO_UPDATE: - blizzard_update_window_auto(0); - break; - case OMAPFB_UPDATE_DISABLED: - break; - } - - return 0; -} - -static enum omapfb_update_mode blizzard_get_update_mode(void) -{ - return blizzard.update_mode; -} - -static inline void set_extif_timings(const struct extif_timings *t) -{ - blizzard.extif->set_timings(t); -} - -static inline unsigned long round_to_extif_ticks(unsigned long ps, int div) -{ - int bus_tick = blizzard.extif_clk_period * div; - return (ps + bus_tick - 1) / bus_tick * bus_tick; -} - -static int calc_reg_timing(unsigned long sysclk, int div) -{ - struct extif_timings *t; - unsigned long systim; - - /* CSOnTime 0, WEOnTime 2 ns, REOnTime 2 ns, - * AccessTime 2 ns + 12.2 ns (regs), - * WEOffTime = WEOnTime + 1 ns, - * REOffTime = REOnTime + 12 ns (regs), - * CSOffTime = REOffTime + 1 ns - * ReadCycle = 2ns + 2*SYSCLK (regs), - * WriteCycle = 2*SYSCLK + 2 ns, - * CSPulseWidth = 10 ns */ - - systim = 1000000000 / (sysclk / 1000); - dev_dbg(blizzard.fbdev->dev, - "Blizzard systim %lu ps extif_clk_period %u div %d\n", - systim, blizzard.extif_clk_period, div); - - t = &blizzard.reg_timings; - memset(t, 0, sizeof(*t)); - - t->clk_div = div; - - t->cs_on_time = 0; - t->we_on_time = round_to_extif_ticks(t->cs_on_time + 2000, div); - t->re_on_time = round_to_extif_ticks(t->cs_on_time + 2000, div); - t->access_time = round_to_extif_ticks(t->re_on_time + 12200, div); - t->we_off_time = round_to_extif_ticks(t->we_on_time + 1000, div); - t->re_off_time = round_to_extif_ticks(t->re_on_time + 13000, div); - t->cs_off_time = round_to_extif_ticks(t->re_off_time + 1000, div); - t->we_cycle_time = round_to_extif_ticks(2 * systim + 2000, div); - if (t->we_cycle_time < t->we_off_time) - t->we_cycle_time = t->we_off_time; - t->re_cycle_time = round_to_extif_ticks(2 * systim + 2000, div); - if (t->re_cycle_time < t->re_off_time) - t->re_cycle_time = t->re_off_time; - t->cs_pulse_width = 0; - - dev_dbg(blizzard.fbdev->dev, "[reg]cson %d csoff %d reon %d reoff %d\n", - t->cs_on_time, t->cs_off_time, t->re_on_time, t->re_off_time); - dev_dbg(blizzard.fbdev->dev, "[reg]weon %d weoff %d recyc %d wecyc %d\n", - t->we_on_time, t->we_off_time, t->re_cycle_time, - t->we_cycle_time); - dev_dbg(blizzard.fbdev->dev, "[reg]rdaccess %d cspulse %d\n", - t->access_time, t->cs_pulse_width); - - return blizzard.extif->convert_timings(t); -} - -static int calc_lut_timing(unsigned long sysclk, int div) -{ - struct extif_timings *t; - unsigned long systim; - - /* CSOnTime 0, WEOnTime 2 ns, REOnTime 2 ns, - * AccessTime 2 ns + 4 * SYSCLK + 26 (lut), - * WEOffTime = WEOnTime + 1 ns, - * REOffTime = REOnTime + 4*SYSCLK + 26 ns (lut), - * CSOffTime = REOffTime + 1 ns - * ReadCycle = 2ns + 4*SYSCLK + 26 ns (lut), - * WriteCycle = 2*SYSCLK + 2 ns, - * CSPulseWidth = 10 ns */ - - systim = 1000000000 / (sysclk / 1000); - dev_dbg(blizzard.fbdev->dev, - "Blizzard systim %lu ps extif_clk_period %u div %d\n", - systim, blizzard.extif_clk_period, div); - - t = &blizzard.lut_timings; - memset(t, 0, sizeof(*t)); - - t->clk_div = div; - - t->cs_on_time = 0; - t->we_on_time = round_to_extif_ticks(t->cs_on_time + 2000, div); - t->re_on_time = round_to_extif_ticks(t->cs_on_time + 2000, div); - t->access_time = round_to_extif_ticks(t->re_on_time + 4 * systim + - 26000, div); - t->we_off_time = round_to_extif_ticks(t->we_on_time + 1000, div); - t->re_off_time = round_to_extif_ticks(t->re_on_time + 4 * systim + - 26000, div); - t->cs_off_time = round_to_extif_ticks(t->re_off_time + 1000, div); - t->we_cycle_time = round_to_extif_ticks(2 * systim + 2000, div); - if (t->we_cycle_time < t->we_off_time) - t->we_cycle_time = t->we_off_time; - t->re_cycle_time = round_to_extif_ticks(2000 + 4 * systim + 26000, div); - if (t->re_cycle_time < t->re_off_time) - t->re_cycle_time = t->re_off_time; - t->cs_pulse_width = 0; - - dev_dbg(blizzard.fbdev->dev, - "[lut]cson %d csoff %d reon %d reoff %d\n", - t->cs_on_time, t->cs_off_time, t->re_on_time, t->re_off_time); - dev_dbg(blizzard.fbdev->dev, - "[lut]weon %d weoff %d recyc %d wecyc %d\n", - t->we_on_time, t->we_off_time, t->re_cycle_time, - t->we_cycle_time); - dev_dbg(blizzard.fbdev->dev, "[lut]rdaccess %d cspulse %d\n", - t->access_time, t->cs_pulse_width); - - return blizzard.extif->convert_timings(t); -} - -static int calc_extif_timings(unsigned long sysclk, int *extif_mem_div) -{ - int max_clk_div; - int div; - - blizzard.extif->get_clk_info(&blizzard.extif_clk_period, &max_clk_div); - for (div = 1; div <= max_clk_div; div++) { - if (calc_reg_timing(sysclk, div) == 0) - break; - } - if (div > max_clk_div) { - dev_dbg(blizzard.fbdev->dev, "reg timing failed\n"); - goto err; - } - *extif_mem_div = div; - - for (div = 1; div <= max_clk_div; div++) { - if (calc_lut_timing(sysclk, div) == 0) - break; - } - - if (div > max_clk_div) - goto err; - - blizzard.extif_clk_div = div; - - return 0; -err: - dev_err(blizzard.fbdev->dev, "can't setup timings\n"); - return -1; -} - -static void calc_blizzard_clk_rates(unsigned long ext_clk, - unsigned long *sys_clk, unsigned long *pix_clk) -{ - int pix_clk_src; - int sys_div = 0, sys_mul = 0; - int pix_div; - - pix_clk_src = blizzard_read_reg(BLIZZARD_CLK_SRC); - pix_div = ((pix_clk_src >> 3) & 0x1f) + 1; - if ((pix_clk_src & (0x3 << 1)) == 0) { - /* Source is the PLL */ - sys_div = (blizzard_read_reg(BLIZZARD_PLL_DIV) & 0x3f) + 1; - sys_mul = blizzard_read_reg(BLIZZARD_PLL_CLOCK_SYNTH_0); - sys_mul |= ((blizzard_read_reg(BLIZZARD_PLL_CLOCK_SYNTH_1) - & 0x0f) << 11); - *sys_clk = ext_clk * sys_mul / sys_div; - } else /* else source is ext clk, or oscillator */ - *sys_clk = ext_clk; - - *pix_clk = *sys_clk / pix_div; /* HZ */ - dev_dbg(blizzard.fbdev->dev, - "ext_clk %ld pix_src %d pix_div %d sys_div %d sys_mul %d\n", - ext_clk, pix_clk_src & (0x3 << 1), pix_div, sys_div, sys_mul); - dev_dbg(blizzard.fbdev->dev, "sys_clk %ld pix_clk %ld\n", - *sys_clk, *pix_clk); -} - -static int setup_tearsync(unsigned long pix_clk, int extif_div) -{ - int hdisp, vdisp; - int hndp, vndp; - int hsw, vsw; - int hs, vs; - int hs_pol_inv, vs_pol_inv; - int use_hsvs, use_ndp; - u8 b; - - hsw = blizzard_read_reg(BLIZZARD_HSW); - vsw = blizzard_read_reg(BLIZZARD_VSW); - hs_pol_inv = !(hsw & 0x80); - vs_pol_inv = !(vsw & 0x80); - hsw = hsw & 0x7f; - vsw = vsw & 0x3f; - - hdisp = blizzard_read_reg(BLIZZARD_HDISP) * 8; - vdisp = blizzard_read_reg(BLIZZARD_VDISP0) + - ((blizzard_read_reg(BLIZZARD_VDISP1) & 0x3) << 8); - - hndp = blizzard_read_reg(BLIZZARD_HNDP) & 0x3f; - vndp = blizzard_read_reg(BLIZZARD_VNDP); - - /* time to transfer one pixel (16bpp) in ps */ - blizzard.pix_tx_time = blizzard.reg_timings.we_cycle_time; - if (blizzard.extif->get_max_tx_rate != NULL) { - /* The external interface might have a rate limitation, - * if so, we have to maximize our transfer rate. - */ - unsigned long min_tx_time; - unsigned long max_tx_rate = blizzard.extif->get_max_tx_rate(); - - dev_dbg(blizzard.fbdev->dev, "max_tx_rate %ld HZ\n", - max_tx_rate); - min_tx_time = 1000000000 / (max_tx_rate / 1000); /* ps */ - if (blizzard.pix_tx_time < min_tx_time) - blizzard.pix_tx_time = min_tx_time; - } - - /* time to update one line in ps */ - blizzard.line_upd_time = (hdisp + hndp) * 1000000 / (pix_clk / 1000); - blizzard.line_upd_time *= 1000; - if (hdisp * blizzard.pix_tx_time > blizzard.line_upd_time) - /* transfer speed too low, we might have to use both - * HS and VS */ - use_hsvs = 1; - else - /* decent transfer speed, we'll always use only VS */ - use_hsvs = 0; - - if (use_hsvs && (hs_pol_inv || vs_pol_inv)) { - /* HS or'ed with VS doesn't work, use the active high - * TE signal based on HNDP / VNDP */ - use_ndp = 1; - hs_pol_inv = 0; - vs_pol_inv = 0; - hs = hndp; - vs = vndp; - } else { - /* Use HS or'ed with VS as a TE signal if both are needed - * or VNDP if only vsync is needed. */ - use_ndp = 0; - hs = hsw; - vs = vsw; - if (!use_hsvs) { - hs_pol_inv = 0; - vs_pol_inv = 0; - } - } - - hs = hs * 1000000 / (pix_clk / 1000); /* ps */ - hs *= 1000; - - vs = vs * (hdisp + hndp) * 1000000 / (pix_clk / 1000); /* ps */ - vs *= 1000; - - if (vs <= hs) - return -EDOM; - /* set VS to 120% of HS to minimize VS detection time */ - vs = hs * 12 / 10; - /* minimize HS too */ - if (hs > 10000) - hs = 10000; - - b = blizzard_read_reg(BLIZZARD_NDISP_CTRL_STATUS); - b &= ~0x3; - b |= use_hsvs ? 1 : 0; - b |= (use_ndp && use_hsvs) ? 0 : 2; - blizzard_write_reg(BLIZZARD_NDISP_CTRL_STATUS, b); - - blizzard.vsync_only = !use_hsvs; - - dev_dbg(blizzard.fbdev->dev, - "pix_clk %ld HZ pix_tx_time %ld ps line_upd_time %ld ps\n", - pix_clk, blizzard.pix_tx_time, blizzard.line_upd_time); - dev_dbg(blizzard.fbdev->dev, - "hs %d ps vs %d ps mode %d vsync_only %d\n", - hs, vs, b & 0x3, !use_hsvs); - - return blizzard.extif->setup_tearsync(1, hs, vs, - hs_pol_inv, vs_pol_inv, - extif_div); -} - -static void blizzard_get_caps(int plane, struct omapfb_caps *caps) -{ - blizzard.int_ctrl->get_caps(plane, caps); - caps->ctrl |= OMAPFB_CAPS_MANUAL_UPDATE | - OMAPFB_CAPS_WINDOW_PIXEL_DOUBLE | - OMAPFB_CAPS_WINDOW_SCALE | - OMAPFB_CAPS_WINDOW_OVERLAY | - OMAPFB_CAPS_WINDOW_ROTATE; - if (blizzard.te_connected) - caps->ctrl |= OMAPFB_CAPS_TEARSYNC; - caps->wnd_color |= (1 << OMAPFB_COLOR_RGB565) | - (1 << OMAPFB_COLOR_YUV420); -} - -static void _save_regs(const struct blizzard_reg_list *list, int cnt) -{ - int i; - - for (i = 0; i < cnt; i++, list++) { - int reg; - for (reg = list->start; reg <= list->end; reg += 2) - blizzard_reg_cache[reg / 2] = blizzard_read_reg(reg); - } -} - -static void _restore_regs(const struct blizzard_reg_list *list, int cnt) -{ - int i; - - for (i = 0; i < cnt; i++, list++) { - int reg; - for (reg = list->start; reg <= list->end; reg += 2) - blizzard_write_reg(reg, blizzard_reg_cache[reg / 2]); - } -} - -static void blizzard_save_all_regs(void) -{ - _save_regs(blizzard_pll_regs, ARRAY_SIZE(blizzard_pll_regs)); - _save_regs(blizzard_gen_regs, ARRAY_SIZE(blizzard_gen_regs)); -} - -static void blizzard_restore_pll_regs(void) -{ - _restore_regs(blizzard_pll_regs, ARRAY_SIZE(blizzard_pll_regs)); -} - -static void blizzard_restore_gen_regs(void) -{ - _restore_regs(blizzard_gen_regs, ARRAY_SIZE(blizzard_gen_regs)); -} - -static void blizzard_suspend(void) -{ - u32 l; - unsigned long tmo; - - if (blizzard.last_color_mode) { - update_full_screen(); - blizzard_sync(); - } - blizzard.update_mode_before_suspend = blizzard.update_mode; - /* the following will disable clocks as well */ - blizzard_set_update_mode(OMAPFB_UPDATE_DISABLED); - - blizzard_save_all_regs(); - - blizzard_stop_sdram(); - - l = blizzard_read_reg(BLIZZARD_POWER_SAVE); - /* Standby, Sleep. We assume we use an external clock. */ - l |= 0x03; - blizzard_write_reg(BLIZZARD_POWER_SAVE, l); - - tmo = jiffies + msecs_to_jiffies(100); - while (!(blizzard_read_reg(BLIZZARD_PLL_MODE) & (1 << 1))) { - if (time_after(jiffies, tmo)) { - dev_err(blizzard.fbdev->dev, - "s1d1374x: sleep timeout, stopping PLL manually\n"); - l = blizzard_read_reg(BLIZZARD_PLL_MODE); - l &= ~0x03; - /* Disable PLL, counter function */ - l |= 0x2; - blizzard_write_reg(BLIZZARD_PLL_MODE, l); - break; - } - msleep(1); - } - - if (blizzard.power_down != NULL) - blizzard.power_down(blizzard.fbdev->dev); -} - -static void blizzard_resume(void) -{ - u32 l; - - if (blizzard.power_up != NULL) - blizzard.power_up(blizzard.fbdev->dev); - - l = blizzard_read_reg(BLIZZARD_POWER_SAVE); - /* Standby, Sleep */ - l &= ~0x03; - blizzard_write_reg(BLIZZARD_POWER_SAVE, l); - - blizzard_restore_pll_regs(); - l = blizzard_read_reg(BLIZZARD_PLL_MODE); - l &= ~0x03; - /* Enable PLL, counter function */ - l |= 0x1; - blizzard_write_reg(BLIZZARD_PLL_MODE, l); - - while (!(blizzard_read_reg(BLIZZARD_PLL_DIV) & (1 << 7))) - msleep(1); - - blizzard_restart_sdram(); - - blizzard_restore_gen_regs(); - - /* Enable display */ - blizzard_write_reg(BLIZZARD_DISPLAY_MODE, 0x01); - - /* the following will enable clocks as necessary */ - blizzard_set_update_mode(blizzard.update_mode_before_suspend); - - /* Force a background update */ - blizzard.zoom_on = 1; - update_full_screen(); - blizzard_sync(); -} - -static int blizzard_init(struct omapfb_device *fbdev, int ext_mode, - struct omapfb_mem_desc *req_vram) -{ - int r = 0, i; - u8 rev, conf; - unsigned long ext_clk; - int extif_div; - unsigned long sys_clk, pix_clk; - struct omapfb_platform_data *omapfb_conf; - struct blizzard_platform_data *ctrl_conf; - - blizzard.fbdev = fbdev; - - BUG_ON(!fbdev->ext_if || !fbdev->int_ctrl); - - blizzard.fbdev = fbdev; - blizzard.extif = fbdev->ext_if; - blizzard.int_ctrl = fbdev->int_ctrl; - - omapfb_conf = fbdev->dev->platform_data; - ctrl_conf = omapfb_conf->ctrl_platform_data; - if (ctrl_conf == NULL || ctrl_conf->get_clock_rate == NULL) { - dev_err(fbdev->dev, "s1d1374x: missing platform data\n"); - r = -ENOENT; - goto err1; - } - - blizzard.power_down = ctrl_conf->power_down; - blizzard.power_up = ctrl_conf->power_up; - - spin_lock_init(&blizzard.req_lock); - - if ((r = blizzard.int_ctrl->init(fbdev, 1, req_vram)) < 0) - goto err1; - - if ((r = blizzard.extif->init(fbdev)) < 0) - goto err2; - - blizzard_ctrl.set_color_key = blizzard.int_ctrl->set_color_key; - blizzard_ctrl.get_color_key = blizzard.int_ctrl->get_color_key; - blizzard_ctrl.setup_mem = blizzard.int_ctrl->setup_mem; - blizzard_ctrl.mmap = blizzard.int_ctrl->mmap; - - ext_clk = ctrl_conf->get_clock_rate(fbdev->dev); - if ((r = calc_extif_timings(ext_clk, &extif_div)) < 0) - goto err3; - - set_extif_timings(&blizzard.reg_timings); - - if (blizzard.power_up != NULL) - blizzard.power_up(fbdev->dev); - - calc_blizzard_clk_rates(ext_clk, &sys_clk, &pix_clk); - - if ((r = calc_extif_timings(sys_clk, &extif_div)) < 0) - goto err3; - set_extif_timings(&blizzard.reg_timings); - - if (!(blizzard_read_reg(BLIZZARD_PLL_DIV) & 0x80)) { - dev_err(fbdev->dev, - "controller not initialized by the bootloader\n"); - r = -ENODEV; - goto err3; - } - - if (ctrl_conf->te_connected) { - if ((r = setup_tearsync(pix_clk, extif_div)) < 0) - goto err3; - blizzard.te_connected = 1; - } - - rev = blizzard_read_reg(BLIZZARD_REV_CODE); - conf = blizzard_read_reg(BLIZZARD_CONFIG); - - switch (rev & 0xfc) { - case 0x9c: - blizzard.version = BLIZZARD_VERSION_S1D13744; - pr_info("omapfb: s1d13744 LCD controller rev %d " - "initialized (CNF pins %x)\n", rev & 0x03, conf & 0x07); - break; - case 0xa4: - blizzard.version = BLIZZARD_VERSION_S1D13745; - pr_info("omapfb: s1d13745 LCD controller rev %d " - "initialized (CNF pins %x)\n", rev & 0x03, conf & 0x07); - break; - default: - dev_err(fbdev->dev, "invalid s1d1374x revision %02x\n", - rev); - r = -ENODEV; - goto err3; - } - - blizzard.max_transmit_size = blizzard.extif->max_transmit_size; - - blizzard.update_mode = OMAPFB_UPDATE_DISABLED; - - blizzard.auto_update_window.x = 0; - blizzard.auto_update_window.y = 0; - blizzard.auto_update_window.width = fbdev->panel->x_res; - blizzard.auto_update_window.height = fbdev->panel->y_res; - blizzard.auto_update_window.out_x = 0; - blizzard.auto_update_window.out_y = 0; - blizzard.auto_update_window.out_width = fbdev->panel->x_res; - blizzard.auto_update_window.out_height = fbdev->panel->y_res; - blizzard.auto_update_window.format = 0; - - blizzard.screen_width = fbdev->panel->x_res; - blizzard.screen_height = fbdev->panel->y_res; - - init_timer(&blizzard.auto_update_timer); - blizzard.auto_update_timer.function = blizzard_update_window_auto; - blizzard.auto_update_timer.data = 0; - - INIT_LIST_HEAD(&blizzard.free_req_list); - INIT_LIST_HEAD(&blizzard.pending_req_list); - for (i = 0; i < ARRAY_SIZE(blizzard.req_pool); i++) - list_add(&blizzard.req_pool[i].entry, &blizzard.free_req_list); - BUG_ON(i <= IRQ_REQ_POOL_SIZE); - sema_init(&blizzard.req_sema, i - IRQ_REQ_POOL_SIZE); - - return 0; -err3: - if (blizzard.power_down != NULL) - blizzard.power_down(fbdev->dev); - blizzard.extif->cleanup(); -err2: - blizzard.int_ctrl->cleanup(); -err1: - return r; -} - -static void blizzard_cleanup(void) -{ - blizzard_set_update_mode(OMAPFB_UPDATE_DISABLED); - blizzard.extif->cleanup(); - blizzard.int_ctrl->cleanup(); - if (blizzard.power_down != NULL) - blizzard.power_down(blizzard.fbdev->dev); -} - -struct lcd_ctrl blizzard_ctrl = { - .name = "blizzard", - .init = blizzard_init, - .cleanup = blizzard_cleanup, - .bind_client = blizzard_bind_client, - .get_caps = blizzard_get_caps, - .set_update_mode = blizzard_set_update_mode, - .get_update_mode = blizzard_get_update_mode, - .setup_plane = blizzard_setup_plane, - .set_scale = blizzard_set_scale, - .enable_plane = blizzard_enable_plane, - .set_rotate = blizzard_set_rotate, - .update_window = blizzard_update_window_async, - .sync = blizzard_sync, - .suspend = blizzard_suspend, - .resume = blizzard_resume, -}; - diff --git a/drivers/video/omap/omapfb_main.c b/drivers/video/omap/omapfb_main.c index b291bfaac80..440a5dd0665 100644 --- a/drivers/video/omap/omapfb_main.c +++ b/drivers/video/omap/omapfb_main.c @@ -104,7 +104,6 @@ static struct platform_device omapdss_device = { * --------------------------------------------------------------------------- */ extern struct lcd_ctrl hwa742_ctrl; -extern struct lcd_ctrl blizzard_ctrl; static const struct lcd_ctrl *ctrls[] = { #ifdef CONFIG_ARCH_OMAP1 @@ -116,9 +115,6 @@ static const struct lcd_ctrl *ctrls[] = { #ifdef CONFIG_FB_OMAP_LCDC_HWA742 &hwa742_ctrl, #endif -#ifdef CONFIG_FB_OMAP_LCDC_BLIZZARD - &blizzard_ctrl, -#endif }; #ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL -- cgit v1.2.3 From 8dc50ec7755650859a7bfc17de8846ef1efa24a4 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Tue, 20 Sep 2011 09:49:49 +0300 Subject: OMAPFB: Remove OMAP2/3 support from old omapfb driver Old omapfb driver (drivers/video/omap/) is no longer used for OMAP2+ devices, and thus we can remove OMAP2+ support from it and make it an OMAP1 omapfb driver. Signed-off-by: Tomi Valkeinen --- drivers/video/omap/Kconfig | 9 +- drivers/video/omap/Makefile | 5 +- drivers/video/omap/dispc.c | 1547 -------------------------------------- drivers/video/omap/dispc.h | 46 -- drivers/video/omap/omapfb.h | 4 - drivers/video/omap/omapfb_main.c | 16 - drivers/video/omap/rfbi.c | 598 --------------- 7 files changed, 5 insertions(+), 2220 deletions(-) delete mode 100644 drivers/video/omap/dispc.c delete mode 100644 drivers/video/omap/dispc.h delete mode 100644 drivers/video/omap/rfbi.c diff --git a/drivers/video/omap/Kconfig b/drivers/video/omap/Kconfig index ab234d59711..1e7536d9a8f 100644 --- a/drivers/video/omap/Kconfig +++ b/drivers/video/omap/Kconfig @@ -1,11 +1,10 @@ config FB_OMAP tristate "OMAP frame buffer support (EXPERIMENTAL)" - depends on FB && (OMAP2_DSS = "n") - depends on ARCH_OMAP1 || ARCH_OMAP2 || ARCH_OMAP3 + depends on FB + depends on ARCH_OMAP1 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select TWL4030_CORE if MACH_OMAP_2430SDP help Frame buffer driver for OMAP based boards. @@ -42,7 +41,7 @@ config FB_OMAP_LCD_MIPID config FB_OMAP_BOOTLOADER_INIT bool "Check bootloader initialization" - depends on FB_OMAP || FB_OMAP2 + 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 @@ -61,7 +60,7 @@ config FB_OMAP_CONSISTENT_DMA_SIZE config FB_OMAP_DMA_TUNE bool "Set DMA SDRAM access priority high" - depends on FB_OMAP && ARCH_OMAP1 + depends on FB_OMAP help On systems in which video memory is in system memory (SDRAM) this will speed up graphics DMA operations. diff --git a/drivers/video/omap/Makefile b/drivers/video/omap/Makefile index 7042a4ac707..79653750448 100644 --- a/drivers/video/omap/Makefile +++ b/drivers/video/omap/Makefile @@ -1,5 +1,5 @@ # -# Makefile for the new OMAP framebuffer device driver +# Makefile for the OMAP1 framebuffer device driver # obj-$(CONFIG_FB_OMAP) += omapfb.o @@ -7,11 +7,8 @@ obj-$(CONFIG_FB_OMAP) += omapfb.o objs-yy := omapfb_main.o objs-y$(CONFIG_ARCH_OMAP1) += lcdc.o -objs-y$(CONFIG_ARCH_OMAP2) += dispc.o -objs-y$(CONFIG_ARCH_OMAP3) += dispc.o objs-$(CONFIG_ARCH_OMAP1)$(CONFIG_FB_OMAP_LCDC_EXTERNAL) += sossi.o -objs-$(CONFIG_ARCH_OMAP2)$(CONFIG_FB_OMAP_LCDC_EXTERNAL) += rfbi.o objs-y$(CONFIG_FB_OMAP_LCDC_HWA742) += hwa742.o diff --git a/drivers/video/omap/dispc.c b/drivers/video/omap/dispc.c deleted file mode 100644 index 6f61e781f15..00000000000 --- a/drivers/video/omap/dispc.c +++ /dev/null @@ -1,1547 +0,0 @@ -/* - * OMAP2 display controller support - * - * Copyright (C) 2005 Nokia Corporation - * Author: Imre Deak - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "omapfb.h" -#include "dispc.h" - -#define MODULE_NAME "dispc" - -#define DSS_BASE 0x48050000 -#define DSS_SYSCONFIG 0x0010 - -#define DISPC_BASE 0x48050400 - -/* DISPC common */ -#define DISPC_REVISION 0x0000 -#define DISPC_SYSCONFIG 0x0010 -#define DISPC_SYSSTATUS 0x0014 -#define DISPC_IRQSTATUS 0x0018 -#define DISPC_IRQENABLE 0x001C -#define DISPC_CONTROL 0x0040 -#define DISPC_CONFIG 0x0044 -#define DISPC_CAPABLE 0x0048 -#define DISPC_DEFAULT_COLOR0 0x004C -#define DISPC_DEFAULT_COLOR1 0x0050 -#define DISPC_TRANS_COLOR0 0x0054 -#define DISPC_TRANS_COLOR1 0x0058 -#define DISPC_LINE_STATUS 0x005C -#define DISPC_LINE_NUMBER 0x0060 -#define DISPC_TIMING_H 0x0064 -#define DISPC_TIMING_V 0x0068 -#define DISPC_POL_FREQ 0x006C -#define DISPC_DIVISOR 0x0070 -#define DISPC_SIZE_DIG 0x0078 -#define DISPC_SIZE_LCD 0x007C - -#define DISPC_DATA_CYCLE1 0x01D4 -#define DISPC_DATA_CYCLE2 0x01D8 -#define DISPC_DATA_CYCLE3 0x01DC - -/* DISPC GFX plane */ -#define DISPC_GFX_BA0 0x0080 -#define DISPC_GFX_BA1 0x0084 -#define DISPC_GFX_POSITION 0x0088 -#define DISPC_GFX_SIZE 0x008C -#define DISPC_GFX_ATTRIBUTES 0x00A0 -#define DISPC_GFX_FIFO_THRESHOLD 0x00A4 -#define DISPC_GFX_FIFO_SIZE_STATUS 0x00A8 -#define DISPC_GFX_ROW_INC 0x00AC -#define DISPC_GFX_PIXEL_INC 0x00B0 -#define DISPC_GFX_WINDOW_SKIP 0x00B4 -#define DISPC_GFX_TABLE_BA 0x00B8 - -/* DISPC Video plane 1/2 */ -#define DISPC_VID1_BASE 0x00BC -#define DISPC_VID2_BASE 0x014C - -/* Offsets into DISPC_VID1/2_BASE */ -#define DISPC_VID_BA0 0x0000 -#define DISPC_VID_BA1 0x0004 -#define DISPC_VID_POSITION 0x0008 -#define DISPC_VID_SIZE 0x000C -#define DISPC_VID_ATTRIBUTES 0x0010 -#define DISPC_VID_FIFO_THRESHOLD 0x0014 -#define DISPC_VID_FIFO_SIZE_STATUS 0x0018 -#define DISPC_VID_ROW_INC 0x001C -#define DISPC_VID_PIXEL_INC 0x0020 -#define DISPC_VID_FIR 0x0024 -#define DISPC_VID_PICTURE_SIZE 0x0028 -#define DISPC_VID_ACCU0 0x002C -#define DISPC_VID_ACCU1 0x0030 - -/* 8 elements in 8 byte increments */ -#define DISPC_VID_FIR_COEF_H0 0x0034 -/* 8 elements in 8 byte increments */ -#define DISPC_VID_FIR_COEF_HV0 0x0038 -/* 5 elements in 4 byte increments */ -#define DISPC_VID_CONV_COEF0 0x0074 - -#define DISPC_IRQ_FRAMEMASK 0x0001 -#define DISPC_IRQ_VSYNC 0x0002 -#define DISPC_IRQ_EVSYNC_EVEN 0x0004 -#define DISPC_IRQ_EVSYNC_ODD 0x0008 -#define DISPC_IRQ_ACBIAS_COUNT_STAT 0x0010 -#define DISPC_IRQ_PROG_LINE_NUM 0x0020 -#define DISPC_IRQ_GFX_FIFO_UNDERFLOW 0x0040 -#define DISPC_IRQ_GFX_END_WIN 0x0080 -#define DISPC_IRQ_PAL_GAMMA_MASK 0x0100 -#define DISPC_IRQ_OCP_ERR 0x0200 -#define DISPC_IRQ_VID1_FIFO_UNDERFLOW 0x0400 -#define DISPC_IRQ_VID1_END_WIN 0x0800 -#define DISPC_IRQ_VID2_FIFO_UNDERFLOW 0x1000 -#define DISPC_IRQ_VID2_END_WIN 0x2000 -#define DISPC_IRQ_SYNC_LOST 0x4000 - -#define DISPC_IRQ_MASK_ALL 0x7fff - -#define DISPC_IRQ_MASK_ERROR (DISPC_IRQ_GFX_FIFO_UNDERFLOW | \ - DISPC_IRQ_VID1_FIFO_UNDERFLOW | \ - DISPC_IRQ_VID2_FIFO_UNDERFLOW | \ - DISPC_IRQ_SYNC_LOST) - -#define RFBI_CONTROL 0x48050040 - -#define MAX_PALETTE_SIZE (256 * 16) - -#define FLD_MASK(pos, len) (((1 << len) - 1) << pos) - -#define MOD_REG_FLD(reg, mask, val) \ - dispc_write_reg((reg), (dispc_read_reg(reg) & ~(mask)) | (val)); - -#define OMAP2_SRAM_START 0x40200000 -/* Maximum size, in reality this is smaller if SRAM is partially locked. */ -#define OMAP2_SRAM_SIZE 0xa0000 /* 640k */ - -/* We support the SDRAM / SRAM types. See OMAPFB_PLANE_MEMTYPE_* in omapfb.h */ -#define DISPC_MEMTYPE_NUM 2 - -#define RESMAP_SIZE(_page_cnt) \ - ((_page_cnt + (sizeof(unsigned long) * 8) - 1) / 8) -#define RESMAP_PTR(_res_map, _page_nr) \ - (((_res_map)->map) + (_page_nr) / (sizeof(unsigned long) * 8)) -#define RESMAP_MASK(_page_nr) \ - (1 << ((_page_nr) & (sizeof(unsigned long) * 8 - 1))) - -struct resmap { - unsigned long start; - unsigned page_cnt; - unsigned long *map; -}; - -#define MAX_IRQ_HANDLERS 4 - -static struct { - void __iomem *base; - - struct omapfb_mem_desc mem_desc; - struct resmap *res_map[DISPC_MEMTYPE_NUM]; - atomic_t map_count[OMAPFB_PLANE_NUM]; - - dma_addr_t palette_paddr; - void *palette_vaddr; - - int ext_mode; - - struct { - u32 irq_mask; - void (*callback)(void *); - void *data; - } irq_handlers[MAX_IRQ_HANDLERS]; - struct completion frame_done; - - int fir_hinc[OMAPFB_PLANE_NUM]; - int fir_vinc[OMAPFB_PLANE_NUM]; - - struct clk *dss_ick, *dss1_fck; - struct clk *dss_54m_fck; - - enum omapfb_update_mode update_mode; - struct omapfb_device *fbdev; - - struct omapfb_color_key color_key; -} dispc; - -static void enable_lcd_clocks(int enable); - -static void inline dispc_write_reg(int idx, u32 val) -{ - __raw_writel(val, dispc.base + idx); -} - -static u32 inline dispc_read_reg(int idx) -{ - u32 l = __raw_readl(dispc.base + idx); - return l; -} - -/* Select RFBI or bypass mode */ -static void enable_rfbi_mode(int enable) -{ - void __iomem *rfbi_control; - u32 l; - - l = dispc_read_reg(DISPC_CONTROL); - /* Enable RFBI, GPIO0/1 */ - l &= ~((1 << 11) | (1 << 15) | (1 << 16)); - l |= enable ? (1 << 11) : 0; - /* RFBI En: GPIO0/1=10 RFBI Dis: GPIO0/1=11 */ - l |= 1 << 15; - l |= enable ? 0 : (1 << 16); - dispc_write_reg(DISPC_CONTROL, l); - - /* Set bypass mode in RFBI module */ - rfbi_control = ioremap(RFBI_CONTROL, SZ_1K); - if (!rfbi_control) { - pr_err("Unable to ioremap rfbi_control\n"); - return; - } - l = __raw_readl(rfbi_control); - l |= enable ? 0 : (1 << 1); - __raw_writel(l, rfbi_control); - iounmap(rfbi_control); -} - -static void set_lcd_data_lines(int data_lines) -{ - u32 l; - int code = 0; - - switch (data_lines) { - case 12: - code = 0; - break; - case 16: - code = 1; - break; - case 18: - code = 2; - break; - case 24: - code = 3; - break; - default: - BUG(); - } - - l = dispc_read_reg(DISPC_CONTROL); - l &= ~(0x03 << 8); - l |= code << 8; - dispc_write_reg(DISPC_CONTROL, l); -} - -static void set_load_mode(int mode) -{ - BUG_ON(mode & ~(DISPC_LOAD_CLUT_ONLY | DISPC_LOAD_FRAME_ONLY | - DISPC_LOAD_CLUT_ONCE_FRAME)); - MOD_REG_FLD(DISPC_CONFIG, 0x03 << 1, mode << 1); -} - -void omap_dispc_set_lcd_size(int x, int y) -{ - BUG_ON((x > (1 << 11)) || (y > (1 << 11))); - enable_lcd_clocks(1); - MOD_REG_FLD(DISPC_SIZE_LCD, FLD_MASK(16, 11) | FLD_MASK(0, 11), - ((y - 1) << 16) | (x - 1)); - enable_lcd_clocks(0); -} -EXPORT_SYMBOL(omap_dispc_set_lcd_size); - -void omap_dispc_set_digit_size(int x, int y) -{ - BUG_ON((x > (1 << 11)) || (y > (1 << 11))); - enable_lcd_clocks(1); - MOD_REG_FLD(DISPC_SIZE_DIG, FLD_MASK(16, 11) | FLD_MASK(0, 11), - ((y - 1) << 16) | (x - 1)); - enable_lcd_clocks(0); -} -EXPORT_SYMBOL(omap_dispc_set_digit_size); - -static void setup_plane_fifo(int plane, int ext_mode) -{ - const u32 ftrs_reg[] = { DISPC_GFX_FIFO_THRESHOLD, - DISPC_VID1_BASE + DISPC_VID_FIFO_THRESHOLD, - DISPC_VID2_BASE + DISPC_VID_FIFO_THRESHOLD }; - const u32 fsz_reg[] = { DISPC_GFX_FIFO_SIZE_STATUS, - DISPC_VID1_BASE + DISPC_VID_FIFO_SIZE_STATUS, - DISPC_VID2_BASE + DISPC_VID_FIFO_SIZE_STATUS }; - int low, high; - u32 l; - - BUG_ON(plane > 2); - - l = dispc_read_reg(fsz_reg[plane]); - l &= FLD_MASK(0, 11); - if (ext_mode) { - low = l * 3 / 4; - high = l; - } else { - low = l / 4; - high = l * 3 / 4; - } - MOD_REG_FLD(ftrs_reg[plane], FLD_MASK(16, 12) | FLD_MASK(0, 12), - (high << 16) | low); -} - -void omap_dispc_enable_lcd_out(int enable) -{ - enable_lcd_clocks(1); - MOD_REG_FLD(DISPC_CONTROL, 1, enable ? 1 : 0); - enable_lcd_clocks(0); -} -EXPORT_SYMBOL(omap_dispc_enable_lcd_out); - -void omap_dispc_enable_digit_out(int enable) -{ - enable_lcd_clocks(1); - MOD_REG_FLD(DISPC_CONTROL, 1 << 1, enable ? 1 << 1 : 0); - enable_lcd_clocks(0); -} -EXPORT_SYMBOL(omap_dispc_enable_digit_out); - -static inline int _setup_plane(int plane, int channel_out, - u32 paddr, int screen_width, - int pos_x, int pos_y, int width, int height, - int color_mode) -{ - const u32 at_reg[] = { DISPC_GFX_ATTRIBUTES, - DISPC_VID1_BASE + DISPC_VID_ATTRIBUTES, - DISPC_VID2_BASE + DISPC_VID_ATTRIBUTES }; - const u32 ba_reg[] = { DISPC_GFX_BA0, DISPC_VID1_BASE + DISPC_VID_BA0, - DISPC_VID2_BASE + DISPC_VID_BA0 }; - const u32 ps_reg[] = { DISPC_GFX_POSITION, - DISPC_VID1_BASE + DISPC_VID_POSITION, - DISPC_VID2_BASE + DISPC_VID_POSITION }; - const u32 sz_reg[] = { DISPC_GFX_SIZE, - DISPC_VID1_BASE + DISPC_VID_PICTURE_SIZE, - DISPC_VID2_BASE + DISPC_VID_PICTURE_SIZE }; - const u32 ri_reg[] = { DISPC_GFX_ROW_INC, - DISPC_VID1_BASE + DISPC_VID_ROW_INC, - DISPC_VID2_BASE + DISPC_VID_ROW_INC }; - const u32 vs_reg[] = { 0, DISPC_VID1_BASE + DISPC_VID_SIZE, - DISPC_VID2_BASE + DISPC_VID_SIZE }; - - int chout_shift, burst_shift; - int chout_val; - int color_code; - int bpp; - int cconv_en; - int set_vsize; - u32 l; - -#ifdef VERBOSE - dev_dbg(dispc.fbdev->dev, "plane %d channel %d paddr %#08x scr_width %d" - " pos_x %d pos_y %d width %d height %d color_mode %d\n", - plane, channel_out, paddr, screen_width, pos_x, pos_y, - width, height, color_mode); -#endif - - set_vsize = 0; - switch (plane) { - case OMAPFB_PLANE_GFX: - burst_shift = 6; - chout_shift = 8; - break; - case OMAPFB_PLANE_VID1: - case OMAPFB_PLANE_VID2: - burst_shift = 14; - chout_shift = 16; - set_vsize = 1; - break; - default: - return -EINVAL; - } - - switch (channel_out) { - case OMAPFB_CHANNEL_OUT_LCD: - chout_val = 0; - break; - case OMAPFB_CHANNEL_OUT_DIGIT: - chout_val = 1; - break; - default: - return -EINVAL; - } - - cconv_en = 0; - switch (color_mode) { - case OMAPFB_COLOR_RGB565: - color_code = DISPC_RGB_16_BPP; - bpp = 16; - break; - case OMAPFB_COLOR_YUV422: - if (plane == 0) - return -EINVAL; - color_code = DISPC_UYVY_422; - cconv_en = 1; - bpp = 16; - break; - case OMAPFB_COLOR_YUY422: - if (plane == 0) - return -EINVAL; - color_code = DISPC_YUV2_422; - cconv_en = 1; - bpp = 16; - break; - default: - return -EINVAL; - } - - l = dispc_read_reg(at_reg[plane]); - - l &= ~(0x0f << 1); - l |= color_code << 1; - l &= ~(1 << 9); - l |= cconv_en << 9; - - l &= ~(0x03 << burst_shift); - l |= DISPC_BURST_8x32 << burst_shift; - - l &= ~(1 << chout_shift); - l |= chout_val << chout_shift; - - dispc_write_reg(at_reg[plane], l); - - dispc_write_reg(ba_reg[plane], paddr); - MOD_REG_FLD(ps_reg[plane], - FLD_MASK(16, 11) | FLD_MASK(0, 11), (pos_y << 16) | pos_x); - - MOD_REG_FLD(sz_reg[plane], FLD_MASK(16, 11) | FLD_MASK(0, 11), - ((height - 1) << 16) | (width - 1)); - - if (set_vsize) { - /* Set video size if set_scale hasn't set it */ - if (!dispc.fir_vinc[plane]) - MOD_REG_FLD(vs_reg[plane], - FLD_MASK(16, 11), (height - 1) << 16); - if (!dispc.fir_hinc[plane]) - MOD_REG_FLD(vs_reg[plane], - FLD_MASK(0, 11), width - 1); - } - - dispc_write_reg(ri_reg[plane], (screen_width - width) * bpp / 8 + 1); - - return height * screen_width * bpp / 8; -} - -static int omap_dispc_setup_plane(int plane, int channel_out, - unsigned long offset, - int screen_width, - int pos_x, int pos_y, int width, int height, - int color_mode) -{ - u32 paddr; - int r; - - if ((unsigned)plane > dispc.mem_desc.region_cnt) - return -EINVAL; - paddr = dispc.mem_desc.region[plane].paddr + offset; - enable_lcd_clocks(1); - r = _setup_plane(plane, channel_out, paddr, - screen_width, - pos_x, pos_y, width, height, color_mode); - enable_lcd_clocks(0); - return r; -} - -static void write_firh_reg(int plane, int reg, u32 value) -{ - u32 base; - - if (plane == 1) - base = DISPC_VID1_BASE + DISPC_VID_FIR_COEF_H0; - else - base = DISPC_VID2_BASE + DISPC_VID_FIR_COEF_H0; - dispc_write_reg(base + reg * 8, value); -} - -static void write_firhv_reg(int plane, int reg, u32 value) -{ - u32 base; - - if (plane == 1) - base = DISPC_VID1_BASE + DISPC_VID_FIR_COEF_HV0; - else - base = DISPC_VID2_BASE + DISPC_VID_FIR_COEF_HV0; - dispc_write_reg(base + reg * 8, value); -} - -static void set_upsampling_coef_table(int plane) -{ - const u32 coef[][2] = { - { 0x00800000, 0x00800000 }, - { 0x0D7CF800, 0x037B02FF }, - { 0x1E70F5FF, 0x0C6F05FE }, - { 0x335FF5FE, 0x205907FB }, - { 0xF74949F7, 0x00404000 }, - { 0xF55F33FB, 0x075920FE }, - { 0xF5701EFE, 0x056F0CFF }, - { 0xF87C0DFF, 0x027B0300 }, - }; - int i; - - for (i = 0; i < 8; i++) { - write_firh_reg(plane, i, coef[i][0]); - write_firhv_reg(plane, i, coef[i][1]); - } -} - -static int omap_dispc_set_scale(int plane, - int orig_width, int orig_height, - int out_width, int out_height) -{ - const u32 at_reg[] = { 0, DISPC_VID1_BASE + DISPC_VID_ATTRIBUTES, - DISPC_VID2_BASE + DISPC_VID_ATTRIBUTES }; - const u32 vs_reg[] = { 0, DISPC_VID1_BASE + DISPC_VID_SIZE, - DISPC_VID2_BASE + DISPC_VID_SIZE }; - const u32 fir_reg[] = { 0, DISPC_VID1_BASE + DISPC_VID_FIR, - DISPC_VID2_BASE + DISPC_VID_FIR }; - - u32 l; - int fir_hinc; - int fir_vinc; - - if ((unsigned)plane > OMAPFB_PLANE_NUM) - return -ENODEV; - - if (plane == OMAPFB_PLANE_GFX && - (out_width != orig_width || out_height != orig_height)) - return -EINVAL; - - enable_lcd_clocks(1); - if (orig_width < out_width) { - /* - * Upsampling. - * Currently you can only scale both dimensions in one way. - */ - if (orig_height > out_height || - orig_width * 8 < out_width || - orig_height * 8 < out_height) { - enable_lcd_clocks(0); - return -EINVAL; - } - set_upsampling_coef_table(plane); - } else if (orig_width > out_width) { - /* Downsampling not yet supported - */ - - enable_lcd_clocks(0); - return -EINVAL; - } - if (!orig_width || orig_width == out_width) - fir_hinc = 0; - else - fir_hinc = 1024 * orig_width / out_width; - if (!orig_height || orig_height == out_height) - fir_vinc = 0; - else - fir_vinc = 1024 * orig_height / out_height; - dispc.fir_hinc[plane] = fir_hinc; - dispc.fir_vinc[plane] = fir_vinc; - - MOD_REG_FLD(fir_reg[plane], - FLD_MASK(16, 12) | FLD_MASK(0, 12), - ((fir_vinc & 4095) << 16) | - (fir_hinc & 4095)); - - dev_dbg(dispc.fbdev->dev, "out_width %d out_height %d orig_width %d " - "orig_height %d fir_hinc %d fir_vinc %d\n", - out_width, out_height, orig_width, orig_height, - fir_hinc, fir_vinc); - - MOD_REG_FLD(vs_reg[plane], - FLD_MASK(16, 11) | FLD_MASK(0, 11), - ((out_height - 1) << 16) | (out_width - 1)); - - l = dispc_read_reg(at_reg[plane]); - l &= ~(0x03 << 5); - l |= fir_hinc ? (1 << 5) : 0; - l |= fir_vinc ? (1 << 6) : 0; - dispc_write_reg(at_reg[plane], l); - - enable_lcd_clocks(0); - return 0; -} - -static int omap_dispc_enable_plane(int plane, int enable) -{ - const u32 at_reg[] = { DISPC_GFX_ATTRIBUTES, - DISPC_VID1_BASE + DISPC_VID_ATTRIBUTES, - DISPC_VID2_BASE + DISPC_VID_ATTRIBUTES }; - if ((unsigned int)plane > dispc.mem_desc.region_cnt) - return -EINVAL; - - enable_lcd_clocks(1); - MOD_REG_FLD(at_reg[plane], 1, enable ? 1 : 0); - enable_lcd_clocks(0); - - return 0; -} - -static int omap_dispc_set_color_key(struct omapfb_color_key *ck) -{ - u32 df_reg, tr_reg; - int shift, val; - - switch (ck->channel_out) { - case OMAPFB_CHANNEL_OUT_LCD: - df_reg = DISPC_DEFAULT_COLOR0; - tr_reg = DISPC_TRANS_COLOR0; - shift = 10; - break; - case OMAPFB_CHANNEL_OUT_DIGIT: - df_reg = DISPC_DEFAULT_COLOR1; - tr_reg = DISPC_TRANS_COLOR1; - shift = 12; - break; - default: - return -EINVAL; - } - switch (ck->key_type) { - case OMAPFB_COLOR_KEY_DISABLED: - val = 0; - break; - case OMAPFB_COLOR_KEY_GFX_DST: - val = 1; - break; - case OMAPFB_COLOR_KEY_VID_SRC: - val = 3; - break; - default: - return -EINVAL; - } - enable_lcd_clocks(1); - MOD_REG_FLD(DISPC_CONFIG, FLD_MASK(shift, 2), val << shift); - - if (val != 0) - dispc_write_reg(tr_reg, ck->trans_key); - dispc_write_reg(df_reg, ck->background); - enable_lcd_clocks(0); - - dispc.color_key = *ck; - - return 0; -} - -static int omap_dispc_get_color_key(struct omapfb_color_key *ck) -{ - *ck = dispc.color_key; - return 0; -} - -static void load_palette(void) -{ -} - -static int omap_dispc_set_update_mode(enum omapfb_update_mode mode) -{ - int r = 0; - - if (mode != dispc.update_mode) { - switch (mode) { - case OMAPFB_AUTO_UPDATE: - case OMAPFB_MANUAL_UPDATE: - enable_lcd_clocks(1); - omap_dispc_enable_lcd_out(1); - dispc.update_mode = mode; - break; - case OMAPFB_UPDATE_DISABLED: - init_completion(&dispc.frame_done); - omap_dispc_enable_lcd_out(0); - if (!wait_for_completion_timeout(&dispc.frame_done, - msecs_to_jiffies(500))) { - dev_err(dispc.fbdev->dev, - "timeout waiting for FRAME DONE\n"); - } - dispc.update_mode = mode; - enable_lcd_clocks(0); - break; - default: - r = -EINVAL; - } - } - - return r; -} - -static void omap_dispc_get_caps(int plane, struct omapfb_caps *caps) -{ - caps->ctrl |= OMAPFB_CAPS_PLANE_RELOCATE_MEM; - if (plane > 0) - caps->ctrl |= OMAPFB_CAPS_PLANE_SCALE; - caps->plane_color |= (1 << OMAPFB_COLOR_RGB565) | - (1 << OMAPFB_COLOR_YUV422) | - (1 << OMAPFB_COLOR_YUY422); - if (plane == 0) - caps->plane_color |= (1 << OMAPFB_COLOR_CLUT_8BPP) | - (1 << OMAPFB_COLOR_CLUT_4BPP) | - (1 << OMAPFB_COLOR_CLUT_2BPP) | - (1 << OMAPFB_COLOR_CLUT_1BPP) | - (1 << OMAPFB_COLOR_RGB444); -} - -static enum omapfb_update_mode omap_dispc_get_update_mode(void) -{ - return dispc.update_mode; -} - -static void setup_color_conv_coef(void) -{ - u32 mask = FLD_MASK(16, 11) | FLD_MASK(0, 11); - int cf1_reg = DISPC_VID1_BASE + DISPC_VID_CONV_COEF0; - int cf2_reg = DISPC_VID2_BASE + DISPC_VID_CONV_COEF0; - int at1_reg = DISPC_VID1_BASE + DISPC_VID_ATTRIBUTES; - int at2_reg = DISPC_VID2_BASE + DISPC_VID_ATTRIBUTES; - const struct color_conv_coef { - int ry, rcr, rcb, gy, gcr, gcb, by, bcr, bcb; - int full_range; - } ctbl_bt601_5 = { - 298, 409, 0, 298, -208, -100, 298, 0, 517, 0, - }; - const struct color_conv_coef *ct; -#define CVAL(x, y) (((x & 2047) << 16) | (y & 2047)) - - ct = &ctbl_bt601_5; - - MOD_REG_FLD(cf1_reg, mask, CVAL(ct->rcr, ct->ry)); - MOD_REG_FLD(cf1_reg + 4, mask, CVAL(ct->gy, ct->rcb)); - MOD_REG_FLD(cf1_reg + 8, mask, CVAL(ct->gcb, ct->gcr)); - MOD_REG_FLD(cf1_reg + 12, mask, CVAL(ct->bcr, ct->by)); - MOD_REG_FLD(cf1_reg + 16, mask, CVAL(0, ct->bcb)); - - MOD_REG_FLD(cf2_reg, mask, CVAL(ct->rcr, ct->ry)); - MOD_REG_FLD(cf2_reg + 4, mask, CVAL(ct->gy, ct->rcb)); - MOD_REG_FLD(cf2_reg + 8, mask, CVAL(ct->gcb, ct->gcr)); - MOD_REG_FLD(cf2_reg + 12, mask, CVAL(ct->bcr, ct->by)); - MOD_REG_FLD(cf2_reg + 16, mask, CVAL(0, ct->bcb)); -#undef CVAL - - MOD_REG_FLD(at1_reg, (1 << 11), ct->full_range); - MOD_REG_FLD(at2_reg, (1 << 11), ct->full_range); -} - -static void calc_ck_div(int is_tft, int pck, int *lck_div, int *pck_div) -{ - unsigned long fck, lck; - - *lck_div = 1; - pck = max(1, pck); - fck = clk_get_rate(dispc.dss1_fck); - lck = fck; - *pck_div = (lck + pck - 1) / pck; - if (is_tft) - *pck_div = max(2, *pck_div); - else - *pck_div = max(3, *pck_div); - if (*pck_div > 255) { - *pck_div = 255; - lck = pck * *pck_div; - *lck_div = fck / lck; - BUG_ON(*lck_div < 1); - if (*lck_div > 255) { - *lck_div = 255; - dev_warn(dispc.fbdev->dev, "pixclock %d kHz too low.\n", - pck / 1000); - } - } -} - -static void set_lcd_tft_mode(int enable) -{ - u32 mask; - - mask = 1 << 3; - MOD_REG_FLD(DISPC_CONTROL, mask, enable ? mask : 0); -} - -static void set_lcd_timings(void) -{ - u32 l; - int lck_div, pck_div; - struct lcd_panel *panel = dispc.fbdev->panel; - int is_tft = panel->config & OMAP_LCDC_PANEL_TFT; - unsigned long fck; - - l = dispc_read_reg(DISPC_TIMING_H); - l &= ~(FLD_MASK(0, 6) | FLD_MASK(8, 8) | FLD_MASK(20, 8)); - l |= ( max(1, (min(64, panel->hsw))) - 1 ) << 0; - l |= ( max(1, (min(256, panel->hfp))) - 1 ) << 8; - l |= ( max(1, (min(256, panel->hbp))) - 1 ) << 20; - dispc_write_reg(DISPC_TIMING_H, l); - - l = dispc_read_reg(DISPC_TIMING_V); - l &= ~(FLD_MASK(0, 6) | FLD_MASK(8, 8) | FLD_MASK(20, 8)); - l |= ( max(1, (min(64, panel->vsw))) - 1 ) << 0; - l |= ( max(0, (min(255, panel->vfp))) - 0 ) << 8; - l |= ( max(0, (min(255, panel->vbp))) - 0 ) << 20; - dispc_write_reg(DISPC_TIMING_V, l); - - l = dispc_read_reg(DISPC_POL_FREQ); - l &= ~FLD_MASK(12, 6); - l |= (panel->config & OMAP_LCDC_SIGNAL_MASK) << 12; - l |= panel->acb & 0xff; - dispc_write_reg(DISPC_POL_FREQ, l); - - calc_ck_div(is_tft, panel->pixel_clock * 1000, &lck_div, &pck_div); - - l = dispc_read_reg(DISPC_DIVISOR); - l &= ~(FLD_MASK(16, 8) | FLD_MASK(0, 8)); - l |= (lck_div << 16) | (pck_div << 0); - dispc_write_reg(DISPC_DIVISOR, l); - - /* update panel info with the exact clock */ - fck = clk_get_rate(dispc.dss1_fck); - panel->pixel_clock = fck / lck_div / pck_div / 1000; -} - -static void recalc_irq_mask(void) -{ - int i; - unsigned long irq_mask = DISPC_IRQ_MASK_ERROR; - - for (i = 0; i < MAX_IRQ_HANDLERS; i++) { - if (!dispc.irq_handlers[i].callback) - continue; - - irq_mask |= dispc.irq_handlers[i].irq_mask; - } - - enable_lcd_clocks(1); - MOD_REG_FLD(DISPC_IRQENABLE, 0x7fff, irq_mask); - enable_lcd_clocks(0); -} - -int omap_dispc_request_irq(unsigned long irq_mask, void (*callback)(void *data), - void *data) -{ - int i; - - BUG_ON(callback == NULL); - - for (i = 0; i < MAX_IRQ_HANDLERS; i++) { - if (dispc.irq_handlers[i].callback) - continue; - - dispc.irq_handlers[i].irq_mask = irq_mask; - dispc.irq_handlers[i].callback = callback; - dispc.irq_handlers[i].data = data; - recalc_irq_mask(); - - return 0; - } - - return -EBUSY; -} -EXPORT_SYMBOL(omap_dispc_request_irq); - -void omap_dispc_free_irq(unsigned long irq_mask, void (*callback)(void *data), - void *data) -{ - int i; - - for (i = 0; i < MAX_IRQ_HANDLERS; i++) { - if (dispc.irq_handlers[i].callback == callback && - dispc.irq_handlers[i].data == data) { - dispc.irq_handlers[i].irq_mask = 0; - dispc.irq_handlers[i].callback = NULL; - dispc.irq_handlers[i].data = NULL; - recalc_irq_mask(); - return; - } - } - - BUG(); -} -EXPORT_SYMBOL(omap_dispc_free_irq); - -static irqreturn_t omap_dispc_irq_handler(int irq, void *dev) -{ - u32 stat; - int i = 0; - - enable_lcd_clocks(1); - - stat = dispc_read_reg(DISPC_IRQSTATUS); - if (stat & DISPC_IRQ_FRAMEMASK) - complete(&dispc.frame_done); - - if (stat & DISPC_IRQ_MASK_ERROR) { - if (printk_ratelimit()) { - dev_err(dispc.fbdev->dev, "irq error status %04x\n", - stat & 0x7fff); - } - } - - for (i = 0; i < MAX_IRQ_HANDLERS; i++) { - if (unlikely(dispc.irq_handlers[i].callback && - (stat & dispc.irq_handlers[i].irq_mask))) - dispc.irq_handlers[i].callback( - dispc.irq_handlers[i].data); - } - - dispc_write_reg(DISPC_IRQSTATUS, stat); - - enable_lcd_clocks(0); - - return IRQ_HANDLED; -} - -static int get_dss_clocks(void) -{ - dispc.dss_ick = clk_get(&dispc.fbdev->dssdev->dev, "ick"); - if (IS_ERR(dispc.dss_ick)) { - dev_err(dispc.fbdev->dev, "can't get ick\n"); - return PTR_ERR(dispc.dss_ick); - } - - dispc.dss1_fck = clk_get(&dispc.fbdev->dssdev->dev, "fck"); - if (IS_ERR(dispc.dss1_fck)) { - dev_err(dispc.fbdev->dev, "can't get dss1_fck\n"); - clk_put(dispc.dss_ick); - return PTR_ERR(dispc.dss1_fck); - } - - dispc.dss_54m_fck = clk_get(&dispc.fbdev->dssdev->dev, "tv_clk"); - if (IS_ERR(dispc.dss_54m_fck)) { - dev_err(dispc.fbdev->dev, "can't get tv_fck\n"); - clk_put(dispc.dss_ick); - clk_put(dispc.dss1_fck); - return PTR_ERR(dispc.dss_54m_fck); - } - - return 0; -} - -static void put_dss_clocks(void) -{ - clk_put(dispc.dss_54m_fck); - clk_put(dispc.dss1_fck); - clk_put(dispc.dss_ick); -} - -static void enable_lcd_clocks(int enable) -{ - if (enable) { - clk_enable(dispc.dss_ick); - clk_enable(dispc.dss1_fck); - } else { - clk_disable(dispc.dss1_fck); - clk_disable(dispc.dss_ick); - } -} - -static void enable_digit_clocks(int enable) -{ - if (enable) - clk_enable(dispc.dss_54m_fck); - else - clk_disable(dispc.dss_54m_fck); -} - -static void omap_dispc_suspend(void) -{ - if (dispc.update_mode == OMAPFB_AUTO_UPDATE) { - init_completion(&dispc.frame_done); - omap_dispc_enable_lcd_out(0); - if (!wait_for_completion_timeout(&dispc.frame_done, - msecs_to_jiffies(500))) { - dev_err(dispc.fbdev->dev, - "timeout waiting for FRAME DONE\n"); - } - enable_lcd_clocks(0); - } -} - -static void omap_dispc_resume(void) -{ - if (dispc.update_mode == OMAPFB_AUTO_UPDATE) { - enable_lcd_clocks(1); - if (!dispc.ext_mode) { - set_lcd_timings(); - load_palette(); - } - omap_dispc_enable_lcd_out(1); - } -} - - -static int omap_dispc_update_window(struct fb_info *fbi, - struct omapfb_update_window *win, - void (*complete_callback)(void *arg), - void *complete_callback_data) -{ - return dispc.update_mode == OMAPFB_UPDATE_DISABLED ? -ENODEV : 0; -} - -static int mmap_kern(struct omapfb_mem_region *region) -{ - struct vm_struct *kvma; - struct vm_area_struct vma; - pgprot_t pgprot; - unsigned long vaddr; - - kvma = get_vm_area(region->size, VM_IOREMAP); - if (kvma == NULL) { - dev_err(dispc.fbdev->dev, "can't get kernel vm area\n"); - return -ENOMEM; - } - vma.vm_mm = &init_mm; - - vaddr = (unsigned long)kvma->addr; - - pgprot = pgprot_writecombine(pgprot_kernel); - vma.vm_start = vaddr; - vma.vm_end = vaddr + region->size; - if (io_remap_pfn_range(&vma, vaddr, region->paddr >> PAGE_SHIFT, - region->size, pgprot) < 0) { - dev_err(dispc.fbdev->dev, "kernel mmap for FBMEM failed\n"); - return -EAGAIN; - } - region->vaddr = (void *)vaddr; - - return 0; -} - -static void mmap_user_open(struct vm_area_struct *vma) -{ - int plane = (int)vma->vm_private_data; - - atomic_inc(&dispc.map_count[plane]); -} - -static void mmap_user_close(struct vm_area_struct *vma) -{ - int plane = (int)vma->vm_private_data; - - atomic_dec(&dispc.map_count[plane]); -} - -static const struct vm_operations_struct mmap_user_ops = { - .open = mmap_user_open, - .close = mmap_user_close, -}; - -static int omap_dispc_mmap_user(struct fb_info *info, - struct vm_area_struct *vma) -{ - struct omapfb_plane_struct *plane = info->par; - unsigned long off; - unsigned long start; - u32 len; - - if (vma->vm_end - vma->vm_start == 0) - return 0; - if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) - return -EINVAL; - off = vma->vm_pgoff << PAGE_SHIFT; - - start = info->fix.smem_start; - len = info->fix.smem_len; - if (off >= len) - return -EINVAL; - if ((vma->vm_end - vma->vm_start + off) > len) - return -EINVAL; - off += start; - vma->vm_pgoff = off >> PAGE_SHIFT; - vma->vm_flags |= VM_IO | VM_RESERVED; - vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); - vma->vm_ops = &mmap_user_ops; - vma->vm_private_data = (void *)plane->idx; - if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT, - vma->vm_end - vma->vm_start, vma->vm_page_prot)) - return -EAGAIN; - /* vm_ops.open won't be called for mmap itself. */ - atomic_inc(&dispc.map_count[plane->idx]); - return 0; -} - -static void unmap_kern(struct omapfb_mem_region *region) -{ - vunmap(region->vaddr); -} - -static int alloc_palette_ram(void) -{ - dispc.palette_vaddr = dma_alloc_writecombine(dispc.fbdev->dev, - MAX_PALETTE_SIZE, &dispc.palette_paddr, GFP_KERNEL); - if (dispc.palette_vaddr == NULL) { - dev_err(dispc.fbdev->dev, "failed to alloc palette memory\n"); - return -ENOMEM; - } - - return 0; -} - -static void free_palette_ram(void) -{ - dma_free_writecombine(dispc.fbdev->dev, MAX_PALETTE_SIZE, - dispc.palette_vaddr, dispc.palette_paddr); -} - -static int alloc_fbmem(struct omapfb_mem_region *region) -{ - region->vaddr = dma_alloc_writecombine(dispc.fbdev->dev, - region->size, ®ion->paddr, GFP_KERNEL); - - if (region->vaddr == NULL) { - dev_err(dispc.fbdev->dev, "unable to allocate FB DMA memory\n"); - return -ENOMEM; - } - - return 0; -} - -static void free_fbmem(struct omapfb_mem_region *region) -{ - dma_free_writecombine(dispc.fbdev->dev, region->size, - region->vaddr, region->paddr); -} - -static struct resmap *init_resmap(unsigned long start, size_t size) -{ - unsigned page_cnt; - struct resmap *res_map; - - page_cnt = PAGE_ALIGN(size) / PAGE_SIZE; - res_map = - kzalloc(sizeof(struct resmap) + RESMAP_SIZE(page_cnt), GFP_KERNEL); - if (res_map == NULL) - return NULL; - res_map->start = start; - res_map->page_cnt = page_cnt; - res_map->map = (unsigned long *)(res_map + 1); - return res_map; -} - -static void cleanup_resmap(struct resmap *res_map) -{ - kfree(res_map); -} - -static inline int resmap_mem_type(unsigned long start) -{ - if (start >= OMAP2_SRAM_START && - start < OMAP2_SRAM_START + OMAP2_SRAM_SIZE) - return OMAPFB_MEMTYPE_SRAM; - else - return OMAPFB_MEMTYPE_SDRAM; -} - -static inline int resmap_page_reserved(struct resmap *res_map, unsigned page_nr) -{ - return *RESMAP_PTR(res_map, page_nr) & RESMAP_MASK(page_nr) ? 1 : 0; -} - -static inline void resmap_reserve_page(struct resmap *res_map, unsigned page_nr) -{ - BUG_ON(resmap_page_reserved(res_map, page_nr)); - *RESMAP_PTR(res_map, page_nr) |= RESMAP_MASK(page_nr); -} - -static inline void resmap_free_page(struct resmap *res_map, unsigned page_nr) -{ - BUG_ON(!resmap_page_reserved(res_map, page_nr)); - *RESMAP_PTR(res_map, page_nr) &= ~RESMAP_MASK(page_nr); -} - -static void resmap_reserve_region(unsigned long start, size_t size) -{ - - struct resmap *res_map; - unsigned start_page; - unsigned end_page; - int mtype; - unsigned i; - - mtype = resmap_mem_type(start); - res_map = dispc.res_map[mtype]; - dev_dbg(dispc.fbdev->dev, "reserve mem type %d start %08lx size %d\n", - mtype, start, size); - start_page = (start - res_map->start) / PAGE_SIZE; - end_page = start_page + PAGE_ALIGN(size) / PAGE_SIZE; - for (i = start_page; i < end_page; i++) - resmap_reserve_page(res_map, i); -} - -static void resmap_free_region(unsigned long start, size_t size) -{ - struct resmap *res_map; - unsigned start_page; - unsigned end_page; - unsigned i; - int mtype; - - mtype = resmap_mem_type(start); - res_map = dispc.res_map[mtype]; - dev_dbg(dispc.fbdev->dev, "free mem type %d start %08lx size %d\n", - mtype, start, size); - start_page = (start - res_map->start) / PAGE_SIZE; - end_page = start_page + PAGE_ALIGN(size) / PAGE_SIZE; - for (i = start_page; i < end_page; i++) - resmap_free_page(res_map, i); -} - -static unsigned long resmap_alloc_region(int mtype, size_t size) -{ - unsigned i; - unsigned total; - unsigned start_page; - unsigned long start; - struct resmap *res_map = dispc.res_map[mtype]; - - BUG_ON(mtype >= DISPC_MEMTYPE_NUM || res_map == NULL || !size); - - size = PAGE_ALIGN(size) / PAGE_SIZE; - start_page = 0; - total = 0; - for (i = 0; i < res_map->page_cnt; i++) { - if (resmap_page_reserved(res_map, i)) { - start_page = i + 1; - total = 0; - } else if (++total == size) - break; - } - if (total < size) - return 0; - - start = res_map->start + start_page * PAGE_SIZE; - resmap_reserve_region(start, size * PAGE_SIZE); - - return start; -} - -/* Note that this will only work for user mappings, we don't deal with - * kernel mappings here, so fbcon will keep using the old region. - */ -static int omap_dispc_setup_mem(int plane, size_t size, int mem_type, - unsigned long *paddr) -{ - struct omapfb_mem_region *rg; - unsigned long new_addr = 0; - - if ((unsigned)plane > dispc.mem_desc.region_cnt) - return -EINVAL; - if (mem_type >= DISPC_MEMTYPE_NUM) - return -EINVAL; - if (dispc.res_map[mem_type] == NULL) - return -ENOMEM; - rg = &dispc.mem_desc.region[plane]; - if (size == rg->size && mem_type == rg->type) - return 0; - if (atomic_read(&dispc.map_count[plane])) - return -EBUSY; - if (rg->size != 0) - resmap_free_region(rg->paddr, rg->size); - if (size != 0) { - new_addr = resmap_alloc_region(mem_type, size); - if (!new_addr) { - /* Reallocate old region. */ - resmap_reserve_region(rg->paddr, rg->size); - return -ENOMEM; - } - } - rg->paddr = new_addr; - rg->size = size; - rg->type = mem_type; - - *paddr = new_addr; - - return 0; -} - -static int setup_fbmem(struct omapfb_mem_desc *req_md) -{ - struct omapfb_mem_region *rg; - int i; - int r; - unsigned long mem_start[DISPC_MEMTYPE_NUM]; - unsigned long mem_end[DISPC_MEMTYPE_NUM]; - - if (!req_md->region_cnt) { - dev_err(dispc.fbdev->dev, "no memory regions defined\n"); - return -ENOENT; - } - - rg = &req_md->region[0]; - memset(mem_start, 0xff, sizeof(mem_start)); - memset(mem_end, 0, sizeof(mem_end)); - - for (i = 0; i < req_md->region_cnt; i++, rg++) { - int mtype; - if (rg->paddr) { - rg->alloc = 0; - if (rg->vaddr == NULL) { - rg->map = 1; - if ((r = mmap_kern(rg)) < 0) - return r; - } - } else { - if (rg->type != OMAPFB_MEMTYPE_SDRAM) { - dev_err(dispc.fbdev->dev, - "unsupported memory type\n"); - return -EINVAL; - } - rg->alloc = rg->map = 1; - if ((r = alloc_fbmem(rg)) < 0) - return r; - } - mtype = rg->type; - - if (rg->paddr < mem_start[mtype]) - mem_start[mtype] = rg->paddr; - if (rg->paddr + rg->size > mem_end[mtype]) - mem_end[mtype] = rg->paddr + rg->size; - } - - for (i = 0; i < DISPC_MEMTYPE_NUM; i++) { - unsigned long start; - size_t size; - if (mem_end[i] == 0) - continue; - start = mem_start[i]; - size = mem_end[i] - start; - dispc.res_map[i] = init_resmap(start, size); - r = -ENOMEM; - if (dispc.res_map[i] == NULL) - goto fail; - /* Initial state is that everything is reserved. This - * includes possible holes as well, which will never be - * freed. - */ - resmap_reserve_region(start, size); - } - - dispc.mem_desc = *req_md; - - return 0; -fail: - for (i = 0; i < DISPC_MEMTYPE_NUM; i++) { - if (dispc.res_map[i] != NULL) - cleanup_resmap(dispc.res_map[i]); - } - return r; -} - -static void cleanup_fbmem(void) -{ - struct omapfb_mem_region *rg; - int i; - - for (i = 0; i < DISPC_MEMTYPE_NUM; i++) { - if (dispc.res_map[i] != NULL) - cleanup_resmap(dispc.res_map[i]); - } - rg = &dispc.mem_desc.region[0]; - for (i = 0; i < dispc.mem_desc.region_cnt; i++, rg++) { - if (rg->alloc) - free_fbmem(rg); - else { - if (rg->map) - unmap_kern(rg); - } - } -} - -static int omap_dispc_init(struct omapfb_device *fbdev, int ext_mode, - struct omapfb_mem_desc *req_vram) -{ - int r; - u32 l; - struct lcd_panel *panel = fbdev->panel; - void __iomem *ram_fw_base; - int tmo = 10000; - int skip_init = 0; - int i; - - memset(&dispc, 0, sizeof(dispc)); - - dispc.base = ioremap(DISPC_BASE, SZ_1K); - if (!dispc.base) { - dev_err(fbdev->dev, "can't ioremap DISPC\n"); - return -ENOMEM; - } - - dispc.fbdev = fbdev; - dispc.ext_mode = ext_mode; - - init_completion(&dispc.frame_done); - - if ((r = get_dss_clocks()) < 0) - goto fail0; - - enable_lcd_clocks(1); - -#ifdef CONFIG_FB_OMAP_BOOTLOADER_INIT - l = dispc_read_reg(DISPC_CONTROL); - /* LCD enabled ? */ - if (l & 1) { - pr_info("omapfb: skipping hardware initialization\n"); - skip_init = 1; - } -#endif - - if (!skip_init) { - /* Reset monitoring works only w/ the 54M clk */ - enable_digit_clocks(1); - - /* Soft reset */ - MOD_REG_FLD(DISPC_SYSCONFIG, 1 << 1, 1 << 1); - - while (!(dispc_read_reg(DISPC_SYSSTATUS) & 1)) { - if (!--tmo) { - dev_err(dispc.fbdev->dev, "soft reset failed\n"); - r = -ENODEV; - enable_digit_clocks(0); - goto fail1; - } - } - - enable_digit_clocks(0); - } - - /* Enable smart standby/idle, autoidle and wakeup */ - l = dispc_read_reg(DISPC_SYSCONFIG); - l &= ~((3 << 12) | (3 << 3)); - l |= (2 << 12) | (2 << 3) | (1 << 2) | (1 << 0); - dispc_write_reg(DISPC_SYSCONFIG, l); - omap_writel(1 << 0, DSS_BASE + DSS_SYSCONFIG); - - /* Set functional clock autogating */ - l = dispc_read_reg(DISPC_CONFIG); - l |= 1 << 9; - dispc_write_reg(DISPC_CONFIG, l); - - l = dispc_read_reg(DISPC_IRQSTATUS); - dispc_write_reg(DISPC_IRQSTATUS, l); - - recalc_irq_mask(); - - if ((r = request_irq(INT_24XX_DSS_IRQ, omap_dispc_irq_handler, - 0, MODULE_NAME, fbdev)) < 0) { - dev_err(dispc.fbdev->dev, "can't get DSS IRQ\n"); - goto fail1; - } - - /* L3 firewall setting: enable access to OCM RAM */ - ram_fw_base = ioremap(0x68005000, SZ_1K); - if (!ram_fw_base) { - dev_err(dispc.fbdev->dev, "Cannot ioremap to enable OCM RAM\n"); - goto fail1; - } - __raw_writel(0x402000b0, ram_fw_base + 0xa0); - iounmap(ram_fw_base); - - if ((r = alloc_palette_ram()) < 0) - goto fail2; - - if ((r = setup_fbmem(req_vram)) < 0) - goto fail3; - - if (!skip_init) { - for (i = 0; i < dispc.mem_desc.region_cnt; i++) { - memset(dispc.mem_desc.region[i].vaddr, 0, - dispc.mem_desc.region[i].size); - } - - /* Set logic clock to fck, pixel clock to fck/2 for now */ - MOD_REG_FLD(DISPC_DIVISOR, FLD_MASK(16, 8), 1 << 16); - MOD_REG_FLD(DISPC_DIVISOR, FLD_MASK(0, 8), 2 << 0); - - setup_plane_fifo(0, ext_mode); - setup_plane_fifo(1, ext_mode); - setup_plane_fifo(2, ext_mode); - - setup_color_conv_coef(); - - set_lcd_tft_mode(panel->config & OMAP_LCDC_PANEL_TFT); - set_load_mode(DISPC_LOAD_FRAME_ONLY); - - if (!ext_mode) { - set_lcd_data_lines(panel->data_lines); - omap_dispc_set_lcd_size(panel->x_res, panel->y_res); - set_lcd_timings(); - } else - set_lcd_data_lines(panel->bpp); - enable_rfbi_mode(ext_mode); - } - - l = dispc_read_reg(DISPC_REVISION); - pr_info("omapfb: DISPC version %d.%d initialized\n", - l >> 4 & 0x0f, l & 0x0f); - enable_lcd_clocks(0); - - return 0; -fail3: - free_palette_ram(); -fail2: - free_irq(INT_24XX_DSS_IRQ, fbdev); -fail1: - enable_lcd_clocks(0); - put_dss_clocks(); -fail0: - iounmap(dispc.base); - return r; -} - -static void omap_dispc_cleanup(void) -{ - int i; - - omap_dispc_set_update_mode(OMAPFB_UPDATE_DISABLED); - /* This will also disable clocks that are on */ - for (i = 0; i < dispc.mem_desc.region_cnt; i++) - omap_dispc_enable_plane(i, 0); - cleanup_fbmem(); - free_palette_ram(); - free_irq(INT_24XX_DSS_IRQ, dispc.fbdev); - put_dss_clocks(); - iounmap(dispc.base); -} - -const struct lcd_ctrl omap2_int_ctrl = { - .name = "internal", - .init = omap_dispc_init, - .cleanup = omap_dispc_cleanup, - .get_caps = omap_dispc_get_caps, - .set_update_mode = omap_dispc_set_update_mode, - .get_update_mode = omap_dispc_get_update_mode, - .update_window = omap_dispc_update_window, - .suspend = omap_dispc_suspend, - .resume = omap_dispc_resume, - .setup_plane = omap_dispc_setup_plane, - .setup_mem = omap_dispc_setup_mem, - .set_scale = omap_dispc_set_scale, - .enable_plane = omap_dispc_enable_plane, - .set_color_key = omap_dispc_set_color_key, - .get_color_key = omap_dispc_get_color_key, - .mmap = omap_dispc_mmap_user, -}; diff --git a/drivers/video/omap/dispc.h b/drivers/video/omap/dispc.h deleted file mode 100644 index c15ea77f060..00000000000 --- a/drivers/video/omap/dispc.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef _DISPC_H -#define _DISPC_H - -#include - -#define DISPC_PLANE_GFX 0 -#define DISPC_PLANE_VID1 1 -#define DISPC_PLANE_VID2 2 - -#define DISPC_RGB_1_BPP 0x00 -#define DISPC_RGB_2_BPP 0x01 -#define DISPC_RGB_4_BPP 0x02 -#define DISPC_RGB_8_BPP 0x03 -#define DISPC_RGB_12_BPP 0x04 -#define DISPC_RGB_16_BPP 0x06 -#define DISPC_RGB_24_BPP 0x08 -#define DISPC_RGB_24_BPP_UNPACK_32 0x09 -#define DISPC_YUV2_422 0x0a -#define DISPC_UYVY_422 0x0b - -#define DISPC_BURST_4x32 0 -#define DISPC_BURST_8x32 1 -#define DISPC_BURST_16x32 2 - -#define DISPC_LOAD_CLUT_AND_FRAME 0x00 -#define DISPC_LOAD_CLUT_ONLY 0x01 -#define DISPC_LOAD_FRAME_ONLY 0x02 -#define DISPC_LOAD_CLUT_ONCE_FRAME 0x03 - -#define DISPC_TFT_DATA_LINES_12 0 -#define DISPC_TFT_DATA_LINES_16 1 -#define DISPC_TFT_DATA_LINES_18 2 -#define DISPC_TFT_DATA_LINES_24 3 - -extern void omap_dispc_set_lcd_size(int width, int height); - -extern void omap_dispc_enable_lcd_out(int enable); -extern void omap_dispc_enable_digit_out(int enable); - -extern int omap_dispc_request_irq(unsigned long irq_mask, - void (*callback)(void *data), void *data); -extern void omap_dispc_free_irq(unsigned long irq_mask, - void (*callback)(void *data), void *data); - -extern const struct lcd_ctrl omap2_int_ctrl; -#endif diff --git a/drivers/video/omap/omapfb.h b/drivers/video/omap/omapfb.h index af3c9e571ec..3a5ab13845f 100644 --- a/drivers/video/omap/omapfb.h +++ b/drivers/video/omap/omapfb.h @@ -207,11 +207,7 @@ struct omapfb_device { struct platform_device *dssdev; /* dummy dev for clocks */ }; -#ifdef CONFIG_ARCH_OMAP1 extern struct lcd_ctrl omap1_lcd_ctrl; -#else -extern struct lcd_ctrl omap2_disp_ctrl; -#endif extern void omapfb_register_panel(struct lcd_panel *panel); extern void omapfb_write_first_pixel(struct omapfb_device *fbdev, u16 pixval); diff --git a/drivers/video/omap/omapfb_main.c b/drivers/video/omap/omapfb_main.c index 440a5dd0665..73924bc9959 100644 --- a/drivers/video/omap/omapfb_main.c +++ b/drivers/video/omap/omapfb_main.c @@ -34,7 +34,6 @@ #include "omapfb.h" #include "lcdc.h" -#include "dispc.h" #define MODULE_NAME "omapfb" @@ -106,11 +105,7 @@ static struct platform_device omapdss_device = { extern struct lcd_ctrl hwa742_ctrl; static const struct lcd_ctrl *ctrls[] = { -#ifdef CONFIG_ARCH_OMAP1 &omap1_int_ctrl, -#else - &omap2_int_ctrl, -#endif #ifdef CONFIG_FB_OMAP_LCDC_HWA742 &hwa742_ctrl, @@ -118,11 +113,7 @@ static const struct lcd_ctrl *ctrls[] = { }; #ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL -#ifdef CONFIG_ARCH_OMAP1 extern struct lcd_ctrl_extif omap1_ext_if; -#else -extern struct lcd_ctrl_extif omap2_ext_if; -#endif #endif static void omapfb_rqueue_lock(struct omapfb_device *fbdev) @@ -1717,16 +1708,9 @@ static int omapfb_do_probe(struct platform_device *pdev, mutex_init(&fbdev->rqueue_mutex); -#ifdef CONFIG_ARCH_OMAP1 fbdev->int_ctrl = &omap1_int_ctrl; #ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL fbdev->ext_if = &omap1_ext_if; -#endif -#else /* OMAP2 */ - fbdev->int_ctrl = &omap2_int_ctrl; -#ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL - fbdev->ext_if = &omap2_ext_if; -#endif #endif if (omapfb_find_ctrl(fbdev) < 0) { dev_err(fbdev->dev, diff --git a/drivers/video/omap/rfbi.c b/drivers/video/omap/rfbi.c deleted file mode 100644 index 2c1a3402bef..00000000000 --- a/drivers/video/omap/rfbi.c +++ /dev/null @@ -1,598 +0,0 @@ -/* - * OMAP2 Remote Frame Buffer Interface support - * - * Copyright (C) 2005 Nokia Corporation - * Author: Juha Yrjölä - * Imre Deak - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ -#include -#include -#include -#include -#include -#include -#include -#include - -#include "omapfb.h" -#include "dispc.h" - -/* To work around an RFBI transfer rate limitation */ -#define OMAP_RFBI_RATE_LIMIT 1 - -#define RFBI_BASE 0x48050800 -#define RFBI_REVISION 0x0000 -#define RFBI_SYSCONFIG 0x0010 -#define RFBI_SYSSTATUS 0x0014 -#define RFBI_CONTROL 0x0040 -#define RFBI_PIXEL_CNT 0x0044 -#define RFBI_LINE_NUMBER 0x0048 -#define RFBI_CMD 0x004c -#define RFBI_PARAM 0x0050 -#define RFBI_DATA 0x0054 -#define RFBI_READ 0x0058 -#define RFBI_STATUS 0x005c -#define RFBI_CONFIG0 0x0060 -#define RFBI_ONOFF_TIME0 0x0064 -#define RFBI_CYCLE_TIME0 0x0068 -#define RFBI_DATA_CYCLE1_0 0x006c -#define RFBI_DATA_CYCLE2_0 0x0070 -#define RFBI_DATA_CYCLE3_0 0x0074 -#define RFBI_VSYNC_WIDTH 0x0090 -#define RFBI_HSYNC_WIDTH 0x0094 - -#define DISPC_BASE 0x48050400 -#define DISPC_CONTROL 0x0040 -#define DISPC_IRQ_FRAMEMASK 0x0001 - -static struct { - void __iomem *base; - void (*lcdc_callback)(void *data); - void *lcdc_callback_data; - unsigned long l4_khz; - int bits_per_cycle; - struct omapfb_device *fbdev; - struct clk *dss_ick; - struct clk *dss1_fck; - unsigned tearsync_pin_cnt; - unsigned tearsync_mode; -} rfbi; - -static inline void rfbi_write_reg(int idx, u32 val) -{ - __raw_writel(val, rfbi.base + idx); -} - -static inline u32 rfbi_read_reg(int idx) -{ - return __raw_readl(rfbi.base + idx); -} - -static int rfbi_get_clocks(void) -{ - rfbi.dss_ick = clk_get(&rfbi.fbdev->dssdev->dev, "ick"); - if (IS_ERR(rfbi.dss_ick)) { - dev_err(rfbi.fbdev->dev, "can't get ick\n"); - return PTR_ERR(rfbi.dss_ick); - } - - rfbi.dss1_fck = clk_get(&rfbi.fbdev->dssdev->dev, "fck"); - if (IS_ERR(rfbi.dss1_fck)) { - dev_err(rfbi.fbdev->dev, "can't get dss1_fck\n"); - clk_put(rfbi.dss_ick); - return PTR_ERR(rfbi.dss1_fck); - } - - return 0; -} - -static void rfbi_put_clocks(void) -{ - clk_put(rfbi.dss1_fck); - clk_put(rfbi.dss_ick); -} - -static void rfbi_enable_clocks(int enable) -{ - if (enable) { - clk_enable(rfbi.dss_ick); - clk_enable(rfbi.dss1_fck); - } else { - clk_disable(rfbi.dss1_fck); - clk_disable(rfbi.dss_ick); - } -} - - -#ifdef VERBOSE -static void rfbi_print_timings(void) -{ - u32 l; - u32 time; - - l = rfbi_read_reg(RFBI_CONFIG0); - time = 1000000000 / rfbi.l4_khz; - if (l & (1 << 4)) - time *= 2; - - dev_dbg(rfbi.fbdev->dev, "Tick time %u ps\n", time); - l = rfbi_read_reg(RFBI_ONOFF_TIME0); - dev_dbg(rfbi.fbdev->dev, - "CSONTIME %d, CSOFFTIME %d, WEONTIME %d, WEOFFTIME %d, " - "REONTIME %d, REOFFTIME %d\n", - l & 0x0f, (l >> 4) & 0x3f, (l >> 10) & 0x0f, (l >> 14) & 0x3f, - (l >> 20) & 0x0f, (l >> 24) & 0x3f); - - l = rfbi_read_reg(RFBI_CYCLE_TIME0); - dev_dbg(rfbi.fbdev->dev, - "WECYCLETIME %d, RECYCLETIME %d, CSPULSEWIDTH %d, " - "ACCESSTIME %d\n", - (l & 0x3f), (l >> 6) & 0x3f, (l >> 12) & 0x3f, - (l >> 22) & 0x3f); -} -#else -static void rfbi_print_timings(void) {} -#endif - -static void rfbi_set_timings(const struct extif_timings *t) -{ - u32 l; - - BUG_ON(!t->converted); - - rfbi_enable_clocks(1); - rfbi_write_reg(RFBI_ONOFF_TIME0, t->tim[0]); - rfbi_write_reg(RFBI_CYCLE_TIME0, t->tim[1]); - - l = rfbi_read_reg(RFBI_CONFIG0); - l &= ~(1 << 4); - l |= (t->tim[2] ? 1 : 0) << 4; - rfbi_write_reg(RFBI_CONFIG0, l); - - rfbi_print_timings(); - rfbi_enable_clocks(0); -} - -static void rfbi_get_clk_info(u32 *clk_period, u32 *max_clk_div) -{ - *clk_period = 1000000000 / rfbi.l4_khz; - *max_clk_div = 2; -} - -static int ps_to_rfbi_ticks(int time, int div) -{ - unsigned long tick_ps; - int ret; - - /* Calculate in picosecs to yield more exact results */ - tick_ps = 1000000000 / (rfbi.l4_khz) * div; - - ret = (time + tick_ps - 1) / tick_ps; - - return ret; -} - -#ifdef OMAP_RFBI_RATE_LIMIT -static unsigned long rfbi_get_max_tx_rate(void) -{ - unsigned long l4_rate, dss1_rate; - int min_l4_ticks = 0; - int i; - - /* According to TI this can't be calculated so make the - * adjustments for a couple of known frequencies and warn for - * others. - */ - static const struct { - unsigned long l4_clk; /* HZ */ - unsigned long dss1_clk; /* HZ */ - unsigned long min_l4_ticks; - } ftab[] = { - { 55, 132, 7, }, /* 7.86 MPix/s */ - { 110, 110, 12, }, /* 9.16 MPix/s */ - { 110, 132, 10, }, /* 11 Mpix/s */ - { 120, 120, 10, }, /* 12 Mpix/s */ - { 133, 133, 10, }, /* 13.3 Mpix/s */ - }; - - l4_rate = rfbi.l4_khz / 1000; - dss1_rate = clk_get_rate(rfbi.dss1_fck) / 1000000; - - for (i = 0; i < ARRAY_SIZE(ftab); i++) { - /* Use a window instead of an exact match, to account - * for different DPLL multiplier / divider pairs. - */ - if (abs(ftab[i].l4_clk - l4_rate) < 3 && - abs(ftab[i].dss1_clk - dss1_rate) < 3) { - min_l4_ticks = ftab[i].min_l4_ticks; - break; - } - } - if (i == ARRAY_SIZE(ftab)) { - /* Can't be sure, return anyway the maximum not - * rate-limited. This might cause a problem only for the - * tearing synchronisation. - */ - dev_err(rfbi.fbdev->dev, - "can't determine maximum RFBI transfer rate\n"); - return rfbi.l4_khz * 1000; - } - return rfbi.l4_khz * 1000 / min_l4_ticks; -} -#else -static int rfbi_get_max_tx_rate(void) -{ - return rfbi.l4_khz * 1000; -} -#endif - - -static int rfbi_convert_timings(struct extif_timings *t) -{ - u32 l; - int reon, reoff, weon, weoff, cson, csoff, cs_pulse; - int actim, recyc, wecyc; - int div = t->clk_div; - - if (div <= 0 || div > 2) - return -1; - - /* Make sure that after conversion it still holds that: - * weoff > weon, reoff > reon, recyc >= reoff, wecyc >= weoff, - * csoff > cson, csoff >= max(weoff, reoff), actim > reon - */ - weon = ps_to_rfbi_ticks(t->we_on_time, div); - weoff = ps_to_rfbi_ticks(t->we_off_time, div); - if (weoff <= weon) - weoff = weon + 1; - if (weon > 0x0f) - return -1; - if (weoff > 0x3f) - return -1; - - reon = ps_to_rfbi_ticks(t->re_on_time, div); - reoff = ps_to_rfbi_ticks(t->re_off_time, div); - if (reoff <= reon) - reoff = reon + 1; - if (reon > 0x0f) - return -1; - if (reoff > 0x3f) - return -1; - - cson = ps_to_rfbi_ticks(t->cs_on_time, div); - csoff = ps_to_rfbi_ticks(t->cs_off_time, div); - if (csoff <= cson) - csoff = cson + 1; - if (csoff < max(weoff, reoff)) - csoff = max(weoff, reoff); - if (cson > 0x0f) - return -1; - if (csoff > 0x3f) - return -1; - - l = cson; - l |= csoff << 4; - l |= weon << 10; - l |= weoff << 14; - l |= reon << 20; - l |= reoff << 24; - - t->tim[0] = l; - - actim = ps_to_rfbi_ticks(t->access_time, div); - if (actim <= reon) - actim = reon + 1; - if (actim > 0x3f) - return -1; - - wecyc = ps_to_rfbi_ticks(t->we_cycle_time, div); - if (wecyc < weoff) - wecyc = weoff; - if (wecyc > 0x3f) - return -1; - - recyc = ps_to_rfbi_ticks(t->re_cycle_time, div); - if (recyc < reoff) - recyc = reoff; - if (recyc > 0x3f) - return -1; - - cs_pulse = ps_to_rfbi_ticks(t->cs_pulse_width, div); - if (cs_pulse > 0x3f) - return -1; - - l = wecyc; - l |= recyc << 6; - l |= cs_pulse << 12; - l |= actim << 22; - - t->tim[1] = l; - - t->tim[2] = div - 1; - - t->converted = 1; - - return 0; -} - -static int rfbi_setup_tearsync(unsigned pin_cnt, - unsigned hs_pulse_time, unsigned vs_pulse_time, - int hs_pol_inv, int vs_pol_inv, int extif_div) -{ - int hs, vs; - int min; - u32 l; - - if (pin_cnt != 1 && pin_cnt != 2) - return -EINVAL; - - hs = ps_to_rfbi_ticks(hs_pulse_time, 1); - vs = ps_to_rfbi_ticks(vs_pulse_time, 1); - if (hs < 2) - return -EDOM; - if (pin_cnt == 2) - min = 2; - else - min = 4; - if (vs < min) - return -EDOM; - if (vs == hs) - return -EINVAL; - rfbi.tearsync_pin_cnt = pin_cnt; - dev_dbg(rfbi.fbdev->dev, - "setup_tearsync: pins %d hs %d vs %d hs_inv %d vs_inv %d\n", - pin_cnt, hs, vs, hs_pol_inv, vs_pol_inv); - - rfbi_enable_clocks(1); - rfbi_write_reg(RFBI_HSYNC_WIDTH, hs); - rfbi_write_reg(RFBI_VSYNC_WIDTH, vs); - - l = rfbi_read_reg(RFBI_CONFIG0); - if (hs_pol_inv) - l &= ~(1 << 21); - else - l |= 1 << 21; - if (vs_pol_inv) - l &= ~(1 << 20); - else - l |= 1 << 20; - rfbi_enable_clocks(0); - - return 0; -} - -static int rfbi_enable_tearsync(int enable, unsigned line) -{ - u32 l; - - dev_dbg(rfbi.fbdev->dev, "tearsync %d line %d mode %d\n", - enable, line, rfbi.tearsync_mode); - if (line > (1 << 11) - 1) - return -EINVAL; - - rfbi_enable_clocks(1); - l = rfbi_read_reg(RFBI_CONFIG0); - l &= ~(0x3 << 2); - if (enable) { - rfbi.tearsync_mode = rfbi.tearsync_pin_cnt; - l |= rfbi.tearsync_mode << 2; - } else - rfbi.tearsync_mode = 0; - rfbi_write_reg(RFBI_CONFIG0, l); - rfbi_write_reg(RFBI_LINE_NUMBER, line); - rfbi_enable_clocks(0); - - return 0; -} - -static void rfbi_write_command(const void *buf, unsigned int len) -{ - rfbi_enable_clocks(1); - if (rfbi.bits_per_cycle == 16) { - const u16 *w = buf; - BUG_ON(len & 1); - for (; len; len -= 2) - rfbi_write_reg(RFBI_CMD, *w++); - } else { - const u8 *b = buf; - BUG_ON(rfbi.bits_per_cycle != 8); - for (; len; len--) - rfbi_write_reg(RFBI_CMD, *b++); - } - rfbi_enable_clocks(0); -} - -static void rfbi_read_data(void *buf, unsigned int len) -{ - rfbi_enable_clocks(1); - if (rfbi.bits_per_cycle == 16) { - u16 *w = buf; - BUG_ON(len & ~1); - for (; len; len -= 2) { - rfbi_write_reg(RFBI_READ, 0); - *w++ = rfbi_read_reg(RFBI_READ); - } - } else { - u8 *b = buf; - BUG_ON(rfbi.bits_per_cycle != 8); - for (; len; len--) { - rfbi_write_reg(RFBI_READ, 0); - *b++ = rfbi_read_reg(RFBI_READ); - } - } - rfbi_enable_clocks(0); -} - -static void rfbi_write_data(const void *buf, unsigned int len) -{ - rfbi_enable_clocks(1); - if (rfbi.bits_per_cycle == 16) { - const u16 *w = buf; - BUG_ON(len & 1); - for (; len; len -= 2) - rfbi_write_reg(RFBI_PARAM, *w++); - } else { - const u8 *b = buf; - BUG_ON(rfbi.bits_per_cycle != 8); - for (; len; len--) - rfbi_write_reg(RFBI_PARAM, *b++); - } - rfbi_enable_clocks(0); -} - -static void rfbi_transfer_area(int width, int height, - void (callback)(void * data), void *data) -{ - u32 w; - - BUG_ON(callback == NULL); - - rfbi_enable_clocks(1); - omap_dispc_set_lcd_size(width, height); - - rfbi.lcdc_callback = callback; - rfbi.lcdc_callback_data = data; - - rfbi_write_reg(RFBI_PIXEL_CNT, width * height); - - w = rfbi_read_reg(RFBI_CONTROL); - w |= 1; /* enable */ - if (!rfbi.tearsync_mode) - w |= 1 << 4; /* internal trigger, reset by HW */ - rfbi_write_reg(RFBI_CONTROL, w); - - omap_dispc_enable_lcd_out(1); -} - -static inline void _stop_transfer(void) -{ - u32 w; - - w = rfbi_read_reg(RFBI_CONTROL); - rfbi_write_reg(RFBI_CONTROL, w & ~(1 << 0)); - rfbi_enable_clocks(0); -} - -static void rfbi_dma_callback(void *data) -{ - _stop_transfer(); - rfbi.lcdc_callback(rfbi.lcdc_callback_data); -} - -static void rfbi_set_bits_per_cycle(int bpc) -{ - u32 l; - - rfbi_enable_clocks(1); - l = rfbi_read_reg(RFBI_CONFIG0); - l &= ~(0x03 << 0); - - switch (bpc) { - case 8: - break; - case 16: - l |= 3; - break; - default: - BUG(); - } - rfbi_write_reg(RFBI_CONFIG0, l); - rfbi.bits_per_cycle = bpc; - rfbi_enable_clocks(0); -} - -static int rfbi_init(struct omapfb_device *fbdev) -{ - u32 l; - int r; - - rfbi.fbdev = fbdev; - rfbi.base = ioremap(RFBI_BASE, SZ_1K); - if (!rfbi.base) { - dev_err(fbdev->dev, "can't ioremap RFBI\n"); - return -ENOMEM; - } - - if ((r = rfbi_get_clocks()) < 0) - return r; - rfbi_enable_clocks(1); - - rfbi.l4_khz = clk_get_rate(rfbi.dss_ick) / 1000; - - /* Reset */ - rfbi_write_reg(RFBI_SYSCONFIG, 1 << 1); - while (!(rfbi_read_reg(RFBI_SYSSTATUS) & (1 << 0))); - - l = rfbi_read_reg(RFBI_SYSCONFIG); - /* Enable autoidle and smart-idle */ - l |= (1 << 0) | (2 << 3); - rfbi_write_reg(RFBI_SYSCONFIG, l); - - /* 16-bit interface, ITE trigger mode, 16-bit data */ - l = (0x03 << 0) | (0x00 << 2) | (0x01 << 5) | (0x02 << 7); - l |= (0 << 9) | (1 << 20) | (1 << 21); - rfbi_write_reg(RFBI_CONFIG0, l); - - rfbi_write_reg(RFBI_DATA_CYCLE1_0, 0x00000010); - - l = rfbi_read_reg(RFBI_CONTROL); - /* Select CS0, clear bypass mode */ - l = (0x01 << 2); - rfbi_write_reg(RFBI_CONTROL, l); - - r = omap_dispc_request_irq(DISPC_IRQ_FRAMEMASK, rfbi_dma_callback, - NULL); - if (r < 0) { - dev_err(fbdev->dev, "can't get DISPC irq\n"); - rfbi_enable_clocks(0); - return r; - } - - l = rfbi_read_reg(RFBI_REVISION); - pr_info("omapfb: RFBI version %d.%d initialized\n", - (l >> 4) & 0x0f, l & 0x0f); - - rfbi_enable_clocks(0); - - return 0; -} - -static void rfbi_cleanup(void) -{ - omap_dispc_free_irq(DISPC_IRQ_FRAMEMASK, rfbi_dma_callback, NULL); - rfbi_put_clocks(); - iounmap(rfbi.base); -} - -const struct lcd_ctrl_extif omap2_ext_if = { - .init = rfbi_init, - .cleanup = rfbi_cleanup, - .get_clk_info = rfbi_get_clk_info, - .get_max_tx_rate = rfbi_get_max_tx_rate, - .set_bits_per_cycle = rfbi_set_bits_per_cycle, - .convert_timings = rfbi_convert_timings, - .set_timings = rfbi_set_timings, - .write_command = rfbi_write_command, - .read_data = rfbi_read_data, - .write_data = rfbi_write_data, - .transfer_area = rfbi_transfer_area, - .setup_tearsync = rfbi_setup_tearsync, - .enable_tearsync = rfbi_enable_tearsync, - - .max_transmit_size = (u32) ~0, -}; - -- cgit v1.2.3 From 2a803c887b654bad7d6699f1270eaac31361afc9 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Mon, 18 Apr 2011 13:18:20 +0300 Subject: OMAPDSS: Remove video SRAM support OMAP SRAM can be used as video memory on OMAP1 and 2. However, there usually is very little SRAM available, thus limiting its use, and no board supported by the kernel currently uses it. This patch removes the use of SRAM as video ram for the omapdss driver to simplify memory handling. Signed-off-by: Tomi Valkeinen Acked-by: Tony Lindgren --- arch/arm/plat-omap/include/plat/vram.h | 21 +------ drivers/video/omap2/dss/dispc.c | 1 - drivers/video/omap2/omapfb/omapfb-ioctl.c | 2 +- drivers/video/omap2/omapfb/omapfb-main.c | 4 +- drivers/video/omap2/vram.c | 99 ++----------------------------- 5 files changed, 9 insertions(+), 118 deletions(-) diff --git a/arch/arm/plat-omap/include/plat/vram.h b/arch/arm/plat-omap/include/plat/vram.h index 0aa4ecd12c7..4d65b7d06e6 100644 --- a/arch/arm/plat-omap/include/plat/vram.h +++ b/arch/arm/plat-omap/include/plat/vram.h @@ -23,40 +23,21 @@ #include -#define OMAP_VRAM_MEMTYPE_SDRAM 0 -#define OMAP_VRAM_MEMTYPE_SRAM 1 -#define OMAP_VRAM_MEMTYPE_MAX 1 - extern int omap_vram_add_region(unsigned long paddr, size_t size); extern int omap_vram_free(unsigned long paddr, size_t size); -extern int omap_vram_alloc(int mtype, size_t size, unsigned long *paddr); +extern int omap_vram_alloc(size_t size, unsigned long *paddr); extern int omap_vram_reserve(unsigned long paddr, size_t size); extern void omap_vram_get_info(unsigned long *vram, unsigned long *free_vram, unsigned long *largest_free_block); #ifdef CONFIG_OMAP2_VRAM extern void omap_vram_set_sdram_vram(u32 size, u32 start); -extern void omap_vram_set_sram_vram(u32 size, u32 start); extern void omap_vram_reserve_sdram_memblock(void); -extern unsigned long omap_vram_reserve_sram(unsigned long sram_pstart, - unsigned long sram_vstart, - unsigned long sram_size, - unsigned long pstart_avail, - unsigned long size_avail); #else static inline void omap_vram_set_sdram_vram(u32 size, u32 start) { } -static inline void omap_vram_set_sram_vram(u32 size, u32 start) { } static inline void omap_vram_reserve_sdram_memblock(void) { } -static inline unsigned long omap_vram_reserve_sram(unsigned long sram_pstart, - unsigned long sram_vstart, - unsigned long sram_size, - unsigned long pstart_avail, - unsigned long size_avail) -{ - return 0; -} #endif #endif diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index e1626a1d5c4..0aecb680f8a 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c @@ -37,7 +37,6 @@ #include #include -#include #include #include