|
@@ -18,6 +18,7 @@
|
|
|
#define DSS_SUBSYS_NAME "APPLY"
|
|
|
|
|
|
#include <linux/kernel.h>
|
|
|
+#include <linux/module.h>
|
|
|
#include <linux/slab.h>
|
|
|
#include <linux/spinlock.h>
|
|
|
#include <linux/jiffies.h>
|
|
@@ -26,6 +27,7 @@
|
|
|
|
|
|
#include "dss.h"
|
|
|
#include "dss_features.h"
|
|
|
+#include "dispc-compat.h"
|
|
|
|
|
|
/*
|
|
|
* We have 4 levels of cache for the dispc settings. First two are in SW and
|
|
@@ -70,7 +72,6 @@ struct ovl_priv_data {
|
|
|
bool shadow_extra_info_dirty;
|
|
|
|
|
|
bool enabled;
|
|
|
- enum omap_channel channel;
|
|
|
u32 fifo_low, fifo_high;
|
|
|
|
|
|
/*
|
|
@@ -105,6 +106,9 @@ struct mgr_priv_data {
|
|
|
|
|
|
struct omap_video_timings timings;
|
|
|
struct dss_lcd_mgr_config lcd_config;
|
|
|
+
|
|
|
+ void (*framedone_handler)(void *);
|
|
|
+ void *framedone_handler_data;
|
|
|
};
|
|
|
|
|
|
static struct {
|
|
@@ -132,7 +136,7 @@ static struct mgr_priv_data *get_mgr_priv(struct omap_overlay_manager *mgr)
|
|
|
return &dss_data.mgr_priv_data_array[mgr->id];
|
|
|
}
|
|
|
|
|
|
-void dss_apply_init(void)
|
|
|
+static void apply_init_priv(void)
|
|
|
{
|
|
|
const int num_ovls = dss_feat_get_num_ovls();
|
|
|
struct mgr_priv_data *mp;
|
|
@@ -414,11 +418,46 @@ static void wait_pending_extra_info_updates(void)
|
|
|
r = wait_for_completion_timeout(&extra_updated_completion, t);
|
|
|
if (r == 0)
|
|
|
DSSWARN("timeout in wait_pending_extra_info_updates\n");
|
|
|
- else if (r < 0)
|
|
|
- DSSERR("wait_pending_extra_info_updates failed: %d\n", r);
|
|
|
}
|
|
|
|
|
|
-int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr)
|
|
|
+static inline struct omap_dss_device *dss_ovl_get_device(struct omap_overlay *ovl)
|
|
|
+{
|
|
|
+ return ovl->manager ?
|
|
|
+ (ovl->manager->output ? ovl->manager->output->device : NULL) :
|
|
|
+ NULL;
|
|
|
+}
|
|
|
+
|
|
|
+static inline struct omap_dss_device *dss_mgr_get_device(struct omap_overlay_manager *mgr)
|
|
|
+{
|
|
|
+ return mgr->output ? mgr->output->device : NULL;
|
|
|
+}
|
|
|
+
|
|
|
+static int dss_mgr_wait_for_vsync(struct omap_overlay_manager *mgr)
|
|
|
+{
|
|
|
+ unsigned long timeout = msecs_to_jiffies(500);
|
|
|
+ struct omap_dss_device *dssdev = mgr->get_device(mgr);
|
|
|
+ u32 irq;
|
|
|
+ int r;
|
|
|
+
|
|
|
+ r = dispc_runtime_get();
|
|
|
+ if (r)
|
|
|
+ return r;
|
|
|
+
|
|
|
+ if (dssdev->type == OMAP_DISPLAY_TYPE_VENC)
|
|
|
+ irq = DISPC_IRQ_EVSYNC_ODD;
|
|
|
+ else if (dssdev->type == OMAP_DISPLAY_TYPE_HDMI)
|
|
|
+ irq = DISPC_IRQ_EVSYNC_EVEN;
|
|
|
+ else
|
|
|
+ irq = dispc_mgr_get_vsync_irq(mgr->id);
|
|
|
+
|
|
|
+ r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
|
|
|
+
|
|
|
+ dispc_runtime_put();
|
|
|
+
|
|
|
+ return r;
|
|
|
+}
|
|
|
+
|
|
|
+static int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr)
|
|
|
{
|
|
|
unsigned long timeout = msecs_to_jiffies(500);
|
|
|
struct mgr_priv_data *mp = get_mgr_priv(mgr);
|
|
@@ -488,7 +527,7 @@ int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr)
|
|
|
return r;
|
|
|
}
|
|
|
|
|
|
-int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl)
|
|
|
+static int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl)
|
|
|
{
|
|
|
unsigned long timeout = msecs_to_jiffies(500);
|
|
|
struct ovl_priv_data *op;
|
|
@@ -573,7 +612,7 @@ static void dss_ovl_write_regs(struct omap_overlay *ovl)
|
|
|
struct mgr_priv_data *mp;
|
|
|
int r;
|
|
|
|
|
|
- DSSDBGF("%d", ovl->id);
|
|
|
+ DSSDBG("writing ovl %d regs", ovl->id);
|
|
|
|
|
|
if (!op->enabled || !op->info_dirty)
|
|
|
return;
|
|
@@ -608,7 +647,7 @@ static void dss_ovl_write_regs_extra(struct omap_overlay *ovl)
|
|
|
struct ovl_priv_data *op = get_ovl_priv(ovl);
|
|
|
struct mgr_priv_data *mp;
|
|
|
|
|
|
- DSSDBGF("%d", ovl->id);
|
|
|
+ DSSDBG("writing ovl %d regs extra", ovl->id);
|
|
|
|
|
|
if (!op->extra_info_dirty)
|
|
|
return;
|
|
@@ -617,7 +656,6 @@ static void dss_ovl_write_regs_extra(struct omap_overlay *ovl)
|
|
|
* disabled */
|
|
|
|
|
|
dispc_ovl_enable(ovl->id, op->enabled);
|
|
|
- dispc_ovl_set_channel_out(ovl->id, op->channel);
|
|
|
dispc_ovl_set_fifo_threshold(ovl->id, op->fifo_low, op->fifo_high);
|
|
|
|
|
|
mp = get_mgr_priv(ovl->manager);
|
|
@@ -632,7 +670,7 @@ static void dss_mgr_write_regs(struct omap_overlay_manager *mgr)
|
|
|
struct mgr_priv_data *mp = get_mgr_priv(mgr);
|
|
|
struct omap_overlay *ovl;
|
|
|
|
|
|
- DSSDBGF("%d", mgr->id);
|
|
|
+ DSSDBG("writing mgr %d regs", mgr->id);
|
|
|
|
|
|
if (!mp->enabled)
|
|
|
return;
|
|
@@ -658,7 +696,7 @@ static void dss_mgr_write_regs_extra(struct omap_overlay_manager *mgr)
|
|
|
{
|
|
|
struct mgr_priv_data *mp = get_mgr_priv(mgr);
|
|
|
|
|
|
- DSSDBGF("%d", mgr->id);
|
|
|
+ DSSDBG("writing mgr %d regs extra", mgr->id);
|
|
|
|
|
|
if (!mp->extra_info_dirty)
|
|
|
return;
|
|
@@ -666,22 +704,8 @@ static void dss_mgr_write_regs_extra(struct omap_overlay_manager *mgr)
|
|
|
dispc_mgr_set_timings(mgr->id, &mp->timings);
|
|
|
|
|
|
/* lcd_config parameters */
|
|
|
- if (dss_mgr_is_lcd(mgr->id)) {
|
|
|
- dispc_mgr_set_io_pad_mode(mp->lcd_config.io_pad_mode);
|
|
|
-
|
|
|
- dispc_mgr_enable_stallmode(mgr->id, mp->lcd_config.stallmode);
|
|
|
- dispc_mgr_enable_fifohandcheck(mgr->id,
|
|
|
- mp->lcd_config.fifohandcheck);
|
|
|
-
|
|
|
- dispc_mgr_set_clock_div(mgr->id, &mp->lcd_config.clock_info);
|
|
|
-
|
|
|
- dispc_mgr_set_tft_data_lines(mgr->id,
|
|
|
- mp->lcd_config.video_port_width);
|
|
|
-
|
|
|
- dispc_lcd_enable_signal_polarity(mp->lcd_config.lcden_sig_polarity);
|
|
|
-
|
|
|
- dispc_mgr_set_lcd_type_tft(mgr->id);
|
|
|
- }
|
|
|
+ if (dss_mgr_is_lcd(mgr->id))
|
|
|
+ dispc_mgr_set_lcd_config(mgr->id, &mp->lcd_config);
|
|
|
|
|
|
mp->extra_info_dirty = false;
|
|
|
if (mp->updating)
|
|
@@ -761,7 +785,7 @@ static void mgr_clear_shadow_dirty(struct omap_overlay_manager *mgr)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-void dss_mgr_start_update(struct omap_overlay_manager *mgr)
|
|
|
+static void dss_mgr_start_update_compat(struct omap_overlay_manager *mgr)
|
|
|
{
|
|
|
struct mgr_priv_data *mp = get_mgr_priv(mgr);
|
|
|
unsigned long flags;
|
|
@@ -786,9 +810,7 @@ void dss_mgr_start_update(struct omap_overlay_manager *mgr)
|
|
|
if (!dss_data.irq_enabled && need_isr())
|
|
|
dss_register_vsync_isr();
|
|
|
|
|
|
- dispc_mgr_enable(mgr->id, true);
|
|
|
-
|
|
|
- mgr_clear_shadow_dirty(mgr);
|
|
|
+ dispc_mgr_enable_sync(mgr->id);
|
|
|
|
|
|
spin_unlock_irqrestore(&data_lock, flags);
|
|
|
}
|
|
@@ -845,7 +867,6 @@ static void dss_apply_irq_handler(void *data, u32 mask)
|
|
|
for (i = 0; i < num_mgrs; i++) {
|
|
|
struct omap_overlay_manager *mgr;
|
|
|
struct mgr_priv_data *mp;
|
|
|
- bool was_updating;
|
|
|
|
|
|
mgr = omap_dss_get_overlay_manager(i);
|
|
|
mp = get_mgr_priv(mgr);
|
|
@@ -853,7 +874,6 @@ static void dss_apply_irq_handler(void *data, u32 mask)
|
|
|
if (!mp->enabled)
|
|
|
continue;
|
|
|
|
|
|
- was_updating = mp->updating;
|
|
|
mp->updating = dispc_mgr_is_enabled(i);
|
|
|
|
|
|
if (!mgr_manual_update(mgr)) {
|
|
@@ -872,6 +892,21 @@ static void dss_apply_irq_handler(void *data, u32 mask)
|
|
|
if (!extra_updating)
|
|
|
complete_all(&extra_updated_completion);
|
|
|
|
|
|
+ /* call framedone handlers for manual update displays */
|
|
|
+ for (i = 0; i < num_mgrs; i++) {
|
|
|
+ struct omap_overlay_manager *mgr;
|
|
|
+ struct mgr_priv_data *mp;
|
|
|
+
|
|
|
+ mgr = omap_dss_get_overlay_manager(i);
|
|
|
+ mp = get_mgr_priv(mgr);
|
|
|
+
|
|
|
+ if (!mgr_manual_update(mgr) || !mp->framedone_handler)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ if (mask & dispc_mgr_get_framedone_irq(i))
|
|
|
+ mp->framedone_handler(mp->framedone_handler_data);
|
|
|
+ }
|
|
|
+
|
|
|
if (!need_isr())
|
|
|
dss_unregister_vsync_isr();
|
|
|
|
|
@@ -906,7 +941,7 @@ static void omap_dss_mgr_apply_mgr(struct omap_overlay_manager *mgr)
|
|
|
mp->info = mp->user_info;
|
|
|
}
|
|
|
|
|
|
-int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
|
|
|
+static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
|
|
|
{
|
|
|
unsigned long flags;
|
|
|
struct omap_overlay *ovl;
|
|
@@ -1005,7 +1040,7 @@ static void dss_setup_fifos(void)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-int dss_mgr_enable(struct omap_overlay_manager *mgr)
|
|
|
+static int dss_mgr_enable_compat(struct omap_overlay_manager *mgr)
|
|
|
{
|
|
|
struct mgr_priv_data *mp = get_mgr_priv(mgr);
|
|
|
unsigned long flags;
|
|
@@ -1035,10 +1070,13 @@ int dss_mgr_enable(struct omap_overlay_manager *mgr)
|
|
|
if (!mgr_manual_update(mgr))
|
|
|
mp->updating = true;
|
|
|
|
|
|
+ if (!dss_data.irq_enabled && need_isr())
|
|
|
+ dss_register_vsync_isr();
|
|
|
+
|
|
|
spin_unlock_irqrestore(&data_lock, flags);
|
|
|
|
|
|
if (!mgr_manual_update(mgr))
|
|
|
- dispc_mgr_enable(mgr->id, true);
|
|
|
+ dispc_mgr_enable_sync(mgr->id);
|
|
|
|
|
|
out:
|
|
|
mutex_unlock(&apply_lock);
|
|
@@ -1052,7 +1090,7 @@ err:
|
|
|
return r;
|
|
|
}
|
|
|
|
|
|
-void dss_mgr_disable(struct omap_overlay_manager *mgr)
|
|
|
+static void dss_mgr_disable_compat(struct omap_overlay_manager *mgr)
|
|
|
{
|
|
|
struct mgr_priv_data *mp = get_mgr_priv(mgr);
|
|
|
unsigned long flags;
|
|
@@ -1063,7 +1101,7 @@ void dss_mgr_disable(struct omap_overlay_manager *mgr)
|
|
|
goto out;
|
|
|
|
|
|
if (!mgr_manual_update(mgr))
|
|
|
- dispc_mgr_enable(mgr->id, false);
|
|
|
+ dispc_mgr_disable_sync(mgr->id);
|
|
|
|
|
|
spin_lock_irqsave(&data_lock, flags);
|
|
|
|
|
@@ -1076,7 +1114,7 @@ out:
|
|
|
mutex_unlock(&apply_lock);
|
|
|
}
|
|
|
|
|
|
-int dss_mgr_set_info(struct omap_overlay_manager *mgr,
|
|
|
+static int dss_mgr_set_info(struct omap_overlay_manager *mgr,
|
|
|
struct omap_overlay_manager_info *info)
|
|
|
{
|
|
|
struct mgr_priv_data *mp = get_mgr_priv(mgr);
|
|
@@ -1097,7 +1135,7 @@ int dss_mgr_set_info(struct omap_overlay_manager *mgr,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-void dss_mgr_get_info(struct omap_overlay_manager *mgr,
|
|
|
+static void dss_mgr_get_info(struct omap_overlay_manager *mgr,
|
|
|
struct omap_overlay_manager_info *info)
|
|
|
{
|
|
|
struct mgr_priv_data *mp = get_mgr_priv(mgr);
|
|
@@ -1110,7 +1148,7 @@ void dss_mgr_get_info(struct omap_overlay_manager *mgr,
|
|
|
spin_unlock_irqrestore(&data_lock, flags);
|
|
|
}
|
|
|
|
|
|
-int dss_mgr_set_output(struct omap_overlay_manager *mgr,
|
|
|
+static int dss_mgr_set_output(struct omap_overlay_manager *mgr,
|
|
|
struct omap_dss_output *output)
|
|
|
{
|
|
|
int r;
|
|
@@ -1142,7 +1180,7 @@ err:
|
|
|
return r;
|
|
|
}
|
|
|
|
|
|
-int dss_mgr_unset_output(struct omap_overlay_manager *mgr)
|
|
|
+static int dss_mgr_unset_output(struct omap_overlay_manager *mgr)
|
|
|
{
|
|
|
int r;
|
|
|
struct mgr_priv_data *mp = get_mgr_priv(mgr);
|
|
@@ -1189,7 +1227,7 @@ static void dss_apply_mgr_timings(struct omap_overlay_manager *mgr,
|
|
|
mp->extra_info_dirty = true;
|
|
|
}
|
|
|
|
|
|
-void dss_mgr_set_timings(struct omap_overlay_manager *mgr,
|
|
|
+static void dss_mgr_set_timings_compat(struct omap_overlay_manager *mgr,
|
|
|
const struct omap_video_timings *timings)
|
|
|
{
|
|
|
unsigned long flags;
|
|
@@ -1217,7 +1255,7 @@ static void dss_apply_mgr_lcd_config(struct omap_overlay_manager *mgr,
|
|
|
mp->extra_info_dirty = true;
|
|
|
}
|
|
|
|
|
|
-void dss_mgr_set_lcd_config(struct omap_overlay_manager *mgr,
|
|
|
+static void dss_mgr_set_lcd_config_compat(struct omap_overlay_manager *mgr,
|
|
|
const struct dss_lcd_mgr_config *config)
|
|
|
{
|
|
|
unsigned long flags;
|
|
@@ -1236,7 +1274,7 @@ out:
|
|
|
spin_unlock_irqrestore(&data_lock, flags);
|
|
|
}
|
|
|
|
|
|
-int dss_ovl_set_info(struct omap_overlay *ovl,
|
|
|
+static int dss_ovl_set_info(struct omap_overlay *ovl,
|
|
|
struct omap_overlay_info *info)
|
|
|
{
|
|
|
struct ovl_priv_data *op = get_ovl_priv(ovl);
|
|
@@ -1257,7 +1295,7 @@ int dss_ovl_set_info(struct omap_overlay *ovl,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-void dss_ovl_get_info(struct omap_overlay *ovl,
|
|
|
+static void dss_ovl_get_info(struct omap_overlay *ovl,
|
|
|
struct omap_overlay_info *info)
|
|
|
{
|
|
|
struct ovl_priv_data *op = get_ovl_priv(ovl);
|
|
@@ -1270,7 +1308,7 @@ void dss_ovl_get_info(struct omap_overlay *ovl,
|
|
|
spin_unlock_irqrestore(&data_lock, flags);
|
|
|
}
|
|
|
|
|
|
-int dss_ovl_set_manager(struct omap_overlay *ovl,
|
|
|
+static int dss_ovl_set_manager(struct omap_overlay *ovl,
|
|
|
struct omap_overlay_manager *mgr)
|
|
|
{
|
|
|
struct ovl_priv_data *op = get_ovl_priv(ovl);
|
|
@@ -1289,45 +1327,40 @@ int dss_ovl_set_manager(struct omap_overlay *ovl,
|
|
|
goto err;
|
|
|
}
|
|
|
|
|
|
+ r = dispc_runtime_get();
|
|
|
+ if (r)
|
|
|
+ goto err;
|
|
|
+
|
|
|
spin_lock_irqsave(&data_lock, flags);
|
|
|
|
|
|
if (op->enabled) {
|
|
|
spin_unlock_irqrestore(&data_lock, flags);
|
|
|
DSSERR("overlay has to be disabled to change the manager\n");
|
|
|
r = -EINVAL;
|
|
|
- goto err;
|
|
|
+ goto err1;
|
|
|
}
|
|
|
|
|
|
- op->channel = mgr->id;
|
|
|
- op->extra_info_dirty = true;
|
|
|
+ dispc_ovl_set_channel_out(ovl->id, mgr->id);
|
|
|
|
|
|
ovl->manager = mgr;
|
|
|
list_add_tail(&ovl->list, &mgr->overlays);
|
|
|
|
|
|
spin_unlock_irqrestore(&data_lock, flags);
|
|
|
|
|
|
- /* XXX: When there is an overlay on a DSI manual update display, and
|
|
|
- * the overlay is first disabled, then moved to tv, and enabled, we
|
|
|
- * seem to get SYNC_LOST_DIGIT error.
|
|
|
- *
|
|
|
- * Waiting doesn't seem to help, but updating the manual update display
|
|
|
- * after disabling the overlay seems to fix this. This hints that the
|
|
|
- * overlay is perhaps somehow tied to the LCD output until the output
|
|
|
- * is updated.
|
|
|
- *
|
|
|
- * Userspace workaround for this is to update the LCD after disabling
|
|
|
- * the overlay, but before moving the overlay to TV.
|
|
|
- */
|
|
|
+ dispc_runtime_put();
|
|
|
|
|
|
mutex_unlock(&apply_lock);
|
|
|
|
|
|
return 0;
|
|
|
+
|
|
|
+err1:
|
|
|
+ dispc_runtime_put();
|
|
|
err:
|
|
|
mutex_unlock(&apply_lock);
|
|
|
return r;
|
|
|
}
|
|
|
|
|
|
-int dss_ovl_unset_manager(struct omap_overlay *ovl)
|
|
|
+static int dss_ovl_unset_manager(struct omap_overlay *ovl)
|
|
|
{
|
|
|
struct ovl_priv_data *op = get_ovl_priv(ovl);
|
|
|
unsigned long flags;
|
|
@@ -1355,9 +1388,24 @@ int dss_ovl_unset_manager(struct omap_overlay *ovl)
|
|
|
/* wait for pending extra_info updates to ensure the ovl is disabled */
|
|
|
wait_pending_extra_info_updates();
|
|
|
|
|
|
+ /*
|
|
|
+ * 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.
|
|
|
+ */
|
|
|
spin_lock_irqsave(&data_lock, flags);
|
|
|
|
|
|
- op->channel = -1;
|
|
|
+ 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;
|
|
|
+ }
|
|
|
|
|
|
ovl->manager = NULL;
|
|
|
list_del(&ovl->list);
|
|
@@ -1372,7 +1420,7 @@ err:
|
|
|
return r;
|
|
|
}
|
|
|
|
|
|
-bool dss_ovl_is_enabled(struct omap_overlay *ovl)
|
|
|
+static bool dss_ovl_is_enabled(struct omap_overlay *ovl)
|
|
|
{
|
|
|
struct ovl_priv_data *op = get_ovl_priv(ovl);
|
|
|
unsigned long flags;
|
|
@@ -1387,7 +1435,7 @@ bool dss_ovl_is_enabled(struct omap_overlay *ovl)
|
|
|
return e;
|
|
|
}
|
|
|
|
|
|
-int dss_ovl_enable(struct omap_overlay *ovl)
|
|
|
+static int dss_ovl_enable(struct omap_overlay *ovl)
|
|
|
{
|
|
|
struct ovl_priv_data *op = get_ovl_priv(ovl);
|
|
|
unsigned long flags;
|
|
@@ -1437,7 +1485,7 @@ err1:
|
|
|
return r;
|
|
|
}
|
|
|
|
|
|
-int dss_ovl_disable(struct omap_overlay *ovl)
|
|
|
+static int dss_ovl_disable(struct omap_overlay *ovl)
|
|
|
{
|
|
|
struct ovl_priv_data *op = get_ovl_priv(ovl);
|
|
|
unsigned long flags;
|
|
@@ -1472,3 +1520,152 @@ err:
|
|
|
return r;
|
|
|
}
|
|
|
|
|
|
+static int dss_mgr_register_framedone_handler_compat(struct omap_overlay_manager *mgr,
|
|
|
+ void (*handler)(void *), void *data)
|
|
|
+{
|
|
|
+ struct mgr_priv_data *mp = get_mgr_priv(mgr);
|
|
|
+
|
|
|
+ if (mp->framedone_handler)
|
|
|
+ return -EBUSY;
|
|
|
+
|
|
|
+ mp->framedone_handler = handler;
|
|
|
+ mp->framedone_handler_data = data;
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static void dss_mgr_unregister_framedone_handler_compat(struct omap_overlay_manager *mgr,
|
|
|
+ void (*handler)(void *), void *data)
|
|
|
+{
|
|
|
+ struct mgr_priv_data *mp = get_mgr_priv(mgr);
|
|
|
+
|
|
|
+ WARN_ON(mp->framedone_handler != handler ||
|
|
|
+ mp->framedone_handler_data != data);
|
|
|
+
|
|
|
+ mp->framedone_handler = NULL;
|
|
|
+ mp->framedone_handler_data = NULL;
|
|
|
+}
|
|
|
+
|
|
|
+static const struct dss_mgr_ops apply_mgr_ops = {
|
|
|
+ .start_update = dss_mgr_start_update_compat,
|
|
|
+ .enable = dss_mgr_enable_compat,
|
|
|
+ .disable = dss_mgr_disable_compat,
|
|
|
+ .set_timings = dss_mgr_set_timings_compat,
|
|
|
+ .set_lcd_config = dss_mgr_set_lcd_config_compat,
|
|
|
+ .register_framedone_handler = dss_mgr_register_framedone_handler_compat,
|
|
|
+ .unregister_framedone_handler = dss_mgr_unregister_framedone_handler_compat,
|
|
|
+};
|
|
|
+
|
|
|
+static int compat_refcnt;
|
|
|
+static DEFINE_MUTEX(compat_init_lock);
|
|
|
+
|
|
|
+int omapdss_compat_init(void)
|
|
|
+{
|
|
|
+ struct platform_device *pdev = dss_get_core_pdev();
|
|
|
+ struct omap_dss_device *dssdev = NULL;
|
|
|
+ int i, r;
|
|
|
+
|
|
|
+ mutex_lock(&compat_init_lock);
|
|
|
+
|
|
|
+ if (compat_refcnt++ > 0)
|
|
|
+ goto out;
|
|
|
+
|
|
|
+ apply_init_priv();
|
|
|
+
|
|
|
+ dss_init_overlay_managers(pdev);
|
|
|
+ dss_init_overlays(pdev);
|
|
|
+
|
|
|
+ for (i = 0; i < omap_dss_get_num_overlay_managers(); i++) {
|
|
|
+ struct omap_overlay_manager *mgr;
|
|
|
+
|
|
|
+ mgr = omap_dss_get_overlay_manager(i);
|
|
|
+
|
|
|
+ mgr->set_output = &dss_mgr_set_output;
|
|
|
+ mgr->unset_output = &dss_mgr_unset_output;
|
|
|
+ mgr->apply = &omap_dss_mgr_apply;
|
|
|
+ mgr->set_manager_info = &dss_mgr_set_info;
|
|
|
+ mgr->get_manager_info = &dss_mgr_get_info;
|
|
|
+ mgr->wait_for_go = &dss_mgr_wait_for_go;
|
|
|
+ mgr->wait_for_vsync = &dss_mgr_wait_for_vsync;
|
|
|
+ mgr->get_device = &dss_mgr_get_device;
|
|
|
+ }
|
|
|
+
|
|
|
+ for (i = 0; i < omap_dss_get_num_overlays(); i++) {
|
|
|
+ struct omap_overlay *ovl = omap_dss_get_overlay(i);
|
|
|
+
|
|
|
+ ovl->is_enabled = &dss_ovl_is_enabled;
|
|
|
+ ovl->enable = &dss_ovl_enable;
|
|
|
+ ovl->disable = &dss_ovl_disable;
|
|
|
+ ovl->set_manager = &dss_ovl_set_manager;
|
|
|
+ ovl->unset_manager = &dss_ovl_unset_manager;
|
|
|
+ ovl->set_overlay_info = &dss_ovl_set_info;
|
|
|
+ ovl->get_overlay_info = &dss_ovl_get_info;
|
|
|
+ ovl->wait_for_go = &dss_mgr_wait_for_go_ovl;
|
|
|
+ ovl->get_device = &dss_ovl_get_device;
|
|
|
+ }
|
|
|
+
|
|
|
+ r = dss_install_mgr_ops(&apply_mgr_ops);
|
|
|
+ if (r)
|
|
|
+ goto err_mgr_ops;
|
|
|
+
|
|
|
+ for_each_dss_dev(dssdev) {
|
|
|
+ r = display_init_sysfs(pdev, dssdev);
|
|
|
+ /* XXX uninit sysfs files on error */
|
|
|
+ if (r)
|
|
|
+ goto err_disp_sysfs;
|
|
|
+ }
|
|
|
+
|
|
|
+ dispc_runtime_get();
|
|
|
+
|
|
|
+ r = dss_dispc_initialize_irq();
|
|
|
+ if (r)
|
|
|
+ goto err_init_irq;
|
|
|
+
|
|
|
+ dispc_runtime_put();
|
|
|
+
|
|
|
+out:
|
|
|
+ mutex_unlock(&compat_init_lock);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+
|
|
|
+err_init_irq:
|
|
|
+ dispc_runtime_put();
|
|
|
+
|
|
|
+err_disp_sysfs:
|
|
|
+ dss_uninstall_mgr_ops();
|
|
|
+
|
|
|
+err_mgr_ops:
|
|
|
+ dss_uninit_overlay_managers(pdev);
|
|
|
+ dss_uninit_overlays(pdev);
|
|
|
+
|
|
|
+ compat_refcnt--;
|
|
|
+
|
|
|
+ mutex_unlock(&compat_init_lock);
|
|
|
+
|
|
|
+ return r;
|
|
|
+}
|
|
|
+EXPORT_SYMBOL(omapdss_compat_init);
|
|
|
+
|
|
|
+void omapdss_compat_uninit(void)
|
|
|
+{
|
|
|
+ struct platform_device *pdev = dss_get_core_pdev();
|
|
|
+ struct omap_dss_device *dssdev = NULL;
|
|
|
+
|
|
|
+ mutex_lock(&compat_init_lock);
|
|
|
+
|
|
|
+ if (--compat_refcnt > 0)
|
|
|
+ goto out;
|
|
|
+
|
|
|
+ dss_dispc_uninitialize_irq();
|
|
|
+
|
|
|
+ for_each_dss_dev(dssdev)
|
|
|
+ display_uninit_sysfs(pdev, dssdev);
|
|
|
+
|
|
|
+ dss_uninstall_mgr_ops();
|
|
|
+
|
|
|
+ dss_uninit_overlay_managers(pdev);
|
|
|
+ dss_uninit_overlays(pdev);
|
|
|
+out:
|
|
|
+ mutex_unlock(&compat_init_lock);
|
|
|
+}
|
|
|
+EXPORT_SYMBOL(omapdss_compat_uninit);
|