Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d10ecc58 authored by Tomi Valkeinen's avatar Tomi Valkeinen
Browse files

Merge omapdss compat layer work

We have two separate, exclusive, users of omapdss: 1) omapfb + omap_vout and 2)
omapdrm. Because omapfb and omap_vout are independent drivers, we've built
layers in omapdss to manage the two simultaneous callers. These layers are not
needed for omapdrm, as omapdrm is the sole user of omapdss, and these layers in
fact only create trouble for omapdrm.

The simple option to improve omapdrm situation would be to copy the omapdss
code for omapdrm. We are trying to avoid this, as omapdss and the panel drivers
are quite a lot of code together, and most of the code would be used without
change.

Thus this series helps the situation by moving the omapdss code required by
omapfb + omap_vout to separate files, creating a distinct layer used only by
omapfb + omap_vout. We call this layer "compat layer". This compat layer then
uses the core omapdss driver to operate the hardware. omapdrm will use the core
omapdss directly, without any layers in between.

After this series, omapfb, omap_vout and omapdrm can all be compiled at the
same time. Obviously omapdrm and omapfb+omap_vout cannot be run at the same
time (the first one to start will "win"), so compiling them at the same time is
only sensible as modules for testing purposes. Normal users should only compile
one of those.

This series does not make omapdrm use the core omapdss API, that will happen in
a separate series for omapdrm.
parents 6b6f1edf a9ee9f08
Loading
Loading
Loading
Loading
+14 −3
Original line number Diff line number Diff line
@@ -2184,14 +2184,23 @@ static int __init omap_vout_probe(struct platform_device *pdev)
	struct omap_dss_device *def_display;
	struct omap2video_device *vid_dev = NULL;

	ret = omapdss_compat_init();
	if (ret) {
		dev_err(&pdev->dev, "failed to init dss\n");
		return ret;
	}

	if (pdev->num_resources == 0) {
		dev_err(&pdev->dev, "probed for an unknown device\n");
		return -ENODEV;
		ret = -ENODEV;
		goto err_dss_init;
	}

	vid_dev = kzalloc(sizeof(struct omap2video_device), GFP_KERNEL);
	if (vid_dev == NULL)
		return -ENOMEM;
	if (vid_dev == NULL) {
		ret = -ENOMEM;
		goto err_dss_init;
	}

	vid_dev->num_displays = 0;
	for_each_dss_dev(dssdev) {
@@ -2286,6 +2295,8 @@ probe_err1:
	}
probe_err0:
	kfree(vid_dev);
err_dss_init:
	omapdss_compat_uninit();
	return ret;
}

+11 −0
Original line number Diff line number Diff line
@@ -572,6 +572,14 @@ static int dev_load(struct drm_device *dev, unsigned long flags)

	dev->dev_private = priv;

	ret = omapdss_compat_init();
	if (ret) {
		dev_err(dev->dev, "coult not init omapdss\n");
		dev->dev_private = NULL;
		kfree(priv);
		return ret;
	}

	priv->wq = alloc_ordered_workqueue("omapdrm", 0);

	INIT_LIST_HEAD(&priv->obj_list);
@@ -583,6 +591,7 @@ static int dev_load(struct drm_device *dev, unsigned long flags)
		dev_err(dev->dev, "omap_modeset_init failed: ret=%d\n", ret);
		dev->dev_private = NULL;
		kfree(priv);
		omapdss_compat_uninit();
		return ret;
	}

@@ -618,6 +627,8 @@ static int dev_unload(struct drm_device *dev)
	flush_workqueue(priv->wq);
	destroy_workqueue(priv->wq);

	omapdss_compat_uninit();

	kfree(dev->dev_private);
	dev->dev_private = NULL;

+5 −2
Original line number Diff line number Diff line
obj-$(CONFIG_OMAP2_DSS) += omapdss.o
# Core DSS files
omapdss-y := core.o dss.o dss_features.o dispc.o dispc_coefs.o display.o \
	manager.o manager-sysfs.o overlay.o overlay-sysfs.o output.o apply.o \
	display-sysfs.o
	output.o
# DSS compat layer files
omapdss-y += manager.o manager-sysfs.o overlay.o overlay-sysfs.o apply.o \
	dispc-compat.o display-sysfs.o
omapdss-$(CONFIG_OMAP2_DSS_DPI) += dpi.o
omapdss-$(CONFIG_OMAP2_DSS_RFBI) += rfbi.o
omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o venc_panel.o
+226 −20
Original line number Diff line number Diff line
@@ -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
@@ -104,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 {
@@ -131,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;
@@ -415,7 +420,44 @@ static void wait_pending_extra_info_updates(void)
		DSSWARN("timeout in wait_pending_extra_info_updates\n");
}

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);
@@ -485,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;
@@ -743,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;
@@ -850,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();

@@ -884,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;
@@ -983,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;
@@ -1033,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;
@@ -1057,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);
@@ -1078,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);
@@ -1091,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;
@@ -1123,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);
@@ -1170,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;
@@ -1198,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;
@@ -1217,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);
@@ -1238,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);
@@ -1251,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);
@@ -1303,7 +1360,7 @@ err:
	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;
@@ -1363,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;
@@ -1378,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;
@@ -1428,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;
@@ -1463,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);
+0 −15
Original line number Diff line number Diff line
@@ -232,11 +232,6 @@ static int __init omap_dss_probe(struct platform_device *pdev)

	dss_features_init(omapdss_get_version());

	dss_apply_init();

	dss_init_overlay_managers(pdev);
	dss_init_overlays(pdev);

	r = dss_initialize_debugfs();
	if (r)
		goto err_debugfs;
@@ -261,9 +256,6 @@ static int omap_dss_remove(struct platform_device *pdev)

	dss_uninitialize_debugfs();

	dss_uninit_overlays(pdev);
	dss_uninit_overlay_managers(pdev);

	return 0;
}

@@ -351,15 +343,10 @@ static int dss_driver_probe(struct device *dev)
				dev_name(dev), dssdev->driver_name,
				dssdrv->driver.name);

	r = dss_init_device(core.pdev, dssdev);
	if (r)
		return r;

	r = dssdrv->probe(dssdev);

	if (r) {
		DSSERR("driver probe failed: %d\n", r);
		dss_uninit_device(core.pdev, dssdev);
		return r;
	}

@@ -380,8 +367,6 @@ static int dss_driver_remove(struct device *dev)

	dssdrv->remove(dssdev);

	dss_uninit_device(core.pdev, dssdev);

	dssdev->driver = NULL;

	return 0;
Loading