* [PATCH] backlight: Add of_find_backlight_by_node() function
From: Thierry Reding @ 2012-11-07 22:08 UTC (permalink / raw)
To: Florian Tobias Schandinat
Cc: linux-fbdev-u79uwXL29TY76Z2rM5mHXA,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
This function finds the struct backlight_device for a given device tree
node. A dummy function is provided so that it safely compiles out if OF
support is disabled.
Signed-off-by: Thierry Reding <thierry.reding@avionic-design.de>
---
drivers/video/backlight/backlight.c | 17 +++++++++++++++++
include/linux/backlight.h | 10 ++++++++++
2 files changed, 27 insertions(+)
diff --git a/drivers/video/backlight/backlight.c b/drivers/video/backlight/backlight.c
index 297db2f..0d1ed4f 100644
--- a/drivers/video/backlight/backlight.c
+++ b/drivers/video/backlight/backlight.c
@@ -370,6 +370,23 @@ void backlight_device_unregister(struct backlight_device *bd)
}
EXPORT_SYMBOL(backlight_device_unregister);
+#if IS_ENABLED(CONFIG_OF)
+static int of_parent_match(struct device *dev, void *data)
+{
+ return dev->parent && dev->parent->of_node = data;
+}
+
+struct backlight_device *of_find_backlight_by_node(struct device_node *node)
+{
+ struct device *dev;
+
+ dev = class_find_device(backlight_class, NULL, node, of_parent_match);
+
+ return dev ? to_backlight_device(dev) : NULL;
+}
+EXPORT_SYMBOL(of_find_backlight_by_node);
+#endif
+
static void __exit backlight_class_exit(void)
{
class_destroy(backlight_class);
diff --git a/include/linux/backlight.h b/include/linux/backlight.h
index 5ffc6dd..11840e9 100644
--- a/include/linux/backlight.h
+++ b/include/linux/backlight.h
@@ -134,4 +134,14 @@ struct generic_bl_info {
void (*kick_battery)(void);
};
+#if IS_ENABLED(CONFIG_OF)
+struct backlight_device *of_find_backlight_by_node(struct device_node *node);
+#else
+static inline struct backlight_device *
+of_find_backlight_by_node(struct device_node *node)
+{
+ return NULL;
+}
+#endif
+
#endif
--
1.8.0
^ permalink raw reply related
* Re: i.MX 257 ARM-CPU: framebuffer error "division by zero"
From: Stefan Koch @ 2012-11-07 20:33 UTC (permalink / raw)
To: linux-fbdev
In-Reply-To: <509A6964.5090305@gmail.com>
The error snipped in first post is not from the beginning it's from the end.
This is from the beginning.
And there is named "imxfb", too.
For this error "video=imxfb:SVGA-16@60" is set in kernel command line:
The full messages are here: http://paste.debian.net/hidden/3d16ba27/
[<80246f78>] (register_framebuffer+0x17c/0x230) from [<80586ab8>]
(imxfb_probe+0x3c8/0x5a8)
[<80586ab8>] (imxfb_probe+0x3c8/0x5a8) from [<80286ba8>]
(platform_drv_probe+0x14/0x18)
[<80286ba8>] (platform_drv_probe+0x14/0x18) from [<802858b0>]
(driver_probe_device+0x80/0x20c)
[<802858b0>] (driver_probe_device+0x80/0x20c) from [<80285ac8>]
(__driver_attach+0x8c/0x90)
[<80285ac8>] (__driver_attach+0x8c/0x90) from [<80284230>]
(bus_for_each_dev+0x64/0x8c)
[<80284230>] (bus_for_each_dev+0x64/0x8c) from [<802849b0>]
(bus_add_driver+0xa4/0x230)
[<802849b0>] (bus_add_driver+0xa4/0x230) from [<80286098>]
(driver_register+0x78/0x140)
[<80286098>] (driver_register+0x78/0x140) from [<80286ef4>]
(platform_driver_probe+0x18/0x9c)
[<80286ef4>] (platform_driver_probe+0x18/0x9c) from [<805866d8>]
(imxfb_init+0x88/0xa0)
[<805866d8>] (imxfb_init+0x88/0xa0) from [<800087e4>]
(do_one_initcall+0x30/0x178)
[<800087e4>] (do_one_initcall+0x30/0x178) from [<80576310>]
(kernel_init+0xe4/0x1b0)
[<80576310>] (kernel_init+0xe4/0x1b0) from [<80015268>]
(kernel_thread_exit+0x0/0x8)
Division by zero in kernel.
[<80019ba4>] (unwind_backtrace+0x0/0xf4) from [<8022accc>] (Ldiv0+0x8/0x10)
[<8022accc>] (Ldiv0+0x8/0x10) from [<8022ac9c>] (__aeabi_uidivmod+0x8/0x18)
[<8022ac9c>] (__aeabi_uidivmod+0x8/0x18) from [<80254198>]
(cfb_imageblit+0x1fc/0x4b0)
[<80254198>] (cfb_imageblit+0x1fc/0x4b0) from [<80251964>]
(bit_putcs+0x2e4/0x420)
[<80251964>] (bit_putcs+0x2e4/0x420) from [<8024bde0>]
(fbcon_putcs+0xec/0x128)
[<8024bde0>] (fbcon_putcs+0xec/0x128) from [<802741f8>]
(do_update_region+0x108/0x18c)
[<802741f8>] (do_update_region+0x108/0x18c) from [<80275970>]
(update_region+0x70/0x88)
[<80275970>] (update_region+0x70/0x88) from [<8024dd08>]
(fbcon_switch+0x468/0x4bc)
[<8024dd08>] (fbcon_switch+0x468/0x4bc) from [<80276c84>]
(redraw_screen+0x15c/0x278)
[<80276c84>] (redraw_screen+0x15c/0x278) from [<80279e90>]
(take_over_console+0x2cc/0x37c)
[<80279e90>] (take_over_console+0x2cc/0x37c) from [<8024cacc>]
(fbcon_takeover+0x70/0xd4)
[<8024cacc>] (fbcon_takeover+0x70/0xd4) from [<8042541c>]
(notifier_call_chain+0x44/0x84)
[<8042541c>] (notifier_call_chain+0x44/0x84) from [<8004a2a0>]
(__blocking_notifier_call_chain+0x4c/0x64)
[<8004a2a0>] (__blocking_notifier_call_chain+0x4c/0x64) from
[<8004a2d0>] (blocking_notifier_call_chain+0x18/0x20)
[<8004a2d0>] (blocking_notifier_call_chain+0x18/0x20) from [<80246f78>]
(register_framebuffer+0x17c/0x230)
[<80246f78>] (register_framebuffer+0x17c/0x230) from [<80586ab8>]
(imxfb_probe+0x3c8/0x5a8)
[<80586ab8>] (imxfb_probe+0x3c8/0x5a8) from [<80286ba8>]
(platform_drv_probe+0x14/0x18)
[<80286ba8>] (platform_drv_probe+0x14/0x18) from [<802858b0>]
(driver_probe_device+0x80/0x20c)
[<802858b0>] (driver_probe_device+0x80/0x20c) from [<80285ac8>]
(__driver_attach+0x8c/0x90)
[<80285ac8>] (__driver_attach+0x8c/0x90) from [<80284230>]
(bus_for_each_dev+0x64/0x8c)
[<80284230>] (bus_for_each_dev+0x64/0x8c) from [<802849b0>]
(bus_add_driver+0xa4/0x230)
[<802849b0>] (bus_add_driver+0xa4/0x230) from [<80286098>]
(driver_register+0x78/0x140)
[<80286098>] (driver_register+0x78/0x140) from [<80286ef4>]
(platform_driver_probe+0x18/0x9c)
[<80286ef4>] (platform_driver_probe+0x18/0x9c) from [<805866d8>]
(imxfb_init+0x88/0xa0)
[<805866d8>] (imxfb_init+0x88/0xa0) from [<800087e4>]
(do_one_initcall+0x30/0x178)
[<800087e4>] (do_one_initcall+0x30/0x178) from [<80576310>]
(kernel_init+0xe4/0x1b0)
[<80576310>] (kernel_init+0xe4/0x1b0) from [<80015268>]
(kernel_thread_exit+0x0/0x8)
Without this setting the CPU does stop working (for JTAG debugger it has
the same effect as board is in power off state):
177772 bytes written at address 0x811ffc00
downloaded 177772 bytes in 19.548666s (8.881 KiB/s)
WARNING: unknown debug reason: 0xf
ThumbEE -- incomplete support
target state: halted
target halted in ThumbEE state due to debug-request, current mode: System
cpsr: 0xffffffff pc: 0xfffffff9
MMU: enabled, D-Cache: enabled, I-Cache: enabled
^ permalink raw reply
* Re: [PATCH 12/12] OMAPDSS: DPI: always use DSI PLL if available
From: Rob Clark @ 2012-11-07 19:18 UTC (permalink / raw)
To: Tomi Valkeinen
Cc: Tomi Valkeinen, Archit Taneja, linux-omap, linux-fbdev, dri-devel
In-Reply-To: <509A7A95.804@ti.com>
On Wed, Nov 7, 2012 at 9:13 AM, Tomi Valkeinen <tomi.valkeinen@ti.com> wrote:
> On 2012-11-07 16:32, Rob Clark wrote:
>> On Wed, Nov 7, 2012 at 4:01 AM, Tomi Valkeinen <tomi.valkeinen@ti.com> wrote:
>
>>> Hotplugging is not some abstract future scenario, we already have
>>> hardware that could use it. For example, omap3 SDP board has a
>>> switchable output to DVI or LCD panel. In this case we know what the two
>>> options are, but the disabled component is still effectually removed
>>> from the system, and plugged back in when it's enabled.
>>
>> I would look at this as two different connectors which can not be used
>> at the same time. You have this scenario with desktop graphics cards.
>
> Yes, that's an option with fixed amount of display devices. But doesn't
> work for capes.
Only if capes are hotpluggable.. otherwise probe what cape(s?) are
present at boot time (is this possible to detect a cape from sw?), and
create the associated connector(s).
Anyways, I think we are stretching a bit hard for use cases for
hot-pluggable panels.. I just prefer to ignore hotplug for now and
come back to it when there is a more legitimate use-case.
>>> Hotplug is not a high priority item, but I do wish we get it supported
>>> in common panel framework. Then it's at least possible to extend drm in
>>> the future to support it.
>>>
>>>
>>>
>>> Anyway, this makes me wonder... omapdrm currently maps the elements of
>>> the whole video pipeline to drm elements (encoder, connector, etc).
>>> Would it make more sense to just map the DISPC to these drm elements?
>>> Connector would then be the output from DISPC.
>>
>> I think:
>>
>> plane->overlay
>> crtc->manager
>>
>> is pretty clear. And really
>>
>> encoder->output
>>
>> should be the way it is.. on the branch w/ omapdss/omapdrm kms
>
> I'm not so sure. The output (dpi/dsi/hdmi...) is the second step in our
> chain. The primary "output" is in the DISPC module, the overlay manager.
> That's where the timings, pixel clock, etc. are programmed. The second
> step, our output, is really a converter IP. It receives the primary
> output, converts it and outputs something else. Just like an external
> converter chip would do.
>
the timings, pixel clock, vblank/framedone irqs, that all maps to crtc.
encoder = converter, so I think this fits. "An encoder takes pixel
data from a CRTC and converts it to a format suitable for any attached
connectors" (from drm docbook)
> And the output can be quite a bit anything. For example, with DBI or DSI
> command mode outputs we don't have any of the conventional video
> timings. It doesn't make sense to program, say, video blanking periods
> to those outputs. But even with DBI and DSI we do have video blanking
> periods in the DISPC's output, the ovl mgr.
the encoder has mode_fixup() which can alter the timings that end up
getting set, which might be a way to account for this. I guess really
it should be the panel driver that is telling the encoder what
adjusted timings to give to the crtc.. so the panel driver doesn't
quite map to connector.
> Of course, at the end of the chain we have a panel that uses normal
> video timings (well, most likely but not necessarily), and so we could
> program those timings at the end of the chain, in the block before the
> panel. But even then the encoder doesn't really map to the DSS's output
> block, as the DSS's output block may not have the conventional timings
> (like DBI), or they may be something totally different than what we get
> in the end of the chain to the panel.
>
> So I think mapping encoder to output will not work with multiple display
> blocks in a chain. Thus I'd see the encoder would better match the
> DISPC's output, or alternatively perhaps the block which is just before
> the panel (whatever that is, sometimes it can be OMAP's DSI/HDMI/etc).
> However, the latter may be a bit strange as the block could be an
> external component, possibly hotpluggable.
>
>> re-write, this is how it is for plane/crtc, except for now:
>>
>> encoder+connector->dssdev
>>
>> Basically the encoder is doing the "control" stuff (power on/off, set
>> timings, etc), and the connector is only doing non control stuff
>> (detect, reading edid, etc).
>>
>> But I think this will probably change a bit as CFP comes into the
>> picture. Currently the drm connector is somewhat a "passive" element,
>> but I think this will have to change a bit w/ CFP.
>>
>>> This would map the drm elements to the static hardware blocks, and the
>>> meaning of those blocks would be quite similar to what they are in the
>>> desktop world (I guess).
>>>
>>> The panel driver, the external chips, and the DSS internal output blocks
>>> (dsi, dpi, ...) would be handled separately from those drm elements. The
>>> DSS internal blocks are static, of course, but they can be effectively
>>> considered the same way as external chips.
>>
>> I think dsi/dpi/etc map to encoder. The big question is where the
>> panel's fit. But to userspace somehow this should look like
>> connectors. I think:
>>
>> encoder->output
>> connector->panel
>>
>> could work.. although connector is less passive than KMS currently
>> assumes. And "panel" could really be a whole chain in the case of
>> bridge chips, etc. I don't know, maybe there are better ways. But I
>> think userspace really just wants to know "which monitor" which is
>> basically connector.
>
> Hmm yes. Well, even if we map encoder and connector to the ovl manager,
> the userspace could see which monitor there is. Obviously we need to
> make changes for that to work, but as a model it feels a lot more
> natural to me than using output and panel for encoder and connector.
well, what we call 'ovl mgr' is really where the (vblank) interrupt
generation is. This really should be the crtc. I tried it
differently initially, and it wasn't really working out.
> Perhaps it's wrong to say "map connector to ovl mgr". It would be more
> like "this connector observes the chain connected to this ovl mgr", even
> though the connector wouldn't observe any block in the chain directly.
> Just observing the plug in/out status, etc.
>
> But I think encoder really maps quite well directly to the output side
> of overlay manager.
>
>>> The omapdrm driver needs of course to access those separate elements
>>> also, but that shouldn't be a problem. If omapdrm needs to call a
>>> function in the panel driver, all it needs to do is go through the chain
>>> to find the panel. Well, except if one output connected two two panels
>>> via a bridge chip...
>>
>> yeah, that is a really ugly case in our hw since it is quite
>> non-transparent (ie. implications about use of planes, etc).
>
> Not really in this case. You're perhaps thinking about connecting two
> outputs to a single panel. Which is problematic also.
yes, sorry, I read that backwards..
> We don't have in sights a board that splits one output to two panels, so
> I think we should just ignore that for now. But two outputs for one
> panel is on the table.
>
>>> And if drm is at some point extended to support panel drivers, or chains
>>> of external display entities, it would be easier to add that support.
>>>
>>> What would it require the manage the elements like that? Would it help?
>>> It sounds to me that this would simplify the model.
>>
>> I'm not really entirely sure.. other than at least other drivers
>> supporting CFP will have the same requirements ;-)
>>
>> I guess the two best options are either bury some sort of chain of
>> panel drivers in the connector, or introduce some internal elements in
>> DRM which are not necessarily visible to userspace. (Or at least
>> userspace should have the option to ignore it for backwards
>> compatibility. For atomic pageflip/modeset, the converting of
>> everything to properties makes it easier to think about exposing new
>> KMS mode object types to userspace.)
>
> Yes, I don't think we should or need to expose these new elements to
> userspace, at least in the first place.
It *might* be useful someday, if there are ever any settings for a
bridge chip, etc, which we'd want to expose to userspace as
properties.. but I think we can come back to that later.
BR,
-R
> Tomi
>
>
^ permalink raw reply
* Re: tty, vt: lockdep warnings
From: Alan Cox @ 2012-11-07 16:56 UTC (permalink / raw)
To: Bjørn Mork
Cc: Sasha Levin, Dave Jones, Hugh Dickins, Sasha Levin, Daniel Vetter,
Greg Kroah-Hartman, Jiri Slaby, linux-kernel, linux-fbdev,
florianSchandinat
In-Reply-To: <87625h9yoe.fsf@nemi.mork.no>
On Wed, 07 Nov 2012 17:15:45 +0100
Bjørn Mork <bjorn@mork.no> wrote:
> Alan Cox <alan@lxorguk.ukuu.org.uk> writes:
>
> > +
> > +static int bind_con_driver(const struct consw *csw, int first, int last,
> > + int deflt)
> > +{
> > + int ret;
> > +
> > + console_unlock();
>
> console_lock() maybe...
Thanks I'll fix that path in v3
^ permalink raw reply
* Re: tty, vt: lockdep warnings
From: Bjørn Mork @ 2012-11-07 16:15 UTC (permalink / raw)
To: Alan Cox
Cc: Sasha Levin, Dave Jones, Hugh Dickins, Sasha Levin, Daniel Vetter,
Greg Kroah-Hartman, Jiri Slaby, linux-kernel, linux-fbdev,
florianSchandinat
In-Reply-To: <20121107160232.18e83ee9@pyramind.ukuu.org.uk>
Alan Cox <alan@lxorguk.ukuu.org.uk> writes:
> +
> +static int bind_con_driver(const struct consw *csw, int first, int last,
> + int deflt)
> +{
> + int ret;
> +
> + console_unlock();
console_lock() maybe...
> + ret = do_bind_con_driver(csw, first, last, deflt);
> + console_unlock();
> + return ret;
> +}
> +
Bjørn
^ permalink raw reply
* Re: tty, vt: lockdep warnings
From: Alan Cox @ 2012-11-07 15:57 UTC (permalink / raw)
To: Sasha Levin
Cc: Dave Jones, Hugh Dickins, Sasha Levin, Daniel Vetter,
Greg Kroah-Hartman, Jiri Slaby, linux-kernel, linux-fbdev,
florianSchandinat
In-Reply-To: <509A665C.3030603@gmail.com>
On Wed, 07 Nov 2012 08:47:08 -0500
Sasha Levin <levinsasha928@gmail.com> wrote:
> On 11/06/2012 12:38 PM, Alan Cox wrote:
> >> > The root
> >> > cause is loading two different framebuffers with one taking over from
> >> > another - that should be an obscure corner case and once the fuzz testing
> >> > can avoid.
> >> >
> >> > I had a semi-informed poke at this and came up with a possible patch (not very tested)
> >>
> >> If this fixes the real problems we've been seeing, I'll dance a jig.
> >
> > Youtube...
>
> +1
>
> > At this point my bigger concern is that it'll just make something else
> > warn instead. The underlying problem is that fbcon layer implements a
> > single threaded notifier whose locking semantics are at best random. It's
> > not calld with a specific set of locks each time. Possibly it sohuld be
> > two notifiers (one for fb stuff, one for console layer stuff) but the
> > entire layer is horrible. I live in home the KMS guys will rip out the
> > useful bits and build a straight kms fb layer with refcounting and the
> > like 8)
> >
> > Testing certainly needed and if it's still blowing up then hopefully
> > further traces will help fix up the other cases we don't know about.
>
> So the good news are that the original lockdep splat I've reported is gone.
>
> The semi-bad news are that there's a new one. It happens less frequently
> but I assume it's not a new splat either, but was well hidden behind the
> other splat.
Doesn't look too bad (fingers crossed)
try
commit 8f965b0816d98ed535fdfccc3e50d84818e9c43b
Author: Alan Cox <alan@linux.intel.com>
Date: Wed Nov 7 15:48:48 2012 +0000
fb: Rework locking to fix lock ordering on takeover
Adjust the console layer to allow a take over call where the caller already
holds the locks. Make the fb layer lock in order.
This s partly a band aid, the fb layer is terminally confused about the
locking rules it uses for its notifiers it seems.
Signed-off-by: Alan Cox <alan@linux.intel.com>
diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index f87d7e8..ea57f27 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -2984,7 +2984,7 @@ int __init vty_init(const struct file_operations *console_fops)
static struct class *vtconsole_class;
-static int bind_con_driver(const struct consw *csw, int first, int last,
+static int do_bind_con_driver(const struct consw *csw, int first, int last,
int deflt)
{
struct module *owner = csw->owner;
@@ -2995,7 +2995,7 @@ static int bind_con_driver(const struct consw *csw, int first, int last,
if (!try_module_get(owner))
return -ENODEV;
- console_lock();
+ WARN_CONSOLE_UNLOCKED();
/* check if driver is registered */
for (i = 0; i < MAX_NR_CON_DRIVER; i++) {
@@ -3080,11 +3080,22 @@ static int bind_con_driver(const struct consw *csw, int first, int last,
retval = 0;
err:
- console_unlock();
module_put(owner);
return retval;
};
+
+static int bind_con_driver(const struct consw *csw, int first, int last,
+ int deflt)
+{
+ int ret;
+
+ console_unlock();
+ ret = do_bind_con_driver(csw, first, last, deflt);
+ console_unlock();
+ return ret;
+}
+
#ifdef CONFIG_VT_HW_CONSOLE_BINDING
static int con_is_graphics(const struct consw *csw, int first, int last)
{
@@ -3196,9 +3207,9 @@ int unbind_con_driver(const struct consw *csw, int first, int last, int deflt)
if (!con_is_bound(csw))
con_driver->flag &= ~CON_DRIVER_FLAG_INIT;
- console_unlock();
/* ignore return value, binding should not fail */
- bind_con_driver(defcsw, first, last, deflt);
+ do_bind_con_driver(defcsw, first, last, deflt);
+ console_unlock();
err:
module_put(owner);
return retval;
@@ -3489,28 +3500,18 @@ int con_debug_leave(void)
}
EXPORT_SYMBOL_GPL(con_debug_leave);
-/**
- * register_con_driver - register console driver to console layer
- * @csw: console driver
- * @first: the first console to take over, minimum value is 0
- * @last: the last console to take over, maximum value is MAX_NR_CONSOLES -1
- *
- * DESCRIPTION: This function registers a console driver which can later
- * bind to a range of consoles specified by @first and @last. It will
- * also initialize the console driver by calling con_startup().
- */
-int register_con_driver(const struct consw *csw, int first, int last)
+static int do_register_con_driver(const struct consw *csw, int first, int last)
{
struct module *owner = csw->owner;
struct con_driver *con_driver;
const char *desc;
int i, retval = 0;
+ WARN_CONSOLE_UNLOCKED();
+
if (!try_module_get(owner))
return -ENODEV;
- console_lock();
-
for (i = 0; i < MAX_NR_CON_DRIVER; i++) {
con_driver = ®istered_con_driver[i];
@@ -3563,10 +3564,29 @@ int register_con_driver(const struct consw *csw, int first, int last)
}
err:
- console_unlock();
module_put(owner);
return retval;
}
+
+/**
+ * register_con_driver - register console driver to console layer
+ * @csw: console driver
+ * @first: the first console to take over, minimum value is 0
+ * @last: the last console to take over, maximum value is MAX_NR_CONSOLES -1
+ *
+ * DESCRIPTION: This function registers a console driver which can later
+ * bind to a range of consoles specified by @first and @last. It will
+ * also initialize the console driver by calling con_startup().
+ */
+int register_con_driver(const struct consw *csw, int first, int last)
+{
+ int retval;
+
+ console_lock();
+ retval = do_register_con_driver(csw, first, last);
+ console_unlock();
+ return retval;
+}
EXPORT_SYMBOL(register_con_driver);
/**
@@ -3622,6 +3642,29 @@ EXPORT_SYMBOL(unregister_con_driver);
*
* take_over_console is basically a register followed by unbind
*/
+int do_take_over_console(const struct consw *csw, int first, int last, int deflt)
+{
+ int err;
+
+ err = do_register_con_driver(csw, first, last);
+ /* if we get an busy error we still want to bind the console driver
+ * and return success, as we may have unbound the console driver
+ * but not unregistered it.
+ */
+ if (err = -EBUSY)
+ err = 0;
+ if (!err)
+ do_bind_con_driver(csw, first, last, deflt);
+
+ return err;
+}
+/*
+ * If we support more console drivers, this function is used
+ * when a driver wants to take over some existing consoles
+ * and become default driver for newly opened ones.
+ *
+ * take_over_console is basically a register followed by unbind
+ */
int take_over_console(const struct consw *csw, int first, int last, int deflt)
{
int err;
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
index fdefa8f..c75f8ce 100644
--- a/drivers/video/console/fbcon.c
+++ b/drivers/video/console/fbcon.c
@@ -529,6 +529,34 @@ static int search_for_mapped_con(void)
return retval;
}
+static int do_fbcon_takeover(int show_logo)
+{
+ int err, i;
+
+ if (!num_registered_fb)
+ return -ENODEV;
+
+ if (!show_logo)
+ logo_shown = FBCON_LOGO_DONTSHOW;
+
+ for (i = first_fb_vc; i <= last_fb_vc; i++)
+ con2fb_map[i] = info_idx;
+
+ err = do_take_over_console(&fb_con, first_fb_vc, last_fb_vc,
+ fbcon_is_default);
+
+ if (err) {
+ for (i = first_fb_vc; i <= last_fb_vc; i++) {
+ con2fb_map[i] = -1;
+ }
+ info_idx = -1;
+ } else {
+ fbcon_has_console_bind = 1;
+ }
+
+ return err;
+}
+
static int fbcon_takeover(int show_logo)
{
int err, i;
@@ -3115,7 +3143,7 @@ static int fbcon_fb_registered(struct fb_info *info)
}
if (info_idx != -1)
- ret = fbcon_takeover(1);
+ ret = do_fbcon_takeover(1);
} else {
for (i = first_fb_vc; i <= last_fb_vc; i++) {
if (con2fb_map_boot[i] = idx)
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index 3ff0105..564ebe9 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -1650,7 +1650,9 @@ static int do_register_framebuffer(struct fb_info *fb_info)
event.info = fb_info;
if (!lock_fb_info(fb_info))
return -ENODEV;
+ console_lock();
fb_notifier_call_chain(FB_EVENT_FB_REGISTERED, &event);
+ console_unlock();
unlock_fb_info(fb_info);
return 0;
}
@@ -1853,11 +1855,8 @@ int fb_new_modelist(struct fb_info *info)
err = 1;
if (!list_empty(&info->modelist)) {
- if (!lock_fb_info(info))
- return -ENODEV;
event.info = info;
err = fb_notifier_call_chain(FB_EVENT_NEW_MODELIST, &event);
- unlock_fb_info(info);
}
return err;
diff --git a/drivers/video/fbsysfs.c b/drivers/video/fbsysfs.c
index a55e366..ef476b0 100644
--- a/drivers/video/fbsysfs.c
+++ b/drivers/video/fbsysfs.c
@@ -177,6 +177,8 @@ static ssize_t store_modes(struct device *device,
if (i * sizeof(struct fb_videomode) != count)
return -EINVAL;
+ if (!lock_fb_info(fb_info))
+ return -ENODEV;
console_lock();
list_splice(&fb_info->modelist, &old_list);
fb_videomode_to_modelist((const struct fb_videomode *)buf, i,
@@ -188,6 +190,7 @@ static ssize_t store_modes(struct device *device,
fb_destroy_modelist(&old_list);
console_unlock();
+ unlock_fb_info(fb_info);
return 0;
}
diff --git a/include/linux/console.h b/include/linux/console.h
index dedb082..4ef4307 100644
--- a/include/linux/console.h
+++ b/include/linux/console.h
@@ -78,6 +78,7 @@ int con_is_bound(const struct consw *csw);
int register_con_driver(const struct consw *csw, int first, int last);
int unregister_con_driver(const struct consw *csw);
int take_over_console(const struct consw *sw, int first, int last, int deflt);
+int do_take_over_console(const struct consw *sw, int first, int last, int deflt);
void give_up_console(const struct consw *sw);
#ifdef CONFIG_HW_CONSOLE
int con_debug_enter(struct vc_data *vc);
^ permalink raw reply related
* Re: [PATCH 12/12] OMAPDSS: DPI: always use DSI PLL if available
From: Tomi Valkeinen @ 2012-11-07 15:13 UTC (permalink / raw)
To: Rob Clark
Cc: Tomi Valkeinen, Archit Taneja, linux-omap, linux-fbdev, dri-devel
In-Reply-To: <CAF6AEGvJqmvkvkbnegVvnt+SxrWajB=Vq-LsY=k1c96eeyQEXA@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 6815 bytes --]
On 2012-11-07 16:32, Rob Clark wrote:
> On Wed, Nov 7, 2012 at 4:01 AM, Tomi Valkeinen <tomi.valkeinen@ti.com> wrote:
>> Hotplugging is not some abstract future scenario, we already have
>> hardware that could use it. For example, omap3 SDP board has a
>> switchable output to DVI or LCD panel. In this case we know what the two
>> options are, but the disabled component is still effectually removed
>> from the system, and plugged back in when it's enabled.
>
> I would look at this as two different connectors which can not be used
> at the same time. You have this scenario with desktop graphics cards.
Yes, that's an option with fixed amount of display devices. But doesn't
work for capes.
>> Hotplug is not a high priority item, but I do wish we get it supported
>> in common panel framework. Then it's at least possible to extend drm in
>> the future to support it.
>>
>>
>>
>> Anyway, this makes me wonder... omapdrm currently maps the elements of
>> the whole video pipeline to drm elements (encoder, connector, etc).
>> Would it make more sense to just map the DISPC to these drm elements?
>> Connector would then be the output from DISPC.
>
> I think:
>
> plane->overlay
> crtc->manager
>
> is pretty clear. And really
>
> encoder->output
>
> should be the way it is.. on the branch w/ omapdss/omapdrm kms
I'm not so sure. The output (dpi/dsi/hdmi...) is the second step in our
chain. The primary "output" is in the DISPC module, the overlay manager.
That's where the timings, pixel clock, etc. are programmed. The second
step, our output, is really a converter IP. It receives the primary
output, converts it and outputs something else. Just like an external
converter chip would do.
And the output can be quite a bit anything. For example, with DBI or DSI
command mode outputs we don't have any of the conventional video
timings. It doesn't make sense to program, say, video blanking periods
to those outputs. But even with DBI and DSI we do have video blanking
periods in the DISPC's output, the ovl mgr.
Of course, at the end of the chain we have a panel that uses normal
video timings (well, most likely but not necessarily), and so we could
program those timings at the end of the chain, in the block before the
panel. But even then the encoder doesn't really map to the DSS's output
block, as the DSS's output block may not have the conventional timings
(like DBI), or they may be something totally different than what we get
in the end of the chain to the panel.
So I think mapping encoder to output will not work with multiple display
blocks in a chain. Thus I'd see the encoder would better match the
DISPC's output, or alternatively perhaps the block which is just before
the panel (whatever that is, sometimes it can be OMAP's DSI/HDMI/etc).
However, the latter may be a bit strange as the block could be an
external component, possibly hotpluggable.
> re-write, this is how it is for plane/crtc, except for now:
>
> encoder+connector->dssdev
>
> Basically the encoder is doing the "control" stuff (power on/off, set
> timings, etc), and the connector is only doing non control stuff
> (detect, reading edid, etc).
>
> But I think this will probably change a bit as CFP comes into the
> picture. Currently the drm connector is somewhat a "passive" element,
> but I think this will have to change a bit w/ CFP.
>
>> This would map the drm elements to the static hardware blocks, and the
>> meaning of those blocks would be quite similar to what they are in the
>> desktop world (I guess).
>>
>> The panel driver, the external chips, and the DSS internal output blocks
>> (dsi, dpi, ...) would be handled separately from those drm elements. The
>> DSS internal blocks are static, of course, but they can be effectively
>> considered the same way as external chips.
>
> I think dsi/dpi/etc map to encoder. The big question is where the
> panel's fit. But to userspace somehow this should look like
> connectors. I think:
>
> encoder->output
> connector->panel
>
> could work.. although connector is less passive than KMS currently
> assumes. And "panel" could really be a whole chain in the case of
> bridge chips, etc. I don't know, maybe there are better ways. But I
> think userspace really just wants to know "which monitor" which is
> basically connector.
Hmm yes. Well, even if we map encoder and connector to the ovl manager,
the userspace could see which monitor there is. Obviously we need to
make changes for that to work, but as a model it feels a lot more
natural to me than using output and panel for encoder and connector.
Perhaps it's wrong to say "map connector to ovl mgr". It would be more
like "this connector observes the chain connected to this ovl mgr", even
though the connector wouldn't observe any block in the chain directly.
Just observing the plug in/out status, etc.
But I think encoder really maps quite well directly to the output side
of overlay manager.
>> The omapdrm driver needs of course to access those separate elements
>> also, but that shouldn't be a problem. If omapdrm needs to call a
>> function in the panel driver, all it needs to do is go through the chain
>> to find the panel. Well, except if one output connected two two panels
>> via a bridge chip...
>
> yeah, that is a really ugly case in our hw since it is quite
> non-transparent (ie. implications about use of planes, etc).
Not really in this case. You're perhaps thinking about connecting two
outputs to a single panel. Which is problematic also.
We don't have in sights a board that splits one output to two panels, so
I think we should just ignore that for now. But two outputs for one
panel is on the table.
>> And if drm is at some point extended to support panel drivers, or chains
>> of external display entities, it would be easier to add that support.
>>
>> What would it require the manage the elements like that? Would it help?
>> It sounds to me that this would simplify the model.
>
> I'm not really entirely sure.. other than at least other drivers
> supporting CFP will have the same requirements ;-)
>
> I guess the two best options are either bury some sort of chain of
> panel drivers in the connector, or introduce some internal elements in
> DRM which are not necessarily visible to userspace. (Or at least
> userspace should have the option to ignore it for backwards
> compatibility. For atomic pageflip/modeset, the converting of
> everything to properties makes it easier to think about exposing new
> KMS mode object types to userspace.)
Yes, I don't think we should or need to expose these new elements to
userspace, at least in the first place.
Tomi
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 897 bytes --]
^ permalink raw reply
* [RFC 11/11] Example: OMAPFB: clear framebuffers using writeback
From: Archit Taneja @ 2012-11-07 14:56 UTC (permalink / raw)
To: tomi.valkeinen; +Cc: linux-fbdev, linux-omap, Archit Taneja
In-Reply-To: <1352299469-17609-1-git-send-email-archit@ti.com>
This is an example to demonstrate how writeback is used to clear framebuffers.
The function omapfb_clear_fb_writeback is added as an alternative to the MPU
intensive function cfb_fillrect.
The writeback is attached to a free manager which has no overlays connected to
it, the manager's default color is set to black, and the size of both writeback
and manager are set to the framebuffer size. writeback_info is configured to
write the manager's output to the framebuffer address, and a mem to me update is
done.
This currently isn't full proof as it the logic of getting a free manager isn't
optimal yet and has a few corner cases.
Signed-off-by: Archit Taneja <archit@ti.com>
---
drivers/video/omap2/omapfb/omapfb-main.c | 132 +++++++++++++++++++++++++++++-
1 file changed, 131 insertions(+), 1 deletion(-)
diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
index be9096c..680f1eb 100644
--- a/drivers/video/omap2/omapfb/omapfb-main.c
+++ b/drivers/video/omap2/omapfb/omapfb-main.c
@@ -1590,8 +1590,131 @@ static int omapfb_allocate_all_fbs(struct omapfb2_device *fbdev)
return 0;
}
+static struct omap_overlay_manager *get_free_manager(struct fb_info *fbi)
+{
+ struct omapfb_info *ofbi = FB2OFB(fbi);
+ struct omapfb2_device *fbdev = ofbi->fbdev;
+ struct omap_overlay *ovl;
+ struct omap_overlay_manager *mgr, *def_mgr;
+ int i;
+
+ ovl = omap_dss_get_overlay(0);
+ def_mgr = ovl->manager;
+
+ for (i = 0; i < fbdev->num_managers; i++) {
+ mgr = fbdev->managers[i];
+ if (mgr != def_mgr)
+ return mgr;
+ }
+
+ return NULL;
+}
+
+static void wb_callback(int err, void *data)
+{
+ struct omap_dss_output *wb = (struct omap_dss_output *) data;
+
+ omapdss_writeback_bus_unlock(wb);
+}
+
+static int omapfb_clear_fb_writeback(struct fb_info *fbi)
+{
+ struct fb_var_screeninfo *var = &fbi->var;
+ struct fb_fix_screeninfo *fix = &fbi->fix;
+ struct omapfb_info *ofbi = FB2OFB(fbi);
+ struct omap_overlay_manager *mgr = NULL;
+ struct omap_overlay_manager_info mgr_info;
+ struct omap_dss_output *wb, *orig_out = NULL;
+ struct omap_dss_writeback_info wb_info;
+ enum omap_color_mode mode;
+ u32 data_start_p = 0;
+ int r;
+
+ wb = omap_dss_get_writeback();
+ if (!wb)
+ return -ENODEV;
+
+ /* find the first unused overlay manager */
+ mgr = get_free_manager(fbi);
+ if (!mgr)
+ return -ENODEV;
+
+ /* free the manager output */
+ if (mgr->output) {
+ orig_out = mgr->output;
+ mgr->unset_output(mgr);
+ }
+
+ /* get framebuffer color mode */
+ r = fb_mode_to_dss_mode(var, &mode);
+ if (r)
+ return r;
+
+ /* calculate framebuffer buffer address */
+ if (ofbi->region->size)
+ omapfb_calc_addr(ofbi, var, fix, 0, &data_start_p);
+
+ /* link the free overlay manager to writeback */
+ mgr->set_output(mgr, wb);
+
+ omapdss_writeback_bus_lock(wb);
+
+ /* enable writeback to configure writeback and overlay manager params */
+ omapdss_writeback_enable(wb);
+
+ /* configure and apply manager info to set default color to zero */
+ mgr->get_manager_info(mgr, &mgr_info);
+
+ mgr_info.default_color = 0x0;
+
+ mgr->set_manager_info(mgr, &mgr_info);
+
+ mgr->apply(mgr);
+
+ /*
+ * configure writeback parameters to write manager output to
+ * framebuffer
+ */
+ omapdss_writeback_set_input_size(wb, fbi->var.xres_virtual,
+ fbi->var.yres_virtual);
+
+ omapdss_writeback_get_info(wb, &wb_info);
+
+ wb_info.paddr = data_start_p;
+ wb_info.rotation_type = OMAP_DSS_ROT_DMA;
+ wb_info.rotation = 0;
+ wb_info.mirror = 0;
+ wb_info.width = fbi->var.xres_virtual;
+ wb_info.buf_width = fbi->var.xres_virtual;
+ wb_info.height = fbi->var.yres_virtual;
+ wb_info.color_mode = mode;
+
+ omapdss_writeback_set_info(wb, &wb_info);
+
+ omapdss_writeback_apply(wb);
+
+ /* start writeback update */
+ omapdss_writeback_update(wb, wb_callback, wb);
+
+ omapdss_writeback_bus_lock(wb);
+
+ /* disable writeback(and the connected manager) */
+ omapdss_writeback_disable(wb);
+
+ omapdss_writeback_bus_unlock(wb);
+
+ /* restore manager back to it's old state */
+ mgr->unset_output(mgr);
+
+ if (orig_out)
+ mgr->set_output(mgr, orig_out);
+
+ return 0;
+}
+
static void omapfb_clear_fb(struct fb_info *fbi)
{
+ int r;
const struct fb_fillrect rect = {
.dx = 0,
.dy = 0,
@@ -1601,7 +1724,14 @@ static void omapfb_clear_fb(struct fb_info *fbi)
.rop = ROP_COPY,
};
- cfb_fillrect(fbi, &rect);
+ r = omapfb_clear_fb_writeback(fbi);
+
+ /*
+ * if clearing through writeback failed, revert to clearing the
+ * framebuffer through MPU
+ */
+ if (r)
+ cfb_fillrect(fbi, &rect);
}
int omapfb_realloc_fbmem(struct fb_info *fbi, unsigned long size, int type)
--
1.7.9.5
^ permalink raw reply related
* [RFC 10/11] ARCH: ARM: OMAP: Create a platform device for writeback
From: Archit Taneja @ 2012-11-07 14:56 UTC (permalink / raw)
To: tomi.valkeinen; +Cc: linux-fbdev, linux-omap, Archit Taneja
In-Reply-To: <1352299469-17609-1-git-send-email-archit@ti.com>
writeback is a like DPI in the sense that it's completelty a part of DISPC.
Hence it doesn't have it's own resource, or a hwmod entity tied to it.
Create a simple platfrom device for writeback in omap_display_init. Set the
parent to the omapdss_dss platform device like done for other DSS submodules.
Signed-off-by: Archit Taneja <archit@ti.com>
---
arch/arm/mach-omap2/display.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/arch/arm/mach-omap2/display.c b/arch/arm/mach-omap2/display.c
index 282c814e..2e01b61 100644
--- a/arch/arm/mach-omap2/display.c
+++ b/arch/arm/mach-omap2/display.c
@@ -414,6 +414,15 @@ int __init omap_display_init(struct omap_dss_board_info *board_data)
}
}
+ if (cpu_is_omap44xx()) {
+ pdev = create_simple_dss_pdev("omapdss_writeback", -1,
+ NULL, 0, dss_pdev);
+ if (IS_ERR(pdev)) {
+ pr_err("Could not build platform_device for omapdss_writeback\n");
+ return PTR_ERR(pdev);
+ }
+ }
+
return 0;
}
--
1.7.9.5
^ permalink raw reply related
* [RFC 09/11] OMAPDSS: FEATURES: Add writeback as supported outputs for OMAP4 managers
From: Archit Taneja @ 2012-11-07 14:56 UTC (permalink / raw)
To: tomi.valkeinen; +Cc: linux-fbdev, linux-omap, Archit Taneja
In-Reply-To: <1352299469-17609-1-git-send-email-archit@ti.com>
The writeback pipeline can connect to any of the OMAP4 overlay managers. Add it
as a supported output in dss features.
Signed-off-by: Archit Taneja <archit@ti.com>
---
drivers/video/omap2/dss/dss_features.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c
index 3e8287c..e8d10cb 100644
--- a/drivers/video/omap2/dss/dss_features.c
+++ b/drivers/video/omap2/dss/dss_features.c
@@ -202,15 +202,15 @@ static const enum omap_dss_output_id omap3630_dss_supported_outputs[] = {
static const enum omap_dss_output_id omap4_dss_supported_outputs[] = {
/* OMAP_DSS_CHANNEL_LCD */
OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
- OMAP_DSS_OUTPUT_DSI1,
+ OMAP_DSS_OUTPUT_DSI1 | OMAP_DSS_OUTPUT_WB,
/* OMAP_DSS_CHANNEL_DIGIT */
OMAP_DSS_OUTPUT_VENC | OMAP_DSS_OUTPUT_HDMI |
- OMAP_DSS_OUTPUT_DPI,
+ OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_WB,
/* OMAP_DSS_CHANNEL_LCD2 */
OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
- OMAP_DSS_OUTPUT_DSI2,
+ OMAP_DSS_OUTPUT_DSI2 | OMAP_DSS_OUTPUT_WB,
};
static const enum omap_dss_output_id omap5_dss_supported_outputs[] = {
--
1.7.9.5
^ permalink raw reply related
* [RFC 08/11] OMAPDSS: APPLY: Check if overlay is connected in mem to mem mode
From: Archit Taneja @ 2012-11-07 14:56 UTC (permalink / raw)
To: tomi.valkeinen; +Cc: linux-fbdev, linux-omap, Archit Taneja
In-Reply-To: <1352299469-17609-1-git-send-email-archit@ti.com>
When a manager is connected to writeback in mem to mem mode, all the connected
fetch and process data at rate suitable for the scalar to perform the required
downscaling. This is because there isn't any display connected here, and hence
no real time constraints. When calling dispc_ovl_setup, pass the correct value
of mem_to_mem parameter so that it can discard pixel clock related scaling
limitations.
Signed-off-by: Archit Taneja <archit@ti.com>
---
drivers/video/omap2/dss/apply.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c
index 2fd08d8..e1c589c 100644
--- a/drivers/video/omap2/dss/apply.c
+++ b/drivers/video/omap2/dss/apply.c
@@ -615,10 +615,13 @@ int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl)
static void dss_ovl_write_regs(struct omap_overlay *ovl)
{
+ struct omap_overlay_manager *mgr = ovl->manager;
+ struct omap_dss_output *out = mgr->output;
struct ovl_priv_data *op = get_ovl_priv(ovl);
struct omap_overlay_info *oi;
bool replication;
struct mgr_priv_data *mp;
+ bool mem_to_mem;
int r;
DSSDBG("writing ovl %d regs", ovl->id);
@@ -628,11 +631,13 @@ static void dss_ovl_write_regs(struct omap_overlay *ovl)
oi = &op->info;
- mp = get_mgr_priv(ovl->manager);
+ mp = get_mgr_priv(mgr);
replication = dss_ovl_use_replication(mp->lcd_config, oi->color_mode);
- r = dispc_ovl_setup(ovl->id, oi, replication, &mp->timings, false);
+ mem_to_mem = output_is_wb(out) ? wb_manual_update(out) : false;
+
+ r = dispc_ovl_setup(ovl->id, oi, replication, &mp->timings, mem_to_mem);
if (r) {
/*
* We can't do much here, as this function can be called from
--
1.7.9.5
^ permalink raw reply related
* [RFC 07/11] OMAPDSS: writeback: add mechanism to do mem to mem updates
From: Archit Taneja @ 2012-11-07 14:56 UTC (permalink / raw)
To: tomi.valkeinen; +Cc: linux-fbdev, linux-omap, Archit Taneja
In-Reply-To: <1352299469-17609-1-git-send-email-archit@ti.com>
writeback in mem to mem mode works like an overlay manager connected to a
display in stallmode. When we set ENABLE in DISPC_WB_ATTRIBUTES writeback, it
starts a mem to mem transfer. On completion, we get a FRAMEDONEWB interrupt and
the ENABLE bit is cleared by HW.
In APPLY, we add dss_wb_start_update, this function is similar to
dss_mgr_start_update, but is responsible for configuring both the manager(and
the overlays connected to it) and the writeback registers. We add an updating
field in the writeback private data which tells APPLY when we are busy and
when we are done with a mem to mem transfer. We register to the framedone isr
when needed and we update the updating field in dss_apply_irq_handler when we
are done with the transfer.
In the writeback output driver, we add a semaphore based way to lock the
writeback resource as we do in DSI command mode. The writeback user is expected
to lock the bus, call omapdss_writeback_update and mention a callback along with
it, and unlock the bus in the callback. omapdss_writeback_update registers to
the FRAMEDONE interrupt to trigger the callback and starts the update by calling
the corresponding APPLY function.
Signed-off-by: Archit Taneja <archit@ti.com>
---
drivers/video/omap2/dss/apply.c | 83 +++++++++++++++++++++++++++
drivers/video/omap2/dss/dss.h | 1 +
drivers/video/omap2/dss/writeback.c | 106 +++++++++++++++++++++++++++++++++++
include/video/omapdss.h | 4 ++
4 files changed, 194 insertions(+)
diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c
index a205ed4..2fd08d8 100644
--- a/drivers/video/omap2/dss/apply.c
+++ b/drivers/video/omap2/dss/apply.c
@@ -114,6 +114,9 @@ struct wb_priv_data {
bool info_dirty;
struct omap_dss_writeback_info info;
+ /* If true, writeback output is enabled */
+ bool updating;
+
/*
* If true in memory to memory mode, a manager is connected to it.
* However, it may not be active.
@@ -285,6 +288,7 @@ static int dss_check_settings_apply(struct omap_overlay_manager *mgr)
static bool need_isr(void)
{
const int num_mgrs = dss_feat_get_num_mgrs();
+ const int num_wbs = dss_feat_get_num_wbs();
int i;
for (i = 0; i < num_mgrs; ++i) {
@@ -362,6 +366,20 @@ static bool need_isr(void)
}
}
+ for (i = 0; i < num_wbs; i++) {
+ struct omap_dss_output *wb = omap_dss_get_writeback();
+ struct wb_priv_data *wp = get_wb_priv(wb);
+
+ if (!wp->enabled)
+ continue;
+
+ if (wb_manual_update(wb)) {
+ /* to catch FRAMEDONEWB */
+ if (wp->updating)
+ return true;
+ }
+ }
+
return false;
}
@@ -841,6 +859,7 @@ static void dss_apply_irq_handler(void *data, u32 mask);
static void dss_register_vsync_isr(void)
{
const int num_mgrs = dss_feat_get_num_mgrs();
+ const int num_wbs = dss_feat_get_num_wbs();
u32 mask;
int r, i;
@@ -851,6 +870,9 @@ static void dss_register_vsync_isr(void)
for (i = 0; i < num_mgrs; ++i)
mask |= dispc_mgr_get_framedone_irq(i);
+ for (i = 0; i < num_wbs; i++)
+ mask |= dispc_wb_get_framedone_irq();
+
r = omap_dispc_register_isr(dss_apply_irq_handler, NULL, mask);
WARN_ON(r);
@@ -860,6 +882,7 @@ static void dss_register_vsync_isr(void)
static void dss_unregister_vsync_isr(void)
{
const int num_mgrs = dss_feat_get_num_mgrs();
+ const int num_wbs = dss_feat_get_num_wbs();
u32 mask;
int r, i;
@@ -870,6 +893,9 @@ static void dss_unregister_vsync_isr(void)
for (i = 0; i < num_mgrs; ++i)
mask |= dispc_mgr_get_framedone_irq(i);
+ for (i = 0; i < num_wbs; i++)
+ mask |= dispc_wb_get_framedone_irq();
+
r = omap_dispc_unregister_isr(dss_apply_irq_handler, NULL, mask);
WARN_ON(r);
@@ -879,6 +905,7 @@ static void dss_unregister_vsync_isr(void)
static void dss_apply_irq_handler(void *data, u32 mask)
{
const int num_mgrs = dss_feat_get_num_mgrs();
+ const int num_wbs = dss_feat_get_num_wbs();
int i;
bool extra_updating;
@@ -906,6 +933,16 @@ static void dss_apply_irq_handler(void *data, u32 mask)
}
}
+ for (i = 0; i < num_wbs; i++) {
+ struct omap_dss_output *wb = omap_dss_get_writeback();
+ struct wb_priv_data *wp = get_wb_priv(wb);
+
+ if (!wp->enabled)
+ continue;
+
+ wp->updating = dispc_wb_is_enabled();
+ }
+
dss_write_regs();
dss_set_go_bits();
@@ -1685,6 +1722,11 @@ void dss_wb_disable(struct omap_dss_output *wb)
if (!wp->enabled)
goto out;
+ if (wp->updating) {
+ DSSERR("can't disable writeback in the middle of an update\n");
+ goto out;
+ }
+
spin_lock_irqsave(&data_lock, flags);
wp->updating = false;
@@ -1694,3 +1736,44 @@ void dss_wb_disable(struct omap_dss_output *wb)
out:
mutex_unlock(&apply_lock);
}
+
+/*
+ * When doing a writeback mem to mem update, the updating field for writeback
+ * private data is true, but for manager private data the updating field is
+ * false. This is because a manager isn't really 'enabled' in HW, it's the
+ * writeback pipeline which initiates the transfer.
+ */
+void dss_wb_start_update(struct omap_dss_output *wb)
+{
+ struct omap_overlay_manager *mgr = wb->manager;
+ struct wb_priv_data *wp = get_wb_priv(wb);
+ unsigned long flags;
+ int r;
+
+ spin_lock_irqsave(&data_lock, flags);
+
+ WARN_ON(wp->updating);
+
+ /* add some similar check for writeback later */
+
+ r = dss_check_settings(mgr);
+ if (r) {
+ DSSERR("cannot start manual update: illegal configuration\n");
+ spin_unlock_irqrestore(&data_lock, flags);
+ return;
+ }
+
+ dss_wb_write_regs(wb);
+
+ dss_mgr_write_regs(mgr);
+ dss_mgr_write_regs_extra(mgr);
+
+ wp->updating = true;
+
+ if (!dss_data.irq_enabled && need_isr())
+ dss_register_vsync_isr();
+
+ dispc_wb_enable(true);
+
+ spin_unlock_irqrestore(&data_lock, flags);
+}
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index f9e7074..8c70b08 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -217,6 +217,7 @@ void dss_wb_get_info(struct omap_dss_output *wb,
int omap_dss_wb_apply(struct omap_dss_output *wb);
int dss_wb_enable(struct omap_dss_output *wb);
void dss_wb_disable(struct omap_dss_output *wb);
+void dss_wb_start_update(struct omap_dss_output *wb);
/* output */
void dss_register_output(struct omap_dss_output *out);
diff --git a/drivers/video/omap2/dss/writeback.c b/drivers/video/omap2/dss/writeback.c
index 09394fb..7a25e99 100644
--- a/drivers/video/omap2/dss/writeback.c
+++ b/drivers/video/omap2/dss/writeback.c
@@ -20,6 +20,8 @@
#include <linux/kernel.h>
#include <linux/err.h>
#include <linux/module.h>
+#include <linux/semaphore.h>
+#include <linux/workqueue.h>
#include <linux/platform_device.h>
#include <video/omapdss.h>
@@ -27,7 +29,15 @@
#include "dss.h"
struct writeback_data {
+ struct platform_device *pdev;
+
struct mutex lock;
+ struct semaphore bus_lock;
+
+ void (*framedone_callback)(int, void *);
+ void *framedone_data;
+
+ struct delayed_work framedone_timeout_work;
struct omap_dss_output output;
/*
@@ -71,6 +81,32 @@ int dss_writeback_calc_channel_in(struct omap_overlay_manager *mgr,
return 0;
}
+void omapdss_writeback_bus_lock(struct omap_dss_output *wb)
+{
+ struct platform_device *wbdev = writeback_get_wbdev_from_output(wb);
+ struct writeback_data *wb_data = writeback_get_drv_data(wbdev);
+
+ down(&wb_data->bus_lock);
+}
+EXPORT_SYMBOL(omapdss_writeback_bus_lock);
+
+void omapdss_writeback_bus_unlock(struct omap_dss_output *wb)
+{
+ struct platform_device *wbdev = writeback_get_wbdev_from_output(wb);
+ struct writeback_data *wb_data = writeback_get_drv_data(wbdev);
+
+ up(&wb_data->bus_lock);
+}
+EXPORT_SYMBOL(omapdss_writeback_bus_unlock);
+
+static bool writeback_bus_is_locked(struct omap_dss_output *wb)
+{
+ struct platform_device *wbdev = writeback_get_wbdev_from_output(wb);
+ struct writeback_data *wb_data = writeback_get_drv_data(wbdev);
+
+ return wb_data->bus_lock.count = 0;
+}
+
void omapdss_writeback_set_input_size(struct omap_dss_output *wb, u16 w, u16 h)
{
struct platform_device *wbdev = writeback_get_wbdev_from_output(wb);
@@ -88,11 +124,39 @@ void omapdss_writeback_set_input_size(struct omap_dss_output *wb, u16 w, u16 h)
}
EXPORT_SYMBOL(omapdss_writeback_set_input_size);
+static void writeback_handle_framedone(struct platform_device *wbdev, int error)
+{
+ struct writeback_data *wb_data = writeback_get_drv_data(wbdev);
+
+ wb_data->framedone_callback(error, wb_data->framedone_data);
+}
+
+static void writeback_framedone_timeout_work_callback(struct work_struct *work)
+{
+ struct writeback_data *wb_data = container_of(work,
+ struct writeback_data, framedone_timeout_work.work);
+
+ DSSERR("FRAMEDONE WB not received for 100ms\n");
+
+ writeback_handle_framedone(wb_data->pdev, -ETIMEDOUT);
+}
+
+static void writeback_framedone_irq_callback(void *data, u32 mask)
+{
+ struct platform_device *wbdev = (struct platform_device *) data;
+ struct writeback_data *wb_data = writeback_get_drv_data(wbdev);
+
+ cancel_delayed_work(&wb_data->framedone_timeout_work);
+
+ writeback_handle_framedone(wb_data->pdev, 0);
+}
+
static void writeback_config_manager(struct omap_dss_output *wb)
{
struct platform_device *wbdev = writeback_get_wbdev_from_output(wb);
struct writeback_data *wb_data = writeback_get_drv_data(wbdev);
struct dss_lcd_mgr_config lcd_config;
+ int r;
dss_mgr_set_timings(wb->manager, &wb_data->input_timings);
@@ -110,6 +174,11 @@ static void writeback_config_manager(struct omap_dss_output *wb)
*/
dss_mgr_set_lcd_config(wb->manager, &lcd_config);
+ r = omap_dispc_register_isr(writeback_framedone_irq_callback,
+ (void *) wbdev, DISPC_IRQ_FRAMEDONEWB);
+ if (r)
+ DSSERR("Failed to register for FRAMEDONEWB irq\n");
+
dss_mgr_enable(wb->manager);
}
@@ -119,6 +188,8 @@ int omapdss_writeback_enable(struct omap_dss_output *wb)
struct writeback_data *wb_data = writeback_get_drv_data(wbdev);
int r;
+ WARN_ON(!writeback_bus_is_locked(wb));
+
mutex_lock(&wb_data->lock);
r = dispc_runtime_get();
@@ -139,18 +210,48 @@ void omapdss_writeback_disable(struct omap_dss_output *wb)
{
struct platform_device *wbdev = writeback_get_wbdev_from_output(wb);
struct writeback_data *wb_data = writeback_get_drv_data(wbdev);
+ int r;
+
+ WARN_ON(!writeback_bus_is_locked(wb));
mutex_lock(&wb_data->lock);
dss_wb_disable(wb);
dss_mgr_disable(wb->manager);
+ r = omap_dispc_unregister_isr(writeback_framedone_irq_callback,
+ (void *) wbdev, DISPC_IRQ_FRAMEDONEWB);
+ if (r)
+ DSSERR("Failed to unregister FRAMEDONEWB irq\n");
+
dispc_runtime_put();
mutex_unlock(&wb_data->lock);
}
EXPORT_SYMBOL(omapdss_writeback_disable);
+int omapdss_writeback_update(struct omap_dss_output *wb,
+ void (*callback)(int, void *), void *data)
+{
+ struct platform_device *wbdev = writeback_get_wbdev_from_output(wb);
+ struct writeback_data *wb_data = writeback_get_drv_data(wbdev);
+ int r;
+
+ WARN_ON(!writeback_bus_is_locked(wb));
+
+ wb_data->framedone_callback = callback;
+ wb_data->framedone_data = data;
+
+ r = schedule_delayed_work(&wb_data->framedone_timeout_work,
+ msecs_to_jiffies(100));
+ BUG_ON(r = 0);
+
+ dss_wb_start_update(wb);
+
+ return 0;
+}
+EXPORT_SYMBOL(omapdss_writeback_update);
+
int omapdss_writeback_apply(struct omap_dss_output *wb)
{
return omap_dss_wb_apply(wb);
@@ -199,7 +300,12 @@ static int __init omap_writeback_probe(struct platform_device *pdev)
dev_set_drvdata(&pdev->dev, wb_data);
+ wb_data->pdev = pdev;
mutex_init(&wb_data->lock);
+ sema_init(&wb_data->bus_lock, 1);
+
+ INIT_DEFERRABLE_WORK(&wb_data->framedone_timeout_work,
+ writeback_framedone_timeout_work_callback);
/* initialize with dummy timings */
wb_data->input_timings = (struct omap_video_timings)
diff --git a/include/video/omapdss.h b/include/video/omapdss.h
index f63c0cb..c7f3ac7 100644
--- a/include/video/omapdss.h
+++ b/include/video/omapdss.h
@@ -837,9 +837,13 @@ void omapdss_rfbi_set_data_lines(struct omap_dss_device *dssdev,
void omapdss_rfbi_set_interface_timings(struct omap_dss_device *dssdev,
struct rfbi_timings *timings);
+void omapdss_writeback_bus_lock(struct omap_dss_output *wb);
+void omapdss_writeback_bus_unlock(struct omap_dss_output *wb);
int omapdss_writeback_enable(struct omap_dss_output *wb);
void omapdss_writeback_disable(struct omap_dss_output *wb);
void omapdss_writeback_set_input_size(struct omap_dss_output *wb, u16 w, u16 h);
+int omapdss_writeback_update(struct omap_dss_output *wb,
+ void (*callback)(int, void *), void *data);
int omapdss_writeback_apply(struct omap_dss_output *wb);
int omapdss_writeback_set_info(struct omap_dss_output *wb,
struct omap_dss_writeback_info *info);
--
1.7.9.5
^ permalink raw reply related
* [RFC 06/11] OMAPDSS: APPLY: configure channel_in for writeback
From: Archit Taneja @ 2012-11-07 14:56 UTC (permalink / raw)
To: tomi.valkeinen; +Cc: linux-fbdev, linux-omap, Archit Taneja
In-Reply-To: <1352299469-17609-1-git-send-email-archit@ti.com>
writeback's input is configured by the CHANNELIN field in DISPC_WB_ATTRIBUTES.
It's an immediate write register field. We need to change writeback's channel
in whenever the manager to which it is connected changes.
When changing managers for overlays, we needed to be certain that the overlay
was disabled. We added some extra waits for that. However, such a thing isn't
required for writeback as it's disabled for sure after we call dss_wb_disable.
Signed-off-by: Archit Taneja <archit@ti.com>
---
drivers/video/omap2/dss/apply.c | 31 +++++++++++++++++++++++++++++++
drivers/video/omap2/dss/dss.h | 9 +++++++++
drivers/video/omap2/dss/writeback.c | 23 +++++++++++++++++++++++
3 files changed, 63 insertions(+)
diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c
index 1ab1755..a205ed4 100644
--- a/drivers/video/omap2/dss/apply.c
+++ b/drivers/video/omap2/dss/apply.c
@@ -1175,6 +1175,22 @@ int dss_mgr_set_output(struct omap_overlay_manager *mgr,
goto err;
}
+ if (output_is_wb(output)) {
+ enum dss_writeback_channel channel;
+
+ r = dss_writeback_calc_channel_in(mgr, &channel);
+ if (r)
+ goto err;
+
+ r = dispc_runtime_get();
+ if (r)
+ goto err;
+
+ dispc_wb_set_channel_in(channel);
+
+ dispc_runtime_put();
+ }
+
output->manager = mgr;
mgr->output = output;
@@ -1210,6 +1226,21 @@ int dss_mgr_unset_output(struct omap_overlay_manager *mgr)
spin_unlock_irqrestore(&data_lock, flags);
+ if (output_is_wb(mgr->output)) {
+ struct omap_dss_output *wb = mgr->output;
+ struct wb_priv_data *wp = get_wb_priv(wb);
+
+ spin_lock_irqsave(&data_lock, flags);
+
+ if (wp->enabled) {
+ DSSERR("WB output can't be unset when enabled\n");
+ r = -EINVAL;
+ goto err1;
+ }
+
+ spin_unlock_irqrestore(&data_lock, flags);
+ }
+
mgr->output->manager = NULL;
mgr->output = NULL;
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index 6238895..f9e7074 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -540,6 +540,15 @@ int hdmi_audio_config(struct omap_dss_audio *audio);
#ifdef CONFIG_OMAP4_DSS_WRITEBACK
int writeback_init_platform_driver(void) __init;
void writeback_uninit_platform_driver(void) __exit;
+int dss_writeback_calc_channel_in(struct omap_overlay_manager *mgr,
+ enum dss_writeback_channel *channel);
+#else
+static inline int dss_writeback_calc_channel_in(struct omap_overlay_manager *mgr,
+ enum dss_writeback_channel *channel)
+{
+ WARN("%s: WB not compiled in, returning 0\n", __func__);
+ return 0;
+}
#endif
/* RFBI */
diff --git a/drivers/video/omap2/dss/writeback.c b/drivers/video/omap2/dss/writeback.c
index 598defd..09394fb 100644
--- a/drivers/video/omap2/dss/writeback.c
+++ b/drivers/video/omap2/dss/writeback.c
@@ -48,6 +48,29 @@ static inline struct platform_device *writeback_get_wbdev_from_output(struct oma
return out->pdev;
}
+int dss_writeback_calc_channel_in(struct omap_overlay_manager *mgr,
+ enum dss_writeback_channel *channel)
+{
+ /*
+ * Add a case for dummy writeback manager once we support connecting
+ * writeback directly to an overlay.
+ */
+ switch (mgr->id) {
+ case OMAP_DSS_CHANNEL_DIGIT:
+ *channel = DSS_WB_TV_MGR;
+ break;
+ case OMAP_DSS_CHANNEL_LCD2:
+ *channel = DSS_WB_LCD2_MGR;
+ break;
+ case OMAP_DSS_CHANNEL_LCD:
+ default:
+ *channel = DSS_WB_LCD1_MGR;
+ break;
+ }
+
+ return 0;
+}
+
void omapdss_writeback_set_input_size(struct omap_dss_output *wb, u16 w, u16 h)
{
struct platform_device *wbdev = writeback_get_wbdev_from_output(wb);
--
1.7.9.5
^ permalink raw reply related
* [RFC 05/11] OMAPDSS: APPLY: Add writeback enable/disable funcs
From: Archit Taneja @ 2012-11-07 14:56 UTC (permalink / raw)
To: tomi.valkeinen; +Cc: linux-fbdev, linux-omap, Archit Taneja
In-Reply-To: <1352299469-17609-1-git-send-email-archit@ti.com>
Add dss_wb_enable/dss_wb_disable funcs in APPLY similar to that of manager's
enable/disable functions. Since, these functions support only writeback in
memory to memory mode, their job is reduced to just setting the private enable
parameter correctly.
Writeback can't be enabled if the manager it is connected to is not enabled
first. dss_wb_enable makes sure that the connected manager is enabled,
dss_wb_disable doesn't have much dependency on whether the connected manager
is disabled before or after.
Add corresponding enable/disable functions in the output driver which the
writeback user will use. The output driver enable function also takes the
responsibility of configuring and enabling the connected manager. The function
writeback_configure_manager configures the manager in stall mode and sets
the dimensions to the desired writeback input size. The output driver disable
functions disables both manager and writeback.
Signed-off-by: Archit Taneja <archit@ti.com>
---
drivers/video/omap2/dss/apply.c | 70 +++++++++++++++++++++++++++++++++++
drivers/video/omap2/dss/dss.h | 2 +
drivers/video/omap2/dss/writeback.c | 63 +++++++++++++++++++++++++++++++
include/video/omapdss.h | 2 +
4 files changed, 137 insertions(+)
diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c
index 8fe7fce..1ab1755 100644
--- a/drivers/video/omap2/dss/apply.c
+++ b/drivers/video/omap2/dss/apply.c
@@ -1593,3 +1593,73 @@ end:
return 0;
}
+
+int dss_wb_enable(struct omap_dss_output *wb)
+{
+ struct wb_priv_data *wp = get_wb_priv(wb);
+ struct mgr_priv_data *mp;
+ unsigned long flags;
+ int r;
+
+ mutex_lock(&apply_lock);
+
+ if (wp->enabled) {
+ r = 0;
+ goto out;
+ }
+
+ if (wb->manager = NULL) {
+ DSSERR("can't enable writeback without a manager\n");
+ r = -EINVAL;
+ goto out;
+ }
+
+ mp = get_mgr_priv(wb->manager);
+
+ spin_lock_irqsave(&data_lock, flags);
+
+ if (!mp->enabled) {
+ DSSERR("can't enable writeback with a disabled manager\n");
+ r = -EINVAL;
+ goto err;
+ }
+
+ wp->enabled = true;
+
+ /*
+ * TODO: check settings here, if we fail, set wp->enabled back to
+ * false
+ */
+
+ spin_unlock_irqrestore(&data_lock, flags);
+
+ mutex_unlock(&apply_lock);
+
+ return 0;
+err:
+ spin_unlock_irqrestore(&data_lock, flags);
+out:
+ mutex_unlock(&apply_lock);
+
+ return r;
+}
+
+void dss_wb_disable(struct omap_dss_output *wb)
+{
+ struct wb_priv_data *wp = get_wb_priv(wb);
+ unsigned long flags;
+
+ mutex_lock(&apply_lock);
+
+ if (!wp->enabled)
+ goto out;
+
+ spin_lock_irqsave(&data_lock, flags);
+
+ wp->updating = false;
+ wp->enabled = false;
+
+ spin_unlock_irqrestore(&data_lock, flags);
+out:
+ mutex_unlock(&apply_lock);
+}
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index 1b9c936..6238895 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -215,6 +215,8 @@ int dss_wb_set_info(struct omap_dss_output *wb,
void dss_wb_get_info(struct omap_dss_output *wb,
struct omap_dss_writeback_info *info);
int omap_dss_wb_apply(struct omap_dss_output *wb);
+int dss_wb_enable(struct omap_dss_output *wb);
+void dss_wb_disable(struct omap_dss_output *wb);
/* output */
void dss_register_output(struct omap_dss_output *out);
diff --git a/drivers/video/omap2/dss/writeback.c b/drivers/video/omap2/dss/writeback.c
index 9a80f72..598defd 100644
--- a/drivers/video/omap2/dss/writeback.c
+++ b/drivers/video/omap2/dss/writeback.c
@@ -65,6 +65,69 @@ void omapdss_writeback_set_input_size(struct omap_dss_output *wb, u16 w, u16 h)
}
EXPORT_SYMBOL(omapdss_writeback_set_input_size);
+static void writeback_config_manager(struct omap_dss_output *wb)
+{
+ struct platform_device *wbdev = writeback_get_wbdev_from_output(wb);
+ struct writeback_data *wb_data = writeback_get_drv_data(wbdev);
+ struct dss_lcd_mgr_config lcd_config;
+
+ dss_mgr_set_timings(wb->manager, &wb_data->input_timings);
+
+ lcd_config.io_pad_mode = DSS_IO_PAD_MODE_BYPASS;
+ lcd_config.stallmode = true;
+ lcd_config.fifohandcheck = false;
+ lcd_config.clock_info.lck_div = 1;
+ lcd_config.clock_info.pck_div = 1;
+ lcd_config.video_port_width = 24;
+ lcd_config.lcden_sig_polarity = false;
+
+ /*
+ * apply lcd_config such that manager appears to be in stallmode, this
+ * makes the manager operate in manual update mode
+ */
+ dss_mgr_set_lcd_config(wb->manager, &lcd_config);
+
+ dss_mgr_enable(wb->manager);
+}
+
+int omapdss_writeback_enable(struct omap_dss_output *wb)
+{
+ struct platform_device *wbdev = writeback_get_wbdev_from_output(wb);
+ struct writeback_data *wb_data = writeback_get_drv_data(wbdev);
+ int r;
+
+ mutex_lock(&wb_data->lock);
+
+ r = dispc_runtime_get();
+ if (r)
+ goto err;
+
+ writeback_config_manager(wb);
+
+ r = dss_wb_enable(wb);
+err:
+ mutex_unlock(&wb_data->lock);
+
+ return r;
+}
+EXPORT_SYMBOL(omapdss_writeback_enable);
+
+void omapdss_writeback_disable(struct omap_dss_output *wb)
+{
+ struct platform_device *wbdev = writeback_get_wbdev_from_output(wb);
+ struct writeback_data *wb_data = writeback_get_drv_data(wbdev);
+
+ mutex_lock(&wb_data->lock);
+
+ dss_wb_disable(wb);
+ dss_mgr_disable(wb->manager);
+
+ dispc_runtime_put();
+
+ mutex_unlock(&wb_data->lock);
+}
+EXPORT_SYMBOL(omapdss_writeback_disable);
+
int omapdss_writeback_apply(struct omap_dss_output *wb)
{
return omap_dss_wb_apply(wb);
diff --git a/include/video/omapdss.h b/include/video/omapdss.h
index d8064ed..f63c0cb 100644
--- a/include/video/omapdss.h
+++ b/include/video/omapdss.h
@@ -837,6 +837,8 @@ void omapdss_rfbi_set_data_lines(struct omap_dss_device *dssdev,
void omapdss_rfbi_set_interface_timings(struct omap_dss_device *dssdev,
struct rfbi_timings *timings);
+int omapdss_writeback_enable(struct omap_dss_output *wb);
+void omapdss_writeback_disable(struct omap_dss_output *wb);
void omapdss_writeback_set_input_size(struct omap_dss_output *wb, u16 w, u16 h);
int omapdss_writeback_apply(struct omap_dss_output *wb);
int omapdss_writeback_set_info(struct omap_dss_output *wb,
--
1.7.9.5
^ permalink raw reply related
* [RFC 04/11] OMAPDSS: writeback: Configure writeback input size
From: Archit Taneja @ 2012-11-07 14:56 UTC (permalink / raw)
To: tomi.valkeinen; +Cc: linux-fbdev, linux-omap, Archit Taneja
In-Reply-To: <1352299469-17609-1-git-send-email-archit@ti.com>
The input to the writeback piepline comes from an overlay manager or an overlay
in mem to mem mode. In both cases the input size configured for writeback should
be the size of the overlay or overlay manager output.
We ignore the case of direct connections between an overlay and writeback for
now. Assuming that writeback output connected only to a manager, we need to
ensure that the manger dimensions change when the user tries to change
writeback's input size.
This is achieved by the output driver calling dss_mgr_set_timings. When applying
the manager timings, we also dirty the writeback_info cache so that the next
writeback update will incorporate the new manager timings. In effect, we don't
maintain private data/cache for the input size of writeback as it's always equal
to the manager's input size. However, we take care of updating the writeback
registers whenever we change the manager's input size.
Signed-off-by: Archit Taneja <archit@ti.com>
---
drivers/video/omap2/dss/apply.c | 18 ++++++++++++++++++
drivers/video/omap2/dss/writeback.c | 31 +++++++++++++++++++++++++++++++
include/video/omapdss.h | 1 +
3 files changed, 50 insertions(+)
diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c
index 76886da..8fe7fce 100644
--- a/drivers/video/omap2/dss/apply.c
+++ b/drivers/video/omap2/dss/apply.c
@@ -223,6 +223,11 @@ static bool wb_manual_update(struct omap_dss_output *wb)
return true;
}
+static bool output_is_wb(struct omap_dss_output *out)
+{
+ return out ? out->id = OMAP_DSS_OUTPUT_WB : false;
+}
+
static int dss_check_settings_low(struct omap_overlay_manager *mgr,
bool applying)
{
@@ -1226,6 +1231,19 @@ static void dss_apply_mgr_timings(struct omap_overlay_manager *mgr,
mp->timings = *timings;
mp->extra_info_dirty = true;
+
+ /*
+ * If the connected output is writeback, and if the width or height of
+ * the overlay manager change, writeback's input size needs to be
+ * changed too. Dirty the writeback info so that it's reconfigured
+ * along with the manager timings change.
+ */
+ if (output_is_wb(mgr->output)) {
+ struct omap_dss_output *wb = mgr->output;
+ struct wb_priv_data *wp = get_wb_priv(wb);
+
+ wp->info_dirty = true;
+ }
}
void dss_mgr_set_timings(struct omap_overlay_manager *mgr,
diff --git a/drivers/video/omap2/dss/writeback.c b/drivers/video/omap2/dss/writeback.c
index c05dd54..9a80f72 100644
--- a/drivers/video/omap2/dss/writeback.c
+++ b/drivers/video/omap2/dss/writeback.c
@@ -30,6 +30,12 @@ struct writeback_data {
struct mutex lock;
struct omap_dss_output output;
+ /*
+ * timings of manager to which writeback is connected, only configured
+ * by writeback driver in mem to mem mode. In capture mode, manager
+ * timings will be configured by the display interface.
+ */
+ struct omap_video_timings input_timings;
};
static inline struct writeback_data *writeback_get_drv_data(struct platform_device *wbdev)
@@ -42,6 +48,23 @@ static inline struct platform_device *writeback_get_wbdev_from_output(struct oma
return out->pdev;
}
+void omapdss_writeback_set_input_size(struct omap_dss_output *wb, u16 w, u16 h)
+{
+ struct platform_device *wbdev = writeback_get_wbdev_from_output(wb);
+ struct writeback_data *wb_data = writeback_get_drv_data(wbdev);
+
+ mutex_lock(&wb_data->lock);
+
+ wb_data->input_timings.x_res = w;
+ wb_data->input_timings.y_res = h;
+
+ if (wb->manager)
+ dss_mgr_set_timings(wb->manager, &wb_data->input_timings);
+
+ mutex_unlock(&wb_data->lock);
+}
+EXPORT_SYMBOL(omapdss_writeback_set_input_size);
+
int omapdss_writeback_apply(struct omap_dss_output *wb)
{
return omap_dss_wb_apply(wb);
@@ -92,6 +115,14 @@ static int __init omap_writeback_probe(struct platform_device *pdev)
mutex_init(&wb_data->lock);
+ /* initialize with dummy timings */
+ wb_data->input_timings = (struct omap_video_timings)
+ { 640, 480, 0, 1, 1, 1, 1, 0, 0, false,
+ OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
+ OMAPDSS_DRIVE_SIG_RISING_EDGE, OMAPDSS_SIG_ACTIVE_HIGH,
+ OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
+ };
+
writeback_init_output(pdev, wb_data);
return 0;
diff --git a/include/video/omapdss.h b/include/video/omapdss.h
index 2bc10cb..d8064ed 100644
--- a/include/video/omapdss.h
+++ b/include/video/omapdss.h
@@ -837,6 +837,7 @@ void omapdss_rfbi_set_data_lines(struct omap_dss_device *dssdev,
void omapdss_rfbi_set_interface_timings(struct omap_dss_device *dssdev,
struct rfbi_timings *timings);
+void omapdss_writeback_set_input_size(struct omap_dss_output *wb, u16 w, u16 h);
int omapdss_writeback_apply(struct omap_dss_output *wb);
int omapdss_writeback_set_info(struct omap_dss_output *wb,
struct omap_dss_writeback_info *info);
--
1.7.9.5
^ permalink raw reply related
* [RFC 03/11] OMAPDSS: APPLY: Apply writeback configurations
From: Archit Taneja @ 2012-11-07 14:56 UTC (permalink / raw)
To: tomi.valkeinen; +Cc: linux-fbdev, linux-omap, Archit Taneja
In-Reply-To: <1352299469-17609-1-git-send-email-archit@ti.com>
Add changes in apply to let a user apply writeback configurations. This
basically involves a writeback user to commit the writeback_info it has set
previously.
Only memory to memory mode is supported for now in APPLY. Actual register
writes would only happen when a mem to mem update is initiated. Therefore,
there isn't a need to support the cases of shadow registers being dirty.
Add the following:
- info and info_dirty fields in private data to represent the lower cache of
writeback info in APPLY.
- Function omap_dss_wb_apply which propagates user_info to info, and an
equivalent function in writeback output driver exposed to writeback users.
- Function dss_wb_write_regs to be used by APPLY to configure writeback DISPC
registers.
- Helper function which tells the mode of writeback.
Signed-off-by: Archit Taneja <archit@ti.com>
---
drivers/video/omap2/dss/apply.c | 68 +++++++++++++++++++++++++++++++++++
drivers/video/omap2/dss/dss.h | 1 +
drivers/video/omap2/dss/writeback.c | 6 ++++
include/video/omapdss.h | 1 +
4 files changed, 76 insertions(+)
diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c
index b2e4f6a..76886da 100644
--- a/drivers/video/omap2/dss/apply.c
+++ b/drivers/video/omap2/dss/apply.c
@@ -110,6 +110,15 @@ struct wb_priv_data {
bool user_info_dirty;
struct omap_dss_writeback_info user_info;
+
+ bool info_dirty;
+ struct omap_dss_writeback_info info;
+
+ /*
+ * If true in memory to memory mode, a manager is connected to it.
+ * However, it may not be active.
+ */
+ bool enabled;
};
static struct {
@@ -209,6 +218,11 @@ static bool mgr_manual_update(struct omap_overlay_manager *mgr)
return mp->lcd_config.stallmode;
}
+static bool wb_manual_update(struct omap_dss_output *wb)
+{
+ return true;
+}
+
static int dss_check_settings_low(struct omap_overlay_manager *mgr,
bool applying)
{
@@ -684,6 +698,36 @@ static void dss_mgr_write_regs_extra(struct omap_overlay_manager *mgr)
mp->shadow_extra_info_dirty = true;
}
+static void dss_wb_write_regs(struct omap_dss_output *wb)
+{
+ struct wb_priv_data *wp = get_wb_priv(wb);
+ struct omap_dss_writeback_info *wi;
+ struct mgr_priv_data *mp;
+ u32 fifo_low, fifo_high;
+ bool use_fifo_merge = false;
+ int r;
+
+ if (!wp->enabled || !wp->info_dirty)
+ return;
+
+ wi = &wp->info;
+
+ mp = get_mgr_priv(wb->manager);
+
+ dispc_ovl_compute_fifo_thresholds(OMAP_DSS_WB, &fifo_low, &fifo_high,
+ use_fifo_merge, wb_manual_update(wb));
+
+ dispc_ovl_set_fifo_threshold(OMAP_DSS_WB, fifo_low, fifo_high);
+
+ r = dispc_wb_setup(wi, wb_manual_update(wb), &mp->timings);
+ if (r) {
+ DSSERR("dispc_wb_setup failed %d\n", r);
+ return;
+ }
+
+ wp->info_dirty = false;
+}
+
static void dss_write_regs(void)
{
const int num_mgrs = omap_dss_get_num_overlay_managers();
@@ -1507,3 +1551,27 @@ void dss_wb_get_info(struct omap_dss_output *wb,
spin_unlock_irqrestore(&data_lock, flags);
}
+
+int omap_dss_wb_apply(struct omap_dss_output *wb)
+{
+ struct wb_priv_data *wp = get_wb_priv(wb);
+ unsigned long flags;
+
+ DSSDBG("omap_dss_wb_apply\n");
+
+ spin_lock_irqsave(&data_lock, flags);
+
+ /* check for settings here */
+
+ if (!wp->user_info_dirty)
+ goto end;
+
+ wp->user_info_dirty = false;
+ wp->info_dirty = true;
+ wp->info = wp->user_info;
+
+end:
+ spin_unlock_irqrestore(&data_lock, flags);
+
+ return 0;
+}
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index f738c1e..1b9c936 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -214,6 +214,7 @@ int dss_wb_set_info(struct omap_dss_output *wb,
struct omap_dss_writeback_info *info);
void dss_wb_get_info(struct omap_dss_output *wb,
struct omap_dss_writeback_info *info);
+int omap_dss_wb_apply(struct omap_dss_output *wb);
/* output */
void dss_register_output(struct omap_dss_output *out);
diff --git a/drivers/video/omap2/dss/writeback.c b/drivers/video/omap2/dss/writeback.c
index be7027b..c05dd54 100644
--- a/drivers/video/omap2/dss/writeback.c
+++ b/drivers/video/omap2/dss/writeback.c
@@ -42,6 +42,12 @@ static inline struct platform_device *writeback_get_wbdev_from_output(struct oma
return out->pdev;
}
+int omapdss_writeback_apply(struct omap_dss_output *wb)
+{
+ return omap_dss_wb_apply(wb);
+}
+EXPORT_SYMBOL(omapdss_writeback_apply);
+
int omapdss_writeback_set_info(struct omap_dss_output *wb,
struct omap_dss_writeback_info *info)
{
diff --git a/include/video/omapdss.h b/include/video/omapdss.h
index 2a3a878..2bc10cb 100644
--- a/include/video/omapdss.h
+++ b/include/video/omapdss.h
@@ -837,6 +837,7 @@ void omapdss_rfbi_set_data_lines(struct omap_dss_device *dssdev,
void omapdss_rfbi_set_interface_timings(struct omap_dss_device *dssdev,
struct rfbi_timings *timings);
+int omapdss_writeback_apply(struct omap_dss_output *wb);
int omapdss_writeback_set_info(struct omap_dss_output *wb,
struct omap_dss_writeback_info *info);
void omapdss_writeback_get_info(struct omap_dss_output *wb,
--
1.7.9.5
^ permalink raw reply related
* [RFC 02/11] OMAPDSS: APPLY: Add get/set info functions for writeback
From: Archit Taneja @ 2012-11-07 14:56 UTC (permalink / raw)
To: tomi.valkeinen; +Cc: linux-fbdev, linux-omap, Archit Taneja
In-Reply-To: <1352299469-17609-1-git-send-email-archit@ti.com>
Writeback contains overlay-like parameters which need to be applied by a user
of writeback.
Create functions in APPLY which get and set user_info of type
omap_dss_writeback_info, these are similar to overlay's dss_ovl_get_info and
dss_ovl_set_info ops. The writeback output driver provides equivalent functions
for a writeback user, these finally call the above APPLY functions.
Add a private data struct for writeback which stores the user_info and it's
state. This struct will be later added with more params to represent the other
levels of the APPLY cache. Add a helper function to retrieve the private data.
Signed-off-by: Archit Taneja <archit@ti.com>
---
drivers/video/omap2/dss/apply.c | 42 +++++++++++++++++++++++++++++++++++
drivers/video/omap2/dss/dss.h | 5 +++++
drivers/video/omap2/dss/writeback.c | 14 ++++++++++++
include/video/omapdss.h | 4 ++++
4 files changed, 65 insertions(+)
diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c
index 7a7b820..b2e4f6a 100644
--- a/drivers/video/omap2/dss/apply.c
+++ b/drivers/video/omap2/dss/apply.c
@@ -106,9 +106,16 @@ struct mgr_priv_data {
struct dss_lcd_mgr_config lcd_config;
};
+struct wb_priv_data {
+
+ bool user_info_dirty;
+ struct omap_dss_writeback_info user_info;
+};
+
static struct {
struct ovl_priv_data ovl_priv_data_array[MAX_DSS_OVERLAYS];
struct mgr_priv_data mgr_priv_data_array[MAX_DSS_MANAGERS];
+ struct wb_priv_data wb_priv_data;
bool irq_enabled;
} dss_data;
@@ -131,6 +138,11 @@ static struct mgr_priv_data *get_mgr_priv(struct omap_overlay_manager *mgr)
return &dss_data.mgr_priv_data_array[mgr->id];
}
+static struct wb_priv_data *get_wb_priv(struct omap_dss_output *wb)
+{
+ return &dss_data.wb_priv_data;
+}
+
void dss_apply_init(void)
{
const int num_ovls = dss_feat_get_num_ovls();
@@ -1465,3 +1477,33 @@ err:
return r;
}
+int dss_wb_set_info(struct omap_dss_output *wb,
+ struct omap_dss_writeback_info *info)
+{
+ struct wb_priv_data *wp = get_wb_priv(wb);
+ unsigned long flags;
+
+ /* TODO: Check validity of info */
+
+ spin_lock_irqsave(&data_lock, flags);
+
+ wp->user_info = *info;
+ wp->user_info_dirty = true;
+
+ spin_unlock_irqrestore(&data_lock, flags);
+
+ return 0;
+}
+
+void dss_wb_get_info(struct omap_dss_output *wb,
+ struct omap_dss_writeback_info *info)
+{
+ struct wb_priv_data *wp = get_wb_priv(wb);
+ unsigned long flags;
+
+ spin_lock_irqsave(&data_lock, flags);
+
+ *info = wp->user_info;
+
+ spin_unlock_irqrestore(&data_lock, flags);
+}
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index f7eb7d6..f738c1e 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -210,6 +210,11 @@ int dss_ovl_set_manager(struct omap_overlay *ovl,
struct omap_overlay_manager *mgr);
int dss_ovl_unset_manager(struct omap_overlay *ovl);
+int dss_wb_set_info(struct omap_dss_output *wb,
+ struct omap_dss_writeback_info *info);
+void dss_wb_get_info(struct omap_dss_output *wb,
+ struct omap_dss_writeback_info *info);
+
/* output */
void dss_register_output(struct omap_dss_output *out);
void dss_unregister_output(struct omap_dss_output *out);
diff --git a/drivers/video/omap2/dss/writeback.c b/drivers/video/omap2/dss/writeback.c
index b5c6406..be7027b 100644
--- a/drivers/video/omap2/dss/writeback.c
+++ b/drivers/video/omap2/dss/writeback.c
@@ -42,6 +42,20 @@ static inline struct platform_device *writeback_get_wbdev_from_output(struct oma
return out->pdev;
}
+int omapdss_writeback_set_info(struct omap_dss_output *wb,
+ struct omap_dss_writeback_info *info)
+{
+ return dss_wb_set_info(wb, info);
+}
+EXPORT_SYMBOL(omapdss_writeback_set_info);
+
+void omapdss_writeback_get_info(struct omap_dss_output *wb,
+ struct omap_dss_writeback_info *info)
+{
+ dss_wb_get_info(wb, info);
+}
+EXPORT_SYMBOL(omapdss_writeback_get_info);
+
struct omap_dss_output *omap_dss_get_writeback(void)
{
return omap_dss_get_output(OMAP_DSS_OUTPUT_WB);
diff --git a/include/video/omapdss.h b/include/video/omapdss.h
index e81fcb2..2a3a878 100644
--- a/include/video/omapdss.h
+++ b/include/video/omapdss.h
@@ -837,6 +837,10 @@ void omapdss_rfbi_set_data_lines(struct omap_dss_device *dssdev,
void omapdss_rfbi_set_interface_timings(struct omap_dss_device *dssdev,
struct rfbi_timings *timings);
+int omapdss_writeback_set_info(struct omap_dss_output *wb,
+ struct omap_dss_writeback_info *info);
+void omapdss_writeback_get_info(struct omap_dss_output *wb,
+ struct omap_dss_writeback_info *info);
#ifdef CONFIG_OMAP4_DSS_WRITEBACK
struct omap_dss_output *omap_dss_get_writeback(void);
#else
--
1.7.9.5
^ permalink raw reply related
* [RFC 01/11] OMAPDSS: Add writeback output driver
From: Archit Taneja @ 2012-11-07 14:56 UTC (permalink / raw)
To: tomi.valkeinen; +Cc: linux-fbdev, linux-omap, Archit Taneja
In-Reply-To: <1352299469-17609-1-git-send-email-archit@ti.com>
Writeback is implemented as an output driver. This lets writeback to connect
to overlay managers, and configure writeback's manager like properties the same
way other output drivers do.
This driver can be considered something similar to the DPI output driver. It
provides functions which configure the writeback's manager-like registers via
apply. One difference though is that these functions won't be used by a panel
driver. They'd be used by a writeback user directly.
Signed-off-by: Archit Taneja <archit@ti.com>
---
drivers/video/omap2/dss/Kconfig | 13 +++++
drivers/video/omap2/dss/Makefile | 1 +
drivers/video/omap2/dss/core.c | 6 +++
drivers/video/omap2/dss/dss.h | 6 +++
drivers/video/omap2/dss/writeback.c | 102 +++++++++++++++++++++++++++++++++++
include/video/omapdss.h | 10 ++++
6 files changed, 138 insertions(+)
create mode 100644 drivers/video/omap2/dss/writeback.c
diff --git a/drivers/video/omap2/dss/Kconfig b/drivers/video/omap2/dss/Kconfig
index 50e8802..9e52d4b 100644
--- a/drivers/video/omap2/dss/Kconfig
+++ b/drivers/video/omap2/dss/Kconfig
@@ -99,6 +99,19 @@ config OMAP2_DSS_DSI
See http://www.mipi.org/ for DSI specifications.
+config OMAP4_DSS_WRITEBACK
+ bool "writeback support"
+ default n
+ help
+ writeback is a DISPC pipeline that takes pixel data from an overlay
+ output or a overlay manager output and writes it back into a specified
+ address in memory.
+
+ writeback pipeline allows us to take benefit of the hardware
+ processing available inside the DISPC like color space conversion,
+ rescaling, compositing etc and perform either a memory-to-memory
+ transfer with data processing, or capture a displayed frame.
+
config OMAP2_DSS_MIN_FCK_PER_PCK
int "Minimum FCK/PCK ratio (for scaling)"
range 0 32
diff --git a/drivers/video/omap2/dss/Makefile b/drivers/video/omap2/dss/Makefile
index 4070191..211a290 100644
--- a/drivers/video/omap2/dss/Makefile
+++ b/drivers/video/omap2/dss/Makefile
@@ -8,4 +8,5 @@ omapdss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o
omapdss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o
omapdss-$(CONFIG_OMAP4_DSS_HDMI) += hdmi.o \
hdmi_panel.o ti_hdmi_4xxx_ip.o
+omapdss-$(CONFIG_OMAP4_DSS_WRITEBACK) += writeback.o
ccflags-$(CONFIG_OMAP2_DSS_DEBUG) += -DDEBUG
diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c
index b1a9ce1..4040868 100644
--- a/drivers/video/omap2/dss/core.c
+++ b/drivers/video/omap2/dss/core.c
@@ -528,6 +528,9 @@ static int (*dss_output_drv_reg_funcs[])(void) __initdata = {
#ifdef CONFIG_OMAP4_DSS_HDMI
hdmi_init_platform_driver,
#endif
+#ifdef CONFIG_OMAP4_DSS_WRITEBACK
+ writeback_init_platform_driver,
+#endif
};
static void (*dss_output_drv_unreg_funcs[])(void) __exitdata = {
@@ -549,6 +552,9 @@ static void (*dss_output_drv_unreg_funcs[])(void) __exitdata = {
#ifdef CONFIG_OMAP4_DSS_HDMI
hdmi_uninit_platform_driver,
#endif
+#ifdef CONFIG_OMAP4_DSS_WRITEBACK
+ writeback_uninit_platform_driver,
+#endif
};
static bool dss_output_drv_loaded[ARRAY_SIZE(dss_output_drv_reg_funcs)];
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index 84a7f6a..f7eb7d6 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -528,6 +528,12 @@ bool hdmi_mode_has_audio(void);
int hdmi_audio_config(struct omap_dss_audio *audio);
#endif
+/* Writeback */
+#ifdef CONFIG_OMAP4_DSS_WRITEBACK
+int writeback_init_platform_driver(void) __init;
+void writeback_uninit_platform_driver(void) __exit;
+#endif
+
/* RFBI */
int rfbi_init_platform_driver(void) __init;
void rfbi_uninit_platform_driver(void) __exit;
diff --git a/drivers/video/omap2/dss/writeback.c b/drivers/video/omap2/dss/writeback.c
new file mode 100644
index 0000000..b5c6406
--- /dev/null
+++ b/drivers/video/omap2/dss/writeback.c
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2012 Texas Instruments
+ * Author: Archit Taneja <archit@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 "WB"
+
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include <video/omapdss.h>
+
+#include "dss.h"
+
+struct writeback_data {
+ struct mutex lock;
+
+ struct omap_dss_output output;
+};
+
+static inline struct writeback_data *writeback_get_drv_data(struct platform_device *wbdev)
+{
+ return dev_get_drvdata(&wbdev->dev);
+}
+
+static inline struct platform_device *writeback_get_wbdev_from_output(struct omap_dss_output *out)
+{
+ return out->pdev;
+}
+
+struct omap_dss_output *omap_dss_get_writeback(void)
+{
+ return omap_dss_get_output(OMAP_DSS_OUTPUT_WB);
+}
+EXPORT_SYMBOL(omap_dss_get_writeback);
+
+static void __init writeback_init_output(struct platform_device *pdev,
+ struct writeback_data *wb_data)
+{
+ struct omap_dss_output *out = &wb_data->output;
+
+ dss_register_output(out);
+
+ out->pdev = pdev;
+ out->id = OMAP_DSS_OUTPUT_WB;
+ out->type = OMAP_DISPLAY_TYPE_NONE;
+}
+
+static int __init omap_writeback_probe(struct platform_device *pdev)
+{
+ struct writeback_data *wb_data;
+
+ wb_data = devm_kzalloc(&pdev->dev, sizeof(*wb_data), GFP_KERNEL);
+ if (!wb_data)
+ return -ENOMEM;
+
+ dev_set_drvdata(&pdev->dev, wb_data);
+
+ mutex_init(&wb_data->lock);
+
+ writeback_init_output(pdev, wb_data);
+
+ return 0;
+}
+
+static int __exit omap_writeback_remove(struct platform_device *pdev)
+{
+ return 0;
+}
+
+static struct platform_driver omap_writeback_driver = {
+ .remove = __exit_p(omap_writeback_remove),
+ .driver = {
+ .name = "omapdss_writeback",
+ .owner = THIS_MODULE,
+ },
+};
+
+int __init writeback_init_platform_driver(void)
+{
+ return platform_driver_probe(&omap_writeback_driver,
+ omap_writeback_probe);
+}
+
+void __exit writeback_uninit_platform_driver(void)
+{
+ platform_driver_unregister(&omap_writeback_driver);
+}
diff --git a/include/video/omapdss.h b/include/video/omapdss.h
index b1248c2..e81fcb2 100644
--- a/include/video/omapdss.h
+++ b/include/video/omapdss.h
@@ -217,6 +217,7 @@ enum omap_dss_output_id {
OMAP_DSS_OUTPUT_DSI2 = 1 << 4,
OMAP_DSS_OUTPUT_VENC = 1 << 5,
OMAP_DSS_OUTPUT_HDMI = 1 << 6,
+ OMAP_DSS_OUTPUT_WB = 1 << 7,
};
/* RFBI */
@@ -836,4 +837,13 @@ void omapdss_rfbi_set_data_lines(struct omap_dss_device *dssdev,
void omapdss_rfbi_set_interface_timings(struct omap_dss_device *dssdev,
struct rfbi_timings *timings);
+#ifdef CONFIG_OMAP4_DSS_WRITEBACK
+struct omap_dss_output *omap_dss_get_writeback(void);
+#else
+static inline struct omap_dss_output *omap_dss_get_writeback(void)
+{
+ return NULL;
+}
+#endif
+
#endif
--
1.7.9.5
^ permalink raw reply related
* [RFC 00/11] OMAPDSS: Add writeback mem to mem mode support
From: Archit Taneja @ 2012-11-07 14:56 UTC (permalink / raw)
To: tomi.valkeinen; +Cc: linux-fbdev, linux-omap, Archit Taneja
This series adds a writeback output driver and makes changes in APPLY to get
mem to mem mode working when writeback is connected to an overlay manager.
A user of writeback is supposed to use the fuctions exported by the writeback
output driver to configure writeback and start a mem to mem transfer. The output
driver internally calls function in APPLY to configure the writeback related
DISPC registers.
An example usage of writeback in omapfb is provided as the last patch.
Reference tree:
git://gitorious.org/~boddob/linux-omap-dss2/archit-dss2-clone.git 3.8/wb_mem_to_mem
Archit Taneja (11):
OMAPDSS: Add writeback output driver
OMAPDSS: APPLY: Add get/set info functions for writeback
OMAPDSS: APPLY: Apply writeback configurations
OMAPDSS: writeback: Configure writeback input size
OMAPDSS: APPLY: Add writeback enable/disable funcs
OMAPDSS: APPLY: configure channel_in for writeback
OMAPDSS: writeback: add mechanism to do mem to mem updates
OMAPDSS: APPLY: Check if overlay is connected in mem to mem mode
OMAPDSS: FEATURES: Add writeback as supported outputs for OMAP4
managers
ARCH: ARM: OMAP: Create a platform device for writeback
Example: OMAPFB: clear framebuffers using writeback
arch/arm/mach-omap2/display.c | 9 +
drivers/video/omap2/dss/Kconfig | 13 ++
drivers/video/omap2/dss/Makefile | 1 +
drivers/video/omap2/dss/apply.c | 321 ++++++++++++++++++++++++++-
drivers/video/omap2/dss/core.c | 6 +
drivers/video/omap2/dss/dss.h | 24 +++
drivers/video/omap2/dss/dss_features.c | 6 +-
drivers/video/omap2/dss/writeback.c | 345 ++++++++++++++++++++++++++++++
drivers/video/omap2/omapfb/omapfb-main.c | 132 +++++++++++-
include/video/omapdss.h | 22 ++
10 files changed, 873 insertions(+), 6 deletions(-)
create mode 100644 drivers/video/omap2/dss/writeback.c
--
1.7.9.5
^ permalink raw reply
* Re: [PATCH 12/12] OMAPDSS: DPI: always use DSI PLL if available
From: Rob Clark @ 2012-11-07 14:32 UTC (permalink / raw)
To: Tomi Valkeinen
Cc: Tomi Valkeinen, Archit Taneja, linux-omap, linux-fbdev, dri-devel
In-Reply-To: <509A3171.8010100@ti.com>
On Wed, Nov 7, 2012 at 4:01 AM, Tomi Valkeinen <tomi.valkeinen@ti.com> wrote:
> On 2012-11-06 16:40, Rob Clark wrote:
>
>> I mean, similar to how we handle the subdev for dmm.. the
>> omap_drm_init() does the platform_driver_register() for the dmm device
>> before the platform_driver_register() for omapdrm itself, so we know
>> if there is a dmm device, the driver gets probed first before omapdrm.
>
> Well, I consider that a bit hacky too. That's not how linux device
> framework is supposed to be used. I know it makes life easier to do the
> registering like that, though.
>
>> It could be a matter of iterating through a list, or something like
>> this.. that is basically an implementation detail. But the end result
>> is that the order the drivers are registered is controlled so the
>> probe sequence works out properly (not to mention suspend/resume
>> sequence).
>
> I feel that this kind of solution just tries to solve the generic
> problem of init/suspend ordering in a single driver, instead of fixing
> the device framework itself.
>
> Or, of course it's possible that our drive architecture just sucks, and
> the device framework is fine. In that case the workaround is even worse,
> and we should fix our drivers.
well, I guess by splitting things up into many pieces, we push the
device framework in ways that it is not pushed on desktop. But I've
enough on my plate so I wasn't going to volunteer to try and fix that
;-)
controlling the order that the drivers are registered is currently the
most straightforward way to not have problems w/ probe/init/suspend..
>>> I think we should support proper hotplugging of the panels. This would
>>> fix the problem about init order, but it would also give us device
>>> hotplug support. Obviously nobody is going to solder panel to a running
>>> board, but I don't see any reason why panels, or, more likely, panels on
>>> an add-on boards (like the capes being discussed in omap ml) would not
>>> be hotpluggable using whatever connector is used on the particular use case.
>>>
>>> And even if we don't support removing of the devices, things like the
>>> add-on capes could cause the panel on the cape to be identified at some
>>> late time (the panel is not described in the board file or DT data, but
>>> found at runtime depending on the ID of the cape). This would add
>>> another step to the init sequence that should be just right, if we don't
>>> support hotplug.
>>
>> If capes are really hot-pluggable, then maybe it is worth thinking
>> about how to make this more dynamic. Although it is a bigger problem,
>> which involves userspace being aware that connectors can dynamically
>> appear/disappear. And the dynamic disappearing is something I worry
>> about more.. it adds the possibility of all sorts of interesting race
>> conditions, such as connectors disappearing in the middle of modeset.
>> I prefer not making things more complicated and error prone than they
>> need to be. If there is not a legitimate use case for connector hw
>> dynamically appearing/disappearing then I don't think we should go
>> there. It sounds nice and simple and clean, but in reality I think it
>> just introduces a whole lot of ways for things to go wrong. A wise
>
> Yes, I agree that it complicates things.
>
>> man once said:
>>
>> https://github.com/robclark/kernel-omap4/blob/master/Documentation/SubmittingPatches#L700
>
> I've done things simple lots of times in the omapdss driver, only to
> have to rewrite the thing in more complex way later to accommodate new
> scenarios. I think it's good to write the code in a bit more generic way
> than the use case at the moment of writing requires, because more often
> than not, it'll save time in the future.
well, if it is not effecting userspace ABI, then I think, when in
doubt I prefer to start simple. It can always be changed later if
needed.
> Hotplugging is not some abstract future scenario, we already have
> hardware that could use it. For example, omap3 SDP board has a
> switchable output to DVI or LCD panel. In this case we know what the two
> options are, but the disabled component is still effectually removed
> from the system, and plugged back in when it's enabled.
I would look at this as two different connectors which can not be used
at the same time. You have this scenario with desktop graphics cards.
> Hotplug is not a high priority item, but I do wish we get it supported
> in common panel framework. Then it's at least possible to extend drm in
> the future to support it.
>
>
>
> Anyway, this makes me wonder... omapdrm currently maps the elements of
> the whole video pipeline to drm elements (encoder, connector, etc).
> Would it make more sense to just map the DISPC to these drm elements?
> Connector would then be the output from DISPC.
I think:
plane->overlay
crtc->manager
is pretty clear. And really
encoder->output
should be the way it is.. on the branch w/ omapdss/omapdrm kms
re-write, this is how it is for plane/crtc, except for now:
encoder+connector->dssdev
Basically the encoder is doing the "control" stuff (power on/off, set
timings, etc), and the connector is only doing non control stuff
(detect, reading edid, etc).
But I think this will probably change a bit as CFP comes into the
picture. Currently the drm connector is somewhat a "passive" element,
but I think this will have to change a bit w/ CFP.
> This would map the drm elements to the static hardware blocks, and the
> meaning of those blocks would be quite similar to what they are in the
> desktop world (I guess).
>
> The panel driver, the external chips, and the DSS internal output blocks
> (dsi, dpi, ...) would be handled separately from those drm elements. The
> DSS internal blocks are static, of course, but they can be effectively
> considered the same way as external chips.
I think dsi/dpi/etc map to encoder. The big question is where the
panel's fit. But to userspace somehow this should look like
connectors. I think:
encoder->output
connector->panel
could work.. although connector is less passive than KMS currently
assumes. And "panel" could really be a whole chain in the case of
bridge chips, etc. I don't know, maybe there are better ways. But I
think userspace really just wants to know "which monitor" which is
basically connector.
> The omapdrm driver needs of course to access those separate elements
> also, but that shouldn't be a problem. If omapdrm needs to call a
> function in the panel driver, all it needs to do is go through the chain
> to find the panel. Well, except if one output connected two two panels
> via a bridge chip...
yeah, that is a really ugly case in our hw since it is quite
non-transparent (ie. implications about use of planes, etc).
> And if drm is at some point extended to support panel drivers, or chains
> of external display entities, it would be easier to add that support.
>
> What would it require the manage the elements like that? Would it help?
> It sounds to me that this would simplify the model.
I'm not really entirely sure.. other than at least other drivers
supporting CFP will have the same requirements ;-)
I guess the two best options are either bury some sort of chain of
panel drivers in the connector, or introduce some internal elements in
DRM which are not necessarily visible to userspace. (Or at least
userspace should have the option to ignore it for backwards
compatibility. For atomic pageflip/modeset, the converting of
everything to properties makes it easier to think about exposing new
KMS mode object types to userspace.)
Either way, I think we need to break this into stages. And first
stage is to ignore chains of panel drivers and just support single
panel drivers (ignoring bridges, etc). I'm not entirely sure what the
second stage should be, but am open to suggestions and seeing how it
evolves.
BR,
-R
> Tomi
>
>
^ permalink raw reply
* Re: i.MX 257 ARM-CPU: framebuffer error "division by zero"
From: Stefan Koch @ 2012-11-07 14:23 UTC (permalink / raw)
To: linux-fbdev
In-Reply-To: <509A6964.5090305@gmail.com>
This mail includes the described two attached screenshots from first mail:
CODE-Screenshot: http://imageshack.us/a/img23/7507/codet.png
BACKTRACE-Screenshot: http://imageshack.us/a/img21/3209/backtrace.png
^ permalink raw reply
* i.MX 257 ARM-CPU: framebuffer error "division by zero"
From: Stefan Koch @ 2012-11-07 14:00 UTC (permalink / raw)
To: linux-fbdev
Hello,
I'm porting Linux 3.6.2 to a board with Freescale IMX 257 ARMv5-CPU.
Linux works mostly, kernel can run, and Debian can run with kernel, too.
So I can get access via UART to Debian's Linux console and install
packages via apt-get and so on.
The next step is to enable the graphics support.
This does the line "imx25_add_imx_fb(&mx25cevipro_fb_pdata);" that
enables the fb.
Linux kernel works fine when this line is commented out, but when it's
active the kernel stops working before print out the first kernel
message on serial line.
So openocd prints with general U-Boot kernel boot (with enabled fb):
WARNING: unknown debug reason: 0xf
ThumbEE -- incomplete support
target state: halted
target halted in ThumbEE state due to debug-request, current mode: System
cpsr: 0xffffffff pc: 0xfffffff9
MMU: enabled, D-Cache: enabled, I-Cache: enabled
If I use gdb for loading and step through the source beginning from
add_imx_fb(...) line then I will get these output from openocd:
Unable to set 32 bit software breakpoint at address 8057c7e0 - check
that memory is read/writable
Unable to set 32 bit software breakpoint at address 8057c7e0 - check
that memory is read/writable
breakpoint not set
> poll
background polling: on
TAP: imx25.cpu (enabled)
target state: halted
target halted in ARM state due to breakpoint, current mode: Supervisor
cpsr: 0x40000013 pc: 0x8057c7e0
MMU: enabled, D-Cache: enabled, I-Cache: enabled
pc doesn't change anymore (so there are no code steps possible after
this moment).
The board bsp (with the add_imx_fb(...) line) is this one:
http://paste.debian.net/hidden/10d828f8/
And this is based on bsp from Freescale MX25 3DS board:
http://paste.debian.net/hidden/50ada4ee/ or
arch/arm/mach-imx/mach-mx25_3ds.c in kernel tree
There a two screenshots from ddd-Debugger attached.
The on is code view, and the other the backtrace.
What could be the problem?
Could be a kernel bug?
Could be this a problem?:
"imx-sdma imx35-sdma: firmware not found" appears when booting the
kernel without enabled fb.
In FB enabled kernel's the last debugable function is
imx_add_platform_device_dmamask()
Both have "dma" in the string...
But for loading a firmware from filesystem, the kernel crashes to early,
I think.
(The display is connected via LVDS).
-------------------------
If I add "video=imxfb:SVGA-16@60" to kernel command line, then there are
new messages when init fb within BSP file:
Division by zero in kernel.
[<80019ba4>] (unwind_backtrace+0x0/0xf4) from [<8022accc>] (Ldiv0+0x8/0x10)
[<8022accc>] (Ldiv0+0x8/0x10) from [<8022ac9c>] (__aeabi_uidivmod+0x8/0x18)
[<8022ac9c>] (__aeabi_uidivmod+0x8/0x18) from [<80254198>]
(cfb_imageblit+0x1fc/0x4b0)
[<80254198>] (cfb_imageblit+0x1fc/0x4b0) from [<80251c94>]
(soft_cursor+0x158/0x1bc)
[<80251c94>] (soft_cursor+0x158/0x1bc) from [<80251664>]
(bit_cursor+0x4ac/0x4c8)
[<80251664>] (bit_cursor+0x4ac/0x4c8) from [<8024bcd8>]
(fb_flashcursor+0x108/0x124)
[<8024bcd8>] (fb_flashcursor+0x108/0x124) from [<8003cc00>]
(process_one_work+0x188/0x4fc)
[<8003cc00>] (process_one_work+0x188/0x4fc) from [<8003d458>]
(worker_thread+0x130/0x598)
[<8003d458>] (worker_thread+0x130/0x598) from [<80043ef0>]
(kthread+0x8c/0x98)
[<80043ef0>] (kthread+0x8c/0x98) from [<80015268>]
(kernel_thread_exit+0x0/0x8)
Division by zero in kernel.
Without this command line parameter the "cpsr: 0xffffffff pc:
0xfffffff9" error still occurs.
Is this a bug in the driver?
Thank you
Stefan Koch
^ permalink raw reply
* Re: tty, vt: lockdep warnings
From: Sasha Levin @ 2012-11-07 13:47 UTC (permalink / raw)
To: Alan Cox
Cc: Dave Jones, Hugh Dickins, Sasha Levin, Daniel Vetter,
Greg Kroah-Hartman, Jiri Slaby, linux-kernel, linux-fbdev,
florianSchandinat
In-Reply-To: <20121106173845.4a50d661@pyramind.ukuu.org.uk>
On 11/06/2012 12:38 PM, Alan Cox wrote:
>> > The root
>> > cause is loading two different framebuffers with one taking over from
>> > another - that should be an obscure corner case and once the fuzz testing
>> > can avoid.
>> >
>> > I had a semi-informed poke at this and came up with a possible patch (not very tested)
>>
>> If this fixes the real problems we've been seeing, I'll dance a jig.
>
> Youtube...
+1
> At this point my bigger concern is that it'll just make something else
> warn instead. The underlying problem is that fbcon layer implements a
> single threaded notifier whose locking semantics are at best random. It's
> not calld with a specific set of locks each time. Possibly it sohuld be
> two notifiers (one for fb stuff, one for console layer stuff) but the
> entire layer is horrible. I live in home the KMS guys will rip out the
> useful bits and build a straight kms fb layer with refcounting and the
> like 8)
>
> Testing certainly needed and if it's still blowing up then hopefully
> further traces will help fix up the other cases we don't know about.
So the good news are that the original lockdep splat I've reported is gone.
The semi-bad news are that there's a new one. It happens less frequently
but I assume it's not a new splat either, but was well hidden behind the
other splat.
[ 1885.997312] ===========================
[ 1885.997312] [ INFO: possible circular locking dependency detected ]
[ 1885.997316] 3.7.0-rc4-next-20121106-sasha-00008-g353b62f #117 Tainted: G W
[ 1885.997316] -------------------------------------------------------
[ 1885.997319] trinity-child26/7820 is trying to acquire lock:
[ 1885.997330] (&fb_info->lock){+.+.+.}, at: [<ffffffff81a665d1>] lock_fb_info+0x21/0x50
[ 1885.997331]
[ 1885.997331] but task is already holding lock:
[ 1885.997336] (console_lock){+.+.+.}, at: [<ffffffff81a6c469>] store_modes+0x59/0x100
[ 1885.997337]
[ 1885.997337] which lock already depends on the new lock.
[ 1885.997337]
[ 1885.997338]
[ 1885.997338] the existing dependency chain (in reverse order) is:
[ 1885.997341]
[ 1885.997341] -> #1 (console_lock){+.+.+.}:
[ 1885.997347] [<ffffffff8118536a>] lock_acquire+0x1aa/0x240
[ 1885.997351] [<ffffffff8110b618>] console_lock+0x68/0x70
[ 1885.997354] [<ffffffff81a689b2>] register_framebuffer+0x242/0x2a0
[ 1885.997359] [<ffffffff8390e4bc>] vga16fb_probe+0x1c0/0x227
[ 1885.997364] [<ffffffff81e6b472>] platform_drv_probe+0x12/0x20
[ 1885.997369] [<ffffffff81e69e95>] driver_probe_device+0x155/0x340
[ 1885.997372] [<ffffffff81e6a15e>] __device_attach+0x2e/0x50
[ 1885.997375] [<ffffffff81e682d6>] bus_for_each_drv+0x56/0xa0
[ 1885.997379] [<ffffffff81e69a88>] device_attach+0x88/0xc0
[ 1885.997382] [<ffffffff81e68516>] bus_probe_device+0x36/0xd0
[ 1885.997385] [<ffffffff81e6639f>] device_add+0x4df/0x750
[ 1885.997388] [<ffffffff81e6bda8>] platform_device_add+0x1e8/0x280
[ 1885.997393] [<ffffffff85b0f35a>] vga16fb_init+0x8d/0xbb
[ 1885.997399] [<ffffffff85acccb2>] do_one_initcall+0x7a/0x135
[ 1885.997402] [<ffffffff838db8d9>] kernel_init+0x299/0x470
[ 1885.997406] [<ffffffff83a98fbc>] ret_from_fork+0x7c/0xb0
[ 1885.997409]
[ 1885.997409] -> #0 (&fb_info->lock){+.+.+.}:
[ 1885.997413] [<ffffffff811825af>] __lock_acquire+0x14df/0x1ca0
[ 1885.997416] [<ffffffff8118536a>] lock_acquire+0x1aa/0x240
[ 1885.997421] [<ffffffff83a944d9>] __mutex_lock_common+0x59/0x5a0
[ 1885.997425] [<ffffffff83a94a5f>] mutex_lock_nested+0x3f/0x50
[ 1885.997427] [<ffffffff81a665d1>] lock_fb_info+0x21/0x50
[ 1885.997430] [<ffffffff81a68b95>] fb_new_modelist+0xf5/0x140
[ 1885.997433] [<ffffffff81a6c4ac>] store_modes+0x9c/0x100
[ 1885.997436] [<ffffffff81e65013>] dev_attr_store+0x13/0x20
[ 1885.997440] [<ffffffff812f820a>] sysfs_write_file+0xfa/0x150
[ 1885.997444] [<ffffffff8127a220>] vfs_write+0xb0/0x180
[ 1885.997447] [<ffffffff8127a3e0>] sys_write+0x50/0xa0
[ 1885.997450] [<ffffffff83a99298>] tracesys+0xe1/0xe6
[ 1885.997451]
[ 1885.997451] other info that might help us debug this:
[ 1885.997451]
[ 1885.997452] Possible unsafe locking scenario:
[ 1885.997452]
[ 1885.997453] CPU0 CPU1
[ 1885.997454] ---- ----
[ 1885.997456] lock(console_lock);
[ 1885.997458] lock(&fb_info->lock);
[ 1885.997460] lock(console_lock);
[ 1885.997462] lock(&fb_info->lock);
[ 1885.997463]
[ 1885.997463] *** DEADLOCK ***
[ 1885.997463]
[ 1885.997464] 3 locks held by trinity-child26/7820:
[ 1885.997470] #0: (&buffer->mutex){+.+.+.}, at: [<ffffffff812f8153>] sysfs_write_file+0x43/0x150
[ 1885.997475] #1: (s_active#388){.+.+.+}, at: [<ffffffff812f81f2>] sysfs_write_file+0xe2/0x150
[ 1885.997481] #2: (console_lock){+.+.+.}, at: [<ffffffff81a6c469>] store_modes+0x59/0x100
[ 1885.997481]
[ 1885.997481] stack backtrace:
[ 1885.997484] Pid: 7820, comm: trinity-child26 Tainted: G W 3.7.0-rc4-next-20121106-sasha-00008-g353b62f #117
[ 1885.997485] Call Trace:
[ 1885.997492] [<ffffffff83a3c736>] print_circular_bug+0x1fb/0x20c
[ 1885.997496] [<ffffffff811825af>] __lock_acquire+0x14df/0x1ca0
[ 1885.997499] [<ffffffff81a01dc3>] ? debug_smp_processor_id+0x23/0x120
[ 1885.997504] [<ffffffff810a3da6>] ? kvm_clock_read+0x46/0x80
[ 1885.997508] [<ffffffff81152fa5>] ? sched_clock_local+0x25/0xa0
[ 1885.997511] [<ffffffff8118536a>] lock_acquire+0x1aa/0x240
[ 1885.997514] [<ffffffff81a665d1>] ? lock_fb_info+0x21/0x50
[ 1885.997517] [<ffffffff83a944d9>] __mutex_lock_common+0x59/0x5a0
[ 1885.997520] [<ffffffff81a665d1>] ? lock_fb_info+0x21/0x50
[ 1885.997523] [<ffffffff81180d3a>] ? __lock_is_held+0x5a/0x80
[ 1885.997526] [<ffffffff81a665d1>] ? lock_fb_info+0x21/0x50
[ 1885.997531] [<ffffffff8125d4dd>] ? kfree+0x20d/0x330
[ 1885.997534] [<ffffffff83a94a5f>] mutex_lock_nested+0x3f/0x50
[ 1885.997537] [<ffffffff81a665d1>] lock_fb_info+0x21/0x50
[ 1885.997539] [<ffffffff81a68b95>] fb_new_modelist+0xf5/0x140
[ 1885.997543] [<ffffffff81a6c4ac>] store_modes+0x9c/0x100
[ 1885.997546] [<ffffffff81e65013>] dev_attr_store+0x13/0x20
[ 1885.997553] [<ffffffff812f820a>] sysfs_write_file+0xfa/0x150
[ 1885.997556] [<ffffffff8127a220>] vfs_write+0xb0/0x180
[ 1885.997558] [<ffffffff8127a3e0>] sys_write+0x50/0xa0
[ 1885.997561] [<ffffffff83a99298>] tracesys+0xe1/0xe6
[ 1885.990746] irq event stamp: 35487
[ 1885.990746] hardirqs last enabled at (35487): [<ffffffff83a977fb>] _raw_spin_unlock_irq+0x2b/0x80
[ 1885.990746] hardirqs last disabled at (35486): [<ffffffff83a975da>] _raw_spin_lock_irq+0x2a/0x90
[ 1885.990746] softirqs last enabled at (34856): [<ffffffff811139a2>] __do_softirq+0x372/0x440
[ 1885.990746] softirqs last disabled at (34831): [<ffffffff83a9a4fc>] call_softirq+0x1c/0x30
^ permalink raw reply
* Re: [PATCH 02/10] arm: at91: move platfarm_data to include/linux/platform_data/atmel.h
From: Marc Kleine-Budde @ 2012-11-07 12:20 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1352287374-25176-2-git-send-email-plagnioj@jcrosoft.com>
[-- Attachment #1: Type: text/plain, Size: 1147 bytes --]
On 11/07/2012 12:22 PM, Jean-Christophe PLAGNIOL-VILLARD wrote:
> Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
> Cc: Nicolas Ferre <nicolas.ferre@atmel.com>
> Cc: linux-ide@vger.kernel.org
> Cc: linux-input@vger.kernel.org
> Cc: linux-mmc@vger.kernel.org
> Cc: linux-can@vger.kernel.org
> Cc: netdev@vger.kernel.org
> Cc: linux-pcmcia@lists.infradead.org
> Cc: rtc-linux@googlegroups.com
> Cc: spi-devel-general@lists.sourceforge.net
> Cc: linux-serial@vger.kernel.org
> Cc: linux-usb@vger.kernel.org
> Cc: linux-fbdev@vger.kernel.org
> ---
> HI all,
>
> If it's ok with everyone this will go via at91
> with the patch serie than clean up the include/mach
Fine with me.
> For preparation to switch to arm multiarch kernel
Acked-by: Marc Kleine-Budde <mkl@pengutronix.de> (for the CAN related changes)
Marc
--
Pengutronix e.K. | Marc Kleine-Budde |
Industrial Linux Solutions | Phone: +49-231-2826-924 |
Vertretung West/Dortmund | Fax: +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686 | http://www.pengutronix.de |
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 259 bytes --]
^ permalink raw reply
* [PATCH 02/10] arm: at91: move platfarm_data to include/linux/platform_data/atmel.h
From: Jean-Christophe PLAGNIOL-VILLARD @ 2012-11-07 11:22 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1352287374-25176-1-git-send-email-plagnioj@jcrosoft.com>
Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
Cc: Nicolas Ferre <nicolas.ferre@atmel.com>
Cc: linux-ide@vger.kernel.org
Cc: linux-input@vger.kernel.org
Cc: linux-mmc@vger.kernel.org
Cc: linux-can@vger.kernel.org
Cc: netdev@vger.kernel.org
Cc: linux-pcmcia@lists.infradead.org
Cc: rtc-linux@googlegroups.com
Cc: spi-devel-general@lists.sourceforge.net
Cc: linux-serial@vger.kernel.org
Cc: linux-usb@vger.kernel.org
Cc: linux-fbdev@vger.kernel.org
---
HI all,
If it's ok with everyone this will go via at91
with the patch serie than clean up the include/mach
For preparation to switch to arm multiarch kernel
Best Regards,
J.
arch/arm/mach-at91/include/mach/board.h | 55 ----------------------
arch/avr32/mach-at32ap/include/mach/board.h | 7 ---
drivers/ata/pata_at91.c | 2 +-
drivers/input/touchscreen/atmel_tsadcc.c | 2 +-
drivers/mmc/host/atmel-mci.c | 2 +-
drivers/net/can/at91_can.c | 3 +-
drivers/net/ethernet/cadence/at91_ether.c | 2 +-
drivers/pcmcia/at91_cf.c | 2 +-
drivers/rtc/rtc-at91sam9.c | 2 +-
drivers/spi/spi-atmel.c | 2 +-
drivers/tty/serial/atmel_serial.c | 2 +-
drivers/usb/gadget/at91_udc.c | 2 +-
drivers/usb/gadget/atmel_usba_udc.c | 2 +-
drivers/usb/host/ohci-at91.c | 2 +-
drivers/video/atmel_lcdfb.c | 2 +-
include/linux/platform_data/atmel.h | 67 +++++++++++++++++++++++++++
16 files changed, 80 insertions(+), 76 deletions(-)
diff --git a/arch/arm/mach-at91/include/mach/board.h b/arch/arm/mach-at91/include/mach/board.h
index c55a436..662451d 100644
--- a/arch/arm/mach-at91/include/mach/board.h
+++ b/arch/arm/mach-at91/include/mach/board.h
@@ -31,42 +31,15 @@
#ifndef __ASM_ARCH_BOARD_H
#define __ASM_ARCH_BOARD_H
-#include <linux/mtd/partitions.h>
-#include <linux/device.h>
-#include <linux/i2c.h>
-#include <linux/leds.h>
-#include <linux/spi/spi.h>
-#include <linux/usb/atmel_usba_udc.h>
-#include <linux/atmel-mci.h>
-#include <sound/atmel-ac97c.h>
-#include <linux/serial.h>
-#include <linux/platform_data/macb.h>
#include <linux/platform_data/atmel.h>
/* USB Device */
-struct at91_udc_data {
- int vbus_pin; /* high = host powering us */
- u8 vbus_active_low; /* vbus polarity */
- u8 vbus_polled; /* Use polling, not interrupt */
- int pullup_pin; /* active = D+ pulled up */
- u8 pullup_active_low; /* true = pullup_pin is active low */
-};
extern void __init at91_add_device_udc(struct at91_udc_data *data);
/* USB High Speed Device */
extern void __init at91_add_device_usba(struct usba_platform_data *data);
/* Compact Flash */
-struct at91_cf_data {
- int irq_pin; /* I/O IRQ */
- int det_pin; /* Card detect */
- int vcc_pin; /* power switching */
- int rst_pin; /* card reset */
- u8 chipselect; /* EBI Chip Select number */
- u8 flags;
-#define AT91_CF_TRUE_IDE 0x01
-#define AT91_IDE_SWAP_A0_A2 0x02
-};
extern void __init at91_add_device_cf(struct at91_cf_data *data);
/* MMC / SD */
@@ -86,16 +59,6 @@ extern void __init at91_add_device_mci(short mmc_id, struct mci_platform_data *d
extern void __init at91_add_device_eth(struct macb_platform_data *data);
/* USB Host */
-#define AT91_MAX_USBH_PORTS 3
-struct at91_usbh_data {
- int vbus_pin[AT91_MAX_USBH_PORTS]; /* port power-control pin */
- int overcurrent_pin[AT91_MAX_USBH_PORTS];
- u8 ports; /* number of ports on root hub */
- u8 overcurrent_supported;
- u8 vbus_pin_active_low[AT91_MAX_USBH_PORTS];
- u8 overcurrent_status[AT91_MAX_USBH_PORTS];
- u8 overcurrent_changed[AT91_MAX_USBH_PORTS];
-};
extern void __init at91_add_device_usbh(struct at91_usbh_data *data);
extern void __init at91_add_device_usbh_ohci(struct at91_usbh_data *data);
extern void __init at91_add_device_usbh_ehci(struct at91_usbh_data *data);
@@ -124,13 +87,6 @@ extern void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pin
extern struct platform_device *atmel_default_console_device;
-struct atmel_uart_data {
- int num; /* port num */
- short use_dma_tx; /* use transmit DMA? */
- short use_dma_rx; /* use receive DMA? */
- void __iomem *regs; /* virt. base address, if any */
- struct serial_rs485 rs485; /* rs485 settings */
-};
extern void __init at91_add_device_serial(void);
/*
@@ -173,24 +129,13 @@ extern void __init at91_add_device_isi(struct isi_platform_data *data,
bool use_pck_as_mck);
/* Touchscreen Controller */
-struct at91_tsadcc_data {
- unsigned int adc_clock;
- u8 pendet_debounce;
- u8 ts_sample_hold_time;
-};
extern void __init at91_add_device_tsadcc(struct at91_tsadcc_data *data);
/* CAN */
-struct at91_can_data {
- void (*transceiver_switch)(int on);
-};
extern void __init at91_add_device_can(struct at91_can_data *data);
/* LEDs */
extern void __init at91_gpio_leds(struct gpio_led *leds, int nr);
extern void __init at91_pwm_leds(struct gpio_led *leds, int nr);
-/* FIXME: this needs a better location, but gets stuff building again */
-extern int at91_suspend_entering_slow_clock(void);
-
#endif
diff --git a/arch/avr32/mach-at32ap/include/mach/board.h b/arch/avr32/mach-at32ap/include/mach/board.h
index 70742ec..dca9345 100644
--- a/arch/avr32/mach-at32ap/include/mach/board.h
+++ b/arch/avr32/mach-at32ap/include/mach/board.h
@@ -34,13 +34,6 @@ extern struct platform_device *atmel_default_console_device;
#define ATMEL_USART_CTS 0x02
#define ATMEL_USART_CLK 0x04
-struct atmel_uart_data {
- int num; /* port num */
- short use_dma_tx; /* use transmit DMA? */
- short use_dma_rx; /* use receive DMA? */
- void __iomem *regs; /* virtual base address, if any */
- struct serial_rs485 rs485; /* rs485 settings */
-};
void at32_map_usart(unsigned int hw_id, unsigned int line, int flags);
struct platform_device *at32_add_device_usart(unsigned int id);
diff --git a/drivers/ata/pata_at91.c b/drivers/ata/pata_at91.c
index 53d3770..2a96bb2 100644
--- a/drivers/ata/pata_at91.c
+++ b/drivers/ata/pata_at91.c
@@ -27,9 +27,9 @@
#include <linux/libata.h>
#include <linux/platform_device.h>
#include <linux/ata_platform.h>
+#include <linux/platform_data/atmel.h>
#include <mach/at91sam9_smc.h>
-#include <mach/board.h>
#include <asm/gpio.h>
#define DRV_NAME "pata_at91"
diff --git a/drivers/input/touchscreen/atmel_tsadcc.c b/drivers/input/touchscreen/atmel_tsadcc.c
index 201b2d2..ea392ee 100644
--- a/drivers/input/touchscreen/atmel_tsadcc.c
+++ b/drivers/input/touchscreen/atmel_tsadcc.c
@@ -22,7 +22,7 @@
#include <linux/clk.h>
#include <linux/platform_device.h>
#include <linux/io.h>
-#include <mach/board.h>
+#include <linux/platform_data/atmel.h>
#include <mach/cpu.h>
/* Register definitions based on AT91SAM9RL64 preliminary draft datasheet */
diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c
index ddf096e..8689989 100644
--- a/drivers/mmc/host/atmel-mci.c
+++ b/drivers/mmc/host/atmel-mci.c
@@ -28,6 +28,7 @@
#include <linux/slab.h>
#include <linux/stat.h>
#include <linux/types.h>
+#include <linux/platform_data/atmel.h>
#include <linux/mmc/host.h>
#include <linux/mmc/sdio.h>
@@ -40,7 +41,6 @@
#include <asm/unaligned.h>
#include <mach/cpu.h>
-#include <mach/board.h>
#include "atmel-mci-regs.h"
diff --git a/drivers/net/can/at91_can.c b/drivers/net/can/at91_can.c
index fcff73a..994b6ac 100644
--- a/drivers/net/can/at91_can.c
+++ b/drivers/net/can/at91_can.c
@@ -33,12 +33,11 @@
#include <linux/spinlock.h>
#include <linux/string.h>
#include <linux/types.h>
+#include <linux/platform_data/atmel.h>
#include <linux/can/dev.h>
#include <linux/can/error.h>
-#include <mach/board.h>
-
#define AT91_MB_MASK(i) ((1 << (i)) - 1)
/* Common registers */
diff --git a/drivers/net/ethernet/cadence/at91_ether.c b/drivers/net/ethernet/cadence/at91_ether.c
index 4e980a7..35fc6edb 100644
--- a/drivers/net/ethernet/cadence/at91_ether.c
+++ b/drivers/net/ethernet/cadence/at91_ether.c
@@ -31,6 +31,7 @@
#include <linux/clk.h>
#include <linux/gfp.h>
#include <linux/phy.h>
+#include <linux/platform_data/atmel.h>
#include <asm/io.h>
#include <asm/uaccess.h>
@@ -38,7 +39,6 @@
#include <mach/at91rm9200_emac.h>
#include <asm/gpio.h>
-#include <mach/board.h>
#include "at91_ether.h"
diff --git a/drivers/pcmcia/at91_cf.c b/drivers/pcmcia/at91_cf.c
index 9694c1e..01463c7 100644
--- a/drivers/pcmcia/at91_cf.c
+++ b/drivers/pcmcia/at91_cf.c
@@ -17,6 +17,7 @@
#include <linux/interrupt.h>
#include <linux/slab.h>
#include <linux/gpio.h>
+#include <linux/platform_data/atmel.h>
#include <pcmcia/ss.h>
@@ -24,7 +25,6 @@
#include <asm/io.h>
#include <asm/sizes.h>
-#include <mach/board.h>
#include <mach/at91rm9200_mc.h>
#include <mach/at91_ramc.h>
diff --git a/drivers/rtc/rtc-at91sam9.c b/drivers/rtc/rtc-at91sam9.c
index 2dfe7a2..e981798 100644
--- a/drivers/rtc/rtc-at91sam9.c
+++ b/drivers/rtc/rtc-at91sam9.c
@@ -19,8 +19,8 @@
#include <linux/interrupt.h>
#include <linux/ioctl.h>
#include <linux/slab.h>
+#include <linux/platform_data/atmel.h>
-#include <mach/board.h>
#include <mach/at91_rtt.h>
#include <mach/cpu.h>
diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c
index 16d6a83..61fb0ec 100644
--- a/drivers/spi/spi-atmel.c
+++ b/drivers/spi/spi-atmel.c
@@ -19,9 +19,9 @@
#include <linux/interrupt.h>
#include <linux/spi/spi.h>
#include <linux/slab.h>
+#include <linux/platform_data/atmel.h>
#include <asm/io.h>
-#include <mach/board.h>
#include <asm/gpio.h>
#include <mach/cpu.h>
diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
index 3d7e1ee..5660ec2 100644
--- a/drivers/tty/serial/atmel_serial.c
+++ b/drivers/tty/serial/atmel_serial.c
@@ -39,12 +39,12 @@
#include <linux/atmel_pdc.h>
#include <linux/atmel_serial.h>
#include <linux/uaccess.h>
+#include <linux/platform_data/atmel.h>
#include <asm/io.h>
#include <asm/ioctls.h>
#include <asm/mach/serial_at91.h>
-#include <mach/board.h>
#ifdef CONFIG_ARM
#include <mach/cpu.h>
diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c
index 89d90b5..a7b042b 100644
--- a/drivers/usb/gadget/at91_udc.c
+++ b/drivers/usb/gadget/at91_udc.c
@@ -31,6 +31,7 @@
#include <linux/usb/gadget.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
+#include <linux/platform_data/atmel.h>
#include <asm/byteorder.h>
#include <mach/hardware.h>
@@ -38,7 +39,6 @@
#include <asm/irq.h>
#include <asm/gpio.h>
-#include <mach/board.h>
#include <mach/cpu.h>
#include <mach/at91sam9261_matrix.h>
#include <mach/at91_matrix.h>
diff --git a/drivers/usb/gadget/atmel_usba_udc.c b/drivers/usb/gadget/atmel_usba_udc.c
index 9a9bced..a7aed84 100644
--- a/drivers/usb/gadget/atmel_usba_udc.c
+++ b/drivers/usb/gadget/atmel_usba_udc.c
@@ -21,9 +21,9 @@
#include <linux/usb/gadget.h>
#include <linux/usb/atmel_usba_udc.h>
#include <linux/delay.h>
+#include <linux/platform_data/atmel.h>
#include <asm/gpio.h>
-#include <mach/board.h>
#include "atmel_usba_udc.h"
diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c
index 0bf72f9..8e62f81 100644
--- a/drivers/usb/host/ohci-at91.c
+++ b/drivers/usb/host/ohci-at91.c
@@ -16,11 +16,11 @@
#include <linux/platform_device.h>
#include <linux/of_platform.h>
#include <linux/of_gpio.h>
+#include <linux/platform_data/atmel.h>
#include <mach/hardware.h>
#include <asm/gpio.h>
-#include <mach/board.h>
#include <mach/cpu.h>
#ifndef CONFIG_ARCH_AT91
diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c
index 94cac9f..12cf5f3 100644
--- a/drivers/video/atmel_lcdfb.c
+++ b/drivers/video/atmel_lcdfb.c
@@ -19,8 +19,8 @@
#include <linux/backlight.h>
#include <linux/gfp.h>
#include <linux/module.h>
+#include <linux/platform_data/atmel.h>
-#include <mach/board.h>
#include <mach/cpu.h>
#include <asm/gpio.h>
diff --git a/include/linux/platform_data/atmel.h b/include/linux/platform_data/atmel.h
index b0f2c56..dbd6d53 100644
--- a/include/linux/platform_data/atmel.h
+++ b/include/linux/platform_data/atmel.h
@@ -8,6 +8,49 @@
#define __ATMEL_H__
#include <linux/mtd/nand.h>
+#include <linux/mtd/partitions.h>
+#include <linux/device.h>
+#include <linux/i2c.h>
+#include <linux/leds.h>
+#include <linux/spi/spi.h>
+#include <linux/usb/atmel_usba_udc.h>
+#include <linux/atmel-mci.h>
+#include <sound/atmel-ac97c.h>
+#include <linux/serial.h>
+#include <linux/platform_data/macb.h>
+
+ /* USB Device */
+struct at91_udc_data {
+ int vbus_pin; /* high = host powering us */
+ u8 vbus_active_low; /* vbus polarity */
+ u8 vbus_polled; /* Use polling, not interrupt */
+ int pullup_pin; /* active = D+ pulled up */
+ u8 pullup_active_low; /* true = pullup_pin is active low */
+};
+
+ /* Compact Flash */
+struct at91_cf_data {
+ int irq_pin; /* I/O IRQ */
+ int det_pin; /* Card detect */
+ int vcc_pin; /* power switching */
+ int rst_pin; /* card reset */
+ u8 chipselect; /* EBI Chip Select number */
+ u8 flags;
+#define AT91_CF_TRUE_IDE 0x01
+#define AT91_IDE_SWAP_A0_A2 0x02
+};
+
+ /* USB Host */
+#define AT91_MAX_USBH_PORTS 3
+struct at91_usbh_data {
+ int vbus_pin[AT91_MAX_USBH_PORTS]; /* port power-control pin */
+ int overcurrent_pin[AT91_MAX_USBH_PORTS];
+ u8 ports; /* number of ports on root hub */
+ u8 overcurrent_supported;
+ u8 vbus_pin_active_low[AT91_MAX_USBH_PORTS];
+ u8 overcurrent_status[AT91_MAX_USBH_PORTS];
+ u8 overcurrent_changed[AT91_MAX_USBH_PORTS];
+};
/* NAND / SmartMedia */
struct atmel_nand_data {
@@ -24,4 +67,28 @@ struct atmel_nand_data {
unsigned int num_parts;
};
+ /* Serial */
+struct atmel_uart_data {
+ int num; /* port num */
+ short use_dma_tx; /* use transmit DMA? */
+ short use_dma_rx; /* use receive DMA? */
+ void __iomem *regs; /* virt. base address, if any */
+ struct serial_rs485 rs485; /* rs485 settings */
+};
+
+ /* Touchscreen Controller */
+struct at91_tsadcc_data {
+ unsigned int adc_clock;
+ u8 pendet_debounce;
+ u8 ts_sample_hold_time;
+};
+
+/* CAN */
+struct at91_can_data {
+ void (*transceiver_switch)(int on);
+};
+
+/* FIXME: this needs a better location, but gets stuff building again */
+extern int at91_suspend_entering_slow_clock(void);
+
#endif /* __ATMEL_H__ */
--
1.7.10.4
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox