2011-11-04 14:48:54 +07:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2011 Texas Instruments
|
|
|
|
* Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
|
|
* under the terms of the GNU General Public License version 2 as published by
|
|
|
|
* the Free Software Foundation.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
|
|
* more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License along with
|
|
|
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define DSS_SUBSYS_NAME "APPLY"
|
|
|
|
|
|
|
|
#include <linux/kernel.h>
|
2012-10-10 14:26:45 +07:00
|
|
|
#include <linux/module.h>
|
2011-11-04 14:48:54 +07:00
|
|
|
#include <linux/slab.h>
|
|
|
|
#include <linux/spinlock.h>
|
|
|
|
#include <linux/jiffies.h>
|
|
|
|
|
|
|
|
#include <video/omapdss.h>
|
|
|
|
|
|
|
|
#include "dss.h"
|
|
|
|
#include "dss_features.h"
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We have 4 levels of cache for the dispc settings. First two are in SW and
|
|
|
|
* the latter two in HW.
|
|
|
|
*
|
2011-11-16 19:31:58 +07:00
|
|
|
* set_info()
|
|
|
|
* v
|
2011-11-04 14:48:54 +07:00
|
|
|
* +--------------------+
|
2011-11-16 19:31:58 +07:00
|
|
|
* | user_info |
|
2011-11-04 14:48:54 +07:00
|
|
|
* +--------------------+
|
|
|
|
* v
|
|
|
|
* apply()
|
|
|
|
* v
|
|
|
|
* +--------------------+
|
2011-11-15 17:04:43 +07:00
|
|
|
* | info |
|
2011-11-04 14:48:54 +07:00
|
|
|
* +--------------------+
|
|
|
|
* v
|
2011-11-15 16:47:39 +07:00
|
|
|
* write_regs()
|
2011-11-04 14:48:54 +07:00
|
|
|
* v
|
|
|
|
* +--------------------+
|
|
|
|
* | shadow registers |
|
|
|
|
* +--------------------+
|
|
|
|
* v
|
|
|
|
* VFP or lcd/digit_enable
|
|
|
|
* v
|
|
|
|
* +--------------------+
|
|
|
|
* | registers |
|
|
|
|
* +--------------------+
|
|
|
|
*/
|
|
|
|
|
2011-11-15 16:56:57 +07:00
|
|
|
struct ovl_priv_data {
|
2011-11-16 19:11:56 +07:00
|
|
|
|
|
|
|
bool user_info_dirty;
|
|
|
|
struct omap_overlay_info user_info;
|
|
|
|
|
2011-11-16 19:31:58 +07:00
|
|
|
bool info_dirty;
|
2011-11-04 14:48:54 +07:00
|
|
|
struct omap_overlay_info info;
|
|
|
|
|
2011-11-16 19:31:58 +07:00
|
|
|
bool shadow_info_dirty;
|
|
|
|
|
OMAPDSS: APPLY: rewrite overlay enable/disable
Overlays are currently enabled and disabled with a boolean in the struct
omap_overlay_info. The overlay info is set with ovl->set_overlay_info(),
and made into use with mgr->apply().
This doesn't work properly, as the enable/disable status may affect also
other overlays, for example when using fifo-merge. Thus the enabling and
disabling of the overlay needs to be done outside the normal overlay
configuration.
This patch achieves that by doing the following things:
1) Add function pointers to struct omap_overlay: enable(), disable() and
is_enabled(). These are used to do the obvious. The functions may block.
2) Move the "enabled" field from struct omap_overlay to ovl_priv_data.
3) Add a new route for settings to be applied to the HW, called
"extra_info". The status of the normal info and extra_info are tracked
separately.
The point here is to allow the normal info to be changed and
applied in non-blocking matter, whereas the extra_info can only be
changed when holding the mutex. This makes it possible to, for example,
set the overlay enable flag, apply it, and wait until the HW has taken
the flag into use.
This is not possible if the enable flag would be in the normal info, as
a new value for the flag could be set at any time from the users of
omapdss.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
2011-11-15 21:37:53 +07:00
|
|
|
bool extra_info_dirty;
|
|
|
|
bool shadow_extra_info_dirty;
|
|
|
|
|
|
|
|
bool enabled;
|
2011-11-16 19:28:12 +07:00
|
|
|
u32 fifo_low, fifo_high;
|
2011-11-26 19:26:46 +07:00
|
|
|
|
|
|
|
/*
|
|
|
|
* True if overlay is to be enabled. Used to check and calculate configs
|
|
|
|
* for the overlay before it is enabled in the HW.
|
|
|
|
*/
|
|
|
|
bool enabling;
|
2011-11-04 14:48:54 +07:00
|
|
|
};
|
|
|
|
|
2011-11-15 17:02:03 +07:00
|
|
|
struct mgr_priv_data {
|
2011-11-16 18:58:07 +07:00
|
|
|
|
|
|
|
bool user_info_dirty;
|
|
|
|
struct omap_overlay_manager_info user_info;
|
|
|
|
|
2011-11-16 19:31:58 +07:00
|
|
|
bool info_dirty;
|
2011-11-04 14:48:54 +07:00
|
|
|
struct omap_overlay_manager_info info;
|
|
|
|
|
2011-11-16 19:31:58 +07:00
|
|
|
bool shadow_info_dirty;
|
|
|
|
|
2011-11-15 20:04:25 +07:00
|
|
|
/* If true, GO bit is up and shadow registers cannot be written.
|
|
|
|
* Never true for manual update displays */
|
|
|
|
bool busy;
|
|
|
|
|
2011-11-18 20:43:29 +07:00
|
|
|
/* If true, dispc output is enabled */
|
|
|
|
bool updating;
|
|
|
|
|
2011-11-15 19:43:53 +07:00
|
|
|
/* If true, a display is enabled using this manager */
|
|
|
|
bool enabled;
|
2012-04-26 21:01:22 +07:00
|
|
|
|
|
|
|
bool extra_info_dirty;
|
|
|
|
bool shadow_extra_info_dirty;
|
|
|
|
|
|
|
|
struct omap_video_timings timings;
|
2012-06-29 16:07:03 +07:00
|
|
|
struct dss_lcd_mgr_config lcd_config;
|
2011-11-04 14:48:54 +07:00
|
|
|
};
|
|
|
|
|
|
|
|
static struct {
|
2011-11-15 16:56:57 +07:00
|
|
|
struct ovl_priv_data ovl_priv_data_array[MAX_DSS_OVERLAYS];
|
2011-11-15 17:02:03 +07:00
|
|
|
struct mgr_priv_data mgr_priv_data_array[MAX_DSS_MANAGERS];
|
2011-11-04 14:48:54 +07:00
|
|
|
|
|
|
|
bool irq_enabled;
|
2011-11-15 17:04:43 +07:00
|
|
|
} dss_data;
|
2011-11-04 14:48:54 +07:00
|
|
|
|
2011-11-15 17:04:43 +07:00
|
|
|
/* protects dss_data */
|
2011-11-15 17:04:10 +07:00
|
|
|
static spinlock_t data_lock;
|
OMAPDSS: APPLY: add mutex
The functions in apply.c, called mostly via function pointers in overlay
and overlay_manager structs, will be divided into two groups. The first
group will not sleep and can be called from interrupts, and the second
group may sleep.
The idea is that the non-sleeping functions may only change certain
settings in overlays and managers, and those settings may only affect
the particular overlay/manager. For example, set the base address of the
overlay.
The blocking functions, however, will handle more complex configuration
changes. For example, when an overlay is enabled and fifo-merge feature
is used, we need to do the enable in multiple steps, waiting in between,
and the change affects multiple overlays and managers.
This patch adds the mutex which is used in the blocking functions to
have exclusive access to overlays and overlay managers.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
2011-11-15 19:28:48 +07:00
|
|
|
/* lock for blocking functions */
|
|
|
|
static DEFINE_MUTEX(apply_lock);
|
2011-11-16 19:37:48 +07:00
|
|
|
static DECLARE_COMPLETION(extra_updated_completion);
|
2011-11-15 17:04:10 +07:00
|
|
|
|
2011-11-15 23:25:23 +07:00
|
|
|
static void dss_register_vsync_isr(void);
|
|
|
|
|
2011-11-15 16:56:57 +07:00
|
|
|
static struct ovl_priv_data *get_ovl_priv(struct omap_overlay *ovl)
|
|
|
|
{
|
2011-11-15 17:04:43 +07:00
|
|
|
return &dss_data.ovl_priv_data_array[ovl->id];
|
2011-11-15 16:56:57 +07:00
|
|
|
}
|
|
|
|
|
2011-11-15 17:02:03 +07:00
|
|
|
static struct mgr_priv_data *get_mgr_priv(struct omap_overlay_manager *mgr)
|
|
|
|
{
|
2011-11-15 17:04:43 +07:00
|
|
|
return &dss_data.mgr_priv_data_array[mgr->id];
|
2011-11-15 17:02:03 +07:00
|
|
|
}
|
|
|
|
|
2012-10-10 14:26:45 +07:00
|
|
|
static void apply_init_priv(void)
|
2011-11-04 14:48:54 +07:00
|
|
|
{
|
2011-11-16 19:11:56 +07:00
|
|
|
const int num_ovls = dss_feat_get_num_ovls();
|
2012-06-29 16:07:03 +07:00
|
|
|
struct mgr_priv_data *mp;
|
2011-11-16 19:11:56 +07:00
|
|
|
int i;
|
|
|
|
|
2011-11-15 17:04:10 +07:00
|
|
|
spin_lock_init(&data_lock);
|
2011-11-16 19:11:56 +07:00
|
|
|
|
|
|
|
for (i = 0; i < num_ovls; ++i) {
|
|
|
|
struct ovl_priv_data *op;
|
|
|
|
|
|
|
|
op = &dss_data.ovl_priv_data_array[i];
|
|
|
|
|
|
|
|
op->info.global_alpha = 255;
|
|
|
|
|
|
|
|
switch (i) {
|
|
|
|
case 0:
|
|
|
|
op->info.zorder = 0;
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
op->info.zorder =
|
|
|
|
dss_has_feature(FEAT_ALPHA_FREE_ZORDER) ? 3 : 0;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
op->info.zorder =
|
|
|
|
dss_has_feature(FEAT_ALPHA_FREE_ZORDER) ? 2 : 0;
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
op->info.zorder =
|
|
|
|
dss_has_feature(FEAT_ALPHA_FREE_ZORDER) ? 1 : 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
op->user_info = op->info;
|
|
|
|
}
|
2012-06-29 16:07:03 +07:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Initialize some of the lcd_config fields for TV manager, this lets
|
|
|
|
* us prevent checking if the manager is LCD or TV at some places
|
|
|
|
*/
|
|
|
|
mp = &dss_data.mgr_priv_data_array[OMAP_DSS_CHANNEL_DIGIT];
|
|
|
|
|
|
|
|
mp->lcd_config.video_port_width = 24;
|
|
|
|
mp->lcd_config.clock_info.lck_div = 1;
|
|
|
|
mp->lcd_config.clock_info.pck_div = 1;
|
2011-11-04 14:48:54 +07:00
|
|
|
}
|
|
|
|
|
2012-05-24 16:38:54 +07:00
|
|
|
/*
|
|
|
|
* A LCD manager's stallmode decides whether it is in manual or auto update. TV
|
|
|
|
* manager is always auto update, stallmode field for TV manager is false by
|
|
|
|
* default
|
|
|
|
*/
|
2011-11-04 14:48:54 +07:00
|
|
|
static bool ovl_manual_update(struct omap_overlay *ovl)
|
|
|
|
{
|
2012-05-24 16:38:54 +07:00
|
|
|
struct mgr_priv_data *mp = get_mgr_priv(ovl->manager);
|
|
|
|
|
|
|
|
return mp->lcd_config.stallmode;
|
2011-11-04 14:48:54 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
static bool mgr_manual_update(struct omap_overlay_manager *mgr)
|
|
|
|
{
|
2012-05-24 16:38:54 +07:00
|
|
|
struct mgr_priv_data *mp = get_mgr_priv(mgr);
|
|
|
|
|
|
|
|
return mp->lcd_config.stallmode;
|
2011-11-04 14:48:54 +07:00
|
|
|
}
|
|
|
|
|
2011-11-17 22:35:28 +07:00
|
|
|
static int dss_check_settings_low(struct omap_overlay_manager *mgr,
|
2012-04-27 02:52:28 +07:00
|
|
|
bool applying)
|
2011-11-17 22:35:28 +07:00
|
|
|
{
|
|
|
|
struct omap_overlay_info *oi;
|
|
|
|
struct omap_overlay_manager_info *mi;
|
|
|
|
struct omap_overlay *ovl;
|
|
|
|
struct omap_overlay_info *ois[MAX_DSS_OVERLAYS];
|
|
|
|
struct ovl_priv_data *op;
|
|
|
|
struct mgr_priv_data *mp;
|
|
|
|
|
|
|
|
mp = get_mgr_priv(mgr);
|
|
|
|
|
2012-05-08 19:49:15 +07:00
|
|
|
if (!mp->enabled)
|
|
|
|
return 0;
|
|
|
|
|
2011-11-17 22:35:28 +07:00
|
|
|
if (applying && mp->user_info_dirty)
|
|
|
|
mi = &mp->user_info;
|
|
|
|
else
|
|
|
|
mi = &mp->info;
|
|
|
|
|
|
|
|
/* collect the infos to be tested into the array */
|
|
|
|
list_for_each_entry(ovl, &mgr->overlays, list) {
|
|
|
|
op = get_ovl_priv(ovl);
|
|
|
|
|
2011-11-26 19:26:46 +07:00
|
|
|
if (!op->enabled && !op->enabling)
|
2011-11-17 22:35:28 +07:00
|
|
|
oi = NULL;
|
|
|
|
else if (applying && op->user_info_dirty)
|
|
|
|
oi = &op->user_info;
|
|
|
|
else
|
|
|
|
oi = &op->info;
|
|
|
|
|
|
|
|
ois[ovl->id] = oi;
|
|
|
|
}
|
|
|
|
|
2012-05-23 18:31:35 +07:00
|
|
|
return dss_mgr_check(mgr, mi, &mp->timings, &mp->lcd_config, ois);
|
2011-11-17 22:35:28 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* check manager and overlay settings using overlay_info from data->info
|
|
|
|
*/
|
2012-04-27 02:52:28 +07:00
|
|
|
static int dss_check_settings(struct omap_overlay_manager *mgr)
|
2011-11-17 22:35:28 +07:00
|
|
|
{
|
2012-04-27 02:52:28 +07:00
|
|
|
return dss_check_settings_low(mgr, false);
|
2011-11-17 22:35:28 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* check manager and overlay settings using overlay_info from ovl->info if
|
|
|
|
* dirty and from data->info otherwise
|
|
|
|
*/
|
2012-04-27 02:52:28 +07:00
|
|
|
static int dss_check_settings_apply(struct omap_overlay_manager *mgr)
|
2011-11-17 22:35:28 +07:00
|
|
|
{
|
2012-04-27 02:52:28 +07:00
|
|
|
return dss_check_settings_low(mgr, true);
|
2011-11-17 22:35:28 +07:00
|
|
|
}
|
|
|
|
|
2011-11-15 23:25:23 +07:00
|
|
|
static bool need_isr(void)
|
|
|
|
{
|
|
|
|
const int num_mgrs = dss_feat_get_num_mgrs();
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < num_mgrs; ++i) {
|
|
|
|
struct omap_overlay_manager *mgr;
|
|
|
|
struct mgr_priv_data *mp;
|
|
|
|
struct omap_overlay *ovl;
|
|
|
|
|
|
|
|
mgr = omap_dss_get_overlay_manager(i);
|
|
|
|
mp = get_mgr_priv(mgr);
|
|
|
|
|
|
|
|
if (!mp->enabled)
|
|
|
|
continue;
|
|
|
|
|
2011-11-18 20:43:29 +07:00
|
|
|
if (mgr_manual_update(mgr)) {
|
|
|
|
/* to catch FRAMEDONE */
|
|
|
|
if (mp->updating)
|
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
/* to catch GO bit going down */
|
|
|
|
if (mp->busy)
|
|
|
|
return true;
|
2011-11-15 23:25:23 +07:00
|
|
|
|
2011-11-18 20:43:29 +07:00
|
|
|
/* to write new values to registers */
|
2011-11-16 19:31:58 +07:00
|
|
|
if (mp->info_dirty)
|
2011-11-18 20:43:29 +07:00
|
|
|
return true;
|
2011-11-15 23:25:23 +07:00
|
|
|
|
2011-11-25 22:26:13 +07:00
|
|
|
/* to set GO bit */
|
|
|
|
if (mp->shadow_info_dirty)
|
|
|
|
return true;
|
|
|
|
|
2012-04-26 21:01:22 +07:00
|
|
|
/*
|
|
|
|
* NOTE: we don't check extra_info flags for disabled
|
|
|
|
* managers, once the manager is enabled, the extra_info
|
|
|
|
* related manager changes will be taken in by HW.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* to write new values to registers */
|
|
|
|
if (mp->extra_info_dirty)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
/* to set GO bit */
|
|
|
|
if (mp->shadow_extra_info_dirty)
|
|
|
|
return true;
|
|
|
|
|
2011-11-18 20:43:29 +07:00
|
|
|
list_for_each_entry(ovl, &mgr->overlays, list) {
|
|
|
|
struct ovl_priv_data *op;
|
2011-11-15 23:25:23 +07:00
|
|
|
|
2011-11-18 20:43:29 +07:00
|
|
|
op = get_ovl_priv(ovl);
|
2011-11-15 23:25:23 +07:00
|
|
|
|
2011-11-25 22:26:13 +07:00
|
|
|
/*
|
|
|
|
* NOTE: we check extra_info flags even for
|
|
|
|
* disabled overlays, as extra_infos need to be
|
|
|
|
* always written.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* to write new values to registers */
|
|
|
|
if (op->extra_info_dirty)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
/* to set GO bit */
|
|
|
|
if (op->shadow_extra_info_dirty)
|
|
|
|
return true;
|
|
|
|
|
2011-11-18 20:43:29 +07:00
|
|
|
if (!op->enabled)
|
|
|
|
continue;
|
2011-11-15 23:25:23 +07:00
|
|
|
|
2011-11-18 20:43:29 +07:00
|
|
|
/* to write new values to registers */
|
2011-11-25 22:26:13 +07:00
|
|
|
if (op->info_dirty)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
/* to set GO bit */
|
|
|
|
if (op->shadow_info_dirty)
|
2011-11-18 20:43:29 +07:00
|
|
|
return true;
|
|
|
|
}
|
2011-11-15 23:25:23 +07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool need_go(struct omap_overlay_manager *mgr)
|
|
|
|
{
|
|
|
|
struct omap_overlay *ovl;
|
|
|
|
struct mgr_priv_data *mp;
|
|
|
|
struct ovl_priv_data *op;
|
|
|
|
|
|
|
|
mp = get_mgr_priv(mgr);
|
|
|
|
|
2012-04-26 21:01:22 +07:00
|
|
|
if (mp->shadow_info_dirty || mp->shadow_extra_info_dirty)
|
2011-11-15 23:25:23 +07:00
|
|
|
return true;
|
|
|
|
|
|
|
|
list_for_each_entry(ovl, &mgr->overlays, list) {
|
|
|
|
op = get_ovl_priv(ovl);
|
2011-11-16 19:31:58 +07:00
|
|
|
if (op->shadow_info_dirty || op->shadow_extra_info_dirty)
|
2011-11-15 23:25:23 +07:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2011-11-16 19:37:48 +07:00
|
|
|
/* returns true if an extra_info field is currently being updated */
|
|
|
|
static bool extra_info_update_ongoing(void)
|
|
|
|
{
|
2012-04-26 21:01:22 +07:00
|
|
|
const int num_mgrs = dss_feat_get_num_mgrs();
|
2011-11-16 19:37:48 +07:00
|
|
|
int i;
|
|
|
|
|
2012-04-26 21:01:22 +07:00
|
|
|
for (i = 0; i < num_mgrs; ++i) {
|
|
|
|
struct omap_overlay_manager *mgr;
|
|
|
|
struct omap_overlay *ovl;
|
|
|
|
struct mgr_priv_data *mp;
|
2011-12-18 02:28:52 +07:00
|
|
|
|
2012-04-26 21:01:22 +07:00
|
|
|
mgr = omap_dss_get_overlay_manager(i);
|
|
|
|
mp = get_mgr_priv(mgr);
|
2011-11-16 19:37:48 +07:00
|
|
|
|
|
|
|
if (!mp->enabled)
|
|
|
|
continue;
|
|
|
|
|
2011-11-25 22:35:35 +07:00
|
|
|
if (!mp->updating)
|
2011-11-16 19:37:48 +07:00
|
|
|
continue;
|
|
|
|
|
2012-04-26 21:01:22 +07:00
|
|
|
if (mp->extra_info_dirty || mp->shadow_extra_info_dirty)
|
2011-11-25 22:35:35 +07:00
|
|
|
return true;
|
2012-04-26 21:01:22 +07:00
|
|
|
|
|
|
|
list_for_each_entry(ovl, &mgr->overlays, list) {
|
|
|
|
struct ovl_priv_data *op = get_ovl_priv(ovl);
|
|
|
|
|
|
|
|
if (op->extra_info_dirty || op->shadow_extra_info_dirty)
|
|
|
|
return true;
|
|
|
|
}
|
2011-11-16 19:37:48 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* wait until no extra_info updates are pending */
|
|
|
|
static void wait_pending_extra_info_updates(void)
|
|
|
|
{
|
|
|
|
bool updating;
|
|
|
|
unsigned long flags;
|
|
|
|
unsigned long t;
|
2012-02-23 17:21:09 +07:00
|
|
|
int r;
|
2011-11-16 19:37:48 +07:00
|
|
|
|
|
|
|
spin_lock_irqsave(&data_lock, flags);
|
|
|
|
|
|
|
|
updating = extra_info_update_ongoing();
|
|
|
|
|
|
|
|
if (!updating) {
|
|
|
|
spin_unlock_irqrestore(&data_lock, flags);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
init_completion(&extra_updated_completion);
|
|
|
|
|
|
|
|
spin_unlock_irqrestore(&data_lock, flags);
|
|
|
|
|
|
|
|
t = msecs_to_jiffies(500);
|
2012-02-23 17:21:09 +07:00
|
|
|
r = wait_for_completion_timeout(&extra_updated_completion, t);
|
|
|
|
if (r == 0)
|
|
|
|
DSSWARN("timeout in wait_pending_extra_info_updates\n");
|
2011-11-16 19:37:48 +07:00
|
|
|
}
|
|
|
|
|
2011-11-04 14:48:54 +07:00
|
|
|
int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr)
|
|
|
|
{
|
|
|
|
unsigned long timeout = msecs_to_jiffies(500);
|
2012-06-26 17:06:55 +07:00
|
|
|
struct mgr_priv_data *mp = get_mgr_priv(mgr);
|
2011-11-04 14:48:54 +07:00
|
|
|
u32 irq;
|
2012-06-26 17:06:55 +07:00
|
|
|
unsigned long flags;
|
2011-11-04 14:48:54 +07:00
|
|
|
int r;
|
|
|
|
int i;
|
|
|
|
|
2012-06-26 17:06:55 +07:00
|
|
|
spin_lock_irqsave(&data_lock, flags);
|
|
|
|
|
|
|
|
if (mgr_manual_update(mgr)) {
|
|
|
|
spin_unlock_irqrestore(&data_lock, flags);
|
2011-11-04 14:48:54 +07:00
|
|
|
return 0;
|
2012-06-26 17:06:55 +07:00
|
|
|
}
|
2011-11-04 14:48:54 +07:00
|
|
|
|
2012-06-26 17:06:55 +07:00
|
|
|
if (!mp->enabled) {
|
|
|
|
spin_unlock_irqrestore(&data_lock, flags);
|
2011-11-04 14:48:54 +07:00
|
|
|
return 0;
|
2012-06-26 17:06:55 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
spin_unlock_irqrestore(&data_lock, flags);
|
2011-11-04 14:48:54 +07:00
|
|
|
|
2012-02-22 13:53:16 +07:00
|
|
|
r = dispc_runtime_get();
|
|
|
|
if (r)
|
|
|
|
return r;
|
|
|
|
|
2011-11-15 16:20:13 +07:00
|
|
|
irq = dispc_mgr_get_vsync_irq(mgr->id);
|
2011-11-04 14:48:54 +07:00
|
|
|
|
|
|
|
i = 0;
|
|
|
|
while (1) {
|
|
|
|
bool shadow_dirty, dirty;
|
|
|
|
|
2011-11-15 17:04:10 +07:00
|
|
|
spin_lock_irqsave(&data_lock, flags);
|
2011-11-16 19:31:58 +07:00
|
|
|
dirty = mp->info_dirty;
|
|
|
|
shadow_dirty = mp->shadow_info_dirty;
|
2011-11-15 17:04:10 +07:00
|
|
|
spin_unlock_irqrestore(&data_lock, flags);
|
2011-11-04 14:48:54 +07:00
|
|
|
|
|
|
|
if (!dirty && !shadow_dirty) {
|
|
|
|
r = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* 4 iterations is the worst case:
|
|
|
|
* 1 - initial iteration, dirty = true (between VFP and VSYNC)
|
|
|
|
* 2 - first VSYNC, dirty = true
|
|
|
|
* 3 - dirty = false, shadow_dirty = true
|
|
|
|
* 4 - shadow_dirty = false */
|
|
|
|
if (i++ == 3) {
|
|
|
|
DSSERR("mgr(%d)->wait_for_go() not finishing\n",
|
|
|
|
mgr->id);
|
|
|
|
r = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
|
|
|
|
if (r == -ERESTARTSYS)
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (r) {
|
|
|
|
DSSERR("mgr(%d)->wait_for_go() timeout\n", mgr->id);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-02-22 13:53:16 +07:00
|
|
|
dispc_runtime_put();
|
|
|
|
|
2011-11-04 14:48:54 +07:00
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl)
|
|
|
|
{
|
|
|
|
unsigned long timeout = msecs_to_jiffies(500);
|
2011-11-15 16:56:57 +07:00
|
|
|
struct ovl_priv_data *op;
|
2012-06-26 17:06:55 +07:00
|
|
|
struct mgr_priv_data *mp;
|
2011-11-04 14:48:54 +07:00
|
|
|
u32 irq;
|
2012-06-26 17:06:55 +07:00
|
|
|
unsigned long flags;
|
2011-11-04 14:48:54 +07:00
|
|
|
int r;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (!ovl->manager)
|
|
|
|
return 0;
|
|
|
|
|
2012-06-26 17:06:55 +07:00
|
|
|
mp = get_mgr_priv(ovl->manager);
|
2011-11-04 14:48:54 +07:00
|
|
|
|
2012-06-26 17:06:55 +07:00
|
|
|
spin_lock_irqsave(&data_lock, flags);
|
|
|
|
|
|
|
|
if (ovl_manual_update(ovl)) {
|
|
|
|
spin_unlock_irqrestore(&data_lock, flags);
|
2011-11-04 14:48:54 +07:00
|
|
|
return 0;
|
2012-06-26 17:06:55 +07:00
|
|
|
}
|
2011-11-04 14:48:54 +07:00
|
|
|
|
2012-06-26 17:06:55 +07:00
|
|
|
if (!mp->enabled) {
|
|
|
|
spin_unlock_irqrestore(&data_lock, flags);
|
2011-11-04 14:48:54 +07:00
|
|
|
return 0;
|
2012-06-26 17:06:55 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
spin_unlock_irqrestore(&data_lock, flags);
|
2011-11-04 14:48:54 +07:00
|
|
|
|
2012-02-22 13:53:16 +07:00
|
|
|
r = dispc_runtime_get();
|
|
|
|
if (r)
|
|
|
|
return r;
|
|
|
|
|
2011-11-15 16:20:13 +07:00
|
|
|
irq = dispc_mgr_get_vsync_irq(ovl->manager->id);
|
2011-11-04 14:48:54 +07:00
|
|
|
|
2011-11-15 16:56:57 +07:00
|
|
|
op = get_ovl_priv(ovl);
|
2011-11-04 14:48:54 +07:00
|
|
|
i = 0;
|
|
|
|
while (1) {
|
|
|
|
bool shadow_dirty, dirty;
|
|
|
|
|
2011-11-15 17:04:10 +07:00
|
|
|
spin_lock_irqsave(&data_lock, flags);
|
2011-11-16 19:31:58 +07:00
|
|
|
dirty = op->info_dirty;
|
|
|
|
shadow_dirty = op->shadow_info_dirty;
|
2011-11-15 17:04:10 +07:00
|
|
|
spin_unlock_irqrestore(&data_lock, flags);
|
2011-11-04 14:48:54 +07:00
|
|
|
|
|
|
|
if (!dirty && !shadow_dirty) {
|
|
|
|
r = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* 4 iterations is the worst case:
|
|
|
|
* 1 - initial iteration, dirty = true (between VFP and VSYNC)
|
|
|
|
* 2 - first VSYNC, dirty = true
|
|
|
|
* 3 - dirty = false, shadow_dirty = true
|
|
|
|
* 4 - shadow_dirty = false */
|
|
|
|
if (i++ == 3) {
|
|
|
|
DSSERR("ovl(%d)->wait_for_go() not finishing\n",
|
|
|
|
ovl->id);
|
|
|
|
r = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
|
|
|
|
if (r == -ERESTARTSYS)
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (r) {
|
|
|
|
DSSERR("ovl(%d)->wait_for_go() timeout\n", ovl->id);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-02-22 13:53:16 +07:00
|
|
|
dispc_runtime_put();
|
|
|
|
|
2011-11-04 14:48:54 +07:00
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
2011-11-15 23:25:23 +07:00
|
|
|
static void dss_ovl_write_regs(struct omap_overlay *ovl)
|
2011-11-04 14:48:54 +07:00
|
|
|
{
|
2011-11-15 23:25:23 +07:00
|
|
|
struct ovl_priv_data *op = get_ovl_priv(ovl);
|
2011-11-04 14:48:54 +07:00
|
|
|
struct omap_overlay_info *oi;
|
2012-06-06 17:55:52 +07:00
|
|
|
bool replication;
|
2011-11-18 20:43:29 +07:00
|
|
|
struct mgr_priv_data *mp;
|
2011-11-04 14:48:54 +07:00
|
|
|
int r;
|
|
|
|
|
2012-09-24 18:42:58 +07:00
|
|
|
DSSDBG("writing ovl %d regs", ovl->id);
|
2011-11-04 14:48:54 +07:00
|
|
|
|
2011-11-16 19:31:58 +07:00
|
|
|
if (!op->enabled || !op->info_dirty)
|
2011-11-15 23:25:23 +07:00
|
|
|
return;
|
2011-11-04 14:48:54 +07:00
|
|
|
|
2011-11-15 23:25:23 +07:00
|
|
|
oi = &op->info;
|
2011-11-04 14:48:54 +07:00
|
|
|
|
2012-05-08 17:23:20 +07:00
|
|
|
mp = get_mgr_priv(ovl->manager);
|
|
|
|
|
2012-06-25 16:28:48 +07:00
|
|
|
replication = dss_ovl_use_replication(mp->lcd_config, oi->color_mode);
|
2011-11-04 14:48:54 +07:00
|
|
|
|
2012-09-26 18:30:37 +07:00
|
|
|
r = dispc_ovl_setup(ovl->id, oi, replication, &mp->timings, false);
|
2011-11-04 14:48:54 +07:00
|
|
|
if (r) {
|
2011-11-15 23:25:23 +07:00
|
|
|
/*
|
|
|
|
* We can't do much here, as this function can be called from
|
|
|
|
* vsync interrupt.
|
|
|
|
*/
|
2011-11-15 16:47:39 +07:00
|
|
|
DSSERR("dispc_ovl_setup failed for ovl %d\n", ovl->id);
|
2011-11-15 23:25:23 +07:00
|
|
|
|
|
|
|
/* This will leave fifo configurations in a nonoptimal state */
|
|
|
|
op->enabled = false;
|
|
|
|
dispc_ovl_enable(ovl->id, false);
|
|
|
|
return;
|
2011-11-04 14:48:54 +07:00
|
|
|
}
|
|
|
|
|
2011-11-16 19:31:58 +07:00
|
|
|
op->info_dirty = false;
|
2011-11-18 20:43:29 +07:00
|
|
|
if (mp->updating)
|
2011-11-16 19:31:58 +07:00
|
|
|
op->shadow_info_dirty = true;
|
2011-11-04 14:48:54 +07:00
|
|
|
}
|
|
|
|
|
OMAPDSS: APPLY: rewrite overlay enable/disable
Overlays are currently enabled and disabled with a boolean in the struct
omap_overlay_info. The overlay info is set with ovl->set_overlay_info(),
and made into use with mgr->apply().
This doesn't work properly, as the enable/disable status may affect also
other overlays, for example when using fifo-merge. Thus the enabling and
disabling of the overlay needs to be done outside the normal overlay
configuration.
This patch achieves that by doing the following things:
1) Add function pointers to struct omap_overlay: enable(), disable() and
is_enabled(). These are used to do the obvious. The functions may block.
2) Move the "enabled" field from struct omap_overlay to ovl_priv_data.
3) Add a new route for settings to be applied to the HW, called
"extra_info". The status of the normal info and extra_info are tracked
separately.
The point here is to allow the normal info to be changed and
applied in non-blocking matter, whereas the extra_info can only be
changed when holding the mutex. This makes it possible to, for example,
set the overlay enable flag, apply it, and wait until the HW has taken
the flag into use.
This is not possible if the enable flag would be in the normal info, as
a new value for the flag could be set at any time from the users of
omapdss.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
2011-11-15 21:37:53 +07:00
|
|
|
static void dss_ovl_write_regs_extra(struct omap_overlay *ovl)
|
|
|
|
{
|
|
|
|
struct ovl_priv_data *op = get_ovl_priv(ovl);
|
2011-11-18 20:43:29 +07:00
|
|
|
struct mgr_priv_data *mp;
|
OMAPDSS: APPLY: rewrite overlay enable/disable
Overlays are currently enabled and disabled with a boolean in the struct
omap_overlay_info. The overlay info is set with ovl->set_overlay_info(),
and made into use with mgr->apply().
This doesn't work properly, as the enable/disable status may affect also
other overlays, for example when using fifo-merge. Thus the enabling and
disabling of the overlay needs to be done outside the normal overlay
configuration.
This patch achieves that by doing the following things:
1) Add function pointers to struct omap_overlay: enable(), disable() and
is_enabled(). These are used to do the obvious. The functions may block.
2) Move the "enabled" field from struct omap_overlay to ovl_priv_data.
3) Add a new route for settings to be applied to the HW, called
"extra_info". The status of the normal info and extra_info are tracked
separately.
The point here is to allow the normal info to be changed and
applied in non-blocking matter, whereas the extra_info can only be
changed when holding the mutex. This makes it possible to, for example,
set the overlay enable flag, apply it, and wait until the HW has taken
the flag into use.
This is not possible if the enable flag would be in the normal info, as
a new value for the flag could be set at any time from the users of
omapdss.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
2011-11-15 21:37:53 +07:00
|
|
|
|
2012-09-24 18:42:58 +07:00
|
|
|
DSSDBG("writing ovl %d regs extra", ovl->id);
|
OMAPDSS: APPLY: rewrite overlay enable/disable
Overlays are currently enabled and disabled with a boolean in the struct
omap_overlay_info. The overlay info is set with ovl->set_overlay_info(),
and made into use with mgr->apply().
This doesn't work properly, as the enable/disable status may affect also
other overlays, for example when using fifo-merge. Thus the enabling and
disabling of the overlay needs to be done outside the normal overlay
configuration.
This patch achieves that by doing the following things:
1) Add function pointers to struct omap_overlay: enable(), disable() and
is_enabled(). These are used to do the obvious. The functions may block.
2) Move the "enabled" field from struct omap_overlay to ovl_priv_data.
3) Add a new route for settings to be applied to the HW, called
"extra_info". The status of the normal info and extra_info are tracked
separately.
The point here is to allow the normal info to be changed and
applied in non-blocking matter, whereas the extra_info can only be
changed when holding the mutex. This makes it possible to, for example,
set the overlay enable flag, apply it, and wait until the HW has taken
the flag into use.
This is not possible if the enable flag would be in the normal info, as
a new value for the flag could be set at any time from the users of
omapdss.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
2011-11-15 21:37:53 +07:00
|
|
|
|
2011-11-15 23:25:23 +07:00
|
|
|
if (!op->extra_info_dirty)
|
|
|
|
return;
|
|
|
|
|
OMAPDSS: APPLY: rewrite overlay enable/disable
Overlays are currently enabled and disabled with a boolean in the struct
omap_overlay_info. The overlay info is set with ovl->set_overlay_info(),
and made into use with mgr->apply().
This doesn't work properly, as the enable/disable status may affect also
other overlays, for example when using fifo-merge. Thus the enabling and
disabling of the overlay needs to be done outside the normal overlay
configuration.
This patch achieves that by doing the following things:
1) Add function pointers to struct omap_overlay: enable(), disable() and
is_enabled(). These are used to do the obvious. The functions may block.
2) Move the "enabled" field from struct omap_overlay to ovl_priv_data.
3) Add a new route for settings to be applied to the HW, called
"extra_info". The status of the normal info and extra_info are tracked
separately.
The point here is to allow the normal info to be changed and
applied in non-blocking matter, whereas the extra_info can only be
changed when holding the mutex. This makes it possible to, for example,
set the overlay enable flag, apply it, and wait until the HW has taken
the flag into use.
This is not possible if the enable flag would be in the normal info, as
a new value for the flag could be set at any time from the users of
omapdss.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
2011-11-15 21:37:53 +07:00
|
|
|
/* note: write also when op->enabled == false, so that the ovl gets
|
|
|
|
* disabled */
|
|
|
|
|
|
|
|
dispc_ovl_enable(ovl->id, op->enabled);
|
2011-11-16 19:28:12 +07:00
|
|
|
dispc_ovl_set_fifo_threshold(ovl->id, op->fifo_low, op->fifo_high);
|
2011-11-15 23:25:23 +07:00
|
|
|
|
2011-11-18 20:43:29 +07:00
|
|
|
mp = get_mgr_priv(ovl->manager);
|
|
|
|
|
2011-11-15 23:25:23 +07:00
|
|
|
op->extra_info_dirty = false;
|
2011-11-18 20:43:29 +07:00
|
|
|
if (mp->updating)
|
|
|
|
op->shadow_extra_info_dirty = true;
|
OMAPDSS: APPLY: rewrite overlay enable/disable
Overlays are currently enabled and disabled with a boolean in the struct
omap_overlay_info. The overlay info is set with ovl->set_overlay_info(),
and made into use with mgr->apply().
This doesn't work properly, as the enable/disable status may affect also
other overlays, for example when using fifo-merge. Thus the enabling and
disabling of the overlay needs to be done outside the normal overlay
configuration.
This patch achieves that by doing the following things:
1) Add function pointers to struct omap_overlay: enable(), disable() and
is_enabled(). These are used to do the obvious. The functions may block.
2) Move the "enabled" field from struct omap_overlay to ovl_priv_data.
3) Add a new route for settings to be applied to the HW, called
"extra_info". The status of the normal info and extra_info are tracked
separately.
The point here is to allow the normal info to be changed and
applied in non-blocking matter, whereas the extra_info can only be
changed when holding the mutex. This makes it possible to, for example,
set the overlay enable flag, apply it, and wait until the HW has taken
the flag into use.
This is not possible if the enable flag would be in the normal info, as
a new value for the flag could be set at any time from the users of
omapdss.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
2011-11-15 21:37:53 +07:00
|
|
|
}
|
|
|
|
|
2011-11-15 16:47:39 +07:00
|
|
|
static void dss_mgr_write_regs(struct omap_overlay_manager *mgr)
|
2011-11-04 14:48:54 +07:00
|
|
|
{
|
2011-11-15 23:25:23 +07:00
|
|
|
struct mgr_priv_data *mp = get_mgr_priv(mgr);
|
|
|
|
struct omap_overlay *ovl;
|
2011-11-04 14:48:54 +07:00
|
|
|
|
2012-09-24 18:42:58 +07:00
|
|
|
DSSDBG("writing mgr %d regs", mgr->id);
|
2011-11-04 14:48:54 +07:00
|
|
|
|
2011-11-15 23:25:23 +07:00
|
|
|
if (!mp->enabled)
|
|
|
|
return;
|
2011-11-04 14:48:54 +07:00
|
|
|
|
2011-11-15 23:25:23 +07:00
|
|
|
WARN_ON(mp->busy);
|
2011-11-04 14:48:54 +07:00
|
|
|
|
|
|
|
/* Commit overlay settings */
|
2011-11-15 23:25:23 +07:00
|
|
|
list_for_each_entry(ovl, &mgr->overlays, list) {
|
|
|
|
dss_ovl_write_regs(ovl);
|
OMAPDSS: APPLY: rewrite overlay enable/disable
Overlays are currently enabled and disabled with a boolean in the struct
omap_overlay_info. The overlay info is set with ovl->set_overlay_info(),
and made into use with mgr->apply().
This doesn't work properly, as the enable/disable status may affect also
other overlays, for example when using fifo-merge. Thus the enabling and
disabling of the overlay needs to be done outside the normal overlay
configuration.
This patch achieves that by doing the following things:
1) Add function pointers to struct omap_overlay: enable(), disable() and
is_enabled(). These are used to do the obvious. The functions may block.
2) Move the "enabled" field from struct omap_overlay to ovl_priv_data.
3) Add a new route for settings to be applied to the HW, called
"extra_info". The status of the normal info and extra_info are tracked
separately.
The point here is to allow the normal info to be changed and
applied in non-blocking matter, whereas the extra_info can only be
changed when holding the mutex. This makes it possible to, for example,
set the overlay enable flag, apply it, and wait until the HW has taken
the flag into use.
This is not possible if the enable flag would be in the normal info, as
a new value for the flag could be set at any time from the users of
omapdss.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
2011-11-15 21:37:53 +07:00
|
|
|
dss_ovl_write_regs_extra(ovl);
|
|
|
|
}
|
|
|
|
|
2011-11-16 19:31:58 +07:00
|
|
|
if (mp->info_dirty) {
|
2011-11-15 23:25:23 +07:00
|
|
|
dispc_mgr_setup(mgr->id, &mp->info);
|
2011-11-04 14:48:54 +07:00
|
|
|
|
2011-11-16 19:31:58 +07:00
|
|
|
mp->info_dirty = false;
|
2011-11-18 20:43:29 +07:00
|
|
|
if (mp->updating)
|
2011-11-16 19:31:58 +07:00
|
|
|
mp->shadow_info_dirty = true;
|
2011-11-04 14:48:54 +07:00
|
|
|
}
|
2011-11-15 23:25:23 +07:00
|
|
|
}
|
|
|
|
|
2012-04-26 21:01:22 +07:00
|
|
|
static void dss_mgr_write_regs_extra(struct omap_overlay_manager *mgr)
|
|
|
|
{
|
|
|
|
struct mgr_priv_data *mp = get_mgr_priv(mgr);
|
|
|
|
|
2012-09-24 18:42:58 +07:00
|
|
|
DSSDBG("writing mgr %d regs extra", mgr->id);
|
2012-04-26 21:01:22 +07:00
|
|
|
|
|
|
|
if (!mp->extra_info_dirty)
|
|
|
|
return;
|
|
|
|
|
|
|
|
dispc_mgr_set_timings(mgr->id, &mp->timings);
|
|
|
|
|
2012-06-29 16:07:03 +07:00
|
|
|
/* lcd_config parameters */
|
2012-09-12 17:30:39 +07:00
|
|
|
if (dss_mgr_is_lcd(mgr->id))
|
|
|
|
dispc_mgr_set_lcd_config(mgr->id, &mp->lcd_config);
|
2012-06-29 16:07:03 +07:00
|
|
|
|
2012-04-26 21:01:22 +07:00
|
|
|
mp->extra_info_dirty = false;
|
|
|
|
if (mp->updating)
|
|
|
|
mp->shadow_extra_info_dirty = true;
|
|
|
|
}
|
|
|
|
|
2011-11-15 23:25:23 +07:00
|
|
|
static void dss_write_regs(void)
|
|
|
|
{
|
|
|
|
const int num_mgrs = omap_dss_get_num_overlay_managers();
|
|
|
|
int i;
|
2011-11-04 14:48:54 +07:00
|
|
|
|
|
|
|
for (i = 0; i < num_mgrs; ++i) {
|
2011-11-15 23:25:23 +07:00
|
|
|
struct omap_overlay_manager *mgr;
|
|
|
|
struct mgr_priv_data *mp;
|
2011-11-17 22:35:28 +07:00
|
|
|
int r;
|
2011-11-15 23:25:23 +07:00
|
|
|
|
2011-11-15 17:02:03 +07:00
|
|
|
mgr = omap_dss_get_overlay_manager(i);
|
|
|
|
mp = get_mgr_priv(mgr);
|
2011-11-04 14:48:54 +07:00
|
|
|
|
2011-11-15 23:25:23 +07:00
|
|
|
if (!mp->enabled || mgr_manual_update(mgr) || mp->busy)
|
2011-11-04 14:48:54 +07:00
|
|
|
continue;
|
|
|
|
|
2012-04-27 02:52:28 +07:00
|
|
|
r = dss_check_settings(mgr);
|
2011-11-17 22:35:28 +07:00
|
|
|
if (r) {
|
|
|
|
DSSERR("cannot write registers for manager %s: "
|
|
|
|
"illegal configuration\n", mgr->name);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2011-11-15 23:25:23 +07:00
|
|
|
dss_mgr_write_regs(mgr);
|
2012-04-26 21:01:22 +07:00
|
|
|
dss_mgr_write_regs_extra(mgr);
|
2011-11-25 22:32:20 +07:00
|
|
|
}
|
|
|
|
}
|
2011-11-15 23:25:23 +07:00
|
|
|
|
2011-11-25 22:32:20 +07:00
|
|
|
static void dss_set_go_bits(void)
|
|
|
|
{
|
|
|
|
const int num_mgrs = omap_dss_get_num_overlay_managers();
|
|
|
|
int i;
|
2011-11-04 14:48:54 +07:00
|
|
|
|
2011-11-25 22:32:20 +07:00
|
|
|
for (i = 0; i < num_mgrs; ++i) {
|
|
|
|
struct omap_overlay_manager *mgr;
|
|
|
|
struct mgr_priv_data *mp;
|
2011-11-04 14:48:54 +07:00
|
|
|
|
2011-11-25 22:32:20 +07:00
|
|
|
mgr = omap_dss_get_overlay_manager(i);
|
|
|
|
mp = get_mgr_priv(mgr);
|
|
|
|
|
|
|
|
if (!mp->enabled || mgr_manual_update(mgr) || mp->busy)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (!need_go(mgr))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
mp->busy = true;
|
|
|
|
|
|
|
|
if (!dss_data.irq_enabled && need_isr())
|
|
|
|
dss_register_vsync_isr();
|
|
|
|
|
|
|
|
dispc_mgr_go(mgr->id);
|
2011-11-15 23:25:23 +07:00
|
|
|
}
|
2011-11-25 22:32:20 +07:00
|
|
|
|
2011-11-04 14:48:54 +07:00
|
|
|
}
|
|
|
|
|
2012-03-07 15:28:48 +07:00
|
|
|
static void mgr_clear_shadow_dirty(struct omap_overlay_manager *mgr)
|
|
|
|
{
|
|
|
|
struct omap_overlay *ovl;
|
|
|
|
struct mgr_priv_data *mp;
|
|
|
|
struct ovl_priv_data *op;
|
|
|
|
|
|
|
|
mp = get_mgr_priv(mgr);
|
|
|
|
mp->shadow_info_dirty = false;
|
2012-04-26 21:01:22 +07:00
|
|
|
mp->shadow_extra_info_dirty = false;
|
2012-03-07 15:28:48 +07:00
|
|
|
|
|
|
|
list_for_each_entry(ovl, &mgr->overlays, list) {
|
|
|
|
op = get_ovl_priv(ovl);
|
|
|
|
op->shadow_info_dirty = false;
|
|
|
|
op->shadow_extra_info_dirty = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-11-04 14:48:54 +07:00
|
|
|
void dss_mgr_start_update(struct omap_overlay_manager *mgr)
|
|
|
|
{
|
2011-11-15 17:02:03 +07:00
|
|
|
struct mgr_priv_data *mp = get_mgr_priv(mgr);
|
OMAPDSS: APPLY: add missing uses of spinlock
The functions in apply.c, called mostly via function pointers in overlay
and overlay_manager structs, will be divided into two groups. The other
group will not sleep and can be called from interrupts, and the other
group may sleep.
The idea is that the non-sleeping functions may only change certain
settings in overlays and managers, and those settings may only affect
the particular overlay/manager. For example, set the base address of the
overlay.
The blocking functions, however, will handle more complex configuration
changes. For example, when an overlay is enabled and fifo-merge feature
is used, we need to do the enable in multiple steps, waiting in between,
and the change affects multiple overlays and managers.
apply.c already contains a spinlock, which has been used to protect
(badly) the dss_data. This patch adds locks/unlocks of the spinlock to
the missing places, and the lock should now properly protect dss_data.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
2011-11-15 19:32:57 +07:00
|
|
|
unsigned long flags;
|
2011-11-17 22:35:28 +07:00
|
|
|
int r;
|
OMAPDSS: APPLY: add missing uses of spinlock
The functions in apply.c, called mostly via function pointers in overlay
and overlay_manager structs, will be divided into two groups. The other
group will not sleep and can be called from interrupts, and the other
group may sleep.
The idea is that the non-sleeping functions may only change certain
settings in overlays and managers, and those settings may only affect
the particular overlay/manager. For example, set the base address of the
overlay.
The blocking functions, however, will handle more complex configuration
changes. For example, when an overlay is enabled and fifo-merge feature
is used, we need to do the enable in multiple steps, waiting in between,
and the change affects multiple overlays and managers.
apply.c already contains a spinlock, which has been used to protect
(badly) the dss_data. This patch adds locks/unlocks of the spinlock to
the missing places, and the lock should now properly protect dss_data.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
2011-11-15 19:32:57 +07:00
|
|
|
|
|
|
|
spin_lock_irqsave(&data_lock, flags);
|
2011-11-04 14:48:54 +07:00
|
|
|
|
2011-11-18 20:43:29 +07:00
|
|
|
WARN_ON(mp->updating);
|
|
|
|
|
2012-04-27 02:52:28 +07:00
|
|
|
r = dss_check_settings(mgr);
|
2011-11-17 22:35:28 +07:00
|
|
|
if (r) {
|
|
|
|
DSSERR("cannot start manual update: illegal configuration\n");
|
|
|
|
spin_unlock_irqrestore(&data_lock, flags);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-11-15 23:25:23 +07:00
|
|
|
dss_mgr_write_regs(mgr);
|
2012-04-26 21:01:22 +07:00
|
|
|
dss_mgr_write_regs_extra(mgr);
|
2011-11-04 14:48:54 +07:00
|
|
|
|
2011-11-18 20:43:29 +07:00
|
|
|
mp->updating = true;
|
2011-11-04 14:48:54 +07:00
|
|
|
|
2011-11-18 20:43:29 +07:00
|
|
|
if (!dss_data.irq_enabled && need_isr())
|
|
|
|
dss_register_vsync_isr();
|
2011-11-04 14:48:54 +07:00
|
|
|
|
2012-10-19 18:14:38 +07:00
|
|
|
dispc_mgr_enable_sync(mgr->id);
|
OMAPDSS: APPLY: add missing uses of spinlock
The functions in apply.c, called mostly via function pointers in overlay
and overlay_manager structs, will be divided into two groups. The other
group will not sleep and can be called from interrupts, and the other
group may sleep.
The idea is that the non-sleeping functions may only change certain
settings in overlays and managers, and those settings may only affect
the particular overlay/manager. For example, set the base address of the
overlay.
The blocking functions, however, will handle more complex configuration
changes. For example, when an overlay is enabled and fifo-merge feature
is used, we need to do the enable in multiple steps, waiting in between,
and the change affects multiple overlays and managers.
apply.c already contains a spinlock, which has been used to protect
(badly) the dss_data. This patch adds locks/unlocks of the spinlock to
the missing places, and the lock should now properly protect dss_data.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
2011-11-15 19:32:57 +07:00
|
|
|
|
|
|
|
spin_unlock_irqrestore(&data_lock, flags);
|
2011-11-04 14:48:54 +07:00
|
|
|
}
|
|
|
|
|
2011-11-15 16:18:12 +07:00
|
|
|
static void dss_apply_irq_handler(void *data, u32 mask);
|
|
|
|
|
|
|
|
static void dss_register_vsync_isr(void)
|
|
|
|
{
|
2011-11-15 16:20:13 +07:00
|
|
|
const int num_mgrs = dss_feat_get_num_mgrs();
|
2011-11-15 16:18:12 +07:00
|
|
|
u32 mask;
|
2011-11-15 16:20:13 +07:00
|
|
|
int r, i;
|
2011-11-15 16:18:12 +07:00
|
|
|
|
2011-11-15 16:20:13 +07:00
|
|
|
mask = 0;
|
|
|
|
for (i = 0; i < num_mgrs; ++i)
|
|
|
|
mask |= dispc_mgr_get_vsync_irq(i);
|
2011-11-15 16:18:12 +07:00
|
|
|
|
2011-11-18 20:43:29 +07:00
|
|
|
for (i = 0; i < num_mgrs; ++i)
|
|
|
|
mask |= dispc_mgr_get_framedone_irq(i);
|
|
|
|
|
2011-11-15 16:18:12 +07:00
|
|
|
r = omap_dispc_register_isr(dss_apply_irq_handler, NULL, mask);
|
|
|
|
WARN_ON(r);
|
|
|
|
|
2011-11-15 17:04:43 +07:00
|
|
|
dss_data.irq_enabled = true;
|
2011-11-15 16:18:12 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void dss_unregister_vsync_isr(void)
|
|
|
|
{
|
2011-11-15 16:20:13 +07:00
|
|
|
const int num_mgrs = dss_feat_get_num_mgrs();
|
2011-11-15 16:18:12 +07:00
|
|
|
u32 mask;
|
2011-11-15 16:20:13 +07:00
|
|
|
int r, i;
|
2011-11-15 16:18:12 +07:00
|
|
|
|
2011-11-15 16:20:13 +07:00
|
|
|
mask = 0;
|
|
|
|
for (i = 0; i < num_mgrs; ++i)
|
|
|
|
mask |= dispc_mgr_get_vsync_irq(i);
|
2011-11-15 16:18:12 +07:00
|
|
|
|
2011-11-18 20:43:29 +07:00
|
|
|
for (i = 0; i < num_mgrs; ++i)
|
|
|
|
mask |= dispc_mgr_get_framedone_irq(i);
|
|
|
|
|
2011-11-15 16:18:12 +07:00
|
|
|
r = omap_dispc_unregister_isr(dss_apply_irq_handler, NULL, mask);
|
|
|
|
WARN_ON(r);
|
|
|
|
|
2011-11-15 17:04:43 +07:00
|
|
|
dss_data.irq_enabled = false;
|
2011-11-15 16:18:12 +07:00
|
|
|
}
|
|
|
|
|
2011-11-16 17:03:22 +07:00
|
|
|
static void dss_apply_irq_handler(void *data, u32 mask)
|
|
|
|
{
|
2011-11-04 14:48:54 +07:00
|
|
|
const int num_mgrs = dss_feat_get_num_mgrs();
|
2011-11-15 23:25:23 +07:00
|
|
|
int i;
|
2011-11-16 19:37:48 +07:00
|
|
|
bool extra_updating;
|
2011-11-04 14:48:54 +07:00
|
|
|
|
2011-11-15 17:04:10 +07:00
|
|
|
spin_lock(&data_lock);
|
2011-11-04 14:48:54 +07:00
|
|
|
|
2011-11-16 17:03:22 +07:00
|
|
|
/* clear busy, updating flags, shadow_dirty flags */
|
2011-11-15 20:04:25 +07:00
|
|
|
for (i = 0; i < num_mgrs; i++) {
|
2011-11-16 17:03:22 +07:00
|
|
|
struct omap_overlay_manager *mgr;
|
|
|
|
struct mgr_priv_data *mp;
|
|
|
|
|
2011-11-15 20:04:25 +07:00
|
|
|
mgr = omap_dss_get_overlay_manager(i);
|
|
|
|
mp = get_mgr_priv(mgr);
|
|
|
|
|
2011-11-16 17:03:22 +07:00
|
|
|
if (!mp->enabled)
|
2011-11-15 20:04:25 +07:00
|
|
|
continue;
|
|
|
|
|
2011-11-16 17:03:22 +07:00
|
|
|
mp->updating = dispc_mgr_is_enabled(i);
|
2011-11-04 14:48:54 +07:00
|
|
|
|
2011-11-16 17:03:22 +07:00
|
|
|
if (!mgr_manual_update(mgr)) {
|
2011-11-25 22:27:45 +07:00
|
|
|
bool was_busy = mp->busy;
|
2011-11-16 17:03:22 +07:00
|
|
|
mp->busy = dispc_mgr_go_busy(i);
|
2011-11-15 20:04:25 +07:00
|
|
|
|
2011-11-25 22:27:45 +07:00
|
|
|
if (was_busy && !mp->busy)
|
2011-11-16 17:03:22 +07:00
|
|
|
mgr_clear_shadow_dirty(mgr);
|
|
|
|
}
|
2011-11-04 14:48:54 +07:00
|
|
|
}
|
|
|
|
|
2011-11-15 23:25:23 +07:00
|
|
|
dss_write_regs();
|
2011-11-25 22:32:20 +07:00
|
|
|
dss_set_go_bits();
|
2011-11-04 14:48:54 +07:00
|
|
|
|
2011-11-16 19:37:48 +07:00
|
|
|
extra_updating = extra_info_update_ongoing();
|
|
|
|
if (!extra_updating)
|
|
|
|
complete_all(&extra_updated_completion);
|
|
|
|
|
2011-11-15 23:25:23 +07:00
|
|
|
if (!need_isr())
|
|
|
|
dss_unregister_vsync_isr();
|
2011-11-04 14:48:54 +07:00
|
|
|
|
2011-11-15 17:04:10 +07:00
|
|
|
spin_unlock(&data_lock);
|
2011-11-04 14:48:54 +07:00
|
|
|
}
|
|
|
|
|
2011-11-15 18:37:33 +07:00
|
|
|
static void omap_dss_mgr_apply_ovl(struct omap_overlay *ovl)
|
2011-11-04 14:48:54 +07:00
|
|
|
{
|
2011-11-15 16:56:57 +07:00
|
|
|
struct ovl_priv_data *op;
|
2011-11-04 14:48:54 +07:00
|
|
|
|
2011-11-15 16:56:57 +07:00
|
|
|
op = get_ovl_priv(ovl);
|
2011-11-04 14:48:54 +07:00
|
|
|
|
2011-11-16 19:11:56 +07:00
|
|
|
if (!op->user_info_dirty)
|
2011-11-15 18:37:33 +07:00
|
|
|
return;
|
2011-11-04 14:48:54 +07:00
|
|
|
|
2011-11-16 19:11:56 +07:00
|
|
|
op->user_info_dirty = false;
|
2011-11-16 19:31:58 +07:00
|
|
|
op->info_dirty = true;
|
2011-11-16 19:11:56 +07:00
|
|
|
op->info = op->user_info;
|
2011-11-04 14:48:54 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void omap_dss_mgr_apply_mgr(struct omap_overlay_manager *mgr)
|
|
|
|
{
|
2011-11-15 17:02:03 +07:00
|
|
|
struct mgr_priv_data *mp;
|
2011-11-04 14:48:54 +07:00
|
|
|
|
2011-11-15 17:02:03 +07:00
|
|
|
mp = get_mgr_priv(mgr);
|
2011-11-04 14:48:54 +07:00
|
|
|
|
2011-11-16 18:58:07 +07:00
|
|
|
if (!mp->user_info_dirty)
|
2011-11-04 14:48:54 +07:00
|
|
|
return;
|
|
|
|
|
2011-11-16 18:58:07 +07:00
|
|
|
mp->user_info_dirty = false;
|
2011-11-16 19:31:58 +07:00
|
|
|
mp->info_dirty = true;
|
2011-11-16 18:58:07 +07:00
|
|
|
mp->info = mp->user_info;
|
2011-11-04 14:48:54 +07:00
|
|
|
}
|
|
|
|
|
2011-11-16 19:28:12 +07:00
|
|
|
int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
|
2011-11-04 14:48:54 +07:00
|
|
|
{
|
2011-11-16 19:28:12 +07:00
|
|
|
unsigned long flags;
|
|
|
|
struct omap_overlay *ovl;
|
2011-11-17 22:35:28 +07:00
|
|
|
int r;
|
2011-11-16 19:28:12 +07:00
|
|
|
|
|
|
|
DSSDBG("omap_dss_mgr_apply(%s)\n", mgr->name);
|
|
|
|
|
|
|
|
spin_lock_irqsave(&data_lock, flags);
|
|
|
|
|
2012-04-27 02:52:28 +07:00
|
|
|
r = dss_check_settings_apply(mgr);
|
2011-11-17 22:35:28 +07:00
|
|
|
if (r) {
|
|
|
|
spin_unlock_irqrestore(&data_lock, flags);
|
|
|
|
DSSERR("failed to apply settings: illegal configuration.\n");
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
2011-11-16 19:28:12 +07:00
|
|
|
/* Configure overlays */
|
|
|
|
list_for_each_entry(ovl, &mgr->overlays, list)
|
|
|
|
omap_dss_mgr_apply_ovl(ovl);
|
|
|
|
|
|
|
|
/* Configure manager */
|
|
|
|
omap_dss_mgr_apply_mgr(mgr);
|
|
|
|
|
|
|
|
dss_write_regs();
|
2011-11-25 22:32:20 +07:00
|
|
|
dss_set_go_bits();
|
2011-11-16 19:28:12 +07:00
|
|
|
|
|
|
|
spin_unlock_irqrestore(&data_lock, flags);
|
|
|
|
|
2011-11-16 21:53:44 +07:00
|
|
|
return 0;
|
2011-11-16 19:28:12 +07:00
|
|
|
}
|
|
|
|
|
2011-11-16 20:25:53 +07:00
|
|
|
static void dss_apply_ovl_enable(struct omap_overlay *ovl, bool enable)
|
|
|
|
{
|
|
|
|
struct ovl_priv_data *op;
|
|
|
|
|
|
|
|
op = get_ovl_priv(ovl);
|
|
|
|
|
|
|
|
if (op->enabled == enable)
|
|
|
|
return;
|
|
|
|
|
|
|
|
op->enabled = enable;
|
|
|
|
op->extra_info_dirty = true;
|
|
|
|
}
|
|
|
|
|
2011-11-26 19:39:16 +07:00
|
|
|
static void dss_apply_ovl_fifo_thresholds(struct omap_overlay *ovl,
|
|
|
|
u32 fifo_low, u32 fifo_high)
|
|
|
|
{
|
|
|
|
struct ovl_priv_data *op = get_ovl_priv(ovl);
|
|
|
|
|
|
|
|
if (op->fifo_low == fifo_low && op->fifo_high == fifo_high)
|
|
|
|
return;
|
|
|
|
|
|
|
|
op->fifo_low = fifo_low;
|
|
|
|
op->fifo_high = fifo_high;
|
|
|
|
op->extra_info_dirty = true;
|
|
|
|
}
|
|
|
|
|
2012-08-06 20:50:14 +07:00
|
|
|
static void dss_ovl_setup_fifo(struct omap_overlay *ovl)
|
2011-11-16 19:28:12 +07:00
|
|
|
{
|
|
|
|
struct ovl_priv_data *op = get_ovl_priv(ovl);
|
|
|
|
u32 fifo_low, fifo_high;
|
2012-08-06 20:50:14 +07:00
|
|
|
bool use_fifo_merge = false;
|
2011-11-04 14:48:54 +07:00
|
|
|
|
2011-11-26 19:36:19 +07:00
|
|
|
if (!op->enabled && !op->enabling)
|
|
|
|
return;
|
|
|
|
|
2012-01-13 18:17:01 +07:00
|
|
|
dispc_ovl_compute_fifo_thresholds(ovl->id, &fifo_low, &fifo_high,
|
2012-05-15 19:31:01 +07:00
|
|
|
use_fifo_merge, ovl_manual_update(ovl));
|
2011-11-16 19:28:12 +07:00
|
|
|
|
2011-11-26 19:39:16 +07:00
|
|
|
dss_apply_ovl_fifo_thresholds(ovl, fifo_low, fifo_high);
|
2011-11-04 14:48:54 +07:00
|
|
|
}
|
|
|
|
|
2012-08-06 20:50:14 +07:00
|
|
|
static void dss_mgr_setup_fifos(struct omap_overlay_manager *mgr)
|
2011-11-04 14:48:54 +07:00
|
|
|
{
|
2011-11-05 15:59:59 +07:00
|
|
|
struct omap_overlay *ovl;
|
2011-11-16 19:28:12 +07:00
|
|
|
struct mgr_priv_data *mp;
|
2011-11-04 14:48:54 +07:00
|
|
|
|
2011-11-16 19:28:12 +07:00
|
|
|
mp = get_mgr_priv(mgr);
|
2011-11-04 14:48:54 +07:00
|
|
|
|
2011-11-16 19:28:12 +07:00
|
|
|
if (!mp->enabled)
|
|
|
|
return;
|
2011-11-04 14:48:54 +07:00
|
|
|
|
2011-11-26 19:36:19 +07:00
|
|
|
list_for_each_entry(ovl, &mgr->overlays, list)
|
2012-08-06 20:50:14 +07:00
|
|
|
dss_ovl_setup_fifo(ovl);
|
2011-11-26 19:36:19 +07:00
|
|
|
}
|
2011-11-04 14:48:54 +07:00
|
|
|
|
2012-08-06 20:50:14 +07:00
|
|
|
static void dss_setup_fifos(void)
|
2011-11-26 19:36:19 +07:00
|
|
|
{
|
|
|
|
const int num_mgrs = omap_dss_get_num_overlay_managers();
|
|
|
|
struct omap_overlay_manager *mgr;
|
|
|
|
int i;
|
2011-11-04 14:48:54 +07:00
|
|
|
|
2011-11-26 19:36:19 +07:00
|
|
|
for (i = 0; i < num_mgrs; ++i) {
|
|
|
|
mgr = omap_dss_get_overlay_manager(i);
|
2012-08-06 20:50:14 +07:00
|
|
|
dss_mgr_setup_fifos(mgr);
|
2011-11-16 19:28:12 +07:00
|
|
|
}
|
2011-11-04 14:48:54 +07:00
|
|
|
}
|
|
|
|
|
2011-11-21 18:34:48 +07:00
|
|
|
int dss_mgr_enable(struct omap_overlay_manager *mgr)
|
2011-11-04 15:22:46 +07:00
|
|
|
{
|
2011-11-15 19:43:53 +07:00
|
|
|
struct mgr_priv_data *mp = get_mgr_priv(mgr);
|
|
|
|
unsigned long flags;
|
2011-11-17 22:35:28 +07:00
|
|
|
int r;
|
2011-11-15 19:43:53 +07:00
|
|
|
|
OMAPDSS: APPLY: add mutex
The functions in apply.c, called mostly via function pointers in overlay
and overlay_manager structs, will be divided into two groups. The first
group will not sleep and can be called from interrupts, and the second
group may sleep.
The idea is that the non-sleeping functions may only change certain
settings in overlays and managers, and those settings may only affect
the particular overlay/manager. For example, set the base address of the
overlay.
The blocking functions, however, will handle more complex configuration
changes. For example, when an overlay is enabled and fifo-merge feature
is used, we need to do the enable in multiple steps, waiting in between,
and the change affects multiple overlays and managers.
This patch adds the mutex which is used in the blocking functions to
have exclusive access to overlays and overlay managers.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
2011-11-15 19:28:48 +07:00
|
|
|
mutex_lock(&apply_lock);
|
|
|
|
|
2011-11-16 21:01:33 +07:00
|
|
|
if (mp->enabled)
|
|
|
|
goto out;
|
|
|
|
|
2011-11-15 19:43:53 +07:00
|
|
|
spin_lock_irqsave(&data_lock, flags);
|
|
|
|
|
2011-11-17 22:35:28 +07:00
|
|
|
mp->enabled = true;
|
2011-11-26 19:29:39 +07:00
|
|
|
|
2012-04-27 02:52:28 +07:00
|
|
|
r = dss_check_settings(mgr);
|
2011-11-17 22:35:28 +07:00
|
|
|
if (r) {
|
|
|
|
DSSERR("failed to enable manager %d: check_settings failed\n",
|
|
|
|
mgr->id);
|
2011-11-21 18:34:48 +07:00
|
|
|
goto err;
|
2011-11-17 22:35:28 +07:00
|
|
|
}
|
|
|
|
|
2012-08-06 20:50:14 +07:00
|
|
|
dss_setup_fifos();
|
2011-11-16 19:28:12 +07:00
|
|
|
|
2011-11-15 23:25:23 +07:00
|
|
|
dss_write_regs();
|
2011-11-25 22:32:20 +07:00
|
|
|
dss_set_go_bits();
|
2011-11-15 23:25:23 +07:00
|
|
|
|
2011-11-18 20:43:29 +07:00
|
|
|
if (!mgr_manual_update(mgr))
|
|
|
|
mp->updating = true;
|
|
|
|
|
2012-08-10 18:17:47 +07:00
|
|
|
if (!dss_data.irq_enabled && need_isr())
|
|
|
|
dss_register_vsync_isr();
|
|
|
|
|
2011-11-15 19:43:53 +07:00
|
|
|
spin_unlock_irqrestore(&data_lock, flags);
|
OMAPDSS: APPLY: add mutex
The functions in apply.c, called mostly via function pointers in overlay
and overlay_manager structs, will be divided into two groups. The first
group will not sleep and can be called from interrupts, and the second
group may sleep.
The idea is that the non-sleeping functions may only change certain
settings in overlays and managers, and those settings may only affect
the particular overlay/manager. For example, set the base address of the
overlay.
The blocking functions, however, will handle more complex configuration
changes. For example, when an overlay is enabled and fifo-merge feature
is used, we need to do the enable in multiple steps, waiting in between,
and the change affects multiple overlays and managers.
This patch adds the mutex which is used in the blocking functions to
have exclusive access to overlays and overlay managers.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
2011-11-15 19:28:48 +07:00
|
|
|
|
2011-11-15 23:25:23 +07:00
|
|
|
if (!mgr_manual_update(mgr))
|
2012-10-19 18:14:38 +07:00
|
|
|
dispc_mgr_enable_sync(mgr->id);
|
2011-11-15 23:25:23 +07:00
|
|
|
|
2011-11-16 21:01:33 +07:00
|
|
|
out:
|
OMAPDSS: APPLY: add mutex
The functions in apply.c, called mostly via function pointers in overlay
and overlay_manager structs, will be divided into two groups. The first
group will not sleep and can be called from interrupts, and the second
group may sleep.
The idea is that the non-sleeping functions may only change certain
settings in overlays and managers, and those settings may only affect
the particular overlay/manager. For example, set the base address of the
overlay.
The blocking functions, however, will handle more complex configuration
changes. For example, when an overlay is enabled and fifo-merge feature
is used, we need to do the enable in multiple steps, waiting in between,
and the change affects multiple overlays and managers.
This patch adds the mutex which is used in the blocking functions to
have exclusive access to overlays and overlay managers.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
2011-11-15 19:28:48 +07:00
|
|
|
mutex_unlock(&apply_lock);
|
2011-11-21 18:34:48 +07:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
err:
|
2011-11-26 19:29:39 +07:00
|
|
|
mp->enabled = false;
|
2011-11-21 18:34:48 +07:00
|
|
|
spin_unlock_irqrestore(&data_lock, flags);
|
|
|
|
mutex_unlock(&apply_lock);
|
|
|
|
return r;
|
2011-11-04 15:22:46 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
void dss_mgr_disable(struct omap_overlay_manager *mgr)
|
|
|
|
{
|
2011-11-15 19:43:53 +07:00
|
|
|
struct mgr_priv_data *mp = get_mgr_priv(mgr);
|
|
|
|
unsigned long flags;
|
|
|
|
|
OMAPDSS: APPLY: add mutex
The functions in apply.c, called mostly via function pointers in overlay
and overlay_manager structs, will be divided into two groups. The first
group will not sleep and can be called from interrupts, and the second
group may sleep.
The idea is that the non-sleeping functions may only change certain
settings in overlays and managers, and those settings may only affect
the particular overlay/manager. For example, set the base address of the
overlay.
The blocking functions, however, will handle more complex configuration
changes. For example, when an overlay is enabled and fifo-merge feature
is used, we need to do the enable in multiple steps, waiting in between,
and the change affects multiple overlays and managers.
This patch adds the mutex which is used in the blocking functions to
have exclusive access to overlays and overlay managers.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
2011-11-15 19:28:48 +07:00
|
|
|
mutex_lock(&apply_lock);
|
|
|
|
|
2011-11-16 21:01:33 +07:00
|
|
|
if (!mp->enabled)
|
|
|
|
goto out;
|
|
|
|
|
2011-11-09 20:30:11 +07:00
|
|
|
if (!mgr_manual_update(mgr))
|
2012-10-19 18:14:38 +07:00
|
|
|
dispc_mgr_disable_sync(mgr->id);
|
2011-11-15 19:43:53 +07:00
|
|
|
|
|
|
|
spin_lock_irqsave(&data_lock, flags);
|
|
|
|
|
2011-11-18 20:43:29 +07:00
|
|
|
mp->updating = false;
|
2011-11-15 19:43:53 +07:00
|
|
|
mp->enabled = false;
|
|
|
|
|
|
|
|
spin_unlock_irqrestore(&data_lock, flags);
|
OMAPDSS: APPLY: add mutex
The functions in apply.c, called mostly via function pointers in overlay
and overlay_manager structs, will be divided into two groups. The first
group will not sleep and can be called from interrupts, and the second
group may sleep.
The idea is that the non-sleeping functions may only change certain
settings in overlays and managers, and those settings may only affect
the particular overlay/manager. For example, set the base address of the
overlay.
The blocking functions, however, will handle more complex configuration
changes. For example, when an overlay is enabled and fifo-merge feature
is used, we need to do the enable in multiple steps, waiting in between,
and the change affects multiple overlays and managers.
This patch adds the mutex which is used in the blocking functions to
have exclusive access to overlays and overlay managers.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
2011-11-15 19:28:48 +07:00
|
|
|
|
2011-11-16 21:01:33 +07:00
|
|
|
out:
|
OMAPDSS: APPLY: add mutex
The functions in apply.c, called mostly via function pointers in overlay
and overlay_manager structs, will be divided into two groups. The first
group will not sleep and can be called from interrupts, and the second
group may sleep.
The idea is that the non-sleeping functions may only change certain
settings in overlays and managers, and those settings may only affect
the particular overlay/manager. For example, set the base address of the
overlay.
The blocking functions, however, will handle more complex configuration
changes. For example, when an overlay is enabled and fifo-merge feature
is used, we need to do the enable in multiple steps, waiting in between,
and the change affects multiple overlays and managers.
This patch adds the mutex which is used in the blocking functions to
have exclusive access to overlays and overlay managers.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
2011-11-15 19:28:48 +07:00
|
|
|
mutex_unlock(&apply_lock);
|
2011-11-04 15:22:46 +07:00
|
|
|
}
|
|
|
|
|
2011-11-15 17:15:18 +07:00
|
|
|
int dss_mgr_set_info(struct omap_overlay_manager *mgr,
|
|
|
|
struct omap_overlay_manager_info *info)
|
|
|
|
{
|
2011-11-16 18:58:07 +07:00
|
|
|
struct mgr_priv_data *mp = get_mgr_priv(mgr);
|
OMAPDSS: APPLY: add missing uses of spinlock
The functions in apply.c, called mostly via function pointers in overlay
and overlay_manager structs, will be divided into two groups. The other
group will not sleep and can be called from interrupts, and the other
group may sleep.
The idea is that the non-sleeping functions may only change certain
settings in overlays and managers, and those settings may only affect
the particular overlay/manager. For example, set the base address of the
overlay.
The blocking functions, however, will handle more complex configuration
changes. For example, when an overlay is enabled and fifo-merge feature
is used, we need to do the enable in multiple steps, waiting in between,
and the change affects multiple overlays and managers.
apply.c already contains a spinlock, which has been used to protect
(badly) the dss_data. This patch adds locks/unlocks of the spinlock to
the missing places, and the lock should now properly protect dss_data.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
2011-11-15 19:32:57 +07:00
|
|
|
unsigned long flags;
|
2011-11-17 19:31:09 +07:00
|
|
|
int r;
|
|
|
|
|
|
|
|
r = dss_mgr_simple_check(mgr, info);
|
|
|
|
if (r)
|
|
|
|
return r;
|
OMAPDSS: APPLY: add missing uses of spinlock
The functions in apply.c, called mostly via function pointers in overlay
and overlay_manager structs, will be divided into two groups. The other
group will not sleep and can be called from interrupts, and the other
group may sleep.
The idea is that the non-sleeping functions may only change certain
settings in overlays and managers, and those settings may only affect
the particular overlay/manager. For example, set the base address of the
overlay.
The blocking functions, however, will handle more complex configuration
changes. For example, when an overlay is enabled and fifo-merge feature
is used, we need to do the enable in multiple steps, waiting in between,
and the change affects multiple overlays and managers.
apply.c already contains a spinlock, which has been used to protect
(badly) the dss_data. This patch adds locks/unlocks of the spinlock to
the missing places, and the lock should now properly protect dss_data.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
2011-11-15 19:32:57 +07:00
|
|
|
|
|
|
|
spin_lock_irqsave(&data_lock, flags);
|
|
|
|
|
2011-11-16 18:58:07 +07:00
|
|
|
mp->user_info = *info;
|
|
|
|
mp->user_info_dirty = true;
|
2011-11-15 17:15:18 +07:00
|
|
|
|
OMAPDSS: APPLY: add missing uses of spinlock
The functions in apply.c, called mostly via function pointers in overlay
and overlay_manager structs, will be divided into two groups. The other
group will not sleep and can be called from interrupts, and the other
group may sleep.
The idea is that the non-sleeping functions may only change certain
settings in overlays and managers, and those settings may only affect
the particular overlay/manager. For example, set the base address of the
overlay.
The blocking functions, however, will handle more complex configuration
changes. For example, when an overlay is enabled and fifo-merge feature
is used, we need to do the enable in multiple steps, waiting in between,
and the change affects multiple overlays and managers.
apply.c already contains a spinlock, which has been used to protect
(badly) the dss_data. This patch adds locks/unlocks of the spinlock to
the missing places, and the lock should now properly protect dss_data.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
2011-11-15 19:32:57 +07:00
|
|
|
spin_unlock_irqrestore(&data_lock, flags);
|
|
|
|
|
2011-11-15 17:15:18 +07:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void dss_mgr_get_info(struct omap_overlay_manager *mgr,
|
|
|
|
struct omap_overlay_manager_info *info)
|
|
|
|
{
|
2011-11-16 18:58:07 +07:00
|
|
|
struct mgr_priv_data *mp = get_mgr_priv(mgr);
|
OMAPDSS: APPLY: add missing uses of spinlock
The functions in apply.c, called mostly via function pointers in overlay
and overlay_manager structs, will be divided into two groups. The other
group will not sleep and can be called from interrupts, and the other
group may sleep.
The idea is that the non-sleeping functions may only change certain
settings in overlays and managers, and those settings may only affect
the particular overlay/manager. For example, set the base address of the
overlay.
The blocking functions, however, will handle more complex configuration
changes. For example, when an overlay is enabled and fifo-merge feature
is used, we need to do the enable in multiple steps, waiting in between,
and the change affects multiple overlays and managers.
apply.c already contains a spinlock, which has been used to protect
(badly) the dss_data. This patch adds locks/unlocks of the spinlock to
the missing places, and the lock should now properly protect dss_data.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
2011-11-15 19:32:57 +07:00
|
|
|
unsigned long flags;
|
|
|
|
|
|
|
|
spin_lock_irqsave(&data_lock, flags);
|
|
|
|
|
2011-11-16 18:58:07 +07:00
|
|
|
*info = mp->user_info;
|
OMAPDSS: APPLY: add missing uses of spinlock
The functions in apply.c, called mostly via function pointers in overlay
and overlay_manager structs, will be divided into two groups. The other
group will not sleep and can be called from interrupts, and the other
group may sleep.
The idea is that the non-sleeping functions may only change certain
settings in overlays and managers, and those settings may only affect
the particular overlay/manager. For example, set the base address of the
overlay.
The blocking functions, however, will handle more complex configuration
changes. For example, when an overlay is enabled and fifo-merge feature
is used, we need to do the enable in multiple steps, waiting in between,
and the change affects multiple overlays and managers.
apply.c already contains a spinlock, which has been used to protect
(badly) the dss_data. This patch adds locks/unlocks of the spinlock to
the missing places, and the lock should now properly protect dss_data.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
2011-11-15 19:32:57 +07:00
|
|
|
|
|
|
|
spin_unlock_irqrestore(&data_lock, flags);
|
2011-11-15 17:15:18 +07:00
|
|
|
}
|
|
|
|
|
2012-09-26 18:12:39 +07:00
|
|
|
int dss_mgr_set_output(struct omap_overlay_manager *mgr,
|
|
|
|
struct omap_dss_output *output)
|
|
|
|
{
|
|
|
|
int r;
|
|
|
|
|
|
|
|
mutex_lock(&apply_lock);
|
|
|
|
|
|
|
|
if (mgr->output) {
|
|
|
|
DSSERR("manager %s is already connected to an output\n",
|
|
|
|
mgr->name);
|
|
|
|
r = -EINVAL;
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((mgr->supported_outputs & output->id) == 0) {
|
|
|
|
DSSERR("output does not support manager %s\n",
|
|
|
|
mgr->name);
|
|
|
|
r = -EINVAL;
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
output->manager = mgr;
|
|
|
|
mgr->output = output;
|
|
|
|
|
|
|
|
mutex_unlock(&apply_lock);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
err:
|
|
|
|
mutex_unlock(&apply_lock);
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
int dss_mgr_unset_output(struct omap_overlay_manager *mgr)
|
|
|
|
{
|
|
|
|
int r;
|
|
|
|
struct mgr_priv_data *mp = get_mgr_priv(mgr);
|
|
|
|
unsigned long flags;
|
|
|
|
|
|
|
|
mutex_lock(&apply_lock);
|
|
|
|
|
|
|
|
if (!mgr->output) {
|
|
|
|
DSSERR("failed to unset output, output not set\n");
|
|
|
|
r = -EINVAL;
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
spin_lock_irqsave(&data_lock, flags);
|
|
|
|
|
|
|
|
if (mp->enabled) {
|
|
|
|
DSSERR("output can't be unset when manager is enabled\n");
|
|
|
|
r = -EINVAL;
|
|
|
|
goto err1;
|
|
|
|
}
|
|
|
|
|
|
|
|
spin_unlock_irqrestore(&data_lock, flags);
|
|
|
|
|
|
|
|
mgr->output->manager = NULL;
|
|
|
|
mgr->output = NULL;
|
|
|
|
|
|
|
|
mutex_unlock(&apply_lock);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
err1:
|
|
|
|
spin_unlock_irqrestore(&data_lock, flags);
|
|
|
|
err:
|
|
|
|
mutex_unlock(&apply_lock);
|
|
|
|
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
2012-04-26 21:01:22 +07:00
|
|
|
static void dss_apply_mgr_timings(struct omap_overlay_manager *mgr,
|
2012-07-19 15:21:14 +07:00
|
|
|
const struct omap_video_timings *timings)
|
2012-04-26 21:01:22 +07:00
|
|
|
{
|
|
|
|
struct mgr_priv_data *mp = get_mgr_priv(mgr);
|
|
|
|
|
|
|
|
mp->timings = *timings;
|
|
|
|
mp->extra_info_dirty = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void dss_mgr_set_timings(struct omap_overlay_manager *mgr,
|
2012-07-19 15:21:14 +07:00
|
|
|
const struct omap_video_timings *timings)
|
2012-04-26 21:01:22 +07:00
|
|
|
{
|
|
|
|
unsigned long flags;
|
2012-08-09 22:13:13 +07:00
|
|
|
struct mgr_priv_data *mp = get_mgr_priv(mgr);
|
2012-04-26 21:01:22 +07:00
|
|
|
|
|
|
|
spin_lock_irqsave(&data_lock, flags);
|
|
|
|
|
2012-08-09 22:13:13 +07:00
|
|
|
if (mp->updating) {
|
|
|
|
DSSERR("cannot set timings for %s: manager needs to be disabled\n",
|
|
|
|
mgr->name);
|
|
|
|
goto out;
|
|
|
|
}
|
2012-04-26 21:01:22 +07:00
|
|
|
|
2012-08-09 22:13:13 +07:00
|
|
|
dss_apply_mgr_timings(mgr, timings);
|
|
|
|
out:
|
2012-04-26 21:01:22 +07:00
|
|
|
spin_unlock_irqrestore(&data_lock, flags);
|
|
|
|
}
|
2011-11-15 17:15:18 +07:00
|
|
|
|
2012-06-29 16:07:03 +07:00
|
|
|
static void dss_apply_mgr_lcd_config(struct omap_overlay_manager *mgr,
|
|
|
|
const struct dss_lcd_mgr_config *config)
|
|
|
|
{
|
|
|
|
struct mgr_priv_data *mp = get_mgr_priv(mgr);
|
|
|
|
|
|
|
|
mp->lcd_config = *config;
|
|
|
|
mp->extra_info_dirty = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void dss_mgr_set_lcd_config(struct omap_overlay_manager *mgr,
|
|
|
|
const struct dss_lcd_mgr_config *config)
|
|
|
|
{
|
|
|
|
unsigned long flags;
|
|
|
|
struct mgr_priv_data *mp = get_mgr_priv(mgr);
|
|
|
|
|
2012-08-09 22:07:45 +07:00
|
|
|
spin_lock_irqsave(&data_lock, flags);
|
2012-06-29 16:07:03 +07:00
|
|
|
|
|
|
|
if (mp->enabled) {
|
|
|
|
DSSERR("cannot apply lcd config for %s: manager needs to be disabled\n",
|
|
|
|
mgr->name);
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
dss_apply_mgr_lcd_config(mgr, config);
|
|
|
|
out:
|
2012-08-09 22:07:45 +07:00
|
|
|
spin_unlock_irqrestore(&data_lock, flags);
|
2012-06-29 16:07:03 +07:00
|
|
|
}
|
|
|
|
|
2011-11-15 17:11:11 +07:00
|
|
|
int dss_ovl_set_info(struct omap_overlay *ovl,
|
|
|
|
struct omap_overlay_info *info)
|
|
|
|
{
|
2011-11-16 19:11:56 +07:00
|
|
|
struct ovl_priv_data *op = get_ovl_priv(ovl);
|
OMAPDSS: APPLY: add missing uses of spinlock
The functions in apply.c, called mostly via function pointers in overlay
and overlay_manager structs, will be divided into two groups. The other
group will not sleep and can be called from interrupts, and the other
group may sleep.
The idea is that the non-sleeping functions may only change certain
settings in overlays and managers, and those settings may only affect
the particular overlay/manager. For example, set the base address of the
overlay.
The blocking functions, however, will handle more complex configuration
changes. For example, when an overlay is enabled and fifo-merge feature
is used, we need to do the enable in multiple steps, waiting in between,
and the change affects multiple overlays and managers.
apply.c already contains a spinlock, which has been used to protect
(badly) the dss_data. This patch adds locks/unlocks of the spinlock to
the missing places, and the lock should now properly protect dss_data.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
2011-11-15 19:32:57 +07:00
|
|
|
unsigned long flags;
|
2011-11-17 19:26:48 +07:00
|
|
|
int r;
|
|
|
|
|
|
|
|
r = dss_ovl_simple_check(ovl, info);
|
|
|
|
if (r)
|
|
|
|
return r;
|
OMAPDSS: APPLY: add missing uses of spinlock
The functions in apply.c, called mostly via function pointers in overlay
and overlay_manager structs, will be divided into two groups. The other
group will not sleep and can be called from interrupts, and the other
group may sleep.
The idea is that the non-sleeping functions may only change certain
settings in overlays and managers, and those settings may only affect
the particular overlay/manager. For example, set the base address of the
overlay.
The blocking functions, however, will handle more complex configuration
changes. For example, when an overlay is enabled and fifo-merge feature
is used, we need to do the enable in multiple steps, waiting in between,
and the change affects multiple overlays and managers.
apply.c already contains a spinlock, which has been used to protect
(badly) the dss_data. This patch adds locks/unlocks of the spinlock to
the missing places, and the lock should now properly protect dss_data.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
2011-11-15 19:32:57 +07:00
|
|
|
|
|
|
|
spin_lock_irqsave(&data_lock, flags);
|
|
|
|
|
2011-11-16 19:11:56 +07:00
|
|
|
op->user_info = *info;
|
|
|
|
op->user_info_dirty = true;
|
2011-11-15 17:11:11 +07:00
|
|
|
|
OMAPDSS: APPLY: add missing uses of spinlock
The functions in apply.c, called mostly via function pointers in overlay
and overlay_manager structs, will be divided into two groups. The other
group will not sleep and can be called from interrupts, and the other
group may sleep.
The idea is that the non-sleeping functions may only change certain
settings in overlays and managers, and those settings may only affect
the particular overlay/manager. For example, set the base address of the
overlay.
The blocking functions, however, will handle more complex configuration
changes. For example, when an overlay is enabled and fifo-merge feature
is used, we need to do the enable in multiple steps, waiting in between,
and the change affects multiple overlays and managers.
apply.c already contains a spinlock, which has been used to protect
(badly) the dss_data. This patch adds locks/unlocks of the spinlock to
the missing places, and the lock should now properly protect dss_data.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
2011-11-15 19:32:57 +07:00
|
|
|
spin_unlock_irqrestore(&data_lock, flags);
|
|
|
|
|
2011-11-15 17:11:11 +07:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void dss_ovl_get_info(struct omap_overlay *ovl,
|
|
|
|
struct omap_overlay_info *info)
|
|
|
|
{
|
2011-11-16 19:11:56 +07:00
|
|
|
struct ovl_priv_data *op = get_ovl_priv(ovl);
|
OMAPDSS: APPLY: add missing uses of spinlock
The functions in apply.c, called mostly via function pointers in overlay
and overlay_manager structs, will be divided into two groups. The other
group will not sleep and can be called from interrupts, and the other
group may sleep.
The idea is that the non-sleeping functions may only change certain
settings in overlays and managers, and those settings may only affect
the particular overlay/manager. For example, set the base address of the
overlay.
The blocking functions, however, will handle more complex configuration
changes. For example, when an overlay is enabled and fifo-merge feature
is used, we need to do the enable in multiple steps, waiting in between,
and the change affects multiple overlays and managers.
apply.c already contains a spinlock, which has been used to protect
(badly) the dss_data. This patch adds locks/unlocks of the spinlock to
the missing places, and the lock should now properly protect dss_data.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
2011-11-15 19:32:57 +07:00
|
|
|
unsigned long flags;
|
|
|
|
|
|
|
|
spin_lock_irqsave(&data_lock, flags);
|
|
|
|
|
2011-11-16 19:11:56 +07:00
|
|
|
*info = op->user_info;
|
OMAPDSS: APPLY: add missing uses of spinlock
The functions in apply.c, called mostly via function pointers in overlay
and overlay_manager structs, will be divided into two groups. The other
group will not sleep and can be called from interrupts, and the other
group may sleep.
The idea is that the non-sleeping functions may only change certain
settings in overlays and managers, and those settings may only affect
the particular overlay/manager. For example, set the base address of the
overlay.
The blocking functions, however, will handle more complex configuration
changes. For example, when an overlay is enabled and fifo-merge feature
is used, we need to do the enable in multiple steps, waiting in between,
and the change affects multiple overlays and managers.
apply.c already contains a spinlock, which has been used to protect
(badly) the dss_data. This patch adds locks/unlocks of the spinlock to
the missing places, and the lock should now properly protect dss_data.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
2011-11-15 19:32:57 +07:00
|
|
|
|
|
|
|
spin_unlock_irqrestore(&data_lock, flags);
|
2011-11-15 17:11:11 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
int dss_ovl_set_manager(struct omap_overlay *ovl,
|
|
|
|
struct omap_overlay_manager *mgr)
|
|
|
|
{
|
OMAPDSS: APPLY: rewrite overlay enable/disable
Overlays are currently enabled and disabled with a boolean in the struct
omap_overlay_info. The overlay info is set with ovl->set_overlay_info(),
and made into use with mgr->apply().
This doesn't work properly, as the enable/disable status may affect also
other overlays, for example when using fifo-merge. Thus the enabling and
disabling of the overlay needs to be done outside the normal overlay
configuration.
This patch achieves that by doing the following things:
1) Add function pointers to struct omap_overlay: enable(), disable() and
is_enabled(). These are used to do the obvious. The functions may block.
2) Move the "enabled" field from struct omap_overlay to ovl_priv_data.
3) Add a new route for settings to be applied to the HW, called
"extra_info". The status of the normal info and extra_info are tracked
separately.
The point here is to allow the normal info to be changed and
applied in non-blocking matter, whereas the extra_info can only be
changed when holding the mutex. This makes it possible to, for example,
set the overlay enable flag, apply it, and wait until the HW has taken
the flag into use.
This is not possible if the enable flag would be in the normal info, as
a new value for the flag could be set at any time from the users of
omapdss.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
2011-11-15 21:37:53 +07:00
|
|
|
struct ovl_priv_data *op = get_ovl_priv(ovl);
|
|
|
|
unsigned long flags;
|
OMAPDSS: APPLY: add mutex
The functions in apply.c, called mostly via function pointers in overlay
and overlay_manager structs, will be divided into two groups. The first
group will not sleep and can be called from interrupts, and the second
group may sleep.
The idea is that the non-sleeping functions may only change certain
settings in overlays and managers, and those settings may only affect
the particular overlay/manager. For example, set the base address of the
overlay.
The blocking functions, however, will handle more complex configuration
changes. For example, when an overlay is enabled and fifo-merge feature
is used, we need to do the enable in multiple steps, waiting in between,
and the change affects multiple overlays and managers.
This patch adds the mutex which is used in the blocking functions to
have exclusive access to overlays and overlay managers.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
2011-11-15 19:28:48 +07:00
|
|
|
int r;
|
|
|
|
|
2011-11-15 17:11:11 +07:00
|
|
|
if (!mgr)
|
|
|
|
return -EINVAL;
|
|
|
|
|
OMAPDSS: APPLY: add mutex
The functions in apply.c, called mostly via function pointers in overlay
and overlay_manager structs, will be divided into two groups. The first
group will not sleep and can be called from interrupts, and the second
group may sleep.
The idea is that the non-sleeping functions may only change certain
settings in overlays and managers, and those settings may only affect
the particular overlay/manager. For example, set the base address of the
overlay.
The blocking functions, however, will handle more complex configuration
changes. For example, when an overlay is enabled and fifo-merge feature
is used, we need to do the enable in multiple steps, waiting in between,
and the change affects multiple overlays and managers.
This patch adds the mutex which is used in the blocking functions to
have exclusive access to overlays and overlay managers.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
2011-11-15 19:28:48 +07:00
|
|
|
mutex_lock(&apply_lock);
|
|
|
|
|
2011-11-15 17:11:11 +07:00
|
|
|
if (ovl->manager) {
|
|
|
|
DSSERR("overlay '%s' already has a manager '%s'\n",
|
|
|
|
ovl->name, ovl->manager->name);
|
OMAPDSS: APPLY: add mutex
The functions in apply.c, called mostly via function pointers in overlay
and overlay_manager structs, will be divided into two groups. The first
group will not sleep and can be called from interrupts, and the second
group may sleep.
The idea is that the non-sleeping functions may only change certain
settings in overlays and managers, and those settings may only affect
the particular overlay/manager. For example, set the base address of the
overlay.
The blocking functions, however, will handle more complex configuration
changes. For example, when an overlay is enabled and fifo-merge feature
is used, we need to do the enable in multiple steps, waiting in between,
and the change affects multiple overlays and managers.
This patch adds the mutex which is used in the blocking functions to
have exclusive access to overlays and overlay managers.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
2011-11-15 19:28:48 +07:00
|
|
|
r = -EINVAL;
|
|
|
|
goto err;
|
2011-11-15 17:11:11 +07:00
|
|
|
}
|
|
|
|
|
OMAPDSS: APPLY: Don't treat an overlay's channel out as shadow bits
An overlay's channel out field isn't a shadow register. The TRM says that it's
taken into effect immediately. This understanding was missing and channel out
was treated as a shadow parameter, and in overlay's private data as extra info.
Program channel out bits directly in dss_ovl_set_manager(). In order to do this
safely, we need to be totally sure that the overlay is disabled in hardware. For
auto update managers, we can assume that the overlay was truly disabled at
dss_ovl_unset_manager() through the wait_pending_extra_info_updates() call.
However, when unsetting manager for an overlay that was previously connected to
a manager in manual update, we can't be sure if the overlay is truly disabled.
That is, op->enabled might not reflect the actual state of the overlay in
hardware. The older manager may require a manual update transfer to truly
disable the overlay. We expect the user of OMAPDSS to take care of this, in
OMAPDSS, we make sure that an overlay's manager isn't unset if there if
extra_info is still dirty for that overlay.
The wrong understanding of channel out bits also explains the reason why we see
sync lost when changing an overlay's manager which was previously connected to a
manual update manager. The following sequence of events caused this:
- When we disable the overlay, no register writes are actually done since the
manager is manual update, op->enabled is set to false, and the
extra_info_dirty flag is set. However, in hardware, the overlay is still
enabled in both shadow and working registers.
- When we unset the manager, the software just configures the overlay's manager
to point to NULL.
- When we set the overlay to a new manager(which is in auto update) through
dss_ovl_set_manager, the check for op->enabled passes, the channel field in
extra info is set to the new manager. When we do an apply on this manager,
the new channel out field is set in the hardware immediately, and since the
overlay enable bit is still set in hardware, the new manager sees that the
overlay is enabled, and tries to retrieve pixels from it, this leads to sync
lost as it might be in the middle of processing a frame when we set the
channel out bit.
The solution to this was to ensure that user space does another update after
disabling the overlay, this actually worked because the overlay was now truly
disabled, and an immediate write to channel out didn't impact since the manager
saw the new overlay as disabled, and doesn't try to retrieve pixels from it.
Remove channel as an extra_info field. Make dss_ovl_unset_manager more strict
about the overlay being disabled when detaching the manager. For overlays
connected to a manual update manager, unset_manager fails if we need another
update to disable the overlay.
We still need to a manual update to ensure the overlay is disabled to get change
the overlay's manager. We could work on doing a dummy update by using DISPC's
capability to gate the different video port signals. This is left for later.
Remove the comment about the sync lost issue.
Signed-off-by: Archit Taneja <archit@ti.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
2012-11-07 16:17:22 +07:00
|
|
|
r = dispc_runtime_get();
|
|
|
|
if (r)
|
|
|
|
goto err;
|
|
|
|
|
OMAPDSS: APPLY: rewrite overlay enable/disable
Overlays are currently enabled and disabled with a boolean in the struct
omap_overlay_info. The overlay info is set with ovl->set_overlay_info(),
and made into use with mgr->apply().
This doesn't work properly, as the enable/disable status may affect also
other overlays, for example when using fifo-merge. Thus the enabling and
disabling of the overlay needs to be done outside the normal overlay
configuration.
This patch achieves that by doing the following things:
1) Add function pointers to struct omap_overlay: enable(), disable() and
is_enabled(). These are used to do the obvious. The functions may block.
2) Move the "enabled" field from struct omap_overlay to ovl_priv_data.
3) Add a new route for settings to be applied to the HW, called
"extra_info". The status of the normal info and extra_info are tracked
separately.
The point here is to allow the normal info to be changed and
applied in non-blocking matter, whereas the extra_info can only be
changed when holding the mutex. This makes it possible to, for example,
set the overlay enable flag, apply it, and wait until the HW has taken
the flag into use.
This is not possible if the enable flag would be in the normal info, as
a new value for the flag could be set at any time from the users of
omapdss.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
2011-11-15 21:37:53 +07:00
|
|
|
spin_lock_irqsave(&data_lock, flags);
|
|
|
|
|
|
|
|
if (op->enabled) {
|
|
|
|
spin_unlock_irqrestore(&data_lock, flags);
|
2011-11-15 17:11:11 +07:00
|
|
|
DSSERR("overlay has to be disabled to change the manager\n");
|
OMAPDSS: APPLY: add mutex
The functions in apply.c, called mostly via function pointers in overlay
and overlay_manager structs, will be divided into two groups. The first
group will not sleep and can be called from interrupts, and the second
group may sleep.
The idea is that the non-sleeping functions may only change certain
settings in overlays and managers, and those settings may only affect
the particular overlay/manager. For example, set the base address of the
overlay.
The blocking functions, however, will handle more complex configuration
changes. For example, when an overlay is enabled and fifo-merge feature
is used, we need to do the enable in multiple steps, waiting in between,
and the change affects multiple overlays and managers.
This patch adds the mutex which is used in the blocking functions to
have exclusive access to overlays and overlay managers.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
2011-11-15 19:28:48 +07:00
|
|
|
r = -EINVAL;
|
OMAPDSS: APPLY: Don't treat an overlay's channel out as shadow bits
An overlay's channel out field isn't a shadow register. The TRM says that it's
taken into effect immediately. This understanding was missing and channel out
was treated as a shadow parameter, and in overlay's private data as extra info.
Program channel out bits directly in dss_ovl_set_manager(). In order to do this
safely, we need to be totally sure that the overlay is disabled in hardware. For
auto update managers, we can assume that the overlay was truly disabled at
dss_ovl_unset_manager() through the wait_pending_extra_info_updates() call.
However, when unsetting manager for an overlay that was previously connected to
a manager in manual update, we can't be sure if the overlay is truly disabled.
That is, op->enabled might not reflect the actual state of the overlay in
hardware. The older manager may require a manual update transfer to truly
disable the overlay. We expect the user of OMAPDSS to take care of this, in
OMAPDSS, we make sure that an overlay's manager isn't unset if there if
extra_info is still dirty for that overlay.
The wrong understanding of channel out bits also explains the reason why we see
sync lost when changing an overlay's manager which was previously connected to a
manual update manager. The following sequence of events caused this:
- When we disable the overlay, no register writes are actually done since the
manager is manual update, op->enabled is set to false, and the
extra_info_dirty flag is set. However, in hardware, the overlay is still
enabled in both shadow and working registers.
- When we unset the manager, the software just configures the overlay's manager
to point to NULL.
- When we set the overlay to a new manager(which is in auto update) through
dss_ovl_set_manager, the check for op->enabled passes, the channel field in
extra info is set to the new manager. When we do an apply on this manager,
the new channel out field is set in the hardware immediately, and since the
overlay enable bit is still set in hardware, the new manager sees that the
overlay is enabled, and tries to retrieve pixels from it, this leads to sync
lost as it might be in the middle of processing a frame when we set the
channel out bit.
The solution to this was to ensure that user space does another update after
disabling the overlay, this actually worked because the overlay was now truly
disabled, and an immediate write to channel out didn't impact since the manager
saw the new overlay as disabled, and doesn't try to retrieve pixels from it.
Remove channel as an extra_info field. Make dss_ovl_unset_manager more strict
about the overlay being disabled when detaching the manager. For overlays
connected to a manual update manager, unset_manager fails if we need another
update to disable the overlay.
We still need to a manual update to ensure the overlay is disabled to get change
the overlay's manager. We could work on doing a dummy update by using DISPC's
capability to gate the different video port signals. This is left for later.
Remove the comment about the sync lost issue.
Signed-off-by: Archit Taneja <archit@ti.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
2012-11-07 16:17:22 +07:00
|
|
|
goto err1;
|
2011-11-15 17:11:11 +07:00
|
|
|
}
|
|
|
|
|
OMAPDSS: APPLY: Don't treat an overlay's channel out as shadow bits
An overlay's channel out field isn't a shadow register. The TRM says that it's
taken into effect immediately. This understanding was missing and channel out
was treated as a shadow parameter, and in overlay's private data as extra info.
Program channel out bits directly in dss_ovl_set_manager(). In order to do this
safely, we need to be totally sure that the overlay is disabled in hardware. For
auto update managers, we can assume that the overlay was truly disabled at
dss_ovl_unset_manager() through the wait_pending_extra_info_updates() call.
However, when unsetting manager for an overlay that was previously connected to
a manager in manual update, we can't be sure if the overlay is truly disabled.
That is, op->enabled might not reflect the actual state of the overlay in
hardware. The older manager may require a manual update transfer to truly
disable the overlay. We expect the user of OMAPDSS to take care of this, in
OMAPDSS, we make sure that an overlay's manager isn't unset if there if
extra_info is still dirty for that overlay.
The wrong understanding of channel out bits also explains the reason why we see
sync lost when changing an overlay's manager which was previously connected to a
manual update manager. The following sequence of events caused this:
- When we disable the overlay, no register writes are actually done since the
manager is manual update, op->enabled is set to false, and the
extra_info_dirty flag is set. However, in hardware, the overlay is still
enabled in both shadow and working registers.
- When we unset the manager, the software just configures the overlay's manager
to point to NULL.
- When we set the overlay to a new manager(which is in auto update) through
dss_ovl_set_manager, the check for op->enabled passes, the channel field in
extra info is set to the new manager. When we do an apply on this manager,
the new channel out field is set in the hardware immediately, and since the
overlay enable bit is still set in hardware, the new manager sees that the
overlay is enabled, and tries to retrieve pixels from it, this leads to sync
lost as it might be in the middle of processing a frame when we set the
channel out bit.
The solution to this was to ensure that user space does another update after
disabling the overlay, this actually worked because the overlay was now truly
disabled, and an immediate write to channel out didn't impact since the manager
saw the new overlay as disabled, and doesn't try to retrieve pixels from it.
Remove channel as an extra_info field. Make dss_ovl_unset_manager more strict
about the overlay being disabled when detaching the manager. For overlays
connected to a manual update manager, unset_manager fails if we need another
update to disable the overlay.
We still need to a manual update to ensure the overlay is disabled to get change
the overlay's manager. We could work on doing a dummy update by using DISPC's
capability to gate the different video port signals. This is left for later.
Remove the comment about the sync lost issue.
Signed-off-by: Archit Taneja <archit@ti.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
2012-11-07 16:17:22 +07:00
|
|
|
dispc_ovl_set_channel_out(ovl->id, mgr->id);
|
2011-11-16 19:17:54 +07:00
|
|
|
|
2011-11-15 17:11:11 +07:00
|
|
|
ovl->manager = mgr;
|
|
|
|
list_add_tail(&ovl->list, &mgr->overlays);
|
|
|
|
|
OMAPDSS: APPLY: rewrite overlay enable/disable
Overlays are currently enabled and disabled with a boolean in the struct
omap_overlay_info. The overlay info is set with ovl->set_overlay_info(),
and made into use with mgr->apply().
This doesn't work properly, as the enable/disable status may affect also
other overlays, for example when using fifo-merge. Thus the enabling and
disabling of the overlay needs to be done outside the normal overlay
configuration.
This patch achieves that by doing the following things:
1) Add function pointers to struct omap_overlay: enable(), disable() and
is_enabled(). These are used to do the obvious. The functions may block.
2) Move the "enabled" field from struct omap_overlay to ovl_priv_data.
3) Add a new route for settings to be applied to the HW, called
"extra_info". The status of the normal info and extra_info are tracked
separately.
The point here is to allow the normal info to be changed and
applied in non-blocking matter, whereas the extra_info can only be
changed when holding the mutex. This makes it possible to, for example,
set the overlay enable flag, apply it, and wait until the HW has taken
the flag into use.
This is not possible if the enable flag would be in the normal info, as
a new value for the flag could be set at any time from the users of
omapdss.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
2011-11-15 21:37:53 +07:00
|
|
|
spin_unlock_irqrestore(&data_lock, flags);
|
|
|
|
|
OMAPDSS: APPLY: Don't treat an overlay's channel out as shadow bits
An overlay's channel out field isn't a shadow register. The TRM says that it's
taken into effect immediately. This understanding was missing and channel out
was treated as a shadow parameter, and in overlay's private data as extra info.
Program channel out bits directly in dss_ovl_set_manager(). In order to do this
safely, we need to be totally sure that the overlay is disabled in hardware. For
auto update managers, we can assume that the overlay was truly disabled at
dss_ovl_unset_manager() through the wait_pending_extra_info_updates() call.
However, when unsetting manager for an overlay that was previously connected to
a manager in manual update, we can't be sure if the overlay is truly disabled.
That is, op->enabled might not reflect the actual state of the overlay in
hardware. The older manager may require a manual update transfer to truly
disable the overlay. We expect the user of OMAPDSS to take care of this, in
OMAPDSS, we make sure that an overlay's manager isn't unset if there if
extra_info is still dirty for that overlay.
The wrong understanding of channel out bits also explains the reason why we see
sync lost when changing an overlay's manager which was previously connected to a
manual update manager. The following sequence of events caused this:
- When we disable the overlay, no register writes are actually done since the
manager is manual update, op->enabled is set to false, and the
extra_info_dirty flag is set. However, in hardware, the overlay is still
enabled in both shadow and working registers.
- When we unset the manager, the software just configures the overlay's manager
to point to NULL.
- When we set the overlay to a new manager(which is in auto update) through
dss_ovl_set_manager, the check for op->enabled passes, the channel field in
extra info is set to the new manager. When we do an apply on this manager,
the new channel out field is set in the hardware immediately, and since the
overlay enable bit is still set in hardware, the new manager sees that the
overlay is enabled, and tries to retrieve pixels from it, this leads to sync
lost as it might be in the middle of processing a frame when we set the
channel out bit.
The solution to this was to ensure that user space does another update after
disabling the overlay, this actually worked because the overlay was now truly
disabled, and an immediate write to channel out didn't impact since the manager
saw the new overlay as disabled, and doesn't try to retrieve pixels from it.
Remove channel as an extra_info field. Make dss_ovl_unset_manager more strict
about the overlay being disabled when detaching the manager. For overlays
connected to a manual update manager, unset_manager fails if we need another
update to disable the overlay.
We still need to a manual update to ensure the overlay is disabled to get change
the overlay's manager. We could work on doing a dummy update by using DISPC's
capability to gate the different video port signals. This is left for later.
Remove the comment about the sync lost issue.
Signed-off-by: Archit Taneja <archit@ti.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
2012-11-07 16:17:22 +07:00
|
|
|
dispc_runtime_put();
|
2011-11-15 17:11:11 +07:00
|
|
|
|
OMAPDSS: APPLY: add mutex
The functions in apply.c, called mostly via function pointers in overlay
and overlay_manager structs, will be divided into two groups. The first
group will not sleep and can be called from interrupts, and the second
group may sleep.
The idea is that the non-sleeping functions may only change certain
settings in overlays and managers, and those settings may only affect
the particular overlay/manager. For example, set the base address of the
overlay.
The blocking functions, however, will handle more complex configuration
changes. For example, when an overlay is enabled and fifo-merge feature
is used, we need to do the enable in multiple steps, waiting in between,
and the change affects multiple overlays and managers.
This patch adds the mutex which is used in the blocking functions to
have exclusive access to overlays and overlay managers.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
2011-11-15 19:28:48 +07:00
|
|
|
mutex_unlock(&apply_lock);
|
|
|
|
|
2011-11-15 17:11:11 +07:00
|
|
|
return 0;
|
OMAPDSS: APPLY: Don't treat an overlay's channel out as shadow bits
An overlay's channel out field isn't a shadow register. The TRM says that it's
taken into effect immediately. This understanding was missing and channel out
was treated as a shadow parameter, and in overlay's private data as extra info.
Program channel out bits directly in dss_ovl_set_manager(). In order to do this
safely, we need to be totally sure that the overlay is disabled in hardware. For
auto update managers, we can assume that the overlay was truly disabled at
dss_ovl_unset_manager() through the wait_pending_extra_info_updates() call.
However, when unsetting manager for an overlay that was previously connected to
a manager in manual update, we can't be sure if the overlay is truly disabled.
That is, op->enabled might not reflect the actual state of the overlay in
hardware. The older manager may require a manual update transfer to truly
disable the overlay. We expect the user of OMAPDSS to take care of this, in
OMAPDSS, we make sure that an overlay's manager isn't unset if there if
extra_info is still dirty for that overlay.
The wrong understanding of channel out bits also explains the reason why we see
sync lost when changing an overlay's manager which was previously connected to a
manual update manager. The following sequence of events caused this:
- When we disable the overlay, no register writes are actually done since the
manager is manual update, op->enabled is set to false, and the
extra_info_dirty flag is set. However, in hardware, the overlay is still
enabled in both shadow and working registers.
- When we unset the manager, the software just configures the overlay's manager
to point to NULL.
- When we set the overlay to a new manager(which is in auto update) through
dss_ovl_set_manager, the check for op->enabled passes, the channel field in
extra info is set to the new manager. When we do an apply on this manager,
the new channel out field is set in the hardware immediately, and since the
overlay enable bit is still set in hardware, the new manager sees that the
overlay is enabled, and tries to retrieve pixels from it, this leads to sync
lost as it might be in the middle of processing a frame when we set the
channel out bit.
The solution to this was to ensure that user space does another update after
disabling the overlay, this actually worked because the overlay was now truly
disabled, and an immediate write to channel out didn't impact since the manager
saw the new overlay as disabled, and doesn't try to retrieve pixels from it.
Remove channel as an extra_info field. Make dss_ovl_unset_manager more strict
about the overlay being disabled when detaching the manager. For overlays
connected to a manual update manager, unset_manager fails if we need another
update to disable the overlay.
We still need to a manual update to ensure the overlay is disabled to get change
the overlay's manager. We could work on doing a dummy update by using DISPC's
capability to gate the different video port signals. This is left for later.
Remove the comment about the sync lost issue.
Signed-off-by: Archit Taneja <archit@ti.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
2012-11-07 16:17:22 +07:00
|
|
|
|
|
|
|
err1:
|
|
|
|
dispc_runtime_put();
|
OMAPDSS: APPLY: add mutex
The functions in apply.c, called mostly via function pointers in overlay
and overlay_manager structs, will be divided into two groups. The first
group will not sleep and can be called from interrupts, and the second
group may sleep.
The idea is that the non-sleeping functions may only change certain
settings in overlays and managers, and those settings may only affect
the particular overlay/manager. For example, set the base address of the
overlay.
The blocking functions, however, will handle more complex configuration
changes. For example, when an overlay is enabled and fifo-merge feature
is used, we need to do the enable in multiple steps, waiting in between,
and the change affects multiple overlays and managers.
This patch adds the mutex which is used in the blocking functions to
have exclusive access to overlays and overlay managers.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
2011-11-15 19:28:48 +07:00
|
|
|
err:
|
|
|
|
mutex_unlock(&apply_lock);
|
|
|
|
return r;
|
2011-11-15 17:11:11 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
int dss_ovl_unset_manager(struct omap_overlay *ovl)
|
|
|
|
{
|
OMAPDSS: APPLY: rewrite overlay enable/disable
Overlays are currently enabled and disabled with a boolean in the struct
omap_overlay_info. The overlay info is set with ovl->set_overlay_info(),
and made into use with mgr->apply().
This doesn't work properly, as the enable/disable status may affect also
other overlays, for example when using fifo-merge. Thus the enabling and
disabling of the overlay needs to be done outside the normal overlay
configuration.
This patch achieves that by doing the following things:
1) Add function pointers to struct omap_overlay: enable(), disable() and
is_enabled(). These are used to do the obvious. The functions may block.
2) Move the "enabled" field from struct omap_overlay to ovl_priv_data.
3) Add a new route for settings to be applied to the HW, called
"extra_info". The status of the normal info and extra_info are tracked
separately.
The point here is to allow the normal info to be changed and
applied in non-blocking matter, whereas the extra_info can only be
changed when holding the mutex. This makes it possible to, for example,
set the overlay enable flag, apply it, and wait until the HW has taken
the flag into use.
This is not possible if the enable flag would be in the normal info, as
a new value for the flag could be set at any time from the users of
omapdss.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
2011-11-15 21:37:53 +07:00
|
|
|
struct ovl_priv_data *op = get_ovl_priv(ovl);
|
|
|
|
unsigned long flags;
|
OMAPDSS: APPLY: add mutex
The functions in apply.c, called mostly via function pointers in overlay
and overlay_manager structs, will be divided into two groups. The first
group will not sleep and can be called from interrupts, and the second
group may sleep.
The idea is that the non-sleeping functions may only change certain
settings in overlays and managers, and those settings may only affect
the particular overlay/manager. For example, set the base address of the
overlay.
The blocking functions, however, will handle more complex configuration
changes. For example, when an overlay is enabled and fifo-merge feature
is used, we need to do the enable in multiple steps, waiting in between,
and the change affects multiple overlays and managers.
This patch adds the mutex which is used in the blocking functions to
have exclusive access to overlays and overlay managers.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
2011-11-15 19:28:48 +07:00
|
|
|
int r;
|
|
|
|
|
|
|
|
mutex_lock(&apply_lock);
|
|
|
|
|
2011-11-15 17:11:11 +07:00
|
|
|
if (!ovl->manager) {
|
|
|
|
DSSERR("failed to detach overlay: manager not set\n");
|
OMAPDSS: APPLY: add mutex
The functions in apply.c, called mostly via function pointers in overlay
and overlay_manager structs, will be divided into two groups. The first
group will not sleep and can be called from interrupts, and the second
group may sleep.
The idea is that the non-sleeping functions may only change certain
settings in overlays and managers, and those settings may only affect
the particular overlay/manager. For example, set the base address of the
overlay.
The blocking functions, however, will handle more complex configuration
changes. For example, when an overlay is enabled and fifo-merge feature
is used, we need to do the enable in multiple steps, waiting in between,
and the change affects multiple overlays and managers.
This patch adds the mutex which is used in the blocking functions to
have exclusive access to overlays and overlay managers.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
2011-11-15 19:28:48 +07:00
|
|
|
r = -EINVAL;
|
|
|
|
goto err;
|
2011-11-15 17:11:11 +07:00
|
|
|
}
|
|
|
|
|
OMAPDSS: APPLY: rewrite overlay enable/disable
Overlays are currently enabled and disabled with a boolean in the struct
omap_overlay_info. The overlay info is set with ovl->set_overlay_info(),
and made into use with mgr->apply().
This doesn't work properly, as the enable/disable status may affect also
other overlays, for example when using fifo-merge. Thus the enabling and
disabling of the overlay needs to be done outside the normal overlay
configuration.
This patch achieves that by doing the following things:
1) Add function pointers to struct omap_overlay: enable(), disable() and
is_enabled(). These are used to do the obvious. The functions may block.
2) Move the "enabled" field from struct omap_overlay to ovl_priv_data.
3) Add a new route for settings to be applied to the HW, called
"extra_info". The status of the normal info and extra_info are tracked
separately.
The point here is to allow the normal info to be changed and
applied in non-blocking matter, whereas the extra_info can only be
changed when holding the mutex. This makes it possible to, for example,
set the overlay enable flag, apply it, and wait until the HW has taken
the flag into use.
This is not possible if the enable flag would be in the normal info, as
a new value for the flag could be set at any time from the users of
omapdss.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
2011-11-15 21:37:53 +07:00
|
|
|
spin_lock_irqsave(&data_lock, flags);
|
|
|
|
|
|
|
|
if (op->enabled) {
|
|
|
|
spin_unlock_irqrestore(&data_lock, flags);
|
2011-11-15 17:11:11 +07:00
|
|
|
DSSERR("overlay has to be disabled to unset the manager\n");
|
OMAPDSS: APPLY: add mutex
The functions in apply.c, called mostly via function pointers in overlay
and overlay_manager structs, will be divided into two groups. The first
group will not sleep and can be called from interrupts, and the second
group may sleep.
The idea is that the non-sleeping functions may only change certain
settings in overlays and managers, and those settings may only affect
the particular overlay/manager. For example, set the base address of the
overlay.
The blocking functions, however, will handle more complex configuration
changes. For example, when an overlay is enabled and fifo-merge feature
is used, we need to do the enable in multiple steps, waiting in between,
and the change affects multiple overlays and managers.
This patch adds the mutex which is used in the blocking functions to
have exclusive access to overlays and overlay managers.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
2011-11-15 19:28:48 +07:00
|
|
|
r = -EINVAL;
|
|
|
|
goto err;
|
2011-11-15 17:11:11 +07:00
|
|
|
}
|
|
|
|
|
2012-09-06 20:10:28 +07:00
|
|
|
spin_unlock_irqrestore(&data_lock, flags);
|
|
|
|
|
|
|
|
/* wait for pending extra_info updates to ensure the ovl is disabled */
|
|
|
|
wait_pending_extra_info_updates();
|
|
|
|
|
OMAPDSS: APPLY: Don't treat an overlay's channel out as shadow bits
An overlay's channel out field isn't a shadow register. The TRM says that it's
taken into effect immediately. This understanding was missing and channel out
was treated as a shadow parameter, and in overlay's private data as extra info.
Program channel out bits directly in dss_ovl_set_manager(). In order to do this
safely, we need to be totally sure that the overlay is disabled in hardware. For
auto update managers, we can assume that the overlay was truly disabled at
dss_ovl_unset_manager() through the wait_pending_extra_info_updates() call.
However, when unsetting manager for an overlay that was previously connected to
a manager in manual update, we can't be sure if the overlay is truly disabled.
That is, op->enabled might not reflect the actual state of the overlay in
hardware. The older manager may require a manual update transfer to truly
disable the overlay. We expect the user of OMAPDSS to take care of this, in
OMAPDSS, we make sure that an overlay's manager isn't unset if there if
extra_info is still dirty for that overlay.
The wrong understanding of channel out bits also explains the reason why we see
sync lost when changing an overlay's manager which was previously connected to a
manual update manager. The following sequence of events caused this:
- When we disable the overlay, no register writes are actually done since the
manager is manual update, op->enabled is set to false, and the
extra_info_dirty flag is set. However, in hardware, the overlay is still
enabled in both shadow and working registers.
- When we unset the manager, the software just configures the overlay's manager
to point to NULL.
- When we set the overlay to a new manager(which is in auto update) through
dss_ovl_set_manager, the check for op->enabled passes, the channel field in
extra info is set to the new manager. When we do an apply on this manager,
the new channel out field is set in the hardware immediately, and since the
overlay enable bit is still set in hardware, the new manager sees that the
overlay is enabled, and tries to retrieve pixels from it, this leads to sync
lost as it might be in the middle of processing a frame when we set the
channel out bit.
The solution to this was to ensure that user space does another update after
disabling the overlay, this actually worked because the overlay was now truly
disabled, and an immediate write to channel out didn't impact since the manager
saw the new overlay as disabled, and doesn't try to retrieve pixels from it.
Remove channel as an extra_info field. Make dss_ovl_unset_manager more strict
about the overlay being disabled when detaching the manager. For overlays
connected to a manual update manager, unset_manager fails if we need another
update to disable the overlay.
We still need to a manual update to ensure the overlay is disabled to get change
the overlay's manager. We could work on doing a dummy update by using DISPC's
capability to gate the different video port signals. This is left for later.
Remove the comment about the sync lost issue.
Signed-off-by: Archit Taneja <archit@ti.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
2012-11-07 16:17:22 +07:00
|
|
|
/*
|
|
|
|
* For a manual update display, there is no guarantee that the overlay
|
|
|
|
* is really disabled in HW, we may need an extra update from this
|
|
|
|
* manager before the configurations can go in. Return an error if the
|
|
|
|
* overlay needed an update from the manager.
|
|
|
|
*
|
|
|
|
* TODO: Instead of returning an error, try to do a dummy manager update
|
|
|
|
* here to disable the overlay in hardware. Use the *GATED fields in
|
|
|
|
* the DISPC_CONFIG registers to do a dummy update.
|
|
|
|
*/
|
2012-09-06 20:10:28 +07:00
|
|
|
spin_lock_irqsave(&data_lock, flags);
|
|
|
|
|
OMAPDSS: APPLY: Don't treat an overlay's channel out as shadow bits
An overlay's channel out field isn't a shadow register. The TRM says that it's
taken into effect immediately. This understanding was missing and channel out
was treated as a shadow parameter, and in overlay's private data as extra info.
Program channel out bits directly in dss_ovl_set_manager(). In order to do this
safely, we need to be totally sure that the overlay is disabled in hardware. For
auto update managers, we can assume that the overlay was truly disabled at
dss_ovl_unset_manager() through the wait_pending_extra_info_updates() call.
However, when unsetting manager for an overlay that was previously connected to
a manager in manual update, we can't be sure if the overlay is truly disabled.
That is, op->enabled might not reflect the actual state of the overlay in
hardware. The older manager may require a manual update transfer to truly
disable the overlay. We expect the user of OMAPDSS to take care of this, in
OMAPDSS, we make sure that an overlay's manager isn't unset if there if
extra_info is still dirty for that overlay.
The wrong understanding of channel out bits also explains the reason why we see
sync lost when changing an overlay's manager which was previously connected to a
manual update manager. The following sequence of events caused this:
- When we disable the overlay, no register writes are actually done since the
manager is manual update, op->enabled is set to false, and the
extra_info_dirty flag is set. However, in hardware, the overlay is still
enabled in both shadow and working registers.
- When we unset the manager, the software just configures the overlay's manager
to point to NULL.
- When we set the overlay to a new manager(which is in auto update) through
dss_ovl_set_manager, the check for op->enabled passes, the channel field in
extra info is set to the new manager. When we do an apply on this manager,
the new channel out field is set in the hardware immediately, and since the
overlay enable bit is still set in hardware, the new manager sees that the
overlay is enabled, and tries to retrieve pixels from it, this leads to sync
lost as it might be in the middle of processing a frame when we set the
channel out bit.
The solution to this was to ensure that user space does another update after
disabling the overlay, this actually worked because the overlay was now truly
disabled, and an immediate write to channel out didn't impact since the manager
saw the new overlay as disabled, and doesn't try to retrieve pixels from it.
Remove channel as an extra_info field. Make dss_ovl_unset_manager more strict
about the overlay being disabled when detaching the manager. For overlays
connected to a manual update manager, unset_manager fails if we need another
update to disable the overlay.
We still need to a manual update to ensure the overlay is disabled to get change
the overlay's manager. We could work on doing a dummy update by using DISPC's
capability to gate the different video port signals. This is left for later.
Remove the comment about the sync lost issue.
Signed-off-by: Archit Taneja <archit@ti.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
2012-11-07 16:17:22 +07:00
|
|
|
if (ovl_manual_update(ovl) && op->extra_info_dirty) {
|
|
|
|
spin_unlock_irqrestore(&data_lock, flags);
|
|
|
|
DSSERR("need an update to change the manager\n");
|
|
|
|
r = -EINVAL;
|
|
|
|
goto err;
|
|
|
|
}
|
2011-11-16 19:17:54 +07:00
|
|
|
|
2011-11-15 17:11:11 +07:00
|
|
|
ovl->manager = NULL;
|
|
|
|
list_del(&ovl->list);
|
|
|
|
|
OMAPDSS: APPLY: rewrite overlay enable/disable
Overlays are currently enabled and disabled with a boolean in the struct
omap_overlay_info. The overlay info is set with ovl->set_overlay_info(),
and made into use with mgr->apply().
This doesn't work properly, as the enable/disable status may affect also
other overlays, for example when using fifo-merge. Thus the enabling and
disabling of the overlay needs to be done outside the normal overlay
configuration.
This patch achieves that by doing the following things:
1) Add function pointers to struct omap_overlay: enable(), disable() and
is_enabled(). These are used to do the obvious. The functions may block.
2) Move the "enabled" field from struct omap_overlay to ovl_priv_data.
3) Add a new route for settings to be applied to the HW, called
"extra_info". The status of the normal info and extra_info are tracked
separately.
The point here is to allow the normal info to be changed and
applied in non-blocking matter, whereas the extra_info can only be
changed when holding the mutex. This makes it possible to, for example,
set the overlay enable flag, apply it, and wait until the HW has taken
the flag into use.
This is not possible if the enable flag would be in the normal info, as
a new value for the flag could be set at any time from the users of
omapdss.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
2011-11-15 21:37:53 +07:00
|
|
|
spin_unlock_irqrestore(&data_lock, flags);
|
|
|
|
|
|
|
|
mutex_unlock(&apply_lock);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
err:
|
|
|
|
mutex_unlock(&apply_lock);
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool dss_ovl_is_enabled(struct omap_overlay *ovl)
|
|
|
|
{
|
|
|
|
struct ovl_priv_data *op = get_ovl_priv(ovl);
|
|
|
|
unsigned long flags;
|
|
|
|
bool e;
|
|
|
|
|
|
|
|
spin_lock_irqsave(&data_lock, flags);
|
|
|
|
|
|
|
|
e = op->enabled;
|
|
|
|
|
|
|
|
spin_unlock_irqrestore(&data_lock, flags);
|
|
|
|
|
|
|
|
return e;
|
|
|
|
}
|
|
|
|
|
|
|
|
int dss_ovl_enable(struct omap_overlay *ovl)
|
|
|
|
{
|
|
|
|
struct ovl_priv_data *op = get_ovl_priv(ovl);
|
|
|
|
unsigned long flags;
|
|
|
|
int r;
|
|
|
|
|
|
|
|
mutex_lock(&apply_lock);
|
|
|
|
|
2011-11-16 21:01:33 +07:00
|
|
|
if (op->enabled) {
|
|
|
|
r = 0;
|
2011-11-17 22:35:28 +07:00
|
|
|
goto err1;
|
2011-11-16 21:01:33 +07:00
|
|
|
}
|
|
|
|
|
2012-09-03 18:44:09 +07:00
|
|
|
if (ovl->manager == NULL || ovl->manager->output == NULL) {
|
OMAPDSS: APPLY: rewrite overlay enable/disable
Overlays are currently enabled and disabled with a boolean in the struct
omap_overlay_info. The overlay info is set with ovl->set_overlay_info(),
and made into use with mgr->apply().
This doesn't work properly, as the enable/disable status may affect also
other overlays, for example when using fifo-merge. Thus the enabling and
disabling of the overlay needs to be done outside the normal overlay
configuration.
This patch achieves that by doing the following things:
1) Add function pointers to struct omap_overlay: enable(), disable() and
is_enabled(). These are used to do the obvious. The functions may block.
2) Move the "enabled" field from struct omap_overlay to ovl_priv_data.
3) Add a new route for settings to be applied to the HW, called
"extra_info". The status of the normal info and extra_info are tracked
separately.
The point here is to allow the normal info to be changed and
applied in non-blocking matter, whereas the extra_info can only be
changed when holding the mutex. This makes it possible to, for example,
set the overlay enable flag, apply it, and wait until the HW has taken
the flag into use.
This is not possible if the enable flag would be in the normal info, as
a new value for the flag could be set at any time from the users of
omapdss.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
2011-11-15 21:37:53 +07:00
|
|
|
r = -EINVAL;
|
2011-11-17 22:35:28 +07:00
|
|
|
goto err1;
|
OMAPDSS: APPLY: rewrite overlay enable/disable
Overlays are currently enabled and disabled with a boolean in the struct
omap_overlay_info. The overlay info is set with ovl->set_overlay_info(),
and made into use with mgr->apply().
This doesn't work properly, as the enable/disable status may affect also
other overlays, for example when using fifo-merge. Thus the enabling and
disabling of the overlay needs to be done outside the normal overlay
configuration.
This patch achieves that by doing the following things:
1) Add function pointers to struct omap_overlay: enable(), disable() and
is_enabled(). These are used to do the obvious. The functions may block.
2) Move the "enabled" field from struct omap_overlay to ovl_priv_data.
3) Add a new route for settings to be applied to the HW, called
"extra_info". The status of the normal info and extra_info are tracked
separately.
The point here is to allow the normal info to be changed and
applied in non-blocking matter, whereas the extra_info can only be
changed when holding the mutex. This makes it possible to, for example,
set the overlay enable flag, apply it, and wait until the HW has taken
the flag into use.
This is not possible if the enable flag would be in the normal info, as
a new value for the flag could be set at any time from the users of
omapdss.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
2011-11-15 21:37:53 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
spin_lock_irqsave(&data_lock, flags);
|
|
|
|
|
2011-11-26 19:26:46 +07:00
|
|
|
op->enabling = true;
|
|
|
|
|
2012-04-27 02:52:28 +07:00
|
|
|
r = dss_check_settings(ovl->manager);
|
2011-11-17 22:35:28 +07:00
|
|
|
if (r) {
|
|
|
|
DSSERR("failed to enable overlay %d: check_settings failed\n",
|
|
|
|
ovl->id);
|
|
|
|
goto err2;
|
|
|
|
}
|
|
|
|
|
2012-08-06 20:50:14 +07:00
|
|
|
dss_setup_fifos();
|
2011-11-16 19:28:12 +07:00
|
|
|
|
2011-11-26 19:26:46 +07:00
|
|
|
op->enabling = false;
|
|
|
|
dss_apply_ovl_enable(ovl, true);
|
|
|
|
|
2011-11-15 23:25:23 +07:00
|
|
|
dss_write_regs();
|
2011-11-25 22:32:20 +07:00
|
|
|
dss_set_go_bits();
|
2011-11-15 23:25:23 +07:00
|
|
|
|
OMAPDSS: APPLY: rewrite overlay enable/disable
Overlays are currently enabled and disabled with a boolean in the struct
omap_overlay_info. The overlay info is set with ovl->set_overlay_info(),
and made into use with mgr->apply().
This doesn't work properly, as the enable/disable status may affect also
other overlays, for example when using fifo-merge. Thus the enabling and
disabling of the overlay needs to be done outside the normal overlay
configuration.
This patch achieves that by doing the following things:
1) Add function pointers to struct omap_overlay: enable(), disable() and
is_enabled(). These are used to do the obvious. The functions may block.
2) Move the "enabled" field from struct omap_overlay to ovl_priv_data.
3) Add a new route for settings to be applied to the HW, called
"extra_info". The status of the normal info and extra_info are tracked
separately.
The point here is to allow the normal info to be changed and
applied in non-blocking matter, whereas the extra_info can only be
changed when holding the mutex. This makes it possible to, for example,
set the overlay enable flag, apply it, and wait until the HW has taken
the flag into use.
This is not possible if the enable flag would be in the normal info, as
a new value for the flag could be set at any time from the users of
omapdss.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
2011-11-15 21:37:53 +07:00
|
|
|
spin_unlock_irqrestore(&data_lock, flags);
|
|
|
|
|
|
|
|
mutex_unlock(&apply_lock);
|
|
|
|
|
|
|
|
return 0;
|
2011-11-17 22:35:28 +07:00
|
|
|
err2:
|
2011-11-26 19:26:46 +07:00
|
|
|
op->enabling = false;
|
2011-11-17 22:35:28 +07:00
|
|
|
spin_unlock_irqrestore(&data_lock, flags);
|
|
|
|
err1:
|
OMAPDSS: APPLY: rewrite overlay enable/disable
Overlays are currently enabled and disabled with a boolean in the struct
omap_overlay_info. The overlay info is set with ovl->set_overlay_info(),
and made into use with mgr->apply().
This doesn't work properly, as the enable/disable status may affect also
other overlays, for example when using fifo-merge. Thus the enabling and
disabling of the overlay needs to be done outside the normal overlay
configuration.
This patch achieves that by doing the following things:
1) Add function pointers to struct omap_overlay: enable(), disable() and
is_enabled(). These are used to do the obvious. The functions may block.
2) Move the "enabled" field from struct omap_overlay to ovl_priv_data.
3) Add a new route for settings to be applied to the HW, called
"extra_info". The status of the normal info and extra_info are tracked
separately.
The point here is to allow the normal info to be changed and
applied in non-blocking matter, whereas the extra_info can only be
changed when holding the mutex. This makes it possible to, for example,
set the overlay enable flag, apply it, and wait until the HW has taken
the flag into use.
This is not possible if the enable flag would be in the normal info, as
a new value for the flag could be set at any time from the users of
omapdss.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
2011-11-15 21:37:53 +07:00
|
|
|
mutex_unlock(&apply_lock);
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
int dss_ovl_disable(struct omap_overlay *ovl)
|
|
|
|
{
|
|
|
|
struct ovl_priv_data *op = get_ovl_priv(ovl);
|
|
|
|
unsigned long flags;
|
|
|
|
int r;
|
|
|
|
|
|
|
|
mutex_lock(&apply_lock);
|
|
|
|
|
2011-11-16 21:01:33 +07:00
|
|
|
if (!op->enabled) {
|
|
|
|
r = 0;
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
2012-09-03 18:44:09 +07:00
|
|
|
if (ovl->manager == NULL || ovl->manager->output == NULL) {
|
OMAPDSS: APPLY: rewrite overlay enable/disable
Overlays are currently enabled and disabled with a boolean in the struct
omap_overlay_info. The overlay info is set with ovl->set_overlay_info(),
and made into use with mgr->apply().
This doesn't work properly, as the enable/disable status may affect also
other overlays, for example when using fifo-merge. Thus the enabling and
disabling of the overlay needs to be done outside the normal overlay
configuration.
This patch achieves that by doing the following things:
1) Add function pointers to struct omap_overlay: enable(), disable() and
is_enabled(). These are used to do the obvious. The functions may block.
2) Move the "enabled" field from struct omap_overlay to ovl_priv_data.
3) Add a new route for settings to be applied to the HW, called
"extra_info". The status of the normal info and extra_info are tracked
separately.
The point here is to allow the normal info to be changed and
applied in non-blocking matter, whereas the extra_info can only be
changed when holding the mutex. This makes it possible to, for example,
set the overlay enable flag, apply it, and wait until the HW has taken
the flag into use.
This is not possible if the enable flag would be in the normal info, as
a new value for the flag could be set at any time from the users of
omapdss.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
2011-11-15 21:37:53 +07:00
|
|
|
r = -EINVAL;
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
spin_lock_irqsave(&data_lock, flags);
|
|
|
|
|
2011-11-16 20:25:53 +07:00
|
|
|
dss_apply_ovl_enable(ovl, false);
|
2011-11-15 23:25:23 +07:00
|
|
|
dss_write_regs();
|
2011-11-25 22:32:20 +07:00
|
|
|
dss_set_go_bits();
|
2011-11-15 23:25:23 +07:00
|
|
|
|
OMAPDSS: APPLY: rewrite overlay enable/disable
Overlays are currently enabled and disabled with a boolean in the struct
omap_overlay_info. The overlay info is set with ovl->set_overlay_info(),
and made into use with mgr->apply().
This doesn't work properly, as the enable/disable status may affect also
other overlays, for example when using fifo-merge. Thus the enabling and
disabling of the overlay needs to be done outside the normal overlay
configuration.
This patch achieves that by doing the following things:
1) Add function pointers to struct omap_overlay: enable(), disable() and
is_enabled(). These are used to do the obvious. The functions may block.
2) Move the "enabled" field from struct omap_overlay to ovl_priv_data.
3) Add a new route for settings to be applied to the HW, called
"extra_info". The status of the normal info and extra_info are tracked
separately.
The point here is to allow the normal info to be changed and
applied in non-blocking matter, whereas the extra_info can only be
changed when holding the mutex. This makes it possible to, for example,
set the overlay enable flag, apply it, and wait until the HW has taken
the flag into use.
This is not possible if the enable flag would be in the normal info, as
a new value for the flag could be set at any time from the users of
omapdss.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
2011-11-15 21:37:53 +07:00
|
|
|
spin_unlock_irqrestore(&data_lock, flags);
|
|
|
|
|
OMAPDSS: APPLY: add mutex
The functions in apply.c, called mostly via function pointers in overlay
and overlay_manager structs, will be divided into two groups. The first
group will not sleep and can be called from interrupts, and the second
group may sleep.
The idea is that the non-sleeping functions may only change certain
settings in overlays and managers, and those settings may only affect
the particular overlay/manager. For example, set the base address of the
overlay.
The blocking functions, however, will handle more complex configuration
changes. For example, when an overlay is enabled and fifo-merge feature
is used, we need to do the enable in multiple steps, waiting in between,
and the change affects multiple overlays and managers.
This patch adds the mutex which is used in the blocking functions to
have exclusive access to overlays and overlay managers.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
2011-11-15 19:28:48 +07:00
|
|
|
mutex_unlock(&apply_lock);
|
|
|
|
|
2011-11-15 17:11:11 +07:00
|
|
|
return 0;
|
OMAPDSS: APPLY: rewrite overlay enable/disable
Overlays are currently enabled and disabled with a boolean in the struct
omap_overlay_info. The overlay info is set with ovl->set_overlay_info(),
and made into use with mgr->apply().
This doesn't work properly, as the enable/disable status may affect also
other overlays, for example when using fifo-merge. Thus the enabling and
disabling of the overlay needs to be done outside the normal overlay
configuration.
This patch achieves that by doing the following things:
1) Add function pointers to struct omap_overlay: enable(), disable() and
is_enabled(). These are used to do the obvious. The functions may block.
2) Move the "enabled" field from struct omap_overlay to ovl_priv_data.
3) Add a new route for settings to be applied to the HW, called
"extra_info". The status of the normal info and extra_info are tracked
separately.
The point here is to allow the normal info to be changed and
applied in non-blocking matter, whereas the extra_info can only be
changed when holding the mutex. This makes it possible to, for example,
set the overlay enable flag, apply it, and wait until the HW has taken
the flag into use.
This is not possible if the enable flag would be in the normal info, as
a new value for the flag could be set at any time from the users of
omapdss.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
2011-11-15 21:37:53 +07:00
|
|
|
|
OMAPDSS: APPLY: add mutex
The functions in apply.c, called mostly via function pointers in overlay
and overlay_manager structs, will be divided into two groups. The first
group will not sleep and can be called from interrupts, and the second
group may sleep.
The idea is that the non-sleeping functions may only change certain
settings in overlays and managers, and those settings may only affect
the particular overlay/manager. For example, set the base address of the
overlay.
The blocking functions, however, will handle more complex configuration
changes. For example, when an overlay is enabled and fifo-merge feature
is used, we need to do the enable in multiple steps, waiting in between,
and the change affects multiple overlays and managers.
This patch adds the mutex which is used in the blocking functions to
have exclusive access to overlays and overlay managers.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
2011-11-15 19:28:48 +07:00
|
|
|
err:
|
|
|
|
mutex_unlock(&apply_lock);
|
|
|
|
return r;
|
2011-11-15 17:11:11 +07:00
|
|
|
}
|
|
|
|
|
2012-10-10 14:26:45 +07:00
|
|
|
static int compat_refcnt;
|
|
|
|
static DEFINE_MUTEX(compat_init_lock);
|
|
|
|
|
|
|
|
int omapdss_compat_init(void)
|
|
|
|
{
|
|
|
|
mutex_lock(&compat_init_lock);
|
|
|
|
|
|
|
|
if (compat_refcnt++ > 0)
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
apply_init_priv();
|
|
|
|
|
|
|
|
out:
|
|
|
|
mutex_unlock(&compat_init_lock);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(omapdss_compat_init);
|
|
|
|
|
|
|
|
void omapdss_compat_uninit(void)
|
|
|
|
{
|
|
|
|
mutex_lock(&compat_init_lock);
|
|
|
|
|
|
|
|
if (--compat_refcnt > 0)
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
out:
|
|
|
|
mutex_unlock(&compat_init_lock);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(omapdss_compat_uninit);
|