* Re: [patch] tgafb: potential NULL dereference in init
From: Dan Carpenter @ 2013-08-27 1:16 UTC (permalink / raw)
To: linux-fbdev
In-Reply-To: <20130826145610.GA12428@elgon.mountain>
On Mon, Aug 26, 2013 at 07:51:04PM +0200, Geert Uytterhoeven wrote:
> On Mon, Aug 26, 2013 at 4:56 PM, Dan Carpenter <dan.carpenter@oracle.com> wrote:
> > --- a/drivers/video/tgafb.c
> > +++ b/drivers/video/tgafb.c
> > @@ -1475,7 +1475,7 @@ tgafb_init_fix(struct fb_info *info)
> > int tga_bus_pci = TGA_BUS_PCI(par->dev);
> > int tga_bus_tc = TGA_BUS_TC(par->dev);
> > u8 tga_type = par->tga_type;
> > - const char *tga_type_name = NULL;
> > + const char *tga_type_name;
>
> Now the real compiler (at least some versions of gcc) will complain
> about an uninitialized variable...
Oh crap! The compiler is totally correct here. I don't know what I was
thinking. I've just double checked now and my compiler does not catch
this (GCC 4.7.2).
Sorry about that.
regards,
dan carpenter
^ permalink raw reply
* Re: [PATCH/RFC v3 06/19] video: display: OF support
From: Philipp Zabel @ 2013-08-27 9:30 UTC (permalink / raw)
To: Laurent Pinchart; +Cc: dri-devel, linux-fbdev, linux-media
In-Reply-To: <1376089398-13322-7-git-send-email-laurent.pinchart+renesas@ideasonboard.com>
Hi Laurent,
I have another small issue with the graph helpers below:
Am Samstag, den 10.08.2013, 01:03 +0200 schrieb Laurent Pinchart:
[...]
> +/* -----------------------------------------------------------------------------
> * Graph Helpers
> */
>
> @@ -420,6 +599,161 @@ int display_entity_link_graph(struct device *dev, struct list_head *entities)
> }
> EXPORT_SYMBOL_GPL(display_entity_link_graph);
>
> +#ifdef CONFIG_OF
> +
> +static int display_of_entity_link_entity(struct device *dev,
> + struct display_entity *entity,
> + struct list_head *entities,
> + struct display_entity *root)
> +{
> + u32 link_flags = MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED;
> + const struct device_node *node = entity->dev->of_node;
> + struct media_entity *local = &entity->entity;
> + struct device_node *ep = NULL;
> + int ret = 0;
> +
> + dev_dbg(dev, "creating links for entity %s\n", local->name);
> +
> + while (1) {
> + struct media_entity *remote = NULL;
> + struct media_pad *remote_pad;
> + struct media_pad *local_pad;
> + struct display_of_link link;
> + struct display_entity *ent;
> + struct device_node *next;
> +
> + /* Get the next endpoint and parse its link. */
> + next = display_of_get_next_endpoint(node, ep);
> + if (next = NULL)
> + break;
> +
> + of_node_put(ep);
> + ep = next;
> +
> + dev_dbg(dev, "processing endpoint %s\n", ep->full_name);
> +
> + ret = display_of_parse_link(ep, &link);
> + if (ret < 0) {
> + dev_err(dev, "failed to parse link for %s\n",
> + ep->full_name);
> + continue;
> + }
> +
> + /* Skip source pads, they will be processed from the other end of
> + * the link.
> + */
> + if (link.local_port >= local->num_pads) {
> + dev_err(dev, "invalid port number %u on %s\n",
> + link.local_port, link.local_node->full_name);
> + display_of_put_link(&link);
> + ret = -EINVAL;
> + break;
> + }
> +
> + local_pad = &local->pads[link.local_port];
> +
> + if (local_pad->flags & MEDIA_PAD_FL_SOURCE) {
> + dev_dbg(dev, "skipping source port %s:%u\n",
> + link.local_node->full_name, link.local_port);
> + display_of_put_link(&link);
> + continue;
> + }
> +
> + /* Find the remote entity. If not found, just skip the link as
> + * it goes out of scope of the entities handled by the notifier.
> + */
> + list_for_each_entry(ent, entities, list) {
> + if (ent->dev->of_node = link.remote_node) {
> + remote = &ent->entity;
> + break;
> + }
> + }
> +
> + if (root->dev->of_node = link.remote_node)
> + remote = &root->entity;
> +
> + if (remote = NULL) {
> + dev_dbg(dev, "no entity found for %s\n",
> + link.remote_node->full_name);
> + display_of_put_link(&link);
> + continue;
> + }
> +
> + if (link.remote_port >= remote->num_pads) {
> + dev_err(dev, "invalid port number %u on %s\n",
> + link.remote_port, link.remote_node->full_name);
> + display_of_put_link(&link);
> + ret = -EINVAL;
> + break;
> + }
> +
> + remote_pad = &remote->pads[link.remote_port];
> +
> + display_of_put_link(&link);
> +
> + /* Create the media link. */
> + dev_dbg(dev, "creating %s:%u -> %s:%u link\n",
> + remote->name, remote_pad->index,
> + local->name, local_pad->index);
> +
> + ret = media_entity_create_link(remote, remote_pad->index,
> + local, local_pad->index,
> + link_flags);
> + if (ret < 0) {
> + dev_err(dev,
> + "failed to create %s:%u -> %s:%u link\n",
> + remote->name, remote_pad->index,
> + local->name, local_pad->index);
> + break;
> + }
> + }
> +
> + of_node_put(ep);
> + return ret;
> +}
> +
> +/**
> + * display_of_entity_link_graph - Link all entities in a graph
> + * @dev: device used to print debugging and error messages
> + * @root: optional root display entity
> + * @entities: list of display entities in the graph
> + *
> + * This function creates media controller links for all entities in a graph
> + * based on the device tree graph representation. It relies on all entities
> + * having been instantiated from the device tree.
> + *
> + * The list of entities is typically taken directly from a display notifier
> + * done list. It will thus not include any display entity not handled by the
> + * notifier, such as entities directly accessible by the caller without going
> + * through the notification process. The optional root entity parameter can be
> + * used to pass such a display entity and include it in the graph. For all
> + * practical purpose the root entity is handled is if it was part of the
> + * entities list.
> + *
> + * Return 0 on success or a negative error code otherwise.
> + */
> +int display_of_entity_link_graph(struct device *dev, struct list_head *entities,
> + struct display_entity *root)
> +{
> + struct display_entity *entity;
> + int ret;
> +
> + list_for_each_entry(entity, entities, list) {
> + if (WARN_ON(entity->match->type != DISPLAY_ENTITY_BUS_DT))
> + return -EINVAL;
> +
> + ret = display_of_entity_link_entity(dev, entity, entities,
> + root);
> + if (ret < 0)
> + return ret;
> + }
> +
> + return display_of_entity_link_entity(dev, root, entities, root);
> +}
> +EXPORT_SYMBOL_GPL(display_of_entity_link_graph);
The root display entity given to display_of_entity_link_graph is documented
to be optional. Therefore, do not try to dereference root if it is NULL:
diff --git a/drivers/video/display/display-core.c b/drivers/video/display/display-core.c
index 328ead7..6c8094f 100644
--- a/drivers/video/display/display-core.c
+++ b/drivers/video/display/display-core.c
@@ -669,7 +669,7 @@ static int display_of_entity_link_entity(struct device *dev,
}
}
- if (root->dev->of_node = link.remote_node)
+ if (root && root->dev->of_node = link.remote_node)
remote = &root->entity;
if (remote = NULL) {
@@ -748,6 +748,9 @@ int display_of_entity_link_graph(struct device *dev, struct list_head *entities,
return ret;
}
+ if (!root)
+ return 0;
+
return display_of_entity_link_entity(dev, root, entities, root);
}
EXPORT_SYMBOL_GPL(display_of_entity_link_graph);
--
1.8.4.rc3
regards
Philipp
^ permalink raw reply related
* Re: [PATCH v11 0/8] PHY framework
From: Felipe Balbi @ 2013-08-27 19:20 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <521B0E79.6060506@ti.com>
[-- Attachment #1: Type: text/plain, Size: 1525 bytes --]
Hi,
On Mon, Aug 26, 2013 at 01:44:49PM +0530, Kishon Vijay Abraham I wrote:
> On Wednesday 21 August 2013 11:16 AM, Kishon Vijay Abraham I wrote:
> > Added a generic PHY framework that provides a set of APIs for the PHY drivers
> > to create/destroy a PHY and APIs for the PHY users to obtain a reference to
> > the PHY with or without using phandle.
> >
> > This framework will be of use only to devices that uses external PHY (PHY
> > functionality is not embedded within the controller).
> >
> > The intention of creating this framework is to bring the phy drivers spread
> > all over the Linux kernel to drivers/phy to increase code re-use and to
> > increase code maintainability.
> >
> > Comments to make PHY as bus wasn't done because PHY devices can be part of
> > other bus and making a same device attached to multiple bus leads to bad
> > design.
> >
> > If the PHY driver has to send notification on connect/disconnect, the PHY
> > driver should make use of the extcon framework. Using this susbsystem
> > to use extcon framwork will have to be analysed.
> >
> > You can find this patch series @
> > git://git.kernel.org/pub/scm/linux/kernel/git/kishon/linux-phy.git testing
>
> Looks like there are not further comments on this series. Can you take this in
> your misc tree?
Do you want me to queue these for you ? There are quite a few users for
this framework already and I know of at least 2 others which will show
up for v3.13.
Let me know.
cheers
--
balbi
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply
* Re: [PATCH v11 0/8] PHY framework
From: Kishon Vijay Abraham I @ 2013-08-28 10:55 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20130827192059.GZ3005@radagast>
Hi,
On Wednesday 28 August 2013 12:50 AM, Felipe Balbi wrote:
> Hi,
>
> On Mon, Aug 26, 2013 at 01:44:49PM +0530, Kishon Vijay Abraham I wrote:
>> On Wednesday 21 August 2013 11:16 AM, Kishon Vijay Abraham I wrote:
>>> Added a generic PHY framework that provides a set of APIs for the PHY drivers
>>> to create/destroy a PHY and APIs for the PHY users to obtain a reference to
>>> the PHY with or without using phandle.
>>>
>>> This framework will be of use only to devices that uses external PHY (PHY
>>> functionality is not embedded within the controller).
>>>
>>> The intention of creating this framework is to bring the phy drivers spread
>>> all over the Linux kernel to drivers/phy to increase code re-use and to
>>> increase code maintainability.
>>>
>>> Comments to make PHY as bus wasn't done because PHY devices can be part of
>>> other bus and making a same device attached to multiple bus leads to bad
>>> design.
>>>
>>> If the PHY driver has to send notification on connect/disconnect, the PHY
>>> driver should make use of the extcon framework. Using this susbsystem
>>> to use extcon framwork will have to be analysed.
>>>
>>> You can find this patch series @
>>> git://git.kernel.org/pub/scm/linux/kernel/git/kishon/linux-phy.git testing
>>
>> Looks like there are not further comments on this series. Can you take this in
>> your misc tree?
>
> Do you want me to queue these for you ? There are quite a few users for
> this framework already and I know of at least 2 others which will show
> up for v3.13.
yeah sure. That would be better I think.
Thanks
Kishon
^ permalink raw reply
* [PATCH v8 0/2] Introduce buffer synchronization framework
From: Inki Dae @ 2013-08-29 7:53 UTC (permalink / raw)
To: dri-devel, linux-fbdev, linux-arm-kernel, linux-media,
linaro-kernel
Cc: maarten.lankhorst, sumit.semwal, kyungmin.park, myungjoo.ham,
Inki Dae
Hi all,
This patch set introduces a buffer synchronization framework based
on DMA BUF[1] and based on ww-mutexes[2] for lock mechanism, and
has been rebased on linux-next.
The purpose of this framework is to provide not only buffer access
control to CPU and CPU, and CPU and DMA, and DMA and DMA but also
easy-to-use interfaces for device drivers and user application.
In addtion, this patch set suggests a way for enhancing performance.
Changelog v8:
Consider the write-and-then-read ordering pointed out by David Herrmann,
- The ordering issue means that a task don't take a lock to the dmabuf
so this task would be stalled even though this task requested a lock to
the dmabuf between other task unlocked and tries to lock the dmabuf
again. For this, we have added a wait event mechanism using only generic
APIs, wait_event_timeout and wake_up functions.
The below is how to handle the ordering issue using this mechanism:
1. Check if there is a sync object added prior to current task's one.
2. If exists, it unlocks the dmabuf so that other task can take a lock
to the dmabuf first.
3. Wait for the wake up event from other task: current task will be
waked up when other task unlocks the dmabuf.
4. Take a lock to the dmabuf again.
- Code cleanups.
Changelog v7:
Fix things pointed out by Konrad Rzeszutek Wilk,
- Use EXPORT_SYMBOL_GPL instead of EXPORT_SYMBOL.
- Make sure to unlock and unreference all dmabuf objects
when dmabuf_sync_fini() is called.
- Add more comments.
- Code cleanups.
Changelog v6:
- Fix sync lock to multiple reads.
- Add select system call support.
. Wake up poll_wait when a dmabuf is unlocked.
- Remove unnecessary the use of mutex lock.
- Add private backend ops callbacks.
. This ops has one callback for device drivers to clean up their
sync object resource when the sync object is freed. For this,
device drivers should implement the free callback properly.
- Update document file.
Changelog v5:
- Rmove a dependence on reservation_object: the reservation_object is used
to hook up to ttm and dma-buf for easy sharing of reservations across
devices. However, the dmabuf sync can be used for all dma devices; v4l2
and drm based drivers, so doesn't need the reservation_object anymore.
With regared to this, it adds 'void *sync' to dma_buf structure.
- All patches are rebased on mainline, Linux v3.10.
Changelog v4:
- Add user side interface for buffer synchronization mechanism and update
descriptions related to the user side interface.
Changelog v3:
- remove cache operation relevant codes and update document file.
Changelog v2:
- use atomic_add_unless to avoid potential bug.
- add a macro for checking valid access type.
- code clean.
For generic user mode interface, we have used fcntl and select system
call[3]. As you know, user application sees a buffer object as a dma-buf
file descriptor. So fcntl() call with the file descriptor means to lock
some buffer region being managed by the dma-buf object. And select() call
means to wait for the completion of CPU or DMA access to the dma-buf
without locking. For more detail, you can refer to the dma-buf-sync.txt
in Documentation/
There are some cases user-space process needs this buffer synchronization
framework. One of which is to primarily enhance GPU rendering performance
in case that 3D app draws somthing in a buffer using CPU, and other process
composes the buffer with its own backbuffer using GPU.
In case of 3D app, the app calls glFlush to submit 3d commands to GPU driver
instead of glFinish for more performance. The reason, we call glFlush, is
that glFinish blocks caller's task until the execution of the 3d commands is
completed. So that makes GPU and CPU more idle. As a result, 3d rendering
performance with glFinish is quite lower than glFlush.
However, the use of glFlush has one issue that the the buffer shared with
GPU could be broken when CPU accesses the buffer just after glFlush because
CPU cannot be aware of the completion of GPU access to the buffer.
Of course, the app can be aware of that time using eglWaitGL but this function
is valid only in case of the same context.
The below summarizes how app's window is displayed on Tizen[4] platform:
1. X client requests a window buffer to Xorg.
2. X client draws something in the window buffer using CPU.
3. X client requests SWAP to Xorg.
4. Xorg notifies a damage event to Composite Manager.
5. Composite Manager gets the window buffer (front buffer) through
DRI2GetBuffers.
6. Composite Manager composes the window buffer and its own back buffer
using GPU. At this time, eglSwapBuffers is called: internally, 3d
commands are flushed to gpu driver.
7. Composite Manager requests SWAP to Xorg.
8. Xorg performs drm page flip. At this time, the window buffer is
displayed on screen.
Web app based on HTML5 also has the same issue. Web browser and Web app
are different process. The Web app can draw something in its own buffer using
CPU, and then the Web Browser can compose the buffer with its own back buffer.
Thus, in such cases, a shared buffer could be broken as one process draws
something in a buffer using CPU, when other process composes the buffer with
its own buffer using GPU without any locking mechanism. That is why we need
user land locking interface, fcntl system call.
And last one is a deferred page flip issue. This issue is that a window
buffer rendered can be displayed on screen in about 32ms in worst case:
assume that the gpu rendering is completed within 16ms.
That can be incurred when compositing a pixmap buffer with a window buffer
using GPU and when vsync is just started. At this time, Xorg waits for
a vblank event to get a window buffer so 3d rendering will be delayed
up to about 16ms. As a result, the window buffer would be displayed in
about two vsyncs (about 32ms) and in turn, that would show slow
responsiveness.
For this, we could enhance the responsiveness with locking mechanism: skipping
one vblank wait. I guess Android, Chrome OS, and other platforms are using
their own locking mechanisms with similar reason; Android sync driver, KDS, and
DMA fence.
The below shows the deferred page flip issue in worst case:
|------------ <- vsync signal
|<------ DRI2GetBuffers
|
|
|
|------------ <- vsync signal
|<------ Request gpu rendering
time |
|
|<------ Request page flip (deferred)
|------------ <- vsync signal
|<------ Displayed on screen
|
|
|
|------------ <- vsync signal
Thanks,
Inki Dae
References:
[1] http://lwn.net/Articles/470339/
[2] https://patchwork.kernel.org/patch/2625361/
[3] http://linux.die.net/man/2/fcntl
[4] https://www.tizen.org/
Inki Dae (2):
dmabuf-sync: Add a buffer synchronization framework
dma-buf: Add user interfaces for dmabuf sync support
Documentation/dma-buf-sync.txt | 286 ++++++++++++
drivers/base/Kconfig | 7 +
drivers/base/Makefile | 1 +
drivers/base/dma-buf.c | 85 ++++
drivers/base/dmabuf-sync.c | 943 ++++++++++++++++++++++++++++++++++++++++
include/linux/dma-buf.h | 16 +
include/linux/dmabuf-sync.h | 257 +++++++++++
7 files changed, 1595 insertions(+), 0 deletions(-)
create mode 100644 Documentation/dma-buf-sync.txt
create mode 100644 drivers/base/dmabuf-sync.c
create mode 100644 include/linux/dmabuf-sync.h
--
1.7.5.4
^ permalink raw reply
* [PATCH v8 1/2] dmabuf-sync: Add a buffer synchronization framework
From: Inki Dae @ 2013-08-29 7:53 UTC (permalink / raw)
To: dri-devel, linux-fbdev, linux-arm-kernel, linux-media,
linaro-kernel
Cc: maarten.lankhorst, sumit.semwal, kyungmin.park, myungjoo.ham,
Inki Dae
In-Reply-To: <1377762801-14057-1-git-send-email-inki.dae@samsung.com>
This patch adds a buffer synchronization framework based on DMA BUF[1]
and and based on ww-mutexes[2] for lock mechanism, and has been rebased
on linux-next.
The purpose of this framework is to provide not only buffer access control
to CPU and DMA but also easy-to-use interfaces for device drivers and
user application. This framework can be used for all dma devices using
system memory as dma buffer, especially for most ARM based SoCs.
Changelog v8:
Consider the write-and-then-read ordering pointed out by David Herrmann,
- The ordering issue means that a task don't take a lock to the dmabuf
so this task would be stalled even though this task requested a lock to
the dmabuf between other task unlocked and tries to lock the dmabuf
again. For this, we have added a wait event mechanism using only generic
APIs, wait_event_timeout and wake_up functions.
The below is how to handle the ordering issue using this mechanism:
1. Check if there is a sync object added prior to current task's one.
2. If exists, it unlocks the dmabuf so that other task can take a lock
to the dmabuf first.
3. Wait for the wake up event from other task: current task will be
waked up when other task unlocks the dmabuf.
4. Take a lock to the dmabuf again.
- Code cleanups.
Changelog v7:
Fix things pointed out by Konrad Rzeszutek Wilk,
- Use EXPORT_SYMBOL_GPL instead of EXPORT_SYMBOL.
- make sure to unlock and unreference all dmabuf objects
when dmabuf_sync_fini() is called.
- Add more comments.
- code cleanups.
Changelog v6:
- Fix sync lock to multiple reads.
- Add select system call support.
. Wake up poll_wait when a dmabuf is unlocked.
- Remove unnecessary the use of mutex lock.
- Add private backend ops callbacks.
. This ops has one callback for device drivers to clean up their
sync object resource when the sync object is freed. For this,
device drivers should implement the free callback properly.
- Update document file.
Changelog v5:
- Rmove a dependence on reservation_object: the reservation_object is used
to hook up to ttm and dma-buf for easy sharing of reservations across
devices. However, the dmabuf sync can be used for all dma devices; v4l2
and drm based drivers, so doesn't need the reservation_object anymore.
With regared to this, it adds 'void *sync' to dma_buf structure.
- All patches are rebased on mainline, Linux v3.10.
Changelog v4:
- Add user side interface for buffer synchronization mechanism and update
descriptions related to the user side interface.
Changelog v3:
- remove cache operation relevant codes and update document file.
Changelog v2:
- use atomic_add_unless to avoid potential bug.
- add a macro for checking valid access type.
- code clean.
The mechanism of this framework has the following steps,
1. Register dmabufs to a sync object - A task gets a new sync object and
can add one or more dmabufs that the task wants to access.
This registering should be performed when a device context or an event
context such as a page flip event is created or before CPU accesses a shared
buffer.
dma_buf_sync_get(a sync object, a dmabuf);
2. Lock a sync object - A task tries to lock all dmabufs added in its own
sync object. Basically, the lock mechanism uses ww-mutex[1] to avoid dead
lock issue and for race condition between CPU and CPU, CPU and DMA, and DMA
and DMA. Taking a lock means that others cannot access all locked dmabufs
until the task that locked the corresponding dmabufs, unlocks all the locked
dmabufs.
This locking should be performed before DMA or CPU accesses these dmabufs.
dma_buf_sync_lock(a sync object);
3. Unlock a sync object - The task unlocks all dmabufs added in its own sync
object. The unlock means that the DMA or CPU accesses to the dmabufs have
been completed so that others may access them.
This unlocking should be performed after DMA or CPU has completed accesses
to the dmabufs.
dma_buf_sync_unlock(a sync object);
4. Unregister one or all dmabufs from a sync object - A task unregisters
the given dmabufs from the sync object. This means that the task dosen't
want to lock the dmabufs.
The unregistering should be performed after DMA or CPU has completed
accesses to the dmabufs or when dma_buf_sync_lock() is failed.
dma_buf_sync_put(a sync object, a dmabuf);
dma_buf_sync_put_all(a sync object);
The described steps may be summarized as:
get -> lock -> CPU or DMA access to a buffer/s -> unlock -> put
This framework includes the following two features.
1. read (shared) and write (exclusive) locks - A task is required to declare
the access type when the task tries to register a dmabuf;
READ, WRITE, READ DMA, or WRITE DMA.
The below is example codes,
struct dmabuf_sync *sync;
sync = dmabuf_sync_init(...);
...
dmabuf_sync_get(sync, dmabuf, DMA_BUF_ACCESS_R);
...
And the below can be used as access types:
DMA_BUF_ACCESS_R - CPU will access a buffer for read.
DMA_BUF_ACCESS_W - CPU will access a buffer for read or write.
DMA_BUF_ACCESS_DMA_R - DMA will access a buffer for read
DMA_BUF_ACCESS_DMA_W - DMA will access a buffer for read or
write.
2. Mandatory resource releasing - a task cannot hold a lock indefinitely.
A task may never try to unlock a buffer after taking a lock to the buffer.
In this case, a timer handler to the corresponding sync object is called
in five (default) seconds and then the timed-out buffer is unlocked by work
queue handler to avoid lockups and to enforce resources of the buffer.
The below is how to use interfaces for device driver:
1. Allocate and Initialize a sync object:
static void xxx_dmabuf_sync_free(void *priv)
{
struct xxx_context *ctx = priv;
if (!ctx)
return;
ctx->sync = NULL;
}
...
static struct dmabuf_sync_priv_ops driver_specific_ops = {
.free = xxx_dmabuf_sync_free,
};
...
struct dmabuf_sync *sync;
sync = dmabuf_sync_init("test sync", &driver_specific_ops, ctx);
...
2. Add a dmabuf to the sync object when setting up dma buffer relevant
registers:
dmabuf_sync_get(sync, dmabuf, DMA_BUF_ACCESS_READ);
...
3. Lock all dmabufs of the sync object before DMA or CPU accesses
the dmabufs:
dmabuf_sync_lock(sync);
...
4. Now CPU or DMA can access all dmabufs locked in step 3.
5. Unlock all dmabufs added in a sync object after DMA or CPU access
to these dmabufs is completed:
dmabuf_sync_unlock(sync);
And call the following functions to release all resources,
dmabuf_sync_put_all(sync);
dmabuf_sync_fini(sync);
You can refer to actual example codes:
"drm/exynos: add dmabuf sync support for g2d driver" and
"drm/exynos: add dmabuf sync support for kms framework" from
https://git.kernel.org/cgit/linux/kernel/git/daeinki/
drm-exynos.git/log/?h=dmabuf-sync
And this framework includes fcntl[3] and select system call as interfaces
exported to user. As you know, user sees a buffer object as a dma-buf file
descriptor. fcntl() call with the file descriptor means to lock some buffer
region being managed by the dma-buf object. And select() call with the file
descriptor means to poll the completion event of CPU or DMA access to
the dma-buf.
The below is how to use interfaces for user application:
fcntl system call:
struct flock filelock;
1. Lock a dma buf:
filelock.l_type = F_WRLCK or F_RDLCK;
/* lock entire region to the dma buf. */
filelock.lwhence = SEEK_CUR;
filelock.l_start = 0;
filelock.l_len = 0;
fcntl(dmabuf fd, F_SETLKW or F_SETLK, &filelock);
...
CPU access to the dma buf
2. Unlock a dma buf:
filelock.l_type = F_UNLCK;
fcntl(dmabuf fd, F_SETLKW or F_SETLK, &filelock);
close(dmabuf fd) call would also unlock the dma buf. And for more
detail, please refer to [3]
select system call:
fd_set wdfs or rdfs;
FD_ZERO(&wdfs or &rdfs);
FD_SET(fd, &wdfs or &rdfs);
select(fd + 1, &rdfs, NULL, NULL, NULL);
or
select(fd + 1, NULL, &wdfs, NULL, NULL);
Every time select system call is called, a caller will wait for
the completion of DMA or CPU access to a shared buffer if there
is someone accessing the shared buffer. If no anyone then select
system call will be returned at once.
References:
[1] http://lwn.net/Articles/470339/
[2] https://patchwork.kernel.org/patch/2625361/
[3] http://linux.die.net/man/2/fcntl
Signed-off-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
Documentation/dma-buf-sync.txt | 286 ++++++++++++
drivers/base/Kconfig | 7 +
drivers/base/Makefile | 1 +
drivers/base/dma-buf.c | 4 +
drivers/base/dmabuf-sync.c | 945 ++++++++++++++++++++++++++++++++++++++++
include/linux/dma-buf.h | 16 +
include/linux/dmabuf-sync.h | 257 +++++++++++
7 files changed, 1516 insertions(+), 0 deletions(-)
create mode 100644 Documentation/dma-buf-sync.txt
create mode 100644 drivers/base/dmabuf-sync.c
create mode 100644 include/linux/dmabuf-sync.h
diff --git a/Documentation/dma-buf-sync.txt b/Documentation/dma-buf-sync.txt
new file mode 100644
index 0000000..5945c8a
--- /dev/null
+++ b/Documentation/dma-buf-sync.txt
@@ -0,0 +1,286 @@
+ DMA Buffer Synchronization Framework
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ Inki Dae
+ <inki dot dae at samsung dot com>
+ <daeinki at gmail dot com>
+
+This document is a guide for device-driver writers describing the DMA buffer
+synchronization API. This document also describes how to use the API to
+use buffer synchronization mechanism between DMA and DMA, CPU and DMA, and
+CPU and CPU.
+
+The DMA Buffer synchronization API provides buffer synchronization mechanism;
+i.e., buffer access control to CPU and DMA, and easy-to-use interfaces for
+device drivers and user application. And this API can be used for all dma
+devices using system memory as dma buffer, especially for most ARM based SoCs.
+
+
+Motivation
+----------
+
+Buffer synchronization issue between DMA and DMA:
+ Sharing a buffer, a device cannot be aware of when the other device
+ will access the shared buffer: a device may access a buffer containing
+ wrong data if the device accesses the shared buffer while another
+ device is still accessing the shared buffer.
+ Therefore, a user process should have waited for the completion of DMA
+ access by another device before a device tries to access the shared
+ buffer.
+
+Buffer synchronization issue between CPU and DMA:
+ A user process should consider that when having to send a buffer, filled
+ by CPU, to a device driver for the device driver to access the buffer as
+ a input buffer while CPU and DMA are sharing the buffer.
+ This means that the user process needs to understand how the device
+ driver is worked. Hence, the conventional mechanism not only makes
+ user application complicated but also incurs performance overhead.
+
+Buffer synchronization issue between CPU and CPU:
+ In case that two processes share one buffer; shared with DMA also,
+ they may need some mechanism to allow process B to access the shared
+ buffer after the completion of CPU access by process A.
+ Therefore, process B should have waited for the completion of CPU access
+ by process A using the mechanism before trying to access the shared
+ buffer.
+
+What is the best way to solve these buffer synchronization issues?
+ We may need a common object that a device driver and a user process
+ notify the common object of when they try to access a shared buffer.
+ That way we could decide when we have to allow or not to allow for CPU
+ or DMA to access the shared buffer through the common object.
+ If so, what could become the common object? Right, that's a dma-buf[1].
+ Now we have already been using the dma-buf to share one buffer with
+ other drivers.
+
+
+Basic concept
+-------------
+
+The mechanism of this framework has the following steps,
+ 1. Register dmabufs to a sync object - A task gets a new sync object and
+ can add one or more dmabufs that the task wants to access.
+ This registering should be performed when a device context or an event
+ context such as a page flip event is created or before CPU accesses a shared
+ buffer.
+
+ dma_buf_sync_get(a sync object, a dmabuf);
+
+ 2. Lock a sync object - A task tries to lock all dmabufs added in its own
+ sync object. Basically, the lock mechanism uses ww-mutexes[2] to avoid dead
+ lock issue and for race condition between CPU and CPU, CPU and DMA, and DMA
+ and DMA. Taking a lock means that others cannot access all locked dmabufs
+ until the task that locked the corresponding dmabufs, unlocks all the locked
+ dmabufs.
+ This locking should be performed before DMA or CPU accesses these dmabufs.
+
+ dma_buf_sync_lock(a sync object);
+
+ 3. Unlock a sync object - The task unlocks all dmabufs added in its own sync
+ object. The unlock means that the DMA or CPU accesses to the dmabufs have
+ been completed so that others may access them.
+ This unlocking should be performed after DMA or CPU has completed accesses
+ to the dmabufs.
+
+ dma_buf_sync_unlock(a sync object);
+
+ 4. Unregister one or all dmabufs from a sync object - A task unregisters
+ the given dmabufs from the sync object. This means that the task dosen't
+ want to lock the dmabufs.
+ The unregistering should be performed after DMA or CPU has completed
+ accesses to the dmabufs or when dma_buf_sync_lock() is failed.
+
+ dma_buf_sync_put(a sync object, a dmabuf);
+ dma_buf_sync_put_all(a sync object);
+
+ The described steps may be summarized as:
+ get -> lock -> CPU or DMA access to a buffer/s -> unlock -> put
+
+This framework includes the following two features.
+ 1. read (shared) and write (exclusive) locks - A task is required to declare
+ the access type when the task tries to register a dmabuf;
+ READ, WRITE, READ DMA, or WRITE DMA.
+
+ The below is example codes,
+ struct dmabuf_sync *sync;
+
+ sync = dmabuf_sync_init(NULL, "test sync");
+
+ dmabuf_sync_get(sync, dmabuf, DMA_BUF_ACCESS_R);
+ ...
+
+ 2. Mandatory resource releasing - a task cannot hold a lock indefinitely.
+ A task may never try to unlock a buffer after taking a lock to the buffer.
+ In this case, a timer handler to the corresponding sync object is called
+ in five (default) seconds and then the timed-out buffer is unlocked by work
+ queue handler to avoid lockups and to enforce resources of the buffer.
+
+
+Access types
+------------
+
+DMA_BUF_ACCESS_R - CPU will access a buffer for read.
+DMA_BUF_ACCESS_W - CPU will access a buffer for read or write.
+DMA_BUF_ACCESS_DMA_R - DMA will access a buffer for read
+DMA_BUF_ACCESS_DMA_W - DMA will access a buffer for read or write.
+
+
+Generic user interfaces
+-----------------------
+
+And this framework includes fcntl[3] and select system calls as interfaces
+exported to user. As you know, user sees a buffer object as a dma-buf file
+descriptor. fcntl() call with the file descriptor means to lock some buffer
+region being managed by the dma-buf object. And select call with the file
+descriptor means to poll the completion event of CPU or DMA access to
+the dma-buf.
+
+
+API set
+-------
+
+bool is_dmabuf_sync_supported(void)
+ - Check if dmabuf sync is supported or not.
+
+struct dmabuf_sync *dmabuf_sync_init(const char *name,
+ struct dmabuf_sync_priv_ops *ops,
+ void priv*)
+ - Allocate and initialize a new sync object. The caller can get a new
+ sync object for buffer synchronization. ops is used for device driver
+ to clean up its own sync object. For this, each device driver should
+ implement a free callback. priv is used for device driver to get its
+ device context when free callback is called.
+
+void dmabuf_sync_fini(struct dmabuf_sync *sync)
+ - Release all resources to the sync object.
+
+int dmabuf_sync_get(struct dmabuf_sync *sync, void *sync_buf,
+ unsigned int type)
+ - Get dmabuf sync object. Internally, this function allocates
+ a dmabuf_sync object and adds a given dmabuf to it, and also takes
+ a reference to the dmabuf. The caller can tie up multiple dmabufs
+ into one sync object by calling this function several times.
+
+void dmabuf_sync_put(struct dmabuf_sync *sync, struct dma_buf *dmabuf)
+ - Put dmabuf sync object to a given dmabuf. Internally, this function
+ removes a given dmabuf from a sync object and remove the sync object.
+ At this time, the dmabuf is putted.
+
+void dmabuf_sync_put_all(struct dmabuf_sync *sync)
+ - Put dmabuf sync object to dmabufs. Internally, this function removes
+ all dmabufs from a sync object and remove the sync object.
+ At this time, all dmabufs are putted.
+
+int dmabuf_sync_lock(struct dmabuf_sync *sync)
+ - Lock all dmabufs added in a sync object. The caller should call this
+ function prior to CPU or DMA access to the dmabufs so that others can
+ not access the dmabufs. Internally, this function avoids dead lock
+ issue with ww-mutexes.
+
+int dmabuf_sync_single_lock(struct dma_buf *dmabuf)
+ - Lock a dmabuf. The caller should call this
+ function prior to CPU or DMA access to the dmabuf so that others can
+ not access the dmabuf.
+
+int dmabuf_sync_unlock(struct dmabuf_sync *sync)
+ - Unlock all dmabufs added in a sync object. The caller should call
+ this function after CPU or DMA access to the dmabufs is completed so
+ that others can access the dmabufs.
+
+void dmabuf_sync_single_unlock(struct dma_buf *dmabuf)
+ - Unlock a dmabuf. The caller should call this function after CPU or
+ DMA access to the dmabuf is completed so that others can access
+ the dmabuf.
+
+
+Tutorial for device driver
+--------------------------
+
+1. Allocate and Initialize a sync object:
+ static void xxx_dmabuf_sync_free(void *priv)
+ {
+ struct xxx_context *ctx = priv;
+
+ if (!ctx)
+ return;
+
+ ctx->sync = NULL;
+ }
+ ...
+
+ static struct dmabuf_sync_priv_ops driver_specific_ops = {
+ .free = xxx_dmabuf_sync_free,
+ };
+ ...
+
+ struct dmabuf_sync *sync;
+
+ sync = dmabuf_sync_init("test sync", &driver_specific_ops, ctx);
+ ...
+
+2. Add a dmabuf to the sync object when setting up dma buffer relevant registers:
+ dmabuf_sync_get(sync, dmabuf, DMA_BUF_ACCESS_READ);
+ ...
+
+3. Lock all dmabufs of the sync object before DMA or CPU accesses the dmabufs:
+ dmabuf_sync_lock(sync);
+ ...
+
+4. Now CPU or DMA can access all dmabufs locked in step 3.
+
+5. Unlock all dmabufs added in a sync object after DMA or CPU access to these
+ dmabufs is completed:
+ dmabuf_sync_unlock(sync);
+
+ And call the following functions to release all resources,
+ dmabuf_sync_put_all(sync);
+ dmabuf_sync_fini(sync);
+
+
+Tutorial for user application
+-----------------------------
+fcntl system call:
+
+ struct flock filelock;
+
+1. Lock a dma buf:
+ filelock.l_type = F_WRLCK or F_RDLCK;
+
+ /* lock entire region to the dma buf. */
+ filelock.lwhence = SEEK_CUR;
+ filelock.l_start = 0;
+ filelock.l_len = 0;
+
+ fcntl(dmabuf fd, F_SETLKW or F_SETLK, &filelock);
+ ...
+ CPU access to the dma buf
+
+2. Unlock a dma buf:
+ filelock.l_type = F_UNLCK;
+
+ fcntl(dmabuf fd, F_SETLKW or F_SETLK, &filelock);
+
+ close(dmabuf fd) call would also unlock the dma buf. And for more
+ detail, please refer to [3]
+
+
+select system call:
+
+ fd_set wdfs or rdfs;
+
+ FD_ZERO(&wdfs or &rdfs);
+ FD_SET(fd, &wdfs or &rdfs);
+
+ select(fd + 1, &rdfs, NULL, NULL, NULL);
+ or
+ select(fd + 1, NULL, &wdfs, NULL, NULL);
+
+ Every time select system call is called, a caller will wait for
+ the completion of DMA or CPU access to a shared buffer if there
+ is someone accessing the shared buffer. If no anyone then select
+ system call will be returned at once.
+
+References:
+[1] http://lwn.net/Articles/470339/
+[2] https://patchwork.kernel.org/patch/2625361/
+[3] http://linux.die.net/man/2/fcntl
diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig
index e373671..23e0fbf 100644
--- a/drivers/base/Kconfig
+++ b/drivers/base/Kconfig
@@ -200,6 +200,13 @@ config DMA_SHARED_BUFFER
APIs extension; the file's descriptor can then be passed on to other
driver.
+config DMABUF_SYNC
+ bool "DMABUF Synchronization Framework"
+ depends on DMA_SHARED_BUFFER
+ help
+ This option enables dmabuf sync framework for buffer synchronization between
+ DMA and DMA, CPU and DMA, and CPU and CPU.
+
config DMA_CMA
bool "DMA Contiguous Memory Allocator"
depends on HAVE_DMA_CONTIGUOUS && CMA
diff --git a/drivers/base/Makefile b/drivers/base/Makefile
index 94e8a80..e88d9b8 100644
--- a/drivers/base/Makefile
+++ b/drivers/base/Makefile
@@ -11,6 +11,7 @@ obj-y += power/
obj-$(CONFIG_HAS_DMA) += dma-mapping.o
obj-$(CONFIG_HAVE_GENERIC_DMA_COHERENT) += dma-coherent.o
obj-$(CONFIG_DMA_SHARED_BUFFER) += dma-buf.o reservation.o
+obj-$(CONFIG_DMABUF_SYNC) += dmabuf-sync.o
obj-$(CONFIG_ISA) += isa.o
obj-$(CONFIG_FW_LOADER) += firmware_class.o
obj-$(CONFIG_NUMA) += node.o
diff --git a/drivers/base/dma-buf.c b/drivers/base/dma-buf.c
index d03da13..cc42a38 100644
--- a/drivers/base/dma-buf.c
+++ b/drivers/base/dma-buf.c
@@ -30,6 +30,7 @@
#include <linux/export.h>
#include <linux/debugfs.h>
#include <linux/seq_file.h>
+#include <linux/dmabuf-sync.h>
static inline int is_dma_buf_file(struct file *);
@@ -57,6 +58,8 @@ static int dma_buf_release(struct inode *inode, struct file *file)
list_del(&dmabuf->list_node);
mutex_unlock(&db_list.lock);
+ dmabuf_sync_reservation_fini(dmabuf);
+
kfree(dmabuf);
return 0;
}
@@ -135,6 +138,7 @@ struct dma_buf *dma_buf_export_named(void *priv, const struct dma_buf_ops *ops,
file = anon_inode_getfile("dmabuf", &dma_buf_fops, dmabuf, flags);
+ dmabuf_sync_reservation_init(dmabuf);
dmabuf->file = file;
mutex_init(&dmabuf->lock);
diff --git a/drivers/base/dmabuf-sync.c b/drivers/base/dmabuf-sync.c
new file mode 100644
index 0000000..1ab05a3
--- /dev/null
+++ b/drivers/base/dmabuf-sync.c
@@ -0,0 +1,945 @@
+/*
+ * Copyright (C) 2013 Samsung Electronics Co.Ltd
+ * Authors:
+ * Inki Dae <inki.dae@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/debugfs.h>
+#include <linux/uaccess.h>
+
+#include <linux/dmabuf-sync.h>
+
+#define MAX_SYNC_TIMEOUT 5 /* Second. */
+#define MAX_WAIT_TIMEOUT 2000 /* Millisecond. */
+
+#define WAKE_UP_SYNC_OBJ(obj) { \
+ if (obj->waiting) { \
+ obj->waiting = false; \
+ wake_up(&obj->wq); \
+ } \
+ }
+
+#define DEL_OBJ_FROM_RSV(obj, rsv) { \
+ struct dmabuf_sync_object *e, *n; \
+ \
+ list_for_each_entry_safe(e, n, &rsv->syncs, r_head) { \
+ if (e = obj && !e->task) \
+ list_del_init(&e->r_head); \
+ } \
+}
+
+int dmabuf_sync_enabled = 1;
+
+MODULE_PARM_DESC(enabled, "Check if dmabuf sync is supported or not");
+module_param_named(enabled, dmabuf_sync_enabled, int, 0444);
+
+DEFINE_WW_CLASS(dmabuf_sync_ww_class);
+EXPORT_SYMBOL_GPL(dmabuf_sync_ww_class);
+
+static void dmabuf_sync_timeout_worker(struct work_struct *work)
+{
+ struct dmabuf_sync *sync = container_of(work, struct dmabuf_sync, work);
+ struct dmabuf_sync_object *sobj;
+
+ mutex_lock(&sync->lock);
+
+ list_for_each_entry(sobj, &sync->syncs, head) {
+ struct dmabuf_sync_reservation *rsvp = sobj->robj;
+
+ mutex_lock(&rsvp->lock);
+
+ pr_warn("%s: timeout = 0x%p [type = %d:%d, "
+ "refcnt = %d, locked = %d]\n",
+ sync->name, sobj->dmabuf,
+ rsvp->accessed_type,
+ sobj->access_type,
+ atomic_read(&rsvp->shared_cnt),
+ rsvp->locked);
+
+ if (rsvp->polled) {
+ rsvp->poll_event = true;
+ rsvp->polled = false;
+ wake_up_interruptible(&rsvp->poll_wait);
+ }
+
+ /*
+ * Wake up a task blocked by dmabuf_sync_wait_prev_objs().
+ *
+ * If sobj->waiting is true, the task is waiting for the wake
+ * up event so wake up the task if a given time period is
+ * elapsed and current task is timed out.
+ */
+ WAKE_UP_SYNC_OBJ(sobj);
+
+ /* Delete a sync object from reservation object of dmabuf. */
+ DEL_OBJ_FROM_RSV(sobj, rsvp);
+
+ if (atomic_add_unless(&rsvp->shared_cnt, -1, 1)) {
+ mutex_unlock(&rsvp->lock);
+ continue;
+ }
+
+ /* unlock only valid sync object. */
+ if (!rsvp->locked) {
+ mutex_unlock(&rsvp->lock);
+ continue;
+ }
+
+ mutex_unlock(&rsvp->lock);
+ ww_mutex_unlock(&rsvp->sync_lock);
+
+ mutex_lock(&rsvp->lock);
+ rsvp->locked = false;
+
+ if (sobj->access_type & DMA_BUF_ACCESS_R)
+ pr_warn("%s: r-unlocked = 0x%p\n",
+ sync->name, sobj->dmabuf);
+ else
+ pr_warn("%s: w-unlocked = 0x%p\n",
+ sync->name, sobj->dmabuf);
+
+ mutex_unlock(&rsvp->lock);
+ }
+
+ sync->status = 0;
+ mutex_unlock(&sync->lock);
+
+ dmabuf_sync_put_all(sync);
+ dmabuf_sync_fini(sync);
+}
+
+static void dmabuf_sync_lock_timeout(unsigned long arg)
+{
+ struct dmabuf_sync *sync = (struct dmabuf_sync *)arg;
+
+ schedule_work(&sync->work);
+}
+
+static void dmabuf_sync_wait_prev_objs(struct dmabuf_sync_object *sobj,
+ struct dmabuf_sync_reservation *rsvp,
+ struct ww_acquire_ctx *ctx)
+{
+ mutex_lock(&rsvp->lock);
+
+ /*
+ * This function handles the write-and-then-read ordering issue.
+ *
+ * The ordering issue:
+ * There is a case that a task don't take a lock to a dmabuf so
+ * this task would be stalled even though this task requested a lock
+ * to the dmabuf between other task unlocked and tries to lock
+ * the dmabuf again.
+ *
+ * How to handle the ordering issue:
+ * 1. Check if there is a sync object added prior to current task's one.
+ * 2. If exists, it unlocks the dmabuf so that other task can take
+ * a lock to the dmabuf first.
+ * 3. Wait for the wake up event from other task: current task will be
+ * waked up when other task unlocks the dmabuf.
+ * 4. Take a lock to the dmabuf again.
+ */
+ if (!list_empty(&rsvp->syncs)) {
+ struct dmabuf_sync_object *r_sobj, *next;
+
+ list_for_each_entry_safe(r_sobj, next, &rsvp->syncs,
+ r_head) {
+ long timeout;
+
+ /*
+ * Find a sync object added to rsvp->syncs by other task
+ * before current task tries to lock the dmabuf again.
+ * If sobj = r_sobj, it means that there is no any task
+ * that added its own sync object to rsvp->syncs so out
+ * of this loop.
+ */
+ if (sobj = r_sobj)
+ break;
+
+ /*
+ * Unlock the dmabuf if there is a sync object added
+ * to rsvp->syncs so that other task can take a lock
+ * first.
+ */
+ if (rsvp->locked) {
+ ww_mutex_unlock(&rsvp->sync_lock);
+ rsvp->locked = false;
+ }
+
+ r_sobj->waiting = true;
+
+ atomic_inc(&r_sobj->refcnt);
+ mutex_unlock(&rsvp->lock);
+
+ /* Wait for the wake up event from other task. */
+ timeout = wait_event_timeout(r_sobj->wq,
+ !r_sobj->waiting,
+ msecs_to_jiffies(MAX_WAIT_TIMEOUT));
+ if (!timeout) {
+ r_sobj->waiting = false;
+ pr_warn("wait event timeout: sobj = 0x%p\n",
+ r_sobj);
+
+ /*
+ * A sync object from fcntl system call has no
+ * timeout handler so delete ane free r_sobj
+ * once timeout here without checking refcnt.
+ */
+ if (r_sobj->task) {
+ list_del_init(&r_sobj->r_head);
+ kfree(r_sobj);
+ }
+ }
+
+ if (!atomic_add_unless(&r_sobj->refcnt, -1, 1))
+ kfree(r_sobj);
+
+ /*
+ * Other task unlocked the dmabuf so take a lock again.
+ */
+ ww_mutex_lock(&rsvp->sync_lock, ctx);
+
+ mutex_lock(&rsvp->lock);
+ rsvp->locked = true;
+ }
+ }
+
+ mutex_unlock(&rsvp->lock);
+}
+
+static int dmabuf_sync_lock_objs(struct dmabuf_sync *sync,
+ struct ww_acquire_ctx *ctx)
+{
+ struct dmabuf_sync_object *contended_sobj = NULL;
+ struct dmabuf_sync_object *res_sobj = NULL;
+ struct dmabuf_sync_object *sobj = NULL;
+ int ret;
+
+ if (ctx)
+ ww_acquire_init(ctx, &dmabuf_sync_ww_class);
+
+retry:
+ list_for_each_entry(sobj, &sync->syncs, head) {
+ struct dmabuf_sync_reservation *rsvp = sobj->robj;
+
+ if (WARN_ON(!rsvp))
+ continue;
+
+ mutex_lock(&rsvp->lock);
+
+ /* Don't lock in case of read and read. */
+ if (rsvp->accessed_type & DMA_BUF_ACCESS_R &&
+ sobj->access_type & DMA_BUF_ACCESS_R) {
+ atomic_inc(&rsvp->shared_cnt);
+ mutex_unlock(&rsvp->lock);
+ continue;
+ }
+
+ if (sobj = res_sobj) {
+ res_sobj = NULL;
+ mutex_unlock(&rsvp->lock);
+ continue;
+ }
+
+ /*
+ * Add a sync object to reservation object of dmabuf
+ * to handle the write-and-then-read ordering issue.
+ *
+ * For more details, see dmabuf_sync_wait_prev_objs function.
+ */
+ list_add_tail(&sobj->r_head, &rsvp->syncs);
+ mutex_unlock(&rsvp->lock);
+
+ ret = ww_mutex_lock(&rsvp->sync_lock, ctx);
+ if (ret < 0) {
+ contended_sobj = sobj;
+
+ if (ret = -EDEADLK)
+ pr_warn("%s: deadlock = 0x%p\n",
+ sync->name, sobj->dmabuf);
+ goto err;
+ }
+
+ mutex_lock(&rsvp->lock);
+ rsvp->locked = true;
+
+ mutex_unlock(&rsvp->lock);
+
+ /*
+ * Check if there is a sync object added to reservation object
+ * of dmabuf before current task takes a lock to the dmabuf.
+ * And ithen wait for the for the wake up event from other task
+ * if exists.
+ */
+ dmabuf_sync_wait_prev_objs(sobj, rsvp, ctx);
+ }
+
+ if (ctx)
+ ww_acquire_done(ctx);
+
+ init_timer(&sync->timer);
+
+ sync->timer.data = (unsigned long)sync;
+ sync->timer.function = dmabuf_sync_lock_timeout;
+ sync->timer.expires = jiffies + (HZ * MAX_SYNC_TIMEOUT);
+
+ add_timer(&sync->timer);
+
+ return 0;
+
+err:
+ list_for_each_entry_continue_reverse(sobj, &sync->syncs, head) {
+ struct dmabuf_sync_reservation *rsvp = sobj->robj;
+
+ mutex_lock(&rsvp->lock);
+
+ /* Don't need to unlock in case of read and read. */
+ if (atomic_add_unless(&rsvp->shared_cnt, -1, 1)) {
+ mutex_unlock(&rsvp->lock);
+ continue;
+ }
+
+ /*
+ * Delete a sync object from reservation object of dmabuf.
+ *
+ * The sync object was added to reservation object of dmabuf
+ * just before ww_mutex_lock() is called.
+ */
+ DEL_OBJ_FROM_RSV(sobj, rsvp);
+ mutex_unlock(&rsvp->lock);
+
+ ww_mutex_unlock(&rsvp->sync_lock);
+
+ mutex_lock(&rsvp->lock);
+ rsvp->locked = false;
+ mutex_unlock(&rsvp->lock);
+ }
+
+ if (res_sobj) {
+ struct dmabuf_sync_reservation *rsvp = res_sobj->robj;
+
+ mutex_lock(&rsvp->lock);
+
+ if (!atomic_add_unless(&rsvp->shared_cnt, -1, 1)) {
+ /*
+ * Delete a sync object from reservation object
+ * of dmabuf.
+ */
+ DEL_OBJ_FROM_RSV(sobj, rsvp);
+ mutex_unlock(&rsvp->lock);
+
+ ww_mutex_unlock(&rsvp->sync_lock);
+
+ mutex_lock(&rsvp->lock);
+ rsvp->locked = false;
+ }
+
+ mutex_unlock(&rsvp->lock);
+ }
+
+ if (ret = -EDEADLK) {
+ ww_mutex_lock_slow(&contended_sobj->robj->sync_lock, ctx);
+ res_sobj = contended_sobj;
+
+ goto retry;
+ }
+
+ if (ctx)
+ ww_acquire_fini(ctx);
+
+ return ret;
+}
+
+static void dmabuf_sync_unlock_objs(struct dmabuf_sync *sync,
+ struct ww_acquire_ctx *ctx)
+{
+ struct dmabuf_sync_object *sobj;
+
+ if (list_empty(&sync->syncs))
+ return;
+
+ mutex_lock(&sync->lock);
+
+ list_for_each_entry(sobj, &sync->syncs, head) {
+ struct dmabuf_sync_reservation *rsvp = sobj->robj;
+
+ mutex_lock(&rsvp->lock);
+
+ if (rsvp->polled) {
+ rsvp->poll_event = true;
+ rsvp->polled = false;
+ wake_up_interruptible(&rsvp->poll_wait);
+ }
+
+ /*
+ * Wake up a task blocked by dmabuf_sync_wait_prev_objs().
+ *
+ * If sobj->waiting is true, the task is waiting for wake_up
+ * call. So wake up the task if a given time period was
+ * elapsed so current task was timed out.
+ */
+ WAKE_UP_SYNC_OBJ(sobj);
+
+ /* Delete a sync object from reservation object of dmabuf. */
+ DEL_OBJ_FROM_RSV(sobj, rsvp);
+
+ if (atomic_add_unless(&rsvp->shared_cnt, -1, 1)) {
+ mutex_unlock(&rsvp->lock);
+ continue;
+ }
+
+ mutex_unlock(&rsvp->lock);
+
+ ww_mutex_unlock(&rsvp->sync_lock);
+
+ mutex_lock(&rsvp->lock);
+ rsvp->locked = false;
+ mutex_unlock(&rsvp->lock);
+ }
+
+ mutex_unlock(&sync->lock);
+
+ if (ctx)
+ ww_acquire_fini(ctx);
+
+ del_timer(&sync->timer);
+}
+
+/**
+ * dmabuf_sync_is_supported - Check if dmabuf sync is supported or not.
+ */
+bool dmabuf_sync_is_supported(void)
+{
+ return dmabuf_sync_enabled = 1;
+}
+EXPORT_SYMBOL_GPL(dmabuf_sync_is_supported);
+
+/**
+ * dmabuf_sync_init - Allocate and initialize a dmabuf sync.
+ *
+ * @priv: A device private data.
+ * @name: A sync object name.
+ *
+ * This function should be called when a device context or an event
+ * context such as a page flip event is created. And the created
+ * dmabuf_sync object should be set to the context.
+ * The caller can get a new sync object for buffer synchronization
+ * through this function.
+ */
+struct dmabuf_sync *dmabuf_sync_init(const char *name,
+ struct dmabuf_sync_priv_ops *ops,
+ void *priv)
+{
+ struct dmabuf_sync *sync;
+
+ sync = kzalloc(sizeof(*sync), GFP_KERNEL);
+ if (!sync)
+ return ERR_PTR(-ENOMEM);
+
+ strncpy(sync->name, name, DMABUF_SYNC_NAME_SIZE);
+
+ sync->ops = ops;
+ sync->priv = priv;
+ INIT_LIST_HEAD(&sync->syncs);
+ mutex_init(&sync->lock);
+ INIT_WORK(&sync->work, dmabuf_sync_timeout_worker);
+
+ return sync;
+}
+EXPORT_SYMBOL_GPL(dmabuf_sync_init);
+
+/**
+ * dmabuf_sync_fini - Release a given dmabuf sync.
+ *
+ * @sync: An object to dmabuf_sync structure.
+ *
+ * This function should be called if some operation is failed after
+ * dmabuf_sync_init call to release relevant resources, and after
+ * dmabuf_sync_unlock function is called.
+ */
+void dmabuf_sync_fini(struct dmabuf_sync *sync)
+{
+ struct dmabuf_sync_object *sobj;
+
+ if (WARN_ON(!sync))
+ return;
+
+ if (list_empty(&sync->syncs))
+ goto free_sync;
+
+ list_for_each_entry(sobj, &sync->syncs, head) {
+ struct dmabuf_sync_reservation *rsvp = sobj->robj;
+
+ mutex_lock(&rsvp->lock);
+
+ if (rsvp->locked) {
+ mutex_unlock(&rsvp->lock);
+ ww_mutex_unlock(&rsvp->sync_lock);
+
+ mutex_lock(&rsvp->lock);
+ rsvp->locked = false;
+ }
+
+ mutex_unlock(&rsvp->lock);
+ }
+
+ /*
+ * If !list_empty(&sync->syncs) then it means that dmabuf_sync_put()
+ * or dmabuf_sync_put_all() was never called. So unreference all
+ * dmabuf objects added to sync->syncs, and remove them from the syncs.
+ */
+ dmabuf_sync_put_all(sync);
+
+free_sync:
+ if (sync->ops && sync->ops->free)
+ sync->ops->free(sync->priv);
+
+ kfree(sync);
+}
+EXPORT_SYMBOL_GPL(dmabuf_sync_fini);
+
+/*
+ * dmabuf_sync_get_obj - Add a given object to sync's list.
+ *
+ * @sync: An object to dmabuf_sync structure.
+ * @dmabuf: An object to dma_buf structure.
+ * @type: A access type to a dma buf.
+ * The DMA_BUF_ACCESS_R means that this dmabuf could be accessed by
+ * others for read access. On the other hand, the DMA_BUF_ACCESS_W
+ * means that this dmabuf couldn't be accessed by others but would be
+ * accessed by caller's dma exclusively. And the DMA_BUF_ACCESS_DMA can be
+ * combined.
+ *
+ * This function creates and initializes a new dmabuf sync object and it adds
+ * the dmabuf sync object to syncs list to track and manage all dmabufs.
+ */
+static int dmabuf_sync_get_obj(struct dmabuf_sync *sync, struct dma_buf *dmabuf,
+ unsigned int type)
+{
+ struct dmabuf_sync_object *sobj;
+
+ if (!dmabuf->sync)
+ return -EFAULT;
+
+ if (!IS_VALID_DMA_BUF_ACCESS_TYPE(type))
+ return -EINVAL;
+
+ if ((type & DMA_BUF_ACCESS_RW) = DMA_BUF_ACCESS_RW)
+ type &= ~DMA_BUF_ACCESS_R;
+
+ sobj = kzalloc(sizeof(*sobj), GFP_KERNEL);
+ if (!sobj)
+ return -ENOMEM;
+
+ get_dma_buf(dmabuf);
+
+ sobj->dmabuf = dmabuf;
+ sobj->robj = dmabuf->sync;
+ sobj->access_type = type;
+ atomic_set(&sobj->refcnt, 1);
+ init_waitqueue_head(&sobj->wq);
+
+ mutex_lock(&sync->lock);
+ list_add_tail(&sobj->head, &sync->syncs);
+ mutex_unlock(&sync->lock);
+
+ return 0;
+}
+
+/*
+ * dmabuf_sync_put_obj - Release a given sync object.
+ *
+ * @sync: An object to dmabuf_sync structure.
+ *
+ * This function should be called if some operation failed after
+ * dmabuf_sync_get_obj call to release a given sync object.
+ */
+static void dmabuf_sync_put_obj(struct dmabuf_sync *sync,
+ struct dma_buf *dmabuf)
+{
+ struct dmabuf_sync_object *sobj;
+
+ mutex_lock(&sync->lock);
+
+ list_for_each_entry(sobj, &sync->syncs, head) {
+ if (sobj->dmabuf != dmabuf)
+ continue;
+
+ dma_buf_put(sobj->dmabuf);
+
+ list_del_init(&sobj->head);
+
+ if (!atomic_add_unless(&sobj->refcnt, -1, 1))
+ kfree(sobj);
+ break;
+ }
+
+ if (list_empty(&sync->syncs))
+ sync->status = 0;
+
+ mutex_unlock(&sync->lock);
+}
+
+/*
+ * dmabuf_sync_put_objs - Release all sync objects of dmabuf_sync.
+ *
+ * @sync: An object to dmabuf_sync structure.
+ *
+ * This function should be called if some operation failed after
+ * dmabuf_sync_get_obj call to release all sync objects.
+ */
+static void dmabuf_sync_put_objs(struct dmabuf_sync *sync)
+{
+ struct dmabuf_sync_object *sobj, *next;
+
+ mutex_lock(&sync->lock);
+
+ list_for_each_entry_safe(sobj, next, &sync->syncs, head) {
+ dma_buf_put(sobj->dmabuf);
+
+ list_del_init(&sobj->head);
+
+ if (!atomic_add_unless(&sobj->refcnt, -1, 1))
+ kfree(sobj);
+ }
+
+ mutex_unlock(&sync->lock);
+
+ sync->status = 0;
+}
+
+/**
+ * dmabuf_sync_lock - lock all dmabufs added to syncs list.
+ *
+ * @sync: An object to dmabuf_sync structure.
+ *
+ * The caller should call this function prior to CPU or DMA access to
+ * the dmabufs so that others can not access the dmabufs.
+ * Internally, this function avoids dead lock issue with ww-mutex.
+ */
+int dmabuf_sync_lock(struct dmabuf_sync *sync)
+{
+ int ret;
+
+ if (!sync)
+ return -EFAULT;
+
+ if (list_empty(&sync->syncs))
+ return -EINVAL;
+
+ if (sync->status != DMABUF_SYNC_GOT)
+ return -EINVAL;
+
+ ret = dmabuf_sync_lock_objs(sync, &sync->ctx);
+ if (ret < 0)
+ return ret;
+
+ sync->status = DMABUF_SYNC_LOCKED;
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(dmabuf_sync_lock);
+
+/**
+ * dmabuf_sync_unlock - unlock all objects added to syncs list.
+ *
+ * @sync: An object to dmabuf_sync structure.
+ *
+ * The caller should call this function after CPU or DMA access to
+ * the dmabufs is completed so that others can access the dmabufs.
+ */
+int dmabuf_sync_unlock(struct dmabuf_sync *sync)
+{
+ if (!sync)
+ return -EFAULT;
+
+ /* If current dmabuf sync object wasn't reserved then just return. */
+ if (sync->status != DMABUF_SYNC_LOCKED)
+ return -EAGAIN;
+
+ dmabuf_sync_unlock_objs(sync, &sync->ctx);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(dmabuf_sync_unlock);
+
+/**
+ * dmabuf_sync_single_lock - lock a dma buf.
+ *
+ * @dmabuf: A dma buf object that tries to lock.
+ * @type: A access type to a dma buf.
+ * The DMA_BUF_ACCESS_R means that this dmabuf could be accessed by
+ * others for read access. On the other hand, the DMA_BUF_ACCESS_W
+ * means that this dmabuf couldn't be accessed by others but would be
+ * accessed by caller's dma exclusively. And the DMA_BUF_ACCESS_DMA can
+ * be combined with other.
+ * @wait: Indicate whether caller is blocked or not.
+ * true means that caller will be blocked, and false means that this
+ * function will return -EAGAIN if this caller can't take the lock
+ * right now.
+ *
+ * The caller should call this function prior to CPU or DMA access to the dmabuf
+ * so that others cannot access the dmabuf.
+ */
+int dmabuf_sync_single_lock(struct dma_buf *dmabuf, unsigned int type,
+ bool wait)
+{
+ struct dmabuf_sync_reservation *robj;
+ struct dmabuf_sync_object *sobj;
+
+ if (!dmabuf->sync)
+ return -EFAULT;
+
+ if (!IS_VALID_DMA_BUF_ACCESS_TYPE(type))
+ return -EINVAL;
+
+ get_dma_buf(dmabuf);
+ robj = dmabuf->sync;
+
+ sobj = kzalloc(sizeof(*sobj), GFP_KERNEL);
+ if (!sobj) {
+ dma_buf_put(dmabuf);
+ return -ENOMEM;
+ }
+
+ sobj->dmabuf = dmabuf;
+ sobj->task = (unsigned long)current;
+ atomic_set(&sobj->refcnt, 1);
+ init_waitqueue_head(&sobj->wq);
+
+ mutex_lock(&robj->lock);
+
+ /* Don't lock in case of read and read. */
+ if (robj->accessed_type & DMA_BUF_ACCESS_R && type & DMA_BUF_ACCESS_R) {
+ atomic_inc(&robj->shared_cnt);
+ mutex_unlock(&robj->lock);
+ return 0;
+ }
+
+ /*
+ * In case of F_SETLK, just return -EAGAIN if this dmabuf has already
+ * been locked.
+ */
+ if (!wait && robj->locked) {
+ mutex_unlock(&robj->lock);
+ dma_buf_put(dmabuf);
+ return -EAGAIN;
+ }
+
+ /*
+ * Add a sync object to reservation object of dmabuf to handle
+ * the write-and-then-read ordering issue.
+ */
+ list_add_tail(&sobj->r_head, &robj->syncs);
+ mutex_unlock(&robj->lock);
+
+ /* Unlocked by dmabuf_sync_single_unlock or dmabuf_sync_unlock. */
+ mutex_lock(&robj->sync_lock.base);
+
+ mutex_lock(&robj->lock);
+ robj->locked = true;
+ mutex_unlock(&robj->lock);
+
+ /*
+ * Check if there is a sync object added to reservation object of
+ * dmabuf before current task takes a lock to the dmabuf, and wait
+ * for the for the wake up event from other task if exists.
+ */
+ dmabuf_sync_wait_prev_objs(sobj, robj, NULL);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(dmabuf_sync_single_lock);
+
+/**
+ * dmabuf_sync_single_unlock - unlock a dma buf.
+ *
+ * @dmabuf: A dma buf object that tries to unlock.
+ *
+ * The caller should call this function after CPU or DMA access to
+ * the dmabuf is completed so that others can access the dmabuf.
+ */
+void dmabuf_sync_single_unlock(struct dma_buf *dmabuf)
+{
+ struct dmabuf_sync_reservation *robj;
+ struct dmabuf_sync_object *sobj, *next;
+
+ if (!dmabuf->sync) {
+ WARN_ON(1);
+ return;
+ }
+
+ robj = dmabuf->sync;
+
+ mutex_lock(&robj->lock);
+
+ if (robj->polled) {
+ robj->poll_event = true;
+ robj->polled = false;
+ wake_up_interruptible(&robj->poll_wait);
+ }
+
+ /*
+ * Wake up a blocked task/tasks by dmabuf_sync_wait_prev_objs()
+ * with two steps.
+ *
+ * 1. Wake up a task waiting for the wake up event to a sync object
+ * of same task, and remove the sync object from reservation
+ * object of dmabuf, and then go to out: requested by same task.
+ * 2. Wait up a task waiting for the wake up event to a sync object
+ * of other task, and remove the sync object if not existed
+ * at step 1: requested by other task.
+ *
+ * The reason, we have to handle it with the above two steps,
+ * is that fcntl system call is called with a file descriptor so
+ * kernel side cannot be aware of which sync object of robj->syncs
+ * should be waked up and deleted at this function.
+ * So for this, we use the above two steps to find a sync object
+ * to be waked up.
+ */
+ list_for_each_entry_safe(sobj, next, &robj->syncs, r_head) {
+ if (sobj->task = (unsigned long)current) {
+ /*
+ * Wake up a task blocked by
+ * dmabuf_sync_wait_prev_objs().
+ */
+ WAKE_UP_SYNC_OBJ(sobj);
+
+ list_del_init(&sobj->r_head);
+
+ if (!atomic_add_unless(&sobj->refcnt, -1, 1))
+ kfree(sobj);
+ goto out;
+ }
+ }
+
+ list_for_each_entry_safe(sobj, next, &robj->syncs, r_head) {
+ if (sobj->task) {
+ /*
+ * Wake up a task blocked by
+ * dmabuf_sync_wait_prev_objs().
+ */
+ WAKE_UP_SYNC_OBJ(sobj);
+
+ list_del_init(&sobj->r_head);
+
+ if (!atomic_add_unless(&sobj->refcnt, -1, 1))
+ kfree(sobj);
+ break;
+ }
+ }
+
+out:
+ if (atomic_add_unless(&robj->shared_cnt, -1 , 1)) {
+ mutex_unlock(&robj->lock);
+ dma_buf_put(dmabuf);
+ return;
+ }
+
+ mutex_unlock(&robj->lock);
+
+ mutex_unlock(&robj->sync_lock.base);
+
+ mutex_lock(&robj->lock);
+ robj->locked = false;
+ mutex_unlock(&robj->lock);
+
+ dma_buf_put(dmabuf);
+
+ return;
+}
+EXPORT_SYMBOL_GPL(dmabuf_sync_single_unlock);
+
+/**
+ * dmabuf_sync_get - Get dmabuf sync object.
+ *
+ * @sync: An object to dmabuf_sync structure.
+ * @sync_buf: A dmabuf object to be synchronized with others.
+ * @type: A access type to a dma buf.
+ * The DMA_BUF_ACCESS_R means that this dmabuf could be accessed by
+ * others for read access. On the other hand, the DMA_BUF_ACCESS_W
+ * means that this dmabuf couldn't be accessed by others but would be
+ * accessed by caller's dma exclusively. And the DMA_BUF_ACCESS_DMA can
+ * be combined with other.
+ *
+ * This function should be called after dmabuf_sync_init function is called.
+ * The caller can tie up multiple dmabufs into one sync object by calling this
+ * function several times. Internally, this function allocates
+ * a dmabuf_sync_object and adds a given dmabuf to it, and also takes
+ * a reference to a dmabuf.
+ */
+int dmabuf_sync_get(struct dmabuf_sync *sync, void *sync_buf, unsigned int type)
+{
+ int ret;
+
+ if (!sync || !sync_buf)
+ return -EFAULT;
+
+ ret = dmabuf_sync_get_obj(sync, sync_buf, type);
+ if (ret < 0)
+ return ret;
+
+ sync->status = DMABUF_SYNC_GOT;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(dmabuf_sync_get);
+
+/**
+ * dmabuf_sync_put - Put dmabuf sync object to a given dmabuf.
+ *
+ * @sync: An object to dmabuf_sync structure.
+ * @dmabuf: An dmabuf object.
+ *
+ * This function should be called if some operation is failed after
+ * dmabuf_sync_get function is called to release the dmabuf, or
+ * dmabuf_sync_unlock function is called. Internally, this function
+ * removes a given dmabuf from a sync object and remove the sync object.
+ * At this time, the dmabuf is putted.
+ */
+void dmabuf_sync_put(struct dmabuf_sync *sync, struct dma_buf *dmabuf)
+{
+ if (!sync || !dmabuf) {
+ WARN_ON(1);
+ return;
+ }
+
+ if (list_empty(&sync->syncs))
+ return;
+
+ dmabuf_sync_put_obj(sync, dmabuf);
+}
+EXPORT_SYMBOL_GPL(dmabuf_sync_put);
+
+/**
+ * dmabuf_sync_put_all - Put dmabuf sync object to dmabufs.
+ *
+ * @sync: An object to dmabuf_sync structure.
+ *
+ * This function should be called if some operation is failed after
+ * dmabuf_sync_get function is called to release all sync objects, or
+ * dmabuf_sync_unlock function is called. Internally, this function
+ * removes dmabufs from a sync object and remove the sync object.
+ * At this time, all dmabufs are putted.
+ */
+void dmabuf_sync_put_all(struct dmabuf_sync *sync)
+{
+ if (!sync) {
+ WARN_ON(1);
+ return;
+ }
+
+ if (list_empty(&sync->syncs))
+ return;
+
+ dmabuf_sync_put_objs(sync);
+}
+EXPORT_SYMBOL_GPL(dmabuf_sync_put_all);
diff --git a/include/linux/dma-buf.h b/include/linux/dma-buf.h
index dfac5ed..0109673 100644
--- a/include/linux/dma-buf.h
+++ b/include/linux/dma-buf.h
@@ -115,6 +115,7 @@ struct dma_buf_ops {
* @exp_name: name of the exporter; useful for debugging.
* @list_node: node for dma_buf accounting and debugging.
* @priv: exporter specific private data for this buffer object.
+ * @sync: sync object linked to this dma-buf
*/
struct dma_buf {
size_t size;
@@ -128,6 +129,7 @@ struct dma_buf {
const char *exp_name;
struct list_head list_node;
void *priv;
+ void *sync;
};
/**
@@ -148,6 +150,20 @@ struct dma_buf_attachment {
void *priv;
};
+#define DMA_BUF_ACCESS_R 0x1
+#define DMA_BUF_ACCESS_W 0x2
+#define DMA_BUF_ACCESS_DMA 0x4
+#define DMA_BUF_ACCESS_RW (DMA_BUF_ACCESS_R | DMA_BUF_ACCESS_W)
+#define DMA_BUF_ACCESS_DMA_R (DMA_BUF_ACCESS_R | DMA_BUF_ACCESS_DMA)
+#define DMA_BUF_ACCESS_DMA_W (DMA_BUF_ACCESS_W | DMA_BUF_ACCESS_DMA)
+#define DMA_BUF_ACCESS_DMA_RW (DMA_BUF_ACCESS_DMA_R | DMA_BUF_ACCESS_DMA_W)
+#define IS_VALID_DMA_BUF_ACCESS_TYPE(t) (t = DMA_BUF_ACCESS_R || \
+ t = DMA_BUF_ACCESS_W || \
+ t = DMA_BUF_ACCESS_DMA_R || \
+ t = DMA_BUF_ACCESS_DMA_W || \
+ t = DMA_BUF_ACCESS_RW || \
+ t = DMA_BUF_ACCESS_DMA_RW)
+
/**
* get_dma_buf - convenience wrapper for get_file.
* @dmabuf: [in] pointer to dma_buf
diff --git a/include/linux/dmabuf-sync.h b/include/linux/dmabuf-sync.h
new file mode 100644
index 0000000..fc0bb4e
--- /dev/null
+++ b/include/linux/dmabuf-sync.h
@@ -0,0 +1,257 @@
+/*
+ * Copyright (C) 2013 Samsung Electronics Co.Ltd
+ * Authors:
+ * Inki Dae <inki.dae@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+
+#include <linux/ww_mutex.h>
+#include <linux/sched.h>
+#include <linux/dma-buf.h>
+
+#define DMABUF_SYNC_NAME_SIZE 64
+
+/*
+ * Status to a dmabuf_sync object.
+ *
+ * @DMABUF_SYNC_GOT: Indicate that one more dmabuf objects have been added
+ * to a sync's list.
+ * @DMABUF_SYNC_LOCKED: Indicate that all dmabuf objects in a sync's list
+ * have been locked.
+ */
+enum dmabuf_sync_status {
+ DMABUF_SYNC_GOT = 1,
+ DMABUF_SYNC_LOCKED,
+};
+
+/*
+ * A structure for dmabuf_sync_reservation.
+ *
+ * @syncs: A list head to sync object and this is global to system.
+ * This contains sync objects of tasks that requested a lock
+ * to this dmabuf.
+ * @sync_lock: This provides read or write lock to a dmabuf.
+ * Except in the below cases, a task will be blocked if the task
+ * tries to lock a dmabuf for CPU or DMA access when other task
+ * already locked the dmabuf.
+ *
+ * Before After
+ * --------------------------
+ * CPU read CPU read
+ * CPU read DMA read
+ * DMA read CPU read
+ * DMA read DMA read
+ *
+ * @lock: Protecting a dmabuf_sync_reservation object.
+ * @poll_wait: A wait queue object to poll a dmabuf object.
+ * @poll_event: Indicate whether a dmabuf object - being polled -
+ * was unlocked or not. If true, a blocked task will be out
+ * of select system call.
+ * @poll: Indicate whether the polling to a dmabuf object was requested
+ * or not by userspace.
+ * @shared_cnt: Shared count to a dmabuf object.
+ * @accessed_type: Indicate how and who a dmabuf object was accessed by.
+ * One of the below types could be set.
+ * DMA_BUF_ACCESS_R -> CPU access for read.
+ * DMA_BUF_ACCRSS_W -> CPU access for write.
+ * DMA_BUF_ACCESS_R | DMA_BUF_ACCESS_DMA -> DMA access for read.
+ * DMA_BUF_ACCESS_W | DMA_BUF_ACCESS_DMA -> DMA access for write.
+ * @locked: Indicate whether a dmabuf object has been locked or not.
+ *
+ */
+struct dmabuf_sync_reservation {
+ struct list_head syncs;
+ struct ww_mutex sync_lock;
+ struct mutex lock;
+ wait_queue_head_t poll_wait;
+ unsigned int poll_event;
+ unsigned int polled;
+ atomic_t shared_cnt;
+ unsigned int accessed_type;
+ unsigned int locked;
+};
+
+/*
+ * A structure for dmabuf_sync_object.
+ *
+ * @head: A list head to be added to dmabuf_sync's syncs.
+ * @r_head: A list head to be added to dmabuf_sync_reservation's syncs.
+ * @robj: A reservation_object object.
+ * @dma_buf: A dma_buf object.
+ * @task: An address value to current task.
+ * This is used to indicate who is a owner of a sync object.
+ * @wq: A wait queue head.
+ * This is used to guarantee that a task can take a lock to a dmabuf
+ * if the task requested a lock to the dmabuf prior to other task.
+ * For more details, see dmabuf_sync_wait_prev_objs function.
+ * @refcnt: A reference count to a sync object.
+ * @access_type: Indicate how a current task tries to access
+ * a given buffer, and one of the below types could be set.
+ * DMA_BUF_ACCESS_R -> CPU access for read.
+ * DMA_BUF_ACCRSS_W -> CPU access for write.
+ * DMA_BUF_ACCESS_R | DMA_BUF_ACCESS_DMA -> DMA access for read.
+ * DMA_BUF_ACCESS_W | DMA_BUF_ACCESS_DMA -> DMA access for write.
+ * @waiting: Indicate whether current task is waiting for the wake up event
+ * from other task or not.
+ */
+struct dmabuf_sync_object {
+ struct list_head head;
+ struct list_head r_head;
+ struct dmabuf_sync_reservation *robj;
+ struct dma_buf *dmabuf;
+ unsigned long task;
+ wait_queue_head_t wq;
+ atomic_t refcnt;
+ unsigned int access_type;
+ unsigned int waiting;
+};
+
+struct dmabuf_sync_priv_ops {
+ void (*free)(void *priv);
+};
+
+/*
+ * A structure for dmabuf_sync.
+ *
+ * @syncs: A list head to sync object and this is global to system.
+ * This contains sync objects of dmabuf_sync owner.
+ * @list: A list entry used as committed list node
+ * @lock: Protecting a dmabuf_sync object.
+ * @ctx: A current context for ww mutex.
+ * @work: A work struct to release resources at timeout.
+ * @priv: A private data.
+ * @name: A string to dmabuf sync owner.
+ * @timer: A timer list to avoid lockup and release resources.
+ * @status: Indicate current status (DMABUF_SYNC_GOT or DMABUF_SYNC_LOCKED).
+ */
+struct dmabuf_sync {
+ struct list_head syncs;
+ struct list_head list;
+ struct mutex lock;
+ struct ww_acquire_ctx ctx;
+ struct work_struct work;
+ void *priv;
+ struct dmabuf_sync_priv_ops *ops;
+ char name[DMABUF_SYNC_NAME_SIZE];
+ struct timer_list timer;
+ unsigned int status;
+};
+
+#ifdef CONFIG_DMABUF_SYNC
+
+extern struct ww_class dmabuf_sync_ww_class;
+
+static inline void dmabuf_sync_reservation_init(struct dma_buf *dmabuf)
+{
+ struct dmabuf_sync_reservation *obj;
+
+ obj = kzalloc(sizeof(*obj), GFP_KERNEL);
+ if (!obj)
+ return;
+
+ dmabuf->sync = obj;
+
+ ww_mutex_init(&obj->sync_lock, &dmabuf_sync_ww_class);
+
+ mutex_init(&obj->lock);
+ atomic_set(&obj->shared_cnt, 1);
+ INIT_LIST_HEAD(&obj->syncs);
+
+ init_waitqueue_head(&obj->poll_wait);
+}
+
+static inline void dmabuf_sync_reservation_fini(struct dma_buf *dmabuf)
+{
+ struct dmabuf_sync_reservation *obj;
+
+ if (!dmabuf->sync)
+ return;
+
+ obj = dmabuf->sync;
+
+ ww_mutex_destroy(&obj->sync_lock);
+
+ kfree(obj);
+}
+
+bool dmabuf_sync_is_supported(void);
+
+struct dmabuf_sync *dmabuf_sync_init(const char *name,
+ struct dmabuf_sync_priv_ops *ops,
+ void *priv);
+
+void dmabuf_sync_fini(struct dmabuf_sync *sync);
+
+int dmabuf_sync_lock(struct dmabuf_sync *sync);
+
+int dmabuf_sync_unlock(struct dmabuf_sync *sync);
+
+int dmabuf_sync_single_lock(struct dma_buf *dmabuf, unsigned int type,
+ bool wait);
+
+void dmabuf_sync_single_unlock(struct dma_buf *dmabuf);
+
+int dmabuf_sync_get(struct dmabuf_sync *sync, void *sync_buf,
+ unsigned int type);
+
+void dmabuf_sync_put(struct dmabuf_sync *sync, struct dma_buf *dmabuf);
+
+void dmabuf_sync_put_all(struct dmabuf_sync *sync);
+
+#else
+
+static inline void dmabuf_sync_reservation_init(struct dma_buf *dmabuf) { }
+
+static inline void dmabuf_sync_reservation_fini(struct dma_buf *dmabuf) { }
+
+static inline bool dmabuf_sync_is_supported(void) { return false; }
+
+static inline struct dmabuf_sync *dmabuf_sync_init(const char *name,
+ struct dmabuf_sync_priv_ops *ops,
+ void *priv)
+{
+ return ERR_PTR(0);
+}
+
+static inline void dmabuf_sync_fini(struct dmabuf_sync *sync) { }
+
+static inline int dmabuf_sync_lock(struct dmabuf_sync *sync)
+{
+ return 0;
+}
+
+static inline int dmabuf_sync_unlock(struct dmabuf_sync *sync)
+{
+ return 0;
+}
+
+static inline int dmabuf_sync_single_lock(struct dma_buf *dmabuf,
+ unsigned int type,
+ bool wait)
+{
+ return 0;
+}
+
+static inline void dmabuf_sync_single_unlock(struct dma_buf *dmabuf)
+{
+ return;
+}
+
+static inline int dmabuf_sync_get(struct dmabuf_sync *sync,
+ void *sync_buf,
+ unsigned int type)
+{
+ return 0;
+}
+
+static inline void dmabuf_sync_put(struct dmabuf_sync *sync,
+ struct dma_buf *dmabuf) { }
+
+static inline void dmabuf_sync_put_all(struct dmabuf_sync *sync) { }
+
+#endif
--
1.7.5.4
^ permalink raw reply related
* [PATCH v2 2/2] dma-buf: Add user interfaces for dmabuf sync support
From: Inki Dae @ 2013-08-29 7:53 UTC (permalink / raw)
To: dri-devel, linux-fbdev, linux-arm-kernel, linux-media,
linaro-kernel
Cc: maarten.lankhorst, sumit.semwal, kyungmin.park, myungjoo.ham,
Inki Dae
In-Reply-To: <1377762801-14057-1-git-send-email-inki.dae@samsung.com>
This patch adds lock and poll callbacks to dma buf file operations,
and these callbacks will be called by fcntl and select system calls.
fcntl and select system calls can be used to wait for the completion
of DMA or CPU access to a shared dmabuf. The difference of them is
fcntl system call takes a lock after the completion but select system
call doesn't. So in case of fcntl system call, it's useful when a task
wants to access a shared dmabuf without any broken. On the other hand,
it's useful when a task wants to just wait for the completion.
Changelog v2:
- Add select system call support.
. The purpose of this feature is to wait for the completion of DMA or
CPU access to a dmabuf without that caller locks the dmabuf again
after the completion.
That is useful when caller wants to be aware of the completion of
DMA access to the dmabuf, and the caller doesn't use intefaces for
the DMA device driver.
Signed-off-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
drivers/base/dma-buf.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 81 insertions(+), 0 deletions(-)
diff --git a/drivers/base/dma-buf.c b/drivers/base/dma-buf.c
index cc42a38..f961907 100644
--- a/drivers/base/dma-buf.c
+++ b/drivers/base/dma-buf.c
@@ -30,6 +30,7 @@
#include <linux/export.h>
#include <linux/debugfs.h>
#include <linux/seq_file.h>
+#include <linux/poll.h>
#include <linux/dmabuf-sync.h>
static inline int is_dma_buf_file(struct file *);
@@ -81,9 +82,89 @@ static int dma_buf_mmap_internal(struct file *file, struct vm_area_struct *vma)
return dmabuf->ops->mmap(dmabuf, vma);
}
+static unsigned int dma_buf_poll(struct file *filp,
+ struct poll_table_struct *poll)
+{
+ struct dma_buf *dmabuf;
+ struct dmabuf_sync_reservation *robj;
+ int ret = 0;
+
+ if (!is_dma_buf_file(filp))
+ return POLLERR;
+
+ dmabuf = filp->private_data;
+ if (!dmabuf || !dmabuf->sync)
+ return POLLERR;
+
+ robj = dmabuf->sync;
+
+ mutex_lock(&robj->lock);
+
+ robj->polled = true;
+
+ /*
+ * CPU or DMA access to this buffer has been completed, and
+ * the blocked task has been waked up. Return poll event
+ * so that the task can get out of select().
+ */
+ if (robj->poll_event) {
+ robj->poll_event = false;
+ mutex_unlock(&robj->lock);
+ return POLLIN | POLLOUT;
+ }
+
+ /*
+ * There is no anyone accessing this buffer so just return.
+ */
+ if (!robj->locked) {
+ mutex_unlock(&robj->lock);
+ return POLLIN | POLLOUT;
+ }
+
+ poll_wait(filp, &robj->poll_wait, poll);
+
+ mutex_unlock(&robj->lock);
+
+ return ret;
+}
+
+static int dma_buf_lock(struct file *file, int cmd, struct file_lock *fl)
+{
+ struct dma_buf *dmabuf;
+ unsigned int type;
+ bool wait = false;
+
+ if (!is_dma_buf_file(file))
+ return -EINVAL;
+
+ dmabuf = file->private_data;
+
+ if ((fl->fl_type & F_UNLCK) = F_UNLCK) {
+ dmabuf_sync_single_unlock(dmabuf);
+ return 0;
+ }
+
+ /* convert flock type to dmabuf sync type. */
+ if ((fl->fl_type & F_WRLCK) = F_WRLCK)
+ type = DMA_BUF_ACCESS_W;
+ else if ((fl->fl_type & F_RDLCK) = F_RDLCK)
+ type = DMA_BUF_ACCESS_R;
+ else
+ return -EINVAL;
+
+ if (fl->fl_flags & FL_SLEEP)
+ wait = true;
+
+ /* TODO. the locking to certain region should also be considered. */
+
+ return dmabuf_sync_single_lock(dmabuf, type, wait);
+}
+
static const struct file_operations dma_buf_fops = {
.release = dma_buf_release,
.mmap = dma_buf_mmap_internal,
+ .poll = dma_buf_poll,
+ .lock = dma_buf_lock,
};
/*
--
1.7.5.4
^ permalink raw reply related
* [PATCH] omap2: panel-generic: Added panel parameters for ortus-com37h3m05dtc/99dtc and sharp-lq070y3
From: Marek Belisko @ 2013-08-29 12:35 UTC (permalink / raw)
To: tomi.valkeinen, plagnioj
Cc: linux-omap, linux-fbdev, linux-kernel, Marek Belisko,
H. Nikolaus Schaller
Signed-off-by: H. Nikolaus Schaller <hns@goldelico.com>
Signed-off-by: Marek Belisko <marek@goldelico.com>
---
drivers/video/omap2/displays/panel-generic-dpi.c | 53 ++++++++++++++++++++++++
1 file changed, 53 insertions(+)
diff --git a/drivers/video/omap2/displays/panel-generic-dpi.c b/drivers/video/omap2/displays/panel-generic-dpi.c
index bebebd4..d573291 100644
--- a/drivers/video/omap2/displays/panel-generic-dpi.c
+++ b/drivers/video/omap2/displays/panel-generic-dpi.c
@@ -107,6 +107,33 @@ static struct panel_config generic_dpi_panels[] = {
.name = "sharp_ls",
},
+ /* Sharp LQ070Y3DG3B */
+ {
+ {
+ .x_res = 800,
+ .y_res = 480,
+
+ .pixel_clock = 33260,
+
+ .hsw = 128,
+ .hfp = 64,
+ .hbp = 64,
+
+ .vsw = 2,
+ .vfp = 8,
+ .vbp = 35,
+
+ .vsync_level = OMAPDSS_SIG_ACTIVE_LOW,
+ .hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
+ .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
+ .de_level = OMAPDSS_SIG_ACTIVE_HIGH,
+ .sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
+ },
+ .power_on_delay = 50,
+ .power_off_delay = 100,
+ .name = "sharp_lq070y3dg3b",
+ },
+
/* Toppoly TDO35S */
{
{
@@ -369,6 +396,32 @@ static struct panel_config generic_dpi_panels[] = {
.name = "ortustech_com43h4m10xtc",
},
+ /* OrtusTech COM37H3M05DTC and COM37H3M99DTC */
+ {
+ {
+ .x_res = 480,
+ .y_res = 640,
+
+ /* pixel clock could be lowered to reduce noise */
+ .pixel_clock = 22153,
+
+ .hsw = 10,
+ .hfp = 8,
+ .hbp = 10,
+
+ .vsw = 3,
+ .vfp = 4,
+ .vbp = 4,
+
+ .vsync_level = OMAPDSS_SIG_ACTIVE_LOW,
+ .hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
+ .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
+ .de_level = OMAPDSS_SIG_ACTIVE_HIGH,
+ .sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
+ },
+ .name = "ortustech_com37h3m05dtc",
+ },
+
/* Innolux AT080TN52 */
{
{
--
1.8.1.2
^ permalink raw reply related
* [PATCH 00/15] OMAPDSS: remove old panel model code
From: Tomi Valkeinen @ 2013-08-29 13:31 UTC (permalink / raw)
To: linux-omap, linux-fbdev; +Cc: Archit Taneja, Tomi Valkeinen
Here's a series removing all the old panel model code from the omapdss driver.
This series depends on the series that changes the board files to use the new
panel drivers.
There's nothing much special in this series, as it's mostly removing code that
is not used. There are also related cleanups, like making functions static if
they are no longer called from outside the file, and such.
Tested on OMAP4 SDP, OMAP4 Panda, OMAP3 Beagle, OMAP3 Beagle xM.
This series can also be found from:
git://git.kernel.org/pub/scm/linux/kernel/git/tomba/linux.git 3.12/dss-legacy-removal
Tomi
Tomi Valkeinen (15):
OMAPDSS: RFBI: Mark RFBI as broken
OMAPDSS: remove omap_dss_device->channel field
OMAPDSS: fix DPI and SDI device ids
OMAPDSS: SDI: change regulator handling
OMAPDSS: DPI: change regulator handling
OMAPDSS: remove all old panel drivers
OMAPDSS: DPI: remove code related to old panel model
OMAPDSS: HDMI: remove code related to old panel model
OMAPDSS: DSI: remove code related to old panel model
OMAPDSS: SDI: remove code related to old panel model
OMAPDSS: VENC: remove code related to old panel model
OMAPDSS: RFBI: remove code related to old panel model
OMAPDSS: DSS: remove legacy dss bus support
OMAPDSS: rename omap_dss_device's 'output' to 'src'
OMAPDSS: rename omap_dss_device's 'device' field to 'dst'
arch/arm/mach-omap2/display.c | 4 +-
drivers/gpu/drm/omapdrm/omap_encoder.c | 2 +-
drivers/video/omap2/Kconfig | 1 -
drivers/video/omap2/Makefile | 1 -
drivers/video/omap2/displays-new/encoder-tfp410.c | 14 +-
.../video/omap2/displays-new/encoder-tpd12s015.c | 14 +-
drivers/video/omap2/displays/Kconfig | 75 -
drivers/video/omap2/displays/Makefile | 11 -
drivers/video/omap2/displays/panel-acx565akm.c | 798 ----------
drivers/video/omap2/displays/panel-generic-dpi.c | 744 ----------
.../omap2/displays/panel-lgphilips-lb035q02.c | 262 ----
drivers/video/omap2/displays/panel-n8x0.c | 616 --------
.../omap2/displays/panel-nec-nl8048hl11-01b.c | 290 ----
drivers/video/omap2/displays/panel-picodlp.c | 559 -------
drivers/video/omap2/displays/panel-picodlp.h | 288 ----
.../video/omap2/displays/panel-sharp-ls037v7dw01.c | 198 ---
drivers/video/omap2/displays/panel-taal.c | 1551 --------------------
drivers/video/omap2/displays/panel-tfp410.c | 353 -----
.../video/omap2/displays/panel-tpo-td043mtea1.c | 596 --------
drivers/video/omap2/dss/Kconfig | 1 +
drivers/video/omap2/dss/Makefile | 5 +-
drivers/video/omap2/dss/apply.c | 4 +-
drivers/video/omap2/dss/core.c | 312 +---
drivers/video/omap2/dss/dpi.c | 121 +-
drivers/video/omap2/dss/dsi.c | 275 +---
drivers/video/omap2/dss/dss.h | 45 -
drivers/video/omap2/dss/hdmi.c | 307 +---
drivers/video/omap2/dss/hdmi_panel.c | 414 ------
drivers/video/omap2/dss/output.c | 22 +-
drivers/video/omap2/dss/rfbi.c | 135 +-
drivers/video/omap2/dss/sdi.c | 119 +-
drivers/video/omap2/dss/venc.c | 122 +-
include/video/omap-panel-data.h | 118 --
include/video/omapdss.h | 106 +-
34 files changed, 185 insertions(+), 8298 deletions(-)
delete mode 100644 drivers/video/omap2/displays/Kconfig
delete mode 100644 drivers/video/omap2/displays/Makefile
delete mode 100644 drivers/video/omap2/displays/panel-acx565akm.c
delete mode 100644 drivers/video/omap2/displays/panel-generic-dpi.c
delete mode 100644 drivers/video/omap2/displays/panel-lgphilips-lb035q02.c
delete mode 100644 drivers/video/omap2/displays/panel-n8x0.c
delete mode 100644 drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c
delete mode 100644 drivers/video/omap2/displays/panel-picodlp.c
delete mode 100644 drivers/video/omap2/displays/panel-picodlp.h
delete mode 100644 drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c
delete mode 100644 drivers/video/omap2/displays/panel-taal.c
delete mode 100644 drivers/video/omap2/displays/panel-tfp410.c
delete mode 100644 drivers/video/omap2/displays/panel-tpo-td043mtea1.c
delete mode 100644 drivers/video/omap2/dss/hdmi_panel.c
--
1.8.1.2
^ permalink raw reply
* [PATCH 01/15] OMAPDSS: RFBI: Mark RFBI as broken
From: Tomi Valkeinen @ 2013-08-29 13:31 UTC (permalink / raw)
To: linux-omap, linux-fbdev; +Cc: Archit Taneja, Tomi Valkeinen
In-Reply-To: <1377783120-14001-1-git-send-email-tomi.valkeinen@ti.com>
OMAPDSS's RFBI encoder driver has not been working for some time. The
Nokia N800 is the only board in the mainline that uses RFBI, but it has
never been fully functional.
The RFBI driver needs to be updated to the new panel model, but as
the driver is rather unmaintained and there's no way to test the
changes, let's mark the driver as broken.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
drivers/video/omap2/dss/Kconfig | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/video/omap2/dss/Kconfig b/drivers/video/omap2/dss/Kconfig
index 8f70a83..dde4281 100644
--- a/drivers/video/omap2/dss/Kconfig
+++ b/drivers/video/omap2/dss/Kconfig
@@ -42,6 +42,7 @@ config OMAP2_DSS_DPI
config OMAP2_DSS_RFBI
bool "RFBI support"
+ depends on BROKEN
default n
help
MIPI DBI support (RFBI, Remote Framebuffer Interface, in Texas
--
1.8.1.2
^ permalink raw reply related
* [PATCH 02/15] OMAPDSS: remove omap_dss_device->channel field
From: Tomi Valkeinen @ 2013-08-29 13:31 UTC (permalink / raw)
To: linux-omap, linux-fbdev; +Cc: Archit Taneja, Tomi Valkeinen
In-Reply-To: <1377783120-14001-1-git-send-email-tomi.valkeinen@ti.com>
The 'channel' field in struct omap_dss_device is no longer used, and can
be removed.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
include/video/omapdss.h | 3 ---
1 file changed, 3 deletions(-)
diff --git a/include/video/omapdss.h b/include/video/omapdss.h
index b394635..3b68dc2 100644
--- a/include/video/omapdss.h
+++ b/include/video/omapdss.h
@@ -765,9 +765,6 @@ struct omap_dss_device {
enum omap_display_type type;
enum omap_display_type output_type;
- /* obsolete, to be removed */
- enum omap_channel channel;
-
union {
struct {
u8 data_lines;
--
1.8.1.2
^ permalink raw reply related
* [PATCH 03/15] OMAPDSS: fix DPI and SDI device ids
From: Tomi Valkeinen @ 2013-08-29 13:31 UTC (permalink / raw)
To: linux-omap, linux-fbdev; +Cc: Archit Taneja, Tomi Valkeinen
In-Reply-To: <1377783120-14001-1-git-send-email-tomi.valkeinen@ti.com>
The DPI and SDI platform devices are currently created with the ID of
-1. The ID doesn't currently affect anything.
However, we have added regulator supply entries for "omapdss_dpi.0" and
"omapdss_sdi.0" to the board files, although these supply entries are
not yet used. As the ID used for the devices is -1, these regulator
supply entries will not work.
To fix the issue, assign ID of 0 to the devices. In the future there may
be more than one DPI or SDI output, so it makes sense to have a proper
ID for them.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
arch/arm/mach-omap2/display.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/arm/mach-omap2/display.c b/arch/arm/mach-omap2/display.c
index ff37be1..03a0516 100644
--- a/arch/arm/mach-omap2/display.c
+++ b/arch/arm/mach-omap2/display.c
@@ -400,7 +400,7 @@ int __init omap_display_init(struct omap_dss_board_info *board_data)
/* Create devices for DPI and SDI */
- pdev = create_simple_dss_pdev("omapdss_dpi", -1,
+ pdev = create_simple_dss_pdev("omapdss_dpi", 0,
board_data, sizeof(*board_data), dss_pdev);
if (IS_ERR(pdev)) {
pr_err("Could not build platform_device for omapdss_dpi\n");
@@ -408,7 +408,7 @@ int __init omap_display_init(struct omap_dss_board_info *board_data)
}
if (cpu_is_omap34xx()) {
- pdev = create_simple_dss_pdev("omapdss_sdi", -1,
+ pdev = create_simple_dss_pdev("omapdss_sdi", 0,
board_data, sizeof(*board_data), dss_pdev);
if (IS_ERR(pdev)) {
pr_err("Could not build platform_device for omapdss_sdi\n");
--
1.8.1.2
^ permalink raw reply related
* [PATCH 04/15] OMAPDSS: SDI: change regulator handling
From: Tomi Valkeinen @ 2013-08-29 13:31 UTC (permalink / raw)
To: linux-omap, linux-fbdev; +Cc: Archit Taneja, Tomi Valkeinen
In-Reply-To: <1377783120-14001-1-git-send-email-tomi.valkeinen@ti.com>
Regulator handling for DPI and SDI is currently handled in the core.c,
using the 'virtual' omapdss platform device. Nowadays we have proper
devices for both DPI and SDI, and so we can handle the regulators inside
the respective drivers.
This patch moves the regulator handling for SDI into sdi.c.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
drivers/video/omap2/dss/core.c | 15 ---------------
drivers/video/omap2/dss/dss.h | 1 -
drivers/video/omap2/dss/sdi.c | 10 +++-------
3 files changed, 3 insertions(+), 23 deletions(-)
diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c
index 1aeb274..a07d626 100644
--- a/drivers/video/omap2/dss/core.c
+++ b/drivers/video/omap2/dss/core.c
@@ -44,7 +44,6 @@ static struct {
struct platform_device *pdev;
struct regulator *vdds_dsi_reg;
- struct regulator *vdds_sdi_reg;
const char *default_display_name;
} core;
@@ -95,20 +94,6 @@ struct regulator *dss_get_vdds_dsi(void)
return reg;
}
-struct regulator *dss_get_vdds_sdi(void)
-{
- struct regulator *reg;
-
- if (core.vdds_sdi_reg != NULL)
- return core.vdds_sdi_reg;
-
- reg = devm_regulator_get(&core.pdev->dev, "vdds_sdi");
- if (!IS_ERR(reg))
- core.vdds_sdi_reg = reg;
-
- return reg;
-}
-
int dss_dsi_enable_pads(int dsi_id, unsigned lane_mask)
{
struct omap_dss_board_info *board_data = core.pdev->dev.platform_data;
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index 50a2362..7d97de4 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -165,7 +165,6 @@ struct platform_device;
struct platform_device *dss_get_core_pdev(void);
struct bus_type *dss_get_bus(void);
struct regulator *dss_get_vdds_dsi(void);
-struct regulator *dss_get_vdds_sdi(void);
int dss_dsi_enable_pads(int dsi_id, unsigned lane_mask);
void dss_dsi_disable_pads(int dsi_id, unsigned lane_mask);
int dss_set_min_bus_tput(struct device *dev, unsigned long tput);
diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c
index 856af2e..82b64e3 100644
--- a/drivers/video/omap2/dss/sdi.c
+++ b/drivers/video/omap2/dss/sdi.c
@@ -267,14 +267,10 @@ static int sdi_init_regulator(void)
if (sdi.vdds_sdi_reg)
return 0;
- vdds_sdi = dss_get_vdds_sdi();
-
+ vdds_sdi = devm_regulator_get(&sdi.pdev->dev, "vdds_sdi");
if (IS_ERR(vdds_sdi)) {
- vdds_sdi = devm_regulator_get(&sdi.pdev->dev, "vdds_sdi");
- if (IS_ERR(vdds_sdi)) {
- DSSERR("can't get VDDS_SDI regulator\n");
- return PTR_ERR(vdds_sdi);
- }
+ DSSERR("can't get VDDS_SDI regulator\n");
+ return PTR_ERR(vdds_sdi);
}
sdi.vdds_sdi_reg = vdds_sdi;
--
1.8.1.2
^ permalink raw reply related
* [PATCH 05/15] OMAPDSS: DPI: change regulator handling
From: Tomi Valkeinen @ 2013-08-29 13:31 UTC (permalink / raw)
To: linux-omap, linux-fbdev; +Cc: Archit Taneja, Tomi Valkeinen
In-Reply-To: <1377783120-14001-1-git-send-email-tomi.valkeinen@ti.com>
Regulator handling for DPI and SDI is currently handled in the core.c,
using the 'virtual' omapdss platform device. Nowadays we have proper
devices for both DPI and SDI, and so we can handle the regulators inside
the respective drivers.
This patch moves the regulator handling for DPI into dpi.c.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
drivers/video/omap2/dss/core.c | 18 ------------------
drivers/video/omap2/dss/dpi.c | 10 +++-------
drivers/video/omap2/dss/dss.h | 1 -
3 files changed, 3 insertions(+), 26 deletions(-)
diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c
index a07d626..71e6a77 100644
--- a/drivers/video/omap2/dss/core.c
+++ b/drivers/video/omap2/dss/core.c
@@ -43,8 +43,6 @@
static struct {
struct platform_device *pdev;
- struct regulator *vdds_dsi_reg;
-
const char *default_display_name;
} core;
@@ -78,22 +76,6 @@ struct platform_device *dss_get_core_pdev(void)
return core.pdev;
}
-/* REGULATORS */
-
-struct regulator *dss_get_vdds_dsi(void)
-{
- struct regulator *reg;
-
- if (core.vdds_dsi_reg != NULL)
- return core.vdds_dsi_reg;
-
- reg = devm_regulator_get(&core.pdev->dev, "vdds_dsi");
- if (!IS_ERR(reg))
- core.vdds_dsi_reg = reg;
-
- return reg;
-}
-
int dss_dsi_enable_pads(int dsi_id, unsigned lane_mask)
{
struct omap_dss_board_info *board_data = core.pdev->dev.platform_data;
diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c
index a6b331e..89c7a6e 100644
--- a/drivers/video/omap2/dss/dpi.c
+++ b/drivers/video/omap2/dss/dpi.c
@@ -554,14 +554,10 @@ static int dpi_init_regulator(void)
if (dpi.vdds_dsi_reg)
return 0;
- vdds_dsi = dss_get_vdds_dsi();
-
+ vdds_dsi = devm_regulator_get(&dpi.pdev->dev, "vdds_dsi");
if (IS_ERR(vdds_dsi)) {
- vdds_dsi = devm_regulator_get(&dpi.pdev->dev, "vdds_dsi");
- if (IS_ERR(vdds_dsi)) {
- DSSERR("can't get VDDS_DSI regulator\n");
- return PTR_ERR(vdds_dsi);
- }
+ DSSERR("can't get VDDS_DSI regulator\n");
+ return PTR_ERR(vdds_dsi);
}
dpi.vdds_dsi_reg = vdds_dsi;
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index 7d97de4..146349f 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -164,7 +164,6 @@ struct platform_device;
/* core */
struct platform_device *dss_get_core_pdev(void);
struct bus_type *dss_get_bus(void);
-struct regulator *dss_get_vdds_dsi(void);
int dss_dsi_enable_pads(int dsi_id, unsigned lane_mask);
void dss_dsi_disable_pads(int dsi_id, unsigned lane_mask);
int dss_set_min_bus_tput(struct device *dev, unsigned long tput);
--
1.8.1.2
^ permalink raw reply related
* [PATCH 07/15] OMAPDSS: DPI: remove code related to old panel model
From: Tomi Valkeinen @ 2013-08-29 13:31 UTC (permalink / raw)
To: linux-omap, linux-fbdev; +Cc: Archit Taneja, Tomi Valkeinen
In-Reply-To: <1377783120-14001-1-git-send-email-tomi.valkeinen@ti.com>
Now that the old panel drivers have been removed, we can remove the
old-model API and related code from the DSS encoder drivers.
This patch removes the code from the DPI driver.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
drivers/video/omap2/dss/dpi.c | 107 ++++--------------------------------------
include/video/omapdss.h | 8 ----
2 files changed, 9 insertions(+), 106 deletions(-)
diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c
index 89c7a6e..b268d04 100644
--- a/drivers/video/omap2/dss/dpi.c
+++ b/drivers/video/omap2/dss/dpi.c
@@ -345,7 +345,7 @@ static void dpi_config_lcd_manager(struct omap_overlay_manager *mgr)
dss_mgr_set_lcd_config(mgr, &dpi.mgr_config);
}
-int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
+static int dpi_display_enable(struct omap_dss_device *dssdev)
{
struct omap_dss_device *out = &dpi.output;
int r;
@@ -423,9 +423,8 @@ err_no_reg:
mutex_unlock(&dpi.lock);
return r;
}
-EXPORT_SYMBOL(omapdss_dpi_display_enable);
-void omapdss_dpi_display_disable(struct omap_dss_device *dssdev)
+static void dpi_display_disable(struct omap_dss_device *dssdev)
{
struct omap_overlay_manager *mgr = dpi.output.manager;
@@ -446,9 +445,8 @@ void omapdss_dpi_display_disable(struct omap_dss_device *dssdev)
mutex_unlock(&dpi.lock);
}
-EXPORT_SYMBOL(omapdss_dpi_display_disable);
-void omapdss_dpi_set_timings(struct omap_dss_device *dssdev,
+static void dpi_set_timings(struct omap_dss_device *dssdev,
struct omap_video_timings *timings)
{
DSSDBG("dpi_set_timings\n");
@@ -459,7 +457,6 @@ void omapdss_dpi_set_timings(struct omap_dss_device *dssdev,
mutex_unlock(&dpi.lock);
}
-EXPORT_SYMBOL(omapdss_dpi_set_timings);
static void dpi_get_timings(struct omap_dss_device *dssdev,
struct omap_video_timings *timings)
@@ -471,7 +468,7 @@ static void dpi_get_timings(struct omap_dss_device *dssdev,
mutex_unlock(&dpi.lock);
}
-int dpi_check_timings(struct omap_dss_device *dssdev,
+static int dpi_check_timings(struct omap_dss_device *dssdev,
struct omap_video_timings *timings)
{
struct omap_overlay_manager *mgr = dpi.output.manager;
@@ -510,9 +507,8 @@ int dpi_check_timings(struct omap_dss_device *dssdev,
return 0;
}
-EXPORT_SYMBOL(dpi_check_timings);
-void omapdss_dpi_set_data_lines(struct omap_dss_device *dssdev, int data_lines)
+static void dpi_set_data_lines(struct omap_dss_device *dssdev, int data_lines)
{
mutex_lock(&dpi.lock);
@@ -520,7 +516,6 @@ void omapdss_dpi_set_data_lines(struct omap_dss_device *dssdev, int data_lines)
mutex_unlock(&dpi.lock);
}
-EXPORT_SYMBOL(omapdss_dpi_set_data_lines);
static int dpi_verify_dsi_pll(struct platform_device *dsidev)
{
@@ -614,76 +609,6 @@ static enum omap_channel dpi_get_channel(void)
}
}
-static struct omap_dss_device *dpi_find_dssdev(struct platform_device *pdev)
-{
- struct omap_dss_board_info *pdata = pdev->dev.platform_data;
- const char *def_disp_name = omapdss_get_default_display_name();
- struct omap_dss_device *def_dssdev;
- int i;
-
- def_dssdev = NULL;
-
- for (i = 0; i < pdata->num_devices; ++i) {
- struct omap_dss_device *dssdev = pdata->devices[i];
-
- if (dssdev->type != OMAP_DISPLAY_TYPE_DPI)
- continue;
-
- if (def_dssdev = NULL)
- def_dssdev = dssdev;
-
- if (def_disp_name != NULL &&
- strcmp(dssdev->name, def_disp_name) = 0) {
- def_dssdev = dssdev;
- break;
- }
- }
-
- return def_dssdev;
-}
-
-static int dpi_probe_pdata(struct platform_device *dpidev)
-{
- struct omap_dss_device *plat_dssdev;
- struct omap_dss_device *dssdev;
- int r;
-
- plat_dssdev = dpi_find_dssdev(dpidev);
-
- if (!plat_dssdev)
- return 0;
-
- r = dpi_init_regulator();
- if (r)
- return r;
-
- dpi_init_pll();
-
- dssdev = dss_alloc_and_init_device(&dpidev->dev);
- if (!dssdev)
- return -ENOMEM;
-
- dss_copy_device_pdata(dssdev, plat_dssdev);
-
- r = omapdss_output_set_device(&dpi.output, dssdev);
- if (r) {
- DSSERR("failed to connect output to new device: %s\n",
- dssdev->name);
- dss_put_device(dssdev);
- return r;
- }
-
- r = dss_add_device(dssdev);
- if (r) {
- DSSERR("device %s register failed: %d\n", dssdev->name, r);
- omapdss_output_unset_device(&dpi.output);
- dss_put_device(dssdev);
- return r;
- }
-
- return 0;
-}
-
static int dpi_connect(struct omap_dss_device *dssdev,
struct omap_dss_device *dst)
{
@@ -733,14 +658,14 @@ static const struct omapdss_dpi_ops dpi_ops = {
.connect = dpi_connect,
.disconnect = dpi_disconnect,
- .enable = omapdss_dpi_display_enable,
- .disable = omapdss_dpi_display_disable,
+ .enable = dpi_display_enable,
+ .disable = dpi_display_disable,
.check_timings = dpi_check_timings,
- .set_timings = omapdss_dpi_set_timings,
+ .set_timings = dpi_set_timings,
.get_timings = dpi_get_timings,
- .set_data_lines = omapdss_dpi_set_data_lines,
+ .set_data_lines = dpi_set_data_lines,
};
static void dpi_init_output(struct platform_device *pdev)
@@ -767,31 +692,17 @@ static void __exit dpi_uninit_output(struct platform_device *pdev)
static int omap_dpi_probe(struct platform_device *pdev)
{
- int r;
-
dpi.pdev = pdev;
mutex_init(&dpi.lock);
dpi_init_output(pdev);
- if (pdev->dev.platform_data) {
- r = dpi_probe_pdata(pdev);
- if (r)
- goto err_probe;
- }
-
return 0;
-
-err_probe:
- dpi_uninit_output(pdev);
- return r;
}
static int __exit omap_dpi_remove(struct platform_device *pdev)
{
- dss_unregister_child_devices(&pdev->dev);
-
dpi_uninit_output(pdev);
return 0;
diff --git a/include/video/omapdss.h b/include/video/omapdss.h
index 3b68dc2..1199e3b 100644
--- a/include/video/omapdss.h
+++ b/include/video/omapdss.h
@@ -1038,14 +1038,6 @@ int omapdss_dsi_display_enable(struct omap_dss_device *dssdev);
void omapdss_dsi_display_disable(struct omap_dss_device *dssdev,
bool disconnect_lanes, bool enter_ulps);
-int omapdss_dpi_display_enable(struct omap_dss_device *dssdev);
-void omapdss_dpi_display_disable(struct omap_dss_device *dssdev);
-void omapdss_dpi_set_timings(struct omap_dss_device *dssdev,
- struct omap_video_timings *timings);
-int dpi_check_timings(struct omap_dss_device *dssdev,
- struct omap_video_timings *timings);
-void omapdss_dpi_set_data_lines(struct omap_dss_device *dssdev, int data_lines);
-
int omapdss_sdi_display_enable(struct omap_dss_device *dssdev);
void omapdss_sdi_display_disable(struct omap_dss_device *dssdev);
void omapdss_sdi_set_timings(struct omap_dss_device *dssdev,
--
1.8.1.2
^ permalink raw reply related
* [PATCH 08/15] OMAPDSS: HDMI: remove code related to old panel model
From: Tomi Valkeinen @ 2013-08-29 13:31 UTC (permalink / raw)
To: linux-omap, linux-fbdev; +Cc: Archit Taneja, Tomi Valkeinen
In-Reply-To: <1377783120-14001-1-git-send-email-tomi.valkeinen@ti.com>
Now that the old panel drivers have been removed, we can remove the
old-model API and related code from the DSS encoder drivers.
This patch removes the code from the HDMI driver.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
drivers/video/omap2/dss/Makefile | 3 +-
drivers/video/omap2/dss/dss.h | 20 --
drivers/video/omap2/dss/hdmi.c | 303 ++++---------------------
drivers/video/omap2/dss/hdmi_panel.c | 414 -----------------------------------
4 files changed, 44 insertions(+), 696 deletions(-)
delete mode 100644 drivers/video/omap2/dss/hdmi_panel.c
diff --git a/drivers/video/omap2/dss/Makefile b/drivers/video/omap2/dss/Makefile
index 61949ff..e022ed1 100644
--- a/drivers/video/omap2/dss/Makefile
+++ b/drivers/video/omap2/dss/Makefile
@@ -10,6 +10,5 @@ omapdss-$(CONFIG_OMAP2_DSS_RFBI) += rfbi.o
omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o venc_panel.o
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_HDMI) += hdmi.o ti_hdmi_4xxx_ip.o
ccflags-$(CONFIG_OMAP2_DSS_DEBUG) += -DDEBUG
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index 146349f..6142885 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -452,26 +452,6 @@ void venc_panel_exit(void);
/* HDMI */
int hdmi_init_platform_driver(void) __init;
void hdmi_uninit_platform_driver(void) __exit;
-int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev);
-void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev);
-int omapdss_hdmi_core_enable(struct omap_dss_device *dssdev);
-void omapdss_hdmi_core_disable(struct omap_dss_device *dssdev);
-void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev,
- struct omap_video_timings *timings);
-int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev,
- struct omap_video_timings *timings);
-int omapdss_hdmi_read_edid(u8 *buf, int len);
-bool omapdss_hdmi_detect(void);
-int hdmi_panel_init(void);
-void hdmi_panel_exit(void);
-#ifdef CONFIG_OMAP4_DSS_HDMI_AUDIO
-int hdmi_audio_enable(void);
-void hdmi_audio_disable(void);
-int hdmi_audio_start(void);
-void hdmi_audio_stop(void);
-bool hdmi_mode_has_audio(void);
-int hdmi_audio_config(struct omap_dss_audio *audio);
-#endif
/* RFBI */
int rfbi_init_platform_driver(void) __init;
diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c
index 44a885b..0b8e4de 100644
--- a/drivers/video/omap2/dss/hdmi.c
+++ b/drivers/video/omap2/dss/hdmi.c
@@ -66,10 +66,6 @@ static struct {
struct clk *sys_clk;
struct regulator *vdda_hdmi_dac_reg;
- int ct_cp_hpd_gpio;
- int ls_oe_gpio;
- int hpd_gpio;
-
bool core_enabled;
struct omap_dss_device output;
@@ -353,40 +349,6 @@ static int hdmi_init_regulator(void)
return 0;
}
-static int hdmi_init_display(struct omap_dss_device *dssdev)
-{
- int r;
-
- struct gpio gpios[] = {
- { hdmi.ct_cp_hpd_gpio, GPIOF_OUT_INIT_LOW, "hdmi_ct_cp_hpd" },
- { hdmi.ls_oe_gpio, GPIOF_OUT_INIT_LOW, "hdmi_ls_oe" },
- { hdmi.hpd_gpio, GPIOF_DIR_IN, "hdmi_hpd" },
- };
-
- DSSDBG("init_display\n");
-
- dss_init_hdmi_ip_ops(&hdmi.ip_data, omapdss_get_version());
-
- r = hdmi_init_regulator();
- if (r)
- return r;
-
- r = gpio_request_array(gpios, ARRAY_SIZE(gpios));
- if (r)
- return r;
-
- return 0;
-}
-
-static void hdmi_uninit_display(struct omap_dss_device *dssdev)
-{
- DSSDBG("uninit_display\n");
-
- gpio_free(hdmi.ct_cp_hpd_gpio);
- gpio_free(hdmi.ls_oe_gpio);
- gpio_free(hdmi.hpd_gpio);
-}
-
static const struct hdmi_config *hdmi_find_timing(
const struct hdmi_config *timings_arr,
int len)
@@ -517,17 +479,9 @@ static int hdmi_power_on_core(struct omap_dss_device *dssdev)
{
int r;
- if (gpio_is_valid(hdmi.ct_cp_hpd_gpio))
- gpio_set_value(hdmi.ct_cp_hpd_gpio, 1);
- if (gpio_is_valid(hdmi.ls_oe_gpio))
- gpio_set_value(hdmi.ls_oe_gpio, 1);
-
- /* wait 300us after CT_CP_HPD for the 5V power output to reach 90% */
- udelay(300);
-
r = regulator_enable(hdmi.vdda_hdmi_dac_reg);
if (r)
- goto err_vdac_enable;
+ return r;
r = hdmi_runtime_get();
if (r)
@@ -542,11 +496,7 @@ static int hdmi_power_on_core(struct omap_dss_device *dssdev)
err_runtime_get:
regulator_disable(hdmi.vdda_hdmi_dac_reg);
-err_vdac_enable:
- if (gpio_is_valid(hdmi.ct_cp_hpd_gpio))
- gpio_set_value(hdmi.ct_cp_hpd_gpio, 0);
- if (gpio_is_valid(hdmi.ls_oe_gpio))
- gpio_set_value(hdmi.ls_oe_gpio, 0);
+
return r;
}
@@ -556,10 +506,6 @@ static void hdmi_power_off_core(struct omap_dss_device *dssdev)
hdmi_runtime_put();
regulator_disable(hdmi.vdda_hdmi_dac_reg);
- if (gpio_is_valid(hdmi.ct_cp_hpd_gpio))
- gpio_set_value(hdmi.ct_cp_hpd_gpio, 0);
- if (gpio_is_valid(hdmi.ls_oe_gpio))
- gpio_set_value(hdmi.ls_oe_gpio, 0);
}
static int hdmi_power_on_full(struct omap_dss_device *dssdev)
@@ -640,7 +586,7 @@ static void hdmi_power_off_full(struct omap_dss_device *dssdev)
hdmi_power_off_core(dssdev);
}
-int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev,
+static int hdmi_display_check_timing(struct omap_dss_device *dssdev,
struct omap_video_timings *timings)
{
struct hdmi_cm cm;
@@ -654,7 +600,7 @@ int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev,
}
-void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev,
+static void hdmi_display_set_timing(struct omap_dss_device *dssdev,
struct omap_video_timings *timings)
{
struct hdmi_cm cm;
@@ -674,7 +620,7 @@ void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev,
mutex_unlock(&hdmi.lock);
}
-static void omapdss_hdmi_display_get_timings(struct omap_dss_device *dssdev,
+static void hdmi_display_get_timings(struct omap_dss_device *dssdev,
struct omap_video_timings *timings)
{
const struct hdmi_config *cfg;
@@ -704,7 +650,7 @@ static void hdmi_dump_regs(struct seq_file *s)
mutex_unlock(&hdmi.lock);
}
-int omapdss_hdmi_read_edid(u8 *buf, int len)
+static int read_edid(u8 *buf, int len)
{
int r;
@@ -721,24 +667,7 @@ int omapdss_hdmi_read_edid(u8 *buf, int len)
return r;
}
-bool omapdss_hdmi_detect(void)
-{
- int r;
-
- mutex_lock(&hdmi.lock);
-
- r = hdmi_runtime_get();
- BUG_ON(r);
-
- r = gpio_get_value(hdmi.hpd_gpio);
-
- hdmi_runtime_put();
- mutex_unlock(&hdmi.lock);
-
- return r = 1;
-}
-
-int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev)
+static int hdmi_display_enable(struct omap_dss_device *dssdev)
{
struct omap_dss_device *out = &hdmi.output;
int r = 0;
@@ -767,7 +696,7 @@ err0:
return r;
}
-void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev)
+static void hdmi_display_disable(struct omap_dss_device *dssdev)
{
DSSDBG("Enter hdmi_display_disable\n");
@@ -778,7 +707,7 @@ void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev)
mutex_unlock(&hdmi.lock);
}
-int omapdss_hdmi_core_enable(struct omap_dss_device *dssdev)
+static int hdmi_core_enable(struct omap_dss_device *dssdev)
{
int r = 0;
@@ -800,7 +729,7 @@ err0:
return r;
}
-void omapdss_hdmi_core_disable(struct omap_dss_device *dssdev)
+static void hdmi_core_disable(struct omap_dss_device *dssdev)
{
DSSDBG("Enter omapdss_hdmi_core_disable\n");
@@ -927,35 +856,7 @@ int hdmi_compute_acr(u32 sample_freq, u32 *n, u32 *cts)
return 0;
}
-int hdmi_audio_enable(void)
-{
- DSSDBG("audio_enable\n");
-
- return hdmi.ip_data.ops->audio_enable(&hdmi.ip_data);
-}
-
-void hdmi_audio_disable(void)
-{
- DSSDBG("audio_disable\n");
-
- hdmi.ip_data.ops->audio_disable(&hdmi.ip_data);
-}
-
-int hdmi_audio_start(void)
-{
- DSSDBG("audio_start\n");
-
- return hdmi.ip_data.ops->audio_start(&hdmi.ip_data);
-}
-
-void hdmi_audio_stop(void)
-{
- DSSDBG("audio_stop\n");
-
- hdmi.ip_data.ops->audio_stop(&hdmi.ip_data);
-}
-
-bool hdmi_mode_has_audio(void)
+static bool hdmi_mode_has_audio(void)
{
if (hdmi.ip_data.cfg.cm.mode = HDMI_HDMI)
return true;
@@ -963,92 +864,8 @@ bool hdmi_mode_has_audio(void)
return false;
}
-int hdmi_audio_config(struct omap_dss_audio *audio)
-{
- return hdmi.ip_data.ops->audio_config(&hdmi.ip_data, audio);
-}
-
#endif
-static struct omap_dss_device *hdmi_find_dssdev(struct platform_device *pdev)
-{
- struct omap_dss_board_info *pdata = pdev->dev.platform_data;
- const char *def_disp_name = omapdss_get_default_display_name();
- struct omap_dss_device *def_dssdev;
- int i;
-
- def_dssdev = NULL;
-
- for (i = 0; i < pdata->num_devices; ++i) {
- struct omap_dss_device *dssdev = pdata->devices[i];
-
- if (dssdev->type != OMAP_DISPLAY_TYPE_HDMI)
- continue;
-
- if (def_dssdev = NULL)
- def_dssdev = dssdev;
-
- if (def_disp_name != NULL &&
- strcmp(dssdev->name, def_disp_name) = 0) {
- def_dssdev = dssdev;
- break;
- }
- }
-
- return def_dssdev;
-}
-
-static int hdmi_probe_pdata(struct platform_device *pdev)
-{
- struct omap_dss_device *plat_dssdev;
- struct omap_dss_device *dssdev;
- struct omap_dss_hdmi_data *priv;
- int r;
-
- plat_dssdev = hdmi_find_dssdev(pdev);
-
- if (!plat_dssdev)
- return 0;
-
- dssdev = dss_alloc_and_init_device(&pdev->dev);
- if (!dssdev)
- return -ENOMEM;
-
- dss_copy_device_pdata(dssdev, plat_dssdev);
-
- priv = dssdev->data;
-
- hdmi.ct_cp_hpd_gpio = priv->ct_cp_hpd_gpio;
- hdmi.ls_oe_gpio = priv->ls_oe_gpio;
- hdmi.hpd_gpio = priv->hpd_gpio;
-
- r = hdmi_init_display(dssdev);
- if (r) {
- DSSERR("device %s init failed: %d\n", dssdev->name, r);
- dss_put_device(dssdev);
- return r;
- }
-
- r = omapdss_output_set_device(&hdmi.output, dssdev);
- if (r) {
- DSSERR("failed to connect output to new device: %s\n",
- dssdev->name);
- dss_put_device(dssdev);
- return r;
- }
-
- r = dss_add_device(dssdev);
- if (r) {
- DSSERR("device %s register failed: %d\n", dssdev->name, r);
- omapdss_output_unset_device(&hdmi.output);
- hdmi_uninit_display(dssdev);
- dss_put_device(dssdev);
- return r;
- }
-
- return 0;
-}
-
static int hdmi_connect(struct omap_dss_device *dssdev,
struct omap_dss_device *dst)
{
@@ -1103,21 +920,21 @@ static int hdmi_read_edid(struct omap_dss_device *dssdev,
need_enable = hdmi.core_enabled = false;
if (need_enable) {
- r = omapdss_hdmi_core_enable(dssdev);
+ r = hdmi_core_enable(dssdev);
if (r)
return r;
}
- r = omapdss_hdmi_read_edid(edid, len);
+ r = read_edid(edid, len);
if (need_enable)
- omapdss_hdmi_core_disable(dssdev);
+ hdmi_core_disable(dssdev);
return r;
}
#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
-static int omapdss_hdmi_audio_enable(struct omap_dss_device *dssdev)
+static int hdmi_audio_enable(struct omap_dss_device *dssdev)
{
int r;
@@ -1128,7 +945,8 @@ static int omapdss_hdmi_audio_enable(struct omap_dss_device *dssdev)
goto err;
}
- r = hdmi_audio_enable();
+
+ r = hdmi.ip_data.ops->audio_enable(&hdmi.ip_data);
if (r)
goto err;
@@ -1140,22 +958,22 @@ err:
return r;
}
-static void omapdss_hdmi_audio_disable(struct omap_dss_device *dssdev)
+static void hdmi_audio_disable(struct omap_dss_device *dssdev)
{
- hdmi_audio_disable();
+ hdmi.ip_data.ops->audio_disable(&hdmi.ip_data);
}
-static int omapdss_hdmi_audio_start(struct omap_dss_device *dssdev)
+static int hdmi_audio_start(struct omap_dss_device *dssdev)
{
- return hdmi_audio_start();
+ return hdmi.ip_data.ops->audio_start(&hdmi.ip_data);
}
-static void omapdss_hdmi_audio_stop(struct omap_dss_device *dssdev)
+static void hdmi_audio_stop(struct omap_dss_device *dssdev)
{
- hdmi_audio_stop();
+ hdmi.ip_data.ops->audio_stop(&hdmi.ip_data);
}
-static bool omapdss_hdmi_audio_supported(struct omap_dss_device *dssdev)
+static bool hdmi_audio_supported(struct omap_dss_device *dssdev)
{
bool r;
@@ -1167,7 +985,7 @@ static bool omapdss_hdmi_audio_supported(struct omap_dss_device *dssdev)
return r;
}
-static int omapdss_hdmi_audio_config(struct omap_dss_device *dssdev,
+static int hdmi_audio_config(struct omap_dss_device *dssdev,
struct omap_dss_audio *audio)
{
int r;
@@ -1179,7 +997,7 @@ static int omapdss_hdmi_audio_config(struct omap_dss_device *dssdev,
goto err;
}
- r = hdmi_audio_config(audio);
+ r = hdmi.ip_data.ops->audio_config(&hdmi.ip_data, audio);
if (r)
goto err;
@@ -1191,30 +1009,30 @@ err:
return r;
}
#else
-static int omapdss_hdmi_audio_enable(struct omap_dss_device *dssdev)
+static int hdmi_audio_enable(struct omap_dss_device *dssdev)
{
return -EPERM;
}
-static void omapdss_hdmi_audio_disable(struct omap_dss_device *dssdev)
+static void hdmi_audio_disable(struct omap_dss_device *dssdev)
{
}
-static int omapdss_hdmi_audio_start(struct omap_dss_device *dssdev)
+static int hdmi_audio_start(struct omap_dss_device *dssdev)
{
return -EPERM;
}
-static void omapdss_hdmi_audio_stop(struct omap_dss_device *dssdev)
+static void hdmi_audio_stop(struct omap_dss_device *dssdev)
{
}
-static bool omapdss_hdmi_audio_supported(struct omap_dss_device *dssdev)
+static bool hdmi_audio_supported(struct omap_dss_device *dssdev)
{
return false;
}
-static int omapdss_hdmi_audio_config(struct omap_dss_device *dssdev,
+static int hdmi_audio_config(struct omap_dss_device *dssdev,
struct omap_dss_audio *audio)
{
return -EPERM;
@@ -1225,21 +1043,21 @@ static const struct omapdss_hdmi_ops hdmi_ops = {
.connect = hdmi_connect,
.disconnect = hdmi_disconnect,
- .enable = omapdss_hdmi_display_enable,
- .disable = omapdss_hdmi_display_disable,
+ .enable = hdmi_display_enable,
+ .disable = hdmi_display_disable,
- .check_timings = omapdss_hdmi_display_check_timing,
- .set_timings = omapdss_hdmi_display_set_timing,
- .get_timings = omapdss_hdmi_display_get_timings,
+ .check_timings = hdmi_display_check_timing,
+ .set_timings = hdmi_display_set_timing,
+ .get_timings = hdmi_display_get_timings,
.read_edid = hdmi_read_edid,
- .audio_enable = omapdss_hdmi_audio_enable,
- .audio_disable = omapdss_hdmi_audio_disable,
- .audio_start = omapdss_hdmi_audio_start,
- .audio_stop = omapdss_hdmi_audio_stop,
- .audio_supported = omapdss_hdmi_audio_supported,
- .audio_config = omapdss_hdmi_audio_config,
+ .audio_enable = hdmi_audio_enable,
+ .audio_disable = hdmi_audio_disable,
+ .audio_start = hdmi_audio_start,
+ .audio_stop = hdmi_audio_stop,
+ .audio_supported = hdmi_audio_supported,
+ .audio_config = hdmi_audio_config,
};
static void hdmi_init_output(struct platform_device *pdev)
@@ -1301,50 +1119,15 @@ static int omapdss_hdmihw_probe(struct platform_device *pdev)
hdmi.ip_data.pll_offset = HDMI_PLLCTRL;
hdmi.ip_data.phy_offset = HDMI_PHY;
- hdmi.ct_cp_hpd_gpio = -1;
- hdmi.ls_oe_gpio = -1;
- hdmi.hpd_gpio = -1;
-
hdmi_init_output(pdev);
- r = hdmi_panel_init();
- if (r) {
- DSSERR("can't init panel\n");
- return r;
- }
-
dss_debugfs_create_file("hdmi", hdmi_dump_regs);
- if (pdev->dev.platform_data) {
- r = hdmi_probe_pdata(pdev);
- if (r)
- goto err_probe;
- }
-
- return 0;
-
-err_probe:
- hdmi_panel_exit();
- hdmi_uninit_output(pdev);
- pm_runtime_disable(&pdev->dev);
- return r;
-}
-
-static int __exit hdmi_remove_child(struct device *dev, void *data)
-{
- struct omap_dss_device *dssdev = to_dss_device(dev);
- hdmi_uninit_display(dssdev);
return 0;
}
static int __exit omapdss_hdmihw_remove(struct platform_device *pdev)
{
- device_for_each_child(&pdev->dev, NULL, hdmi_remove_child);
-
- dss_unregister_child_devices(&pdev->dev);
-
- hdmi_panel_exit();
-
hdmi_uninit_output(pdev);
pm_runtime_disable(&pdev->dev);
diff --git a/drivers/video/omap2/dss/hdmi_panel.c b/drivers/video/omap2/dss/hdmi_panel.c
deleted file mode 100644
index dfb8eda..0000000
--- a/drivers/video/omap2/dss/hdmi_panel.c
+++ /dev/null
@@ -1,414 +0,0 @@
-/*
- * hdmi_panel.c
- *
- * HDMI library support functions for TI OMAP4 processors.
- *
- * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/
- * Authors: Mythri P k <mythripk@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/>.
- */
-
-#include <linux/kernel.h>
-#include <linux/err.h>
-#include <linux/io.h>
-#include <linux/mutex.h>
-#include <linux/module.h>
-#include <video/omapdss.h>
-#include <linux/slab.h>
-
-#include "dss.h"
-
-static struct {
- /* This protects the panel ops, mainly when accessing the HDMI IP. */
- struct mutex lock;
-#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
- /* This protects the audio ops, specifically. */
- spinlock_t audio_lock;
-#endif
-} hdmi;
-
-
-static int hdmi_panel_probe(struct omap_dss_device *dssdev)
-{
- /* Initialize default timings to VGA in DVI mode */
- const struct omap_video_timings default_timings = {
- .x_res = 640,
- .y_res = 480,
- .pixel_clock = 25175,
- .hsw = 96,
- .hfp = 16,
- .hbp = 48,
- .vsw = 2,
- .vfp = 11,
- .vbp = 31,
-
- .vsync_level = OMAPDSS_SIG_ACTIVE_LOW,
- .hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
-
- .interlace = false,
- };
-
- DSSDBG("ENTER hdmi_panel_probe\n");
-
- dssdev->panel.timings = default_timings;
-
- DSSDBG("hdmi_panel_probe x_res= %d y_res = %d\n",
- dssdev->panel.timings.x_res,
- dssdev->panel.timings.y_res);
-
- omapdss_hdmi_display_set_timing(dssdev, &dssdev->panel.timings);
-
- return 0;
-}
-
-static void hdmi_panel_remove(struct omap_dss_device *dssdev)
-{
-
-}
-
-#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
-static int hdmi_panel_audio_enable(struct omap_dss_device *dssdev)
-{
- unsigned long flags;
- int r;
-
- mutex_lock(&hdmi.lock);
- spin_lock_irqsave(&hdmi.audio_lock, flags);
-
- /* enable audio only if the display is active and supports audio */
- if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE ||
- !hdmi_mode_has_audio()) {
- DSSERR("audio not supported or display is off\n");
- r = -EPERM;
- goto err;
- }
-
- r = hdmi_audio_enable();
-
- if (!r)
- dssdev->audio_state = OMAP_DSS_AUDIO_ENABLED;
-
-err:
- spin_unlock_irqrestore(&hdmi.audio_lock, flags);
- mutex_unlock(&hdmi.lock);
- return r;
-}
-
-static void hdmi_panel_audio_disable(struct omap_dss_device *dssdev)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&hdmi.audio_lock, flags);
-
- hdmi_audio_disable();
-
- dssdev->audio_state = OMAP_DSS_AUDIO_DISABLED;
-
- spin_unlock_irqrestore(&hdmi.audio_lock, flags);
-}
-
-static int hdmi_panel_audio_start(struct omap_dss_device *dssdev)
-{
- unsigned long flags;
- int r;
-
- spin_lock_irqsave(&hdmi.audio_lock, flags);
- /*
- * No need to check the panel state. It was checked when trasitioning
- * to AUDIO_ENABLED.
- */
- if (dssdev->audio_state != OMAP_DSS_AUDIO_ENABLED) {
- DSSERR("audio start from invalid state\n");
- r = -EPERM;
- goto err;
- }
-
- r = hdmi_audio_start();
-
- if (!r)
- dssdev->audio_state = OMAP_DSS_AUDIO_PLAYING;
-
-err:
- spin_unlock_irqrestore(&hdmi.audio_lock, flags);
- return r;
-}
-
-static void hdmi_panel_audio_stop(struct omap_dss_device *dssdev)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&hdmi.audio_lock, flags);
-
- hdmi_audio_stop();
- dssdev->audio_state = OMAP_DSS_AUDIO_ENABLED;
-
- spin_unlock_irqrestore(&hdmi.audio_lock, flags);
-}
-
-static bool hdmi_panel_audio_supported(struct omap_dss_device *dssdev)
-{
- bool r = false;
-
- mutex_lock(&hdmi.lock);
-
- if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
- goto err;
-
- if (!hdmi_mode_has_audio())
- goto err;
-
- r = true;
-err:
- mutex_unlock(&hdmi.lock);
- return r;
-}
-
-static int hdmi_panel_audio_config(struct omap_dss_device *dssdev,
- struct omap_dss_audio *audio)
-{
- unsigned long flags;
- int r;
-
- mutex_lock(&hdmi.lock);
- spin_lock_irqsave(&hdmi.audio_lock, flags);
-
- /* config audio only if the display is active and supports audio */
- if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE ||
- !hdmi_mode_has_audio()) {
- DSSERR("audio not supported or display is off\n");
- r = -EPERM;
- goto err;
- }
-
- r = hdmi_audio_config(audio);
-
- if (!r)
- dssdev->audio_state = OMAP_DSS_AUDIO_CONFIGURED;
-
-err:
- spin_unlock_irqrestore(&hdmi.audio_lock, flags);
- mutex_unlock(&hdmi.lock);
- return r;
-}
-
-#else
-static int hdmi_panel_audio_enable(struct omap_dss_device *dssdev)
-{
- return -EPERM;
-}
-
-static void hdmi_panel_audio_disable(struct omap_dss_device *dssdev)
-{
-}
-
-static int hdmi_panel_audio_start(struct omap_dss_device *dssdev)
-{
- return -EPERM;
-}
-
-static void hdmi_panel_audio_stop(struct omap_dss_device *dssdev)
-{
-}
-
-static bool hdmi_panel_audio_supported(struct omap_dss_device *dssdev)
-{
- return false;
-}
-
-static int hdmi_panel_audio_config(struct omap_dss_device *dssdev,
- struct omap_dss_audio *audio)
-{
- return -EPERM;
-}
-#endif
-
-static int hdmi_panel_enable(struct omap_dss_device *dssdev)
-{
- int r = 0;
- DSSDBG("ENTER hdmi_panel_enable\n");
-
- mutex_lock(&hdmi.lock);
-
- if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) {
- r = -EINVAL;
- goto err;
- }
-
- omapdss_hdmi_display_set_timing(dssdev, &dssdev->panel.timings);
-
- r = omapdss_hdmi_display_enable(dssdev);
- if (r) {
- DSSERR("failed to power on\n");
- goto err;
- }
-
- dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
-
-err:
- mutex_unlock(&hdmi.lock);
-
- return r;
-}
-
-static void hdmi_panel_disable(struct omap_dss_device *dssdev)
-{
- mutex_lock(&hdmi.lock);
-
- if (dssdev->state = OMAP_DSS_DISPLAY_ACTIVE) {
- /*
- * TODO: notify audio users that the display was disabled. For
- * now, disable audio locally to not break our audio state
- * machine.
- */
- hdmi_panel_audio_disable(dssdev);
- omapdss_hdmi_display_disable(dssdev);
- }
-
- dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
-
- mutex_unlock(&hdmi.lock);
-}
-
-static void hdmi_get_timings(struct omap_dss_device *dssdev,
- struct omap_video_timings *timings)
-{
- mutex_lock(&hdmi.lock);
-
- *timings = dssdev->panel.timings;
-
- mutex_unlock(&hdmi.lock);
-}
-
-static void hdmi_set_timings(struct omap_dss_device *dssdev,
- struct omap_video_timings *timings)
-{
- DSSDBG("hdmi_set_timings\n");
-
- mutex_lock(&hdmi.lock);
-
- /*
- * TODO: notify audio users that there was a timings change. For
- * now, disable audio locally to not break our audio state machine.
- */
- hdmi_panel_audio_disable(dssdev);
-
- omapdss_hdmi_display_set_timing(dssdev, timings);
- dssdev->panel.timings = *timings;
-
- mutex_unlock(&hdmi.lock);
-}
-
-static int hdmi_check_timings(struct omap_dss_device *dssdev,
- struct omap_video_timings *timings)
-{
- int r = 0;
-
- DSSDBG("hdmi_check_timings\n");
-
- mutex_lock(&hdmi.lock);
-
- r = omapdss_hdmi_display_check_timing(dssdev, timings);
-
- mutex_unlock(&hdmi.lock);
- return r;
-}
-
-static int hdmi_read_edid(struct omap_dss_device *dssdev, u8 *buf, int len)
-{
- int r;
- bool need_enable;
-
- mutex_lock(&hdmi.lock);
-
- need_enable = dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
-
- if (need_enable) {
- r = omapdss_hdmi_core_enable(dssdev);
- if (r)
- goto err;
- }
-
- r = omapdss_hdmi_read_edid(buf, len);
-
- if (need_enable)
- omapdss_hdmi_core_disable(dssdev);
-err:
- mutex_unlock(&hdmi.lock);
-
- return r;
-}
-
-static bool hdmi_detect(struct omap_dss_device *dssdev)
-{
- int r;
- bool need_enable;
-
- mutex_lock(&hdmi.lock);
-
- need_enable = dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
-
- if (need_enable) {
- r = omapdss_hdmi_core_enable(dssdev);
- if (r)
- goto err;
- }
-
- r = omapdss_hdmi_detect();
-
- if (need_enable)
- omapdss_hdmi_core_disable(dssdev);
-err:
- mutex_unlock(&hdmi.lock);
-
- return r;
-}
-
-static struct omap_dss_driver hdmi_driver = {
- .probe = hdmi_panel_probe,
- .remove = hdmi_panel_remove,
- .enable = hdmi_panel_enable,
- .disable = hdmi_panel_disable,
- .get_timings = hdmi_get_timings,
- .set_timings = hdmi_set_timings,
- .check_timings = hdmi_check_timings,
- .read_edid = hdmi_read_edid,
- .detect = hdmi_detect,
- .audio_enable = hdmi_panel_audio_enable,
- .audio_disable = hdmi_panel_audio_disable,
- .audio_start = hdmi_panel_audio_start,
- .audio_stop = hdmi_panel_audio_stop,
- .audio_supported = hdmi_panel_audio_supported,
- .audio_config = hdmi_panel_audio_config,
- .driver = {
- .name = "hdmi_panel",
- .owner = THIS_MODULE,
- },
-};
-
-int hdmi_panel_init(void)
-{
- mutex_init(&hdmi.lock);
-
-#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
- spin_lock_init(&hdmi.audio_lock);
-#endif
-
- return omap_dss_register_driver(&hdmi_driver);
-}
-
-void hdmi_panel_exit(void)
-{
- omap_dss_unregister_driver(&hdmi_driver);
-
-}
--
1.8.1.2
^ permalink raw reply related
* [PATCH 09/15] OMAPDSS: DSI: remove code related to old panel model
From: Tomi Valkeinen @ 2013-08-29 13:31 UTC (permalink / raw)
To: linux-omap, linux-fbdev; +Cc: Archit Taneja, Tomi Valkeinen
In-Reply-To: <1377783120-14001-1-git-send-email-tomi.valkeinen@ti.com>
Now that the old panel drivers have been removed, we can remove the
old-model API and related code from the DSS encoder drivers.
This patch removes the code from the DSI driver.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
drivers/video/omap2/dss/dsi.c | 271 ++++++------------------------------------
include/video/omapdss.h | 51 --------
2 files changed, 35 insertions(+), 287 deletions(-)
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index 99a043b..3daaf7e 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -205,6 +205,8 @@ static int dsi_display_init_dispc(struct platform_device *dsidev,
static void dsi_display_uninit_dispc(struct platform_device *dsidev,
struct omap_overlay_manager *mgr);
+static int dsi_vc_send_null(struct omap_dss_device *dssdev, int channel);
+
#define DSI_MAX_NR_ISRS 2
#define DSI_MAX_NR_LANES 5
@@ -383,16 +385,7 @@ static inline struct dsi_data *dsi_get_dsidrv_data(struct platform_device *dside
static inline struct platform_device *dsi_get_dsidev_from_dssdev(struct omap_dss_device *dssdev)
{
- /* HACK: dssdev can be either the panel device, when using old API, or
- * the dsi device itself, when using the new API. So we solve this for
- * now by checking the dssdev->id. This will be removed when the old API
- * is removed.
- */
- if (dssdev->id = OMAP_DSS_OUTPUT_DSI1 ||
- dssdev->id = OMAP_DSS_OUTPUT_DSI2)
- return to_platform_device(dssdev->dev);
-
- return to_platform_device(dssdev->output->dev);
+ return to_platform_device(dssdev->dev);
}
struct platform_device *dsi_get_dsidev_from_id(int module)
@@ -432,23 +425,21 @@ static inline u32 dsi_read_reg(struct platform_device *dsidev,
return __raw_readl(dsi->base + idx.idx);
}
-void dsi_bus_lock(struct omap_dss_device *dssdev)
+static void dsi_bus_lock(struct omap_dss_device *dssdev)
{
struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
down(&dsi->bus_lock);
}
-EXPORT_SYMBOL(dsi_bus_lock);
-void dsi_bus_unlock(struct omap_dss_device *dssdev)
+static void dsi_bus_unlock(struct omap_dss_device *dssdev)
{
struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
up(&dsi->bus_lock);
}
-EXPORT_SYMBOL(dsi_bus_unlock);
static bool dsi_bus_is_locked(struct platform_device *dsidev)
{
@@ -2713,7 +2704,7 @@ static int dsi_vc_config_source(struct platform_device *dsidev, int channel,
return 0;
}
-void omapdss_dsi_vc_enable_hs(struct omap_dss_device *dssdev, int channel,
+static void dsi_vc_enable_hs(struct omap_dss_device *dssdev, int channel,
bool enable)
{
struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
@@ -2737,7 +2728,6 @@ void omapdss_dsi_vc_enable_hs(struct omap_dss_device *dssdev, int channel,
if (dsi->vm_timings.ddr_clk_always_on && enable)
dsi_vc_send_null(dssdev, channel);
}
-EXPORT_SYMBOL(omapdss_dsi_vc_enable_hs);
static void dsi_vc_flush_long_data(struct platform_device *dsidev, int channel)
{
@@ -2842,7 +2832,7 @@ static int dsi_vc_send_bta(struct platform_device *dsidev, int channel)
return 0;
}
-int dsi_vc_send_bta_sync(struct omap_dss_device *dssdev, int channel)
+static int dsi_vc_send_bta_sync(struct omap_dss_device *dssdev, int channel)
{
struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
DECLARE_COMPLETION_ONSTACK(completion);
@@ -2885,7 +2875,6 @@ err1:
err0:
return r;
}
-EXPORT_SYMBOL(dsi_vc_send_bta_sync);
static inline void dsi_vc_write_long_header(struct platform_device *dsidev,
int channel, u8 data_type, u16 len, u8 ecc)
@@ -3011,14 +3000,13 @@ static int dsi_vc_send_short(struct platform_device *dsidev, int channel,
return 0;
}
-int dsi_vc_send_null(struct omap_dss_device *dssdev, int channel)
+static int dsi_vc_send_null(struct omap_dss_device *dssdev, int channel)
{
struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
return dsi_vc_send_long(dsidev, channel, MIPI_DSI_NULL_PACKET, NULL,
0, 0);
}
-EXPORT_SYMBOL(dsi_vc_send_null);
static int dsi_vc_write_nosync_common(struct platform_device *dsidev,
int channel, u8 *data, int len, enum dss_dsi_content_type type)
@@ -3050,7 +3038,7 @@ static int dsi_vc_write_nosync_common(struct platform_device *dsidev,
return r;
}
-int dsi_vc_dcs_write_nosync(struct omap_dss_device *dssdev, int channel,
+static int dsi_vc_dcs_write_nosync(struct omap_dss_device *dssdev, int channel,
u8 *data, int len)
{
struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
@@ -3058,9 +3046,8 @@ int dsi_vc_dcs_write_nosync(struct omap_dss_device *dssdev, int channel,
return dsi_vc_write_nosync_common(dsidev, channel, data, len,
DSS_DSI_CONTENT_DCS);
}
-EXPORT_SYMBOL(dsi_vc_dcs_write_nosync);
-int dsi_vc_generic_write_nosync(struct omap_dss_device *dssdev, int channel,
+static int dsi_vc_generic_write_nosync(struct omap_dss_device *dssdev, int channel,
u8 *data, int len)
{
struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
@@ -3068,7 +3055,6 @@ int dsi_vc_generic_write_nosync(struct omap_dss_device *dssdev, int channel,
return dsi_vc_write_nosync_common(dsidev, channel, data, len,
DSS_DSI_CONTENT_GENERIC);
}
-EXPORT_SYMBOL(dsi_vc_generic_write_nosync);
static int dsi_vc_write_common(struct omap_dss_device *dssdev, int channel,
u8 *data, int len, enum dss_dsi_content_type type)
@@ -3099,60 +3085,19 @@ err:
return r;
}
-int dsi_vc_dcs_write(struct omap_dss_device *dssdev, int channel, u8 *data,
+static int dsi_vc_dcs_write(struct omap_dss_device *dssdev, int channel, u8 *data,
int len)
{
return dsi_vc_write_common(dssdev, channel, data, len,
DSS_DSI_CONTENT_DCS);
}
-EXPORT_SYMBOL(dsi_vc_dcs_write);
-int dsi_vc_generic_write(struct omap_dss_device *dssdev, int channel, u8 *data,
+static int dsi_vc_generic_write(struct omap_dss_device *dssdev, int channel, u8 *data,
int len)
{
return dsi_vc_write_common(dssdev, channel, data, len,
DSS_DSI_CONTENT_GENERIC);
}
-EXPORT_SYMBOL(dsi_vc_generic_write);
-
-int dsi_vc_dcs_write_0(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd)
-{
- return dsi_vc_dcs_write(dssdev, channel, &dcs_cmd, 1);
-}
-EXPORT_SYMBOL(dsi_vc_dcs_write_0);
-
-int dsi_vc_generic_write_0(struct omap_dss_device *dssdev, int channel)
-{
- return dsi_vc_generic_write(dssdev, channel, NULL, 0);
-}
-EXPORT_SYMBOL(dsi_vc_generic_write_0);
-
-int dsi_vc_dcs_write_1(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd,
- u8 param)
-{
- u8 buf[2];
- buf[0] = dcs_cmd;
- buf[1] = param;
- return dsi_vc_dcs_write(dssdev, channel, buf, 2);
-}
-EXPORT_SYMBOL(dsi_vc_dcs_write_1);
-
-int dsi_vc_generic_write_1(struct omap_dss_device *dssdev, int channel,
- u8 param)
-{
- return dsi_vc_generic_write(dssdev, channel, ¶m, 1);
-}
-EXPORT_SYMBOL(dsi_vc_generic_write_1);
-
-int dsi_vc_generic_write_2(struct omap_dss_device *dssdev, int channel,
- u8 param1, u8 param2)
-{
- u8 buf[2];
- buf[0] = param1;
- buf[1] = param2;
- return dsi_vc_generic_write(dssdev, channel, buf, 2);
-}
-EXPORT_SYMBOL(dsi_vc_generic_write_2);
static int dsi_vc_dcs_send_read_request(struct platform_device *dsidev,
int channel, u8 dcs_cmd)
@@ -3319,7 +3264,7 @@ err:
return r;
}
-int dsi_vc_dcs_read(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd,
+static int dsi_vc_dcs_read(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd,
u8 *buf, int buflen)
{
struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
@@ -3348,7 +3293,6 @@ err:
DSSERR("dsi_vc_dcs_read(ch %d, cmd 0x%02x) failed\n", channel, dcs_cmd);
return r;
}
-EXPORT_SYMBOL(dsi_vc_dcs_read);
static int dsi_vc_generic_read(struct omap_dss_device *dssdev, int channel,
u8 *reqdata, int reqlen, u8 *buf, int buflen)
@@ -3377,56 +3321,7 @@ static int dsi_vc_generic_read(struct omap_dss_device *dssdev, int channel,
return 0;
}
-int dsi_vc_generic_read_0(struct omap_dss_device *dssdev, int channel, u8 *buf,
- int buflen)
-{
- int r;
-
- r = dsi_vc_generic_read(dssdev, channel, NULL, 0, buf, buflen);
- if (r) {
- DSSERR("dsi_vc_generic_read_0(ch %d) failed\n", channel);
- return r;
- }
-
- return 0;
-}
-EXPORT_SYMBOL(dsi_vc_generic_read_0);
-
-int dsi_vc_generic_read_1(struct omap_dss_device *dssdev, int channel, u8 param,
- u8 *buf, int buflen)
-{
- int r;
-
- r = dsi_vc_generic_read(dssdev, channel, ¶m, 1, buf, buflen);
- if (r) {
- DSSERR("dsi_vc_generic_read_1(ch %d) failed\n", channel);
- return r;
- }
-
- return 0;
-}
-EXPORT_SYMBOL(dsi_vc_generic_read_1);
-
-int dsi_vc_generic_read_2(struct omap_dss_device *dssdev, int channel,
- u8 param1, u8 param2, u8 *buf, int buflen)
-{
- int r;
- u8 reqdata[2];
-
- reqdata[0] = param1;
- reqdata[1] = param2;
-
- r = dsi_vc_generic_read(dssdev, channel, reqdata, 2, buf, buflen);
- if (r) {
- DSSERR("dsi_vc_generic_read_2(ch %d) failed\n", channel);
- return r;
- }
-
- return 0;
-}
-EXPORT_SYMBOL(dsi_vc_generic_read_2);
-
-int dsi_vc_set_max_rx_packet_size(struct omap_dss_device *dssdev, int channel,
+static int dsi_vc_set_max_rx_packet_size(struct omap_dss_device *dssdev, int channel,
u16 len)
{
struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
@@ -3434,7 +3329,6 @@ int dsi_vc_set_max_rx_packet_size(struct omap_dss_device *dssdev, int channel,
return dsi_vc_send_short(dsidev, channel,
MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE, len, 0);
}
-EXPORT_SYMBOL(dsi_vc_set_max_rx_packet_size);
static int dsi_enter_ulps(struct platform_device *dsidev)
{
@@ -4068,7 +3962,7 @@ static void dsi_proto_timings(struct platform_device *dsidev)
}
}
-int omapdss_dsi_configure_pins(struct omap_dss_device *dssdev,
+static int dsi_configure_pins(struct omap_dss_device *dssdev,
const struct omap_dsi_pin_config *pin_cfg)
{
struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
@@ -4134,9 +4028,8 @@ int omapdss_dsi_configure_pins(struct omap_dss_device *dssdev,
return 0;
}
-EXPORT_SYMBOL(omapdss_dsi_configure_pins);
-int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel)
+static int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel)
{
struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
@@ -4206,9 +4099,8 @@ err_pix_fmt:
err_init_dispc:
return r;
}
-EXPORT_SYMBOL(dsi_enable_video_output);
-void dsi_disable_video_output(struct omap_dss_device *dssdev, int channel)
+static void dsi_disable_video_output(struct omap_dss_device *dssdev, int channel)
{
struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
@@ -4229,7 +4121,6 @@ void dsi_disable_video_output(struct omap_dss_device *dssdev, int channel)
dsi_display_uninit_dispc(dsidev, mgr);
}
-EXPORT_SYMBOL(dsi_disable_video_output);
static void dsi_update_screen_dispc(struct platform_device *dsidev)
{
@@ -4369,7 +4260,7 @@ static void dsi_framedone_irq_callback(void *data)
dsi_handle_framedone(dsidev, 0);
}
-int omap_dsi_update(struct omap_dss_device *dssdev, int channel,
+static int dsi_update(struct omap_dss_device *dssdev, int channel,
void (*callback)(int, void *), void *data)
{
struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
@@ -4394,7 +4285,6 @@ int omap_dsi_update(struct omap_dss_device *dssdev, int channel,
return 0;
}
-EXPORT_SYMBOL(omap_dsi_update);
/* Display funcs */
@@ -4589,7 +4479,7 @@ static void dsi_display_uninit_dsi(struct platform_device *dsidev,
dsi_pll_uninit(dsidev, disconnect_lanes);
}
-int omapdss_dsi_display_enable(struct omap_dss_device *dssdev)
+static int dsi_display_enable(struct omap_dss_device *dssdev)
{
struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
@@ -4625,9 +4515,8 @@ err_get_dsi:
DSSDBG("dsi_display_enable FAILED\n");
return r;
}
-EXPORT_SYMBOL(omapdss_dsi_display_enable);
-void omapdss_dsi_display_disable(struct omap_dss_device *dssdev,
+static void dsi_display_disable(struct omap_dss_device *dssdev,
bool disconnect_lanes, bool enter_ulps)
{
struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
@@ -4651,9 +4540,8 @@ void omapdss_dsi_display_disable(struct omap_dss_device *dssdev,
mutex_unlock(&dsi->lock);
}
-EXPORT_SYMBOL(omapdss_dsi_display_disable);
-int omapdss_dsi_enable_te(struct omap_dss_device *dssdev, bool enable)
+static int dsi_enable_te(struct omap_dss_device *dssdev, bool enable)
{
struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
@@ -4661,7 +4549,6 @@ int omapdss_dsi_enable_te(struct omap_dss_device *dssdev, bool enable)
dsi->te_enabled = enable;
return 0;
}
-EXPORT_SYMBOL(omapdss_dsi_enable_te);
#ifdef PRINT_VERBOSE_VM_TIMINGS
static void print_dsi_vm(const char *str,
@@ -5136,7 +5023,7 @@ static bool dsi_vm_calc(struct dsi_data *dsi,
dsi_vm_calc_pll_cb, ctx);
}
-int omapdss_dsi_set_config(struct omap_dss_device *dssdev,
+static int dsi_set_config(struct omap_dss_device *dssdev,
const struct omap_dss_dsi_config *config)
{
struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
@@ -5184,7 +5071,6 @@ err:
return r;
}
-EXPORT_SYMBOL(omapdss_dsi_set_config);
/*
* Return a hardcoded channel for the DSI output. This should work for
@@ -5235,7 +5121,7 @@ static enum omap_channel dsi_get_channel(int module_id)
}
}
-int omap_dsi_request_vc(struct omap_dss_device *dssdev, int *channel)
+static int dsi_request_vc(struct omap_dss_device *dssdev, int *channel)
{
struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
@@ -5252,9 +5138,8 @@ int omap_dsi_request_vc(struct omap_dss_device *dssdev, int *channel)
DSSERR("cannot get VC for display %s", dssdev->name);
return -ENOSPC;
}
-EXPORT_SYMBOL(omap_dsi_request_vc);
-int omap_dsi_set_vc_id(struct omap_dss_device *dssdev, int channel, int vc_id)
+static int dsi_set_vc_id(struct omap_dss_device *dssdev, int channel, int vc_id)
{
struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
@@ -5279,9 +5164,8 @@ int omap_dsi_set_vc_id(struct omap_dss_device *dssdev, int channel, int vc_id)
return 0;
}
-EXPORT_SYMBOL(omap_dsi_set_vc_id);
-void omap_dsi_release_vc(struct omap_dss_device *dssdev, int channel)
+static void dsi_release_vc(struct omap_dss_device *dssdev, int channel)
{
struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
@@ -5292,7 +5176,6 @@ void omap_dsi_release_vc(struct omap_dss_device *dssdev, int channel)
dsi->vc[channel].vc_id = 0;
}
}
-EXPORT_SYMBOL(omap_dsi_release_vc);
void dsi_wait_pll_hsdiv_dispc_active(struct platform_device *dsidev)
{
@@ -5348,79 +5231,6 @@ static int dsi_get_clocks(struct platform_device *dsidev)
return 0;
}
-static struct omap_dss_device *dsi_find_dssdev(struct platform_device *pdev)
-{
- struct omap_dss_board_info *pdata = pdev->dev.platform_data;
- struct dsi_data *dsi = dsi_get_dsidrv_data(pdev);
- const char *def_disp_name = omapdss_get_default_display_name();
- struct omap_dss_device *def_dssdev;
- int i;
-
- def_dssdev = NULL;
-
- for (i = 0; i < pdata->num_devices; ++i) {
- struct omap_dss_device *dssdev = pdata->devices[i];
-
- if (dssdev->type != OMAP_DISPLAY_TYPE_DSI)
- continue;
-
- if (dssdev->phy.dsi.module != dsi->module_id)
- continue;
-
- if (def_dssdev = NULL)
- def_dssdev = dssdev;
-
- if (def_disp_name != NULL &&
- strcmp(dssdev->name, def_disp_name) = 0) {
- def_dssdev = dssdev;
- break;
- }
- }
-
- return def_dssdev;
-}
-
-static int dsi_probe_pdata(struct platform_device *dsidev)
-{
- struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
- struct omap_dss_device *plat_dssdev;
- struct omap_dss_device *dssdev;
- int r;
-
- plat_dssdev = dsi_find_dssdev(dsidev);
-
- if (!plat_dssdev)
- return 0;
-
- r = dsi_regulator_init(dsidev);
- if (r)
- return r;
-
- dssdev = dss_alloc_and_init_device(&dsidev->dev);
- if (!dssdev)
- return -ENOMEM;
-
- dss_copy_device_pdata(dssdev, plat_dssdev);
-
- r = omapdss_output_set_device(&dsi->output, dssdev);
- if (r) {
- DSSERR("failed to connect output to new device: %s\n",
- dssdev->name);
- dss_put_device(dssdev);
- return r;
- }
-
- r = dss_add_device(dssdev);
- if (r) {
- DSSERR("device %s register failed: %d\n", dssdev->name, r);
- omapdss_output_unset_device(&dsi->output);
- dss_put_device(dssdev);
- return r;
- }
-
- return 0;
-}
-
static int dsi_connect(struct omap_dss_device *dssdev,
struct omap_dss_device *dst)
{
@@ -5472,24 +5282,24 @@ static const struct omapdss_dsi_ops dsi_ops = {
.bus_lock = dsi_bus_lock,
.bus_unlock = dsi_bus_unlock,
- .enable = omapdss_dsi_display_enable,
- .disable = omapdss_dsi_display_disable,
+ .enable = dsi_display_enable,
+ .disable = dsi_display_disable,
- .enable_hs = omapdss_dsi_vc_enable_hs,
+ .enable_hs = dsi_vc_enable_hs,
- .configure_pins = omapdss_dsi_configure_pins,
- .set_config = omapdss_dsi_set_config,
+ .configure_pins = dsi_configure_pins,
+ .set_config = dsi_set_config,
.enable_video_output = dsi_enable_video_output,
.disable_video_output = dsi_disable_video_output,
- .update = omap_dsi_update,
+ .update = dsi_update,
- .enable_te = omapdss_dsi_enable_te,
+ .enable_te = dsi_enable_te,
- .request_vc = omap_dsi_request_vc,
- .set_vc_id = omap_dsi_set_vc_id,
- .release_vc = omap_dsi_release_vc,
+ .request_vc = dsi_request_vc,
+ .set_vc_id = dsi_set_vc_id,
+ .release_vc = dsi_release_vc,
.dcs_write = dsi_vc_dcs_write,
.dcs_write_nosync = dsi_vc_dcs_write_nosync,
@@ -5627,12 +5437,6 @@ static int omap_dsihw_probe(struct platform_device *dsidev)
dsi_init_output(dsidev);
- if (dsidev->dev.platform_data) {
- r = dsi_probe_pdata(dsidev);
- if (r)
- goto err_probe;
- }
-
dsi_runtime_put(dsidev);
if (dsi->module_id = 0)
@@ -5648,9 +5452,6 @@ static int omap_dsihw_probe(struct platform_device *dsidev)
#endif
return 0;
-err_probe:
- dsi_runtime_put(dsidev);
- dsi_uninit_output(dsidev);
err_runtime_get:
pm_runtime_disable(&dsidev->dev);
return r;
@@ -5662,8 +5463,6 @@ static int __exit omap_dsihw_remove(struct platform_device *dsidev)
WARN_ON(dsi->scp_clk_refcount > 0);
- dss_unregister_child_devices(&dsidev->dev);
-
dsi_uninit_output(dsidev);
pm_runtime_disable(&dsidev->dev);
diff --git a/include/video/omapdss.h b/include/video/omapdss.h
index 1199e3b..6d7297f 100644
--- a/include/video/omapdss.h
+++ b/include/video/omapdss.h
@@ -321,39 +321,6 @@ struct omap_dss_dsi_config {
enum omap_dss_dsi_trans_mode trans_mode;
};
-void dsi_bus_lock(struct omap_dss_device *dssdev);
-void dsi_bus_unlock(struct omap_dss_device *dssdev);
-int dsi_vc_dcs_write(struct omap_dss_device *dssdev, int channel, u8 *data,
- int len);
-int dsi_vc_generic_write(struct omap_dss_device *dssdev, int channel, u8 *data,
- int len);
-int dsi_vc_dcs_write_0(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd);
-int dsi_vc_generic_write_0(struct omap_dss_device *dssdev, int channel);
-int dsi_vc_dcs_write_1(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd,
- u8 param);
-int dsi_vc_generic_write_1(struct omap_dss_device *dssdev, int channel,
- u8 param);
-int dsi_vc_generic_write_2(struct omap_dss_device *dssdev, int channel,
- u8 param1, u8 param2);
-int dsi_vc_dcs_write_nosync(struct omap_dss_device *dssdev, int channel,
- u8 *data, int len);
-int dsi_vc_generic_write_nosync(struct omap_dss_device *dssdev, int channel,
- u8 *data, int len);
-int dsi_vc_dcs_read(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd,
- u8 *buf, int buflen);
-int dsi_vc_generic_read_0(struct omap_dss_device *dssdev, int channel, u8 *buf,
- int buflen);
-int dsi_vc_generic_read_1(struct omap_dss_device *dssdev, int channel, u8 param,
- u8 *buf, int buflen);
-int dsi_vc_generic_read_2(struct omap_dss_device *dssdev, int channel,
- u8 param1, u8 param2, u8 *buf, int buflen);
-int dsi_vc_set_max_rx_packet_size(struct omap_dss_device *dssdev, int channel,
- u16 len);
-int dsi_vc_send_null(struct omap_dss_device *dssdev, int channel);
-int dsi_vc_send_bta_sync(struct omap_dss_device *dssdev, int channel);
-int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel);
-void dsi_disable_video_output(struct omap_dss_device *dssdev, int channel);
-
enum omapdss_version {
OMAPDSS_VER_UNKNOWN = 0,
OMAPDSS_VER_OMAP24xx,
@@ -1020,24 +987,6 @@ int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi,
#define to_dss_driver(x) container_of((x), struct omap_dss_driver, driver)
#define to_dss_device(x) container_of((x), struct omap_dss_device, old_dev)
-void omapdss_dsi_vc_enable_hs(struct omap_dss_device *dssdev, int channel,
- bool enable);
-int omapdss_dsi_enable_te(struct omap_dss_device *dssdev, bool enable);
-int omapdss_dsi_set_config(struct omap_dss_device *dssdev,
- const struct omap_dss_dsi_config *config);
-
-int omap_dsi_update(struct omap_dss_device *dssdev, int channel,
- void (*callback)(int, void *), void *data);
-int omap_dsi_request_vc(struct omap_dss_device *dssdev, int *channel);
-int omap_dsi_set_vc_id(struct omap_dss_device *dssdev, int channel, int vc_id);
-void omap_dsi_release_vc(struct omap_dss_device *dssdev, int channel);
-int omapdss_dsi_configure_pins(struct omap_dss_device *dssdev,
- const struct omap_dsi_pin_config *pin_cfg);
-
-int omapdss_dsi_display_enable(struct omap_dss_device *dssdev);
-void omapdss_dsi_display_disable(struct omap_dss_device *dssdev,
- bool disconnect_lanes, bool enter_ulps);
-
int omapdss_sdi_display_enable(struct omap_dss_device *dssdev);
void omapdss_sdi_display_disable(struct omap_dss_device *dssdev);
void omapdss_sdi_set_timings(struct omap_dss_device *dssdev,
--
1.8.1.2
^ permalink raw reply related
* [PATCH 10/15] OMAPDSS: SDI: remove code related to old panel model
From: Tomi Valkeinen @ 2013-08-29 13:31 UTC (permalink / raw)
To: linux-omap, linux-fbdev; +Cc: Archit Taneja, Tomi Valkeinen
In-Reply-To: <1377783120-14001-1-git-send-email-tomi.valkeinen@ti.com>
Now that the old panel drivers have been removed, we can remove the
old-model API and related code from the DSS encoder drivers.
This patch removes the code from the SDI driver.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
drivers/video/omap2/dss/sdi.c | 105 ++++--------------------------------------
include/video/omapdss.h | 6 ---
2 files changed, 8 insertions(+), 103 deletions(-)
diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c
index 82b64e3..b327688 100644
--- a/drivers/video/omap2/dss/sdi.c
+++ b/drivers/video/omap2/dss/sdi.c
@@ -124,7 +124,7 @@ static void sdi_config_lcd_manager(struct omap_dss_device *dssdev)
dss_mgr_set_lcd_config(mgr, &sdi.mgr_config);
}
-int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
+static int sdi_display_enable(struct omap_dss_device *dssdev)
{
struct omap_dss_device *out = &sdi.output;
struct omap_video_timings *t = &sdi.timings;
@@ -211,9 +211,8 @@ err_get_dispc:
err_reg_enable:
return r;
}
-EXPORT_SYMBOL(omapdss_sdi_display_enable);
-void omapdss_sdi_display_disable(struct omap_dss_device *dssdev)
+static void sdi_display_disable(struct omap_dss_device *dssdev)
{
struct omap_overlay_manager *mgr = sdi.output.manager;
@@ -225,14 +224,12 @@ void omapdss_sdi_display_disable(struct omap_dss_device *dssdev)
regulator_disable(sdi.vdds_sdi_reg);
}
-EXPORT_SYMBOL(omapdss_sdi_display_disable);
-void omapdss_sdi_set_timings(struct omap_dss_device *dssdev,
+static void sdi_set_timings(struct omap_dss_device *dssdev,
struct omap_video_timings *timings)
{
sdi.timings = *timings;
}
-EXPORT_SYMBOL(omapdss_sdi_set_timings);
static void sdi_get_timings(struct omap_dss_device *dssdev,
struct omap_video_timings *timings)
@@ -254,11 +251,10 @@ static int sdi_check_timings(struct omap_dss_device *dssdev,
return 0;
}
-void omapdss_sdi_set_datapairs(struct omap_dss_device *dssdev, int datapairs)
+static void sdi_set_datapairs(struct omap_dss_device *dssdev, int datapairs)
{
sdi.datapairs = datapairs;
}
-EXPORT_SYMBOL(omapdss_sdi_set_datapairs);
static int sdi_init_regulator(void)
{
@@ -278,77 +274,6 @@ static int sdi_init_regulator(void)
return 0;
}
-static struct omap_dss_device *sdi_find_dssdev(struct platform_device *pdev)
-{
- struct omap_dss_board_info *pdata = pdev->dev.platform_data;
- const char *def_disp_name = omapdss_get_default_display_name();
- struct omap_dss_device *def_dssdev;
- int i;
-
- def_dssdev = NULL;
-
- for (i = 0; i < pdata->num_devices; ++i) {
- struct omap_dss_device *dssdev = pdata->devices[i];
-
- if (dssdev->type != OMAP_DISPLAY_TYPE_SDI)
- continue;
-
- if (def_dssdev = NULL)
- def_dssdev = dssdev;
-
- if (def_disp_name != NULL &&
- strcmp(dssdev->name, def_disp_name) = 0) {
- def_dssdev = dssdev;
- break;
- }
- }
-
- return def_dssdev;
-}
-
-static int sdi_probe_pdata(struct platform_device *sdidev)
-{
- struct omap_dss_device *plat_dssdev;
- struct omap_dss_device *dssdev;
- int r;
-
- plat_dssdev = sdi_find_dssdev(sdidev);
-
- if (!plat_dssdev)
- return 0;
-
- dssdev = dss_alloc_and_init_device(&sdidev->dev);
- if (!dssdev)
- return -ENOMEM;
-
- dss_copy_device_pdata(dssdev, plat_dssdev);
-
- r = sdi_init_regulator();
- if (r) {
- DSSERR("device %s init failed: %d\n", dssdev->name, r);
- dss_put_device(dssdev);
- return r;
- }
-
- r = omapdss_output_set_device(&sdi.output, dssdev);
- if (r) {
- DSSERR("failed to connect output to new device: %s\n",
- dssdev->name);
- dss_put_device(dssdev);
- return r;
- }
-
- r = dss_add_device(dssdev);
- if (r) {
- DSSERR("device %s register failed: %d\n", dssdev->name, r);
- omapdss_output_unset_device(&sdi.output);
- dss_put_device(dssdev);
- return r;
- }
-
- return 0;
-}
-
static int sdi_connect(struct omap_dss_device *dssdev,
struct omap_dss_device *dst)
{
@@ -396,14 +321,14 @@ static const struct omapdss_sdi_ops sdi_ops = {
.connect = sdi_connect,
.disconnect = sdi_disconnect,
- .enable = omapdss_sdi_display_enable,
- .disable = omapdss_sdi_display_disable,
+ .enable = sdi_display_enable,
+ .disable = sdi_display_disable,
.check_timings = sdi_check_timings,
- .set_timings = omapdss_sdi_set_timings,
+ .set_timings = sdi_set_timings,
.get_timings = sdi_get_timings,
- .set_datapairs = omapdss_sdi_set_datapairs,
+ .set_datapairs = sdi_set_datapairs,
};
static void sdi_init_output(struct platform_device *pdev)
@@ -430,29 +355,15 @@ static void __exit sdi_uninit_output(struct platform_device *pdev)
static int omap_sdi_probe(struct platform_device *pdev)
{
- int r;
-
sdi.pdev = pdev;
sdi_init_output(pdev);
- if (pdev->dev.platform_data) {
- r = sdi_probe_pdata(pdev);
- if (r)
- goto err_probe;
- }
-
return 0;
-
-err_probe:
- sdi_uninit_output(pdev);
- return r;
}
static int __exit omap_sdi_remove(struct platform_device *pdev)
{
- dss_unregister_child_devices(&pdev->dev);
-
sdi_uninit_output(pdev);
return 0;
diff --git a/include/video/omapdss.h b/include/video/omapdss.h
index 6d7297f..3395804 100644
--- a/include/video/omapdss.h
+++ b/include/video/omapdss.h
@@ -987,12 +987,6 @@ int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi,
#define to_dss_driver(x) container_of((x), struct omap_dss_driver, driver)
#define to_dss_device(x) container_of((x), struct omap_dss_device, old_dev)
-int omapdss_sdi_display_enable(struct omap_dss_device *dssdev);
-void omapdss_sdi_display_disable(struct omap_dss_device *dssdev);
-void omapdss_sdi_set_timings(struct omap_dss_device *dssdev,
- struct omap_video_timings *timings);
-void omapdss_sdi_set_datapairs(struct omap_dss_device *dssdev, int datapairs);
-
int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev);
void omapdss_rfbi_display_disable(struct omap_dss_device *dssdev);
int omap_rfbi_update(struct omap_dss_device *dssdev, void (*callback)(void *),
--
1.8.1.2
^ permalink raw reply related
* [PATCH 11/15] OMAPDSS: VENC: remove code related to old panel model
From: Tomi Valkeinen @ 2013-08-29 13:31 UTC (permalink / raw)
To: linux-omap, linux-fbdev; +Cc: Archit Taneja, Tomi Valkeinen
In-Reply-To: <1377783120-14001-1-git-send-email-tomi.valkeinen@ti.com>
Now that the old panel drivers have been removed, we can remove the
old-model API and related code from the DSS encoder drivers.
This patch removes the code from the VENC driver.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
drivers/video/omap2/dss/Makefile | 2 +-
drivers/video/omap2/dss/dss.h | 14 -----
drivers/video/omap2/dss/venc.c | 118 ++++++---------------------------------
3 files changed, 17 insertions(+), 117 deletions(-)
diff --git a/drivers/video/omap2/dss/Makefile b/drivers/video/omap2/dss/Makefile
index e022ed1..94832eb 100644
--- a/drivers/video/omap2/dss/Makefile
+++ b/drivers/video/omap2/dss/Makefile
@@ -7,7 +7,7 @@ omapdss-y += manager.o manager-sysfs.o overlay.o overlay-sysfs.o apply.o \
dispc-compat.o display-sysfs.o
omapdss-$(CONFIG_OMAP2_DSS_DPI) += dpi.o
omapdss-$(CONFIG_OMAP2_DSS_RFBI) += rfbi.o
-omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o venc_panel.o
+omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o
omapdss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o
omapdss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o
omapdss-$(CONFIG_OMAP4_DSS_HDMI) += hdmi.o ti_hdmi_4xxx_ip.o
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index 6142885..68dd27f 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -434,20 +434,6 @@ int dispc_wb_setup(const struct omap_dss_writeback_info *wi,
/* VENC */
int venc_init_platform_driver(void) __init;
void venc_uninit_platform_driver(void) __exit;
-int omapdss_venc_display_enable(struct omap_dss_device *dssdev);
-void omapdss_venc_display_disable(struct omap_dss_device *dssdev);
-void omapdss_venc_set_timings(struct omap_dss_device *dssdev,
- struct omap_video_timings *timings);
-int omapdss_venc_check_timings(struct omap_dss_device *dssdev,
- struct omap_video_timings *timings);
-u32 omapdss_venc_get_wss(struct omap_dss_device *dssdev);
-int omapdss_venc_set_wss(struct omap_dss_device *dssdev, u32 wss);
-void omapdss_venc_set_type(struct omap_dss_device *dssdev,
- enum omap_dss_venc_type type);
-void omapdss_venc_invert_vid_out_polarity(struct omap_dss_device *dssdev,
- bool invert_polarity);
-int venc_panel_init(void);
-void venc_panel_exit(void);
/* HDMI */
int hdmi_init_platform_driver(void) __init;
diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c
index 496a106..0d8ccde 100644
--- a/drivers/video/omap2/dss/venc.c
+++ b/drivers/video/omap2/dss/venc.c
@@ -492,7 +492,7 @@ static void venc_power_off(struct omap_dss_device *dssdev)
venc_runtime_put();
}
-int omapdss_venc_display_enable(struct omap_dss_device *dssdev)
+static int venc_display_enable(struct omap_dss_device *dssdev)
{
struct omap_dss_device *out = &venc.output;
int r;
@@ -521,7 +521,7 @@ err0:
return r;
}
-void omapdss_venc_display_disable(struct omap_dss_device *dssdev)
+static void venc_display_disable(struct omap_dss_device *dssdev)
{
DSSDBG("venc_display_disable\n");
@@ -532,7 +532,7 @@ void omapdss_venc_display_disable(struct omap_dss_device *dssdev)
mutex_unlock(&venc.venc_lock);
}
-void omapdss_venc_set_timings(struct omap_dss_device *dssdev,
+static void venc_set_timings(struct omap_dss_device *dssdev,
struct omap_video_timings *timings)
{
DSSDBG("venc_set_timings\n");
@@ -550,7 +550,7 @@ void omapdss_venc_set_timings(struct omap_dss_device *dssdev,
mutex_unlock(&venc.venc_lock);
}
-int omapdss_venc_check_timings(struct omap_dss_device *dssdev,
+static int venc_check_timings(struct omap_dss_device *dssdev,
struct omap_video_timings *timings)
{
DSSDBG("venc_check_timings\n");
@@ -574,13 +574,13 @@ static void venc_get_timings(struct omap_dss_device *dssdev,
mutex_unlock(&venc.venc_lock);
}
-u32 omapdss_venc_get_wss(struct omap_dss_device *dssdev)
+static u32 venc_get_wss(struct omap_dss_device *dssdev)
{
/* Invert due to VENC_L21_WC_CTL:INV=1 */
return (venc.wss_data >> 8) ^ 0xfffff;
}
-int omapdss_venc_set_wss(struct omap_dss_device *dssdev, u32 wss)
+static int venc_set_wss(struct omap_dss_device *dssdev, u32 wss)
{
const struct venc_config *config;
int r;
@@ -609,7 +609,7 @@ err:
return r;
}
-void omapdss_venc_set_type(struct omap_dss_device *dssdev,
+static void venc_set_type(struct omap_dss_device *dssdev,
enum omap_dss_venc_type type)
{
mutex_lock(&venc.venc_lock);
@@ -619,7 +619,7 @@ void omapdss_venc_set_type(struct omap_dss_device *dssdev,
mutex_unlock(&venc.venc_lock);
}
-void omapdss_venc_invert_vid_out_polarity(struct omap_dss_device *dssdev,
+static void venc_invert_vid_out_polarity(struct omap_dss_device *dssdev,
bool invert_polarity)
{
mutex_lock(&venc.venc_lock);
@@ -721,74 +721,6 @@ static int venc_get_clocks(struct platform_device *pdev)
return 0;
}
-static struct omap_dss_device *venc_find_dssdev(struct platform_device *pdev)
-{
- struct omap_dss_board_info *pdata = pdev->dev.platform_data;
- const char *def_disp_name = omapdss_get_default_display_name();
- struct omap_dss_device *def_dssdev;
- int i;
-
- def_dssdev = NULL;
-
- for (i = 0; i < pdata->num_devices; ++i) {
- struct omap_dss_device *dssdev = pdata->devices[i];
-
- if (dssdev->type != OMAP_DISPLAY_TYPE_VENC)
- continue;
-
- if (def_dssdev = NULL)
- def_dssdev = dssdev;
-
- if (def_disp_name != NULL &&
- strcmp(dssdev->name, def_disp_name) = 0) {
- def_dssdev = dssdev;
- break;
- }
- }
-
- return def_dssdev;
-}
-
-static int venc_probe_pdata(struct platform_device *vencdev)
-{
- struct omap_dss_device *plat_dssdev;
- struct omap_dss_device *dssdev;
- int r;
-
- plat_dssdev = venc_find_dssdev(vencdev);
-
- if (!plat_dssdev)
- return 0;
-
- r = venc_init_regulator();
- if (r)
- return r;
-
- dssdev = dss_alloc_and_init_device(&vencdev->dev);
- if (!dssdev)
- return -ENOMEM;
-
- dss_copy_device_pdata(dssdev, plat_dssdev);
-
- r = omapdss_output_set_device(&venc.output, dssdev);
- if (r) {
- DSSERR("failed to connect output to new device: %s\n",
- dssdev->name);
- dss_put_device(dssdev);
- return r;
- }
-
- r = dss_add_device(dssdev);
- if (r) {
- DSSERR("device %s register failed: %d\n", dssdev->name, r);
- omapdss_output_unset_device(&venc.output);
- dss_put_device(dssdev);
- return r;
- }
-
- return 0;
-}
-
static int venc_connect(struct omap_dss_device *dssdev,
struct omap_dss_device *dst)
{
@@ -836,18 +768,18 @@ static const struct omapdss_atv_ops venc_ops = {
.connect = venc_connect,
.disconnect = venc_disconnect,
- .enable = omapdss_venc_display_enable,
- .disable = omapdss_venc_display_disable,
+ .enable = venc_display_enable,
+ .disable = venc_display_disable,
- .check_timings = omapdss_venc_check_timings,
- .set_timings = omapdss_venc_set_timings,
+ .check_timings = venc_check_timings,
+ .set_timings = venc_set_timings,
.get_timings = venc_get_timings,
- .set_type = omapdss_venc_set_type,
- .invert_vid_out_polarity = omapdss_venc_invert_vid_out_polarity,
+ .set_type = venc_set_type,
+ .invert_vid_out_polarity = venc_invert_vid_out_polarity,
- .set_wss = omapdss_venc_set_wss,
- .get_wss = omapdss_venc_get_wss,
+ .set_wss = venc_set_wss,
+ .get_wss = venc_get_wss,
};
static void venc_init_output(struct platform_device *pdev)
@@ -913,26 +845,12 @@ static int omap_venchw_probe(struct platform_device *pdev)
venc_runtime_put();
- r = venc_panel_init();
- if (r)
- goto err_panel_init;
-
dss_debugfs_create_file("venc", venc_dump_regs);
venc_init_output(pdev);
- if (pdev->dev.platform_data) {
- r = venc_probe_pdata(pdev);
- if (r)
- goto err_probe;
- }
-
return 0;
-err_probe:
- venc_panel_exit();
- venc_uninit_output(pdev);
-err_panel_init:
err_runtime_get:
pm_runtime_disable(&pdev->dev);
return r;
@@ -940,10 +858,6 @@ err_runtime_get:
static int __exit omap_venchw_remove(struct platform_device *pdev)
{
- dss_unregister_child_devices(&pdev->dev);
-
- venc_panel_exit();
-
venc_uninit_output(pdev);
pm_runtime_disable(&pdev->dev);
--
1.8.1.2
^ permalink raw reply related
* [PATCH 12/15] OMAPDSS: RFBI: remove code related to old panel model
From: Tomi Valkeinen @ 2013-08-29 13:31 UTC (permalink / raw)
To: linux-omap, linux-fbdev; +Cc: Archit Taneja, Tomi Valkeinen
In-Reply-To: <1377783120-14001-1-git-send-email-tomi.valkeinen@ti.com>
Now that the old panel drivers have been removed, we can remove the
old-model API and related code from the DSS encoder drivers.
This patch removes the code from the RFBI driver.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
drivers/video/omap2/dss/rfbi.c | 135 ++++++-----------------------------------
include/video/omapdss.h | 26 --------
2 files changed, 19 insertions(+), 142 deletions(-)
diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c
index fdfe6e6..c8a81a2 100644
--- a/drivers/video/omap2/dss/rfbi.c
+++ b/drivers/video/omap2/dss/rfbi.c
@@ -151,19 +151,17 @@ static void rfbi_runtime_put(void)
WARN_ON(r < 0 && r != -ENOSYS);
}
-void rfbi_bus_lock(void)
+static void rfbi_bus_lock(void)
{
down(&rfbi.bus_lock);
}
-EXPORT_SYMBOL(rfbi_bus_lock);
-void rfbi_bus_unlock(void)
+static void rfbi_bus_unlock(void)
{
up(&rfbi.bus_lock);
}
-EXPORT_SYMBOL(rfbi_bus_unlock);
-void omap_rfbi_write_command(const void *buf, u32 len)
+static void rfbi_write_command(const void *buf, u32 len)
{
switch (rfbi.parallelmode) {
case OMAP_DSS_RFBI_PARALLELMODE_8:
@@ -189,9 +187,8 @@ void omap_rfbi_write_command(const void *buf, u32 len)
BUG();
}
}
-EXPORT_SYMBOL(omap_rfbi_write_command);
-void omap_rfbi_read_data(void *buf, u32 len)
+static void rfbi_read_data(void *buf, u32 len)
{
switch (rfbi.parallelmode) {
case OMAP_DSS_RFBI_PARALLELMODE_8:
@@ -221,9 +218,8 @@ void omap_rfbi_read_data(void *buf, u32 len)
BUG();
}
}
-EXPORT_SYMBOL(omap_rfbi_read_data);
-void omap_rfbi_write_data(const void *buf, u32 len)
+static void rfbi_write_data(const void *buf, u32 len)
{
switch (rfbi.parallelmode) {
case OMAP_DSS_RFBI_PARALLELMODE_8:
@@ -250,9 +246,8 @@ void omap_rfbi_write_data(const void *buf, u32 len)
}
}
-EXPORT_SYMBOL(omap_rfbi_write_data);
-void omap_rfbi_write_pixels(const void __iomem *buf, int scr_width,
+static void rfbi_write_pixels(const void __iomem *buf, int scr_width,
u16 x, u16 y,
u16 w, u16 h)
{
@@ -305,7 +300,6 @@ void omap_rfbi_write_pixels(const void __iomem *buf, int scr_width,
BUG();
}
}
-EXPORT_SYMBOL(omap_rfbi_write_pixels);
static int rfbi_transfer_area(struct omap_dss_device *dssdev,
void (*callback)(void *data), void *data)
@@ -574,7 +568,7 @@ static int rfbi_convert_timings(struct rfbi_timings *t)
}
/* xxx FIX module selection missing */
-int omap_rfbi_setup_te(enum omap_rfbi_te_mode mode,
+static int rfbi_setup_te(enum omap_rfbi_te_mode mode,
unsigned hs_pulse_time, unsigned vs_pulse_time,
int hs_pol_inv, int vs_pol_inv, int extif_div)
{
@@ -613,10 +607,9 @@ int omap_rfbi_setup_te(enum omap_rfbi_te_mode mode,
return 0;
}
-EXPORT_SYMBOL(omap_rfbi_setup_te);
/* xxx FIX module selection missing */
-int omap_rfbi_enable_te(bool enable, unsigned line)
+static int rfbi_enable_te(bool enable, unsigned line)
{
u32 l;
@@ -636,9 +629,8 @@ int omap_rfbi_enable_te(bool enable, unsigned line)
return 0;
}
-EXPORT_SYMBOL(omap_rfbi_enable_te);
-static int rfbi_configure(int rfbi_module, int bpp, int lines)
+static int rfbi_configure_bus(int rfbi_module, int bpp, int lines)
{
u32 l;
int cycle1 = 0, cycle2 = 0, cycle3 = 0;
@@ -770,45 +762,39 @@ static int rfbi_configure(int rfbi_module, int bpp, int lines)
return 0;
}
-int omap_rfbi_configure(struct omap_dss_device *dssdev)
+static int rfbi_configure(struct omap_dss_device *dssdev)
{
- return rfbi_configure(dssdev->phy.rfbi.channel, rfbi.pixel_size,
+ return rfbi_configure_bus(dssdev->phy.rfbi.channel, rfbi.pixel_size,
rfbi.data_lines);
}
-EXPORT_SYMBOL(omap_rfbi_configure);
-int omap_rfbi_update(struct omap_dss_device *dssdev, void (*callback)(void *),
+static int rfbi_update(struct omap_dss_device *dssdev, void (*callback)(void *),
void *data)
{
return rfbi_transfer_area(dssdev, callback, data);
}
-EXPORT_SYMBOL(omap_rfbi_update);
-void omapdss_rfbi_set_size(struct omap_dss_device *dssdev, u16 w, u16 h)
+static void rfbi_set_size(struct omap_dss_device *dssdev, u16 w, u16 h)
{
rfbi.timings.x_res = w;
rfbi.timings.y_res = h;
}
-EXPORT_SYMBOL(omapdss_rfbi_set_size);
-void omapdss_rfbi_set_pixel_size(struct omap_dss_device *dssdev, int pixel_size)
+static void rfbi_set_pixel_size(struct omap_dss_device *dssdev, int pixel_size)
{
rfbi.pixel_size = pixel_size;
}
-EXPORT_SYMBOL(omapdss_rfbi_set_pixel_size);
-void omapdss_rfbi_set_data_lines(struct omap_dss_device *dssdev, int data_lines)
+static void rfbi_set_data_lines(struct omap_dss_device *dssdev, int data_lines)
{
rfbi.data_lines = data_lines;
}
-EXPORT_SYMBOL(omapdss_rfbi_set_data_lines);
-void omapdss_rfbi_set_interface_timings(struct omap_dss_device *dssdev,
+static void rfbi_set_interface_timings(struct omap_dss_device *dssdev,
struct rfbi_timings *timings)
{
rfbi.intf_timings = *timings;
}
-EXPORT_SYMBOL(omapdss_rfbi_set_interface_timings);
static void rfbi_dump_regs(struct seq_file *s)
{
@@ -888,7 +874,7 @@ static void rfbi_config_lcd_manager(struct omap_dss_device *dssdev)
dss_mgr_set_timings(mgr, &rfbi.timings);
}
-int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev)
+static int rfbi_display_enable(struct omap_dss_device *dssdev)
{
struct omap_dss_device *out = &rfbi.output;
int r;
@@ -911,7 +897,7 @@ int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev)
rfbi_config_lcd_manager(dssdev);
- rfbi_configure(dssdev->phy.rfbi.channel, rfbi.pixel_size,
+ rfbi_configure_bus(dssdev->phy.rfbi.channel, rfbi.pixel_size,
rfbi.data_lines);
rfbi_set_timings(dssdev->phy.rfbi.channel, &rfbi.intf_timings);
@@ -921,9 +907,8 @@ err1:
rfbi_runtime_put();
return r;
}
-EXPORT_SYMBOL(omapdss_rfbi_display_enable);
-void omapdss_rfbi_display_disable(struct omap_dss_device *dssdev)
+static void rfbi_display_disable(struct omap_dss_device *dssdev)
{
struct omap_dss_device *out = &rfbi.output;
@@ -932,7 +917,6 @@ void omapdss_rfbi_display_disable(struct omap_dss_device *dssdev)
rfbi_runtime_put();
}
-EXPORT_SYMBOL(omapdss_rfbi_display_disable);
static int rfbi_init_display(struct omap_dss_device *dssdev)
{
@@ -940,77 +924,6 @@ static int rfbi_init_display(struct omap_dss_device *dssdev)
return 0;
}
-static struct omap_dss_device *rfbi_find_dssdev(struct platform_device *pdev)
-{
- struct omap_dss_board_info *pdata = pdev->dev.platform_data;
- const char *def_disp_name = omapdss_get_default_display_name();
- struct omap_dss_device *def_dssdev;
- int i;
-
- def_dssdev = NULL;
-
- for (i = 0; i < pdata->num_devices; ++i) {
- struct omap_dss_device *dssdev = pdata->devices[i];
-
- if (dssdev->type != OMAP_DISPLAY_TYPE_DBI)
- continue;
-
- if (def_dssdev = NULL)
- def_dssdev = dssdev;
-
- if (def_disp_name != NULL &&
- strcmp(dssdev->name, def_disp_name) = 0) {
- def_dssdev = dssdev;
- break;
- }
- }
-
- return def_dssdev;
-}
-
-static int rfbi_probe_pdata(struct platform_device *rfbidev)
-{
- struct omap_dss_device *plat_dssdev;
- struct omap_dss_device *dssdev;
- int r;
-
- plat_dssdev = rfbi_find_dssdev(rfbidev);
-
- if (!plat_dssdev)
- return 0;
-
- dssdev = dss_alloc_and_init_device(&rfbidev->dev);
- if (!dssdev)
- return -ENOMEM;
-
- dss_copy_device_pdata(dssdev, plat_dssdev);
-
- r = rfbi_init_display(dssdev);
- if (r) {
- DSSERR("device %s init failed: %d\n", dssdev->name, r);
- dss_put_device(dssdev);
- return r;
- }
-
- r = omapdss_output_set_device(&rfbi.output, dssdev);
- if (r) {
- DSSERR("failed to connect output to new device: %s\n",
- dssdev->name);
- dss_put_device(dssdev);
- return r;
- }
-
- r = dss_add_device(dssdev);
- if (r) {
- DSSERR("device %s register failed: %d\n", dssdev->name, r);
- omapdss_output_unset_device(&rfbi.output);
- dss_put_device(dssdev);
- return r;
- }
-
- return 0;
-}
-
static void rfbi_init_output(struct platform_device *pdev)
{
struct omap_dss_device *out = &rfbi.output;
@@ -1085,16 +998,8 @@ static int omap_rfbihw_probe(struct platform_device *pdev)
rfbi_init_output(pdev);
- if (pdev->dev.platform_data) {
- r = rfbi_probe_pdata(pdev);
- if (r)
- goto err_probe;
- }
-
return 0;
-err_probe:
- rfbi_uninit_output(pdev);
err_runtime_get:
pm_runtime_disable(&pdev->dev);
return r;
@@ -1102,8 +1007,6 @@ err_runtime_get:
static int __exit omap_rfbihw_remove(struct platform_device *pdev)
{
- dss_unregister_child_devices(&pdev->dev);
-
rfbi_uninit_output(pdev);
pm_runtime_disable(&pdev->dev);
diff --git a/include/video/omapdss.h b/include/video/omapdss.h
index 3395804..ca04b56 100644
--- a/include/video/omapdss.h
+++ b/include/video/omapdss.h
@@ -250,19 +250,6 @@ struct rfbi_timings {
int converted;
};
-void omap_rfbi_write_command(const void *buf, u32 len);
-void omap_rfbi_read_data(void *buf, u32 len);
-void omap_rfbi_write_data(const void *buf, u32 len);
-void omap_rfbi_write_pixels(const void __iomem *buf, int scr_width,
- u16 x, u16 y,
- u16 w, u16 h);
-int omap_rfbi_enable_te(bool enable, unsigned line);
-int omap_rfbi_setup_te(enum omap_rfbi_te_mode mode,
- unsigned hs_pulse_time, unsigned vs_pulse_time,
- int hs_pol_inv, int vs_pol_inv, int extif_div);
-void rfbi_bus_lock(void);
-void rfbi_bus_unlock(void);
-
/* DSI */
enum omap_dss_dsi_trans_mode {
@@ -987,19 +974,6 @@ int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi,
#define to_dss_driver(x) container_of((x), struct omap_dss_driver, driver)
#define to_dss_device(x) container_of((x), struct omap_dss_device, old_dev)
-int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev);
-void omapdss_rfbi_display_disable(struct omap_dss_device *dssdev);
-int omap_rfbi_update(struct omap_dss_device *dssdev, void (*callback)(void *),
- void *data);
-int omap_rfbi_configure(struct omap_dss_device *dssdev);
-void omapdss_rfbi_set_size(struct omap_dss_device *dssdev, u16 w, u16 h);
-void omapdss_rfbi_set_pixel_size(struct omap_dss_device *dssdev,
- int pixel_size);
-void omapdss_rfbi_set_data_lines(struct omap_dss_device *dssdev,
- int data_lines);
-void omapdss_rfbi_set_interface_timings(struct omap_dss_device *dssdev,
- struct rfbi_timings *timings);
-
int omapdss_compat_init(void);
void omapdss_compat_uninit(void);
--
1.8.1.2
^ permalink raw reply related
* [PATCH 13/15] OMAPDSS: DSS: remove legacy dss bus support
From: Tomi Valkeinen @ 2013-08-29 13:31 UTC (permalink / raw)
To: linux-omap, linux-fbdev; +Cc: Archit Taneja, Tomi Valkeinen
In-Reply-To: <1377783120-14001-1-git-send-email-tomi.valkeinen@ti.com>
With all the old panels removed and all the old panel model APIs removed
from the DSS encoders, we can now remove the custom omapdss-bus which
was used in the old panel model.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
drivers/video/omap2/dss/core.c | 279 +----------------------------------------
drivers/video/omap2/dss/dss.h | 9 --
include/video/omapdss.h | 6 -
3 files changed, 3 insertions(+), 291 deletions(-)
diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c
index 71e6a77..54f3320 100644
--- a/drivers/video/omap2/dss/core.c
+++ b/drivers/video/omap2/dss/core.c
@@ -248,235 +248,6 @@ static struct platform_driver omap_dss_driver = {
},
};
-/* BUS */
-static int dss_bus_match(struct device *dev, struct device_driver *driver)
-{
- struct omap_dss_device *dssdev = to_dss_device(dev);
-
- DSSDBG("bus_match. dev %s/%s, drv %s\n",
- dev_name(dev), dssdev->driver_name, driver->name);
-
- return strcmp(dssdev->driver_name, driver->name) = 0;
-}
-
-static struct bus_type dss_bus_type = {
- .name = "omapdss",
- .match = dss_bus_match,
-};
-
-static void dss_bus_release(struct device *dev)
-{
- DSSDBG("bus_release\n");
-}
-
-static struct device dss_bus = {
- .release = dss_bus_release,
-};
-
-struct bus_type *dss_get_bus(void)
-{
- return &dss_bus_type;
-}
-
-/* DRIVER */
-static int dss_driver_probe(struct device *dev)
-{
- int r;
- struct omap_dss_driver *dssdrv = to_dss_driver(dev->driver);
- struct omap_dss_device *dssdev = to_dss_device(dev);
-
- DSSDBG("driver_probe: dev %s/%s, drv %s\n",
- dev_name(dev), dssdev->driver_name,
- dssdrv->driver.name);
-
- r = dssdrv->probe(dssdev);
-
- if (r) {
- DSSERR("driver probe failed: %d\n", r);
- return r;
- }
-
- DSSDBG("probe done for device %s\n", dev_name(dev));
-
- dssdev->driver = dssdrv;
-
- return 0;
-}
-
-static int dss_driver_remove(struct device *dev)
-{
- struct omap_dss_driver *dssdrv = to_dss_driver(dev->driver);
- struct omap_dss_device *dssdev = to_dss_device(dev);
-
- DSSDBG("driver_remove: dev %s/%s\n", dev_name(dev),
- dssdev->driver_name);
-
- dssdrv->remove(dssdev);
-
- dssdev->driver = NULL;
-
- return 0;
-}
-
-static int omapdss_default_connect(struct omap_dss_device *dssdev)
-{
- struct omap_dss_device *out;
- struct omap_overlay_manager *mgr;
- int r;
-
- out = dssdev->output;
-
- if (out = NULL)
- return -ENODEV;
-
- mgr = omap_dss_get_overlay_manager(out->dispc_channel);
- if (!mgr)
- return -ENODEV;
-
- r = dss_mgr_connect(mgr, out);
- if (r)
- return r;
-
- return 0;
-}
-
-static void omapdss_default_disconnect(struct omap_dss_device *dssdev)
-{
- struct omap_dss_device *out;
- struct omap_overlay_manager *mgr;
-
- out = dssdev->output;
-
- if (out = NULL)
- return;
-
- mgr = out->manager;
-
- if (mgr = NULL)
- return;
-
- dss_mgr_disconnect(mgr, out);
-}
-
-int omap_dss_register_driver(struct omap_dss_driver *dssdriver)
-{
- dssdriver->driver.bus = &dss_bus_type;
- dssdriver->driver.probe = dss_driver_probe;
- dssdriver->driver.remove = dss_driver_remove;
-
- if (dssdriver->get_resolution = NULL)
- dssdriver->get_resolution = omapdss_default_get_resolution;
- if (dssdriver->get_recommended_bpp = NULL)
- dssdriver->get_recommended_bpp - omapdss_default_get_recommended_bpp;
- if (dssdriver->get_timings = NULL)
- dssdriver->get_timings = omapdss_default_get_timings;
- if (dssdriver->connect = NULL)
- dssdriver->connect = omapdss_default_connect;
- if (dssdriver->disconnect = NULL)
- dssdriver->disconnect = omapdss_default_disconnect;
-
- return driver_register(&dssdriver->driver);
-}
-EXPORT_SYMBOL(omap_dss_register_driver);
-
-void omap_dss_unregister_driver(struct omap_dss_driver *dssdriver)
-{
- driver_unregister(&dssdriver->driver);
-}
-EXPORT_SYMBOL(omap_dss_unregister_driver);
-
-/* DEVICE */
-
-static void omap_dss_dev_release(struct device *dev)
-{
- struct omap_dss_device *dssdev = to_dss_device(dev);
- kfree(dssdev);
-}
-
-static int disp_num_counter;
-
-struct omap_dss_device *dss_alloc_and_init_device(struct device *parent)
-{
- struct omap_dss_device *dssdev;
-
- dssdev = kzalloc(sizeof(*dssdev), GFP_KERNEL);
- if (!dssdev)
- return NULL;
-
- dssdev->old_dev.bus = &dss_bus_type;
- dssdev->old_dev.parent = parent;
- dssdev->old_dev.release = omap_dss_dev_release;
- dev_set_name(&dssdev->old_dev, "display%d", disp_num_counter++);
-
- device_initialize(&dssdev->old_dev);
-
- return dssdev;
-}
-
-int dss_add_device(struct omap_dss_device *dssdev)
-{
- dssdev->dev = &dssdev->old_dev;
-
- omapdss_register_display(dssdev);
- return device_add(&dssdev->old_dev);
-}
-
-void dss_put_device(struct omap_dss_device *dssdev)
-{
- put_device(&dssdev->old_dev);
-}
-
-void dss_unregister_device(struct omap_dss_device *dssdev)
-{
- device_unregister(&dssdev->old_dev);
- omapdss_unregister_display(dssdev);
-}
-
-static int dss_unregister_dss_dev(struct device *dev, void *data)
-{
- struct omap_dss_device *dssdev = to_dss_device(dev);
- dss_unregister_device(dssdev);
- return 0;
-}
-
-void dss_unregister_child_devices(struct device *parent)
-{
- device_for_each_child(parent, NULL, dss_unregister_dss_dev);
-}
-
-void dss_copy_device_pdata(struct omap_dss_device *dst,
- const struct omap_dss_device *src)
-{
- u8 *d = (u8 *)dst;
- u8 *s = (u8 *)src;
- size_t dsize = sizeof(struct device);
-
- memcpy(d + dsize, s + dsize, sizeof(struct omap_dss_device) - dsize);
-}
-
-/* BUS */
-static int __init omap_dss_bus_register(void)
-{
- int r;
-
- r = bus_register(&dss_bus_type);
- if (r) {
- DSSERR("bus register failed\n");
- return r;
- }
-
- dev_set_name(&dss_bus, "omapdss");
- r = device_register(&dss_bus);
- if (r) {
- DSSERR("bus driver register failed\n");
- bus_unregister(&dss_bus_type);
- return r;
- }
-
- return 0;
-}
-
/* INIT */
static int (*dss_output_drv_reg_funcs[])(void) __initdata = {
#ifdef CONFIG_OMAP2_DSS_DSI
@@ -553,6 +324,8 @@ static int __init omap_dss_register_drivers(void)
dss_output_drv_loaded[i] = true;
}
+ dss_initialized = true;
+
return 0;
err_dispc:
@@ -578,64 +351,18 @@ static void __exit omap_dss_unregister_drivers(void)
platform_driver_unregister(&omap_dss_driver);
}
-#ifdef CONFIG_OMAP2_DSS_MODULE
-static void omap_dss_bus_unregister(void)
-{
- device_unregister(&dss_bus);
-
- bus_unregister(&dss_bus_type);
-}
-
static int __init omap_dss_init(void)
{
- int r;
-
- r = omap_dss_bus_register();
- if (r)
- return r;
-
- r = omap_dss_register_drivers();
- if (r) {
- omap_dss_bus_unregister();
- return r;
- }
-
- dss_initialized = true;
-
- return 0;
+ return omap_dss_register_drivers();
}
static void __exit omap_dss_exit(void)
{
omap_dss_unregister_drivers();
-
- omap_dss_bus_unregister();
}
module_init(omap_dss_init);
module_exit(omap_dss_exit);
-#else
-static int __init omap_dss_init(void)
-{
- return omap_dss_bus_register();
-}
-
-static int __init omap_dss_init2(void)
-{
- int r;
-
- r = omap_dss_register_drivers();
- if (r)
- return r;
-
- dss_initialized = true;
-
- return 0;
-}
-
-core_initcall(omap_dss_init);
-device_initcall(omap_dss_init2);
-#endif
MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@nokia.com>");
MODULE_DESCRIPTION("OMAP2/3 Display Subsystem");
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index 68dd27f..e172531 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -163,20 +163,11 @@ struct platform_device;
/* core */
struct platform_device *dss_get_core_pdev(void);
-struct bus_type *dss_get_bus(void);
int dss_dsi_enable_pads(int dsi_id, unsigned lane_mask);
void dss_dsi_disable_pads(int dsi_id, unsigned lane_mask);
int dss_set_min_bus_tput(struct device *dev, unsigned long tput);
int dss_debugfs_create_file(const char *name, void (*write)(struct seq_file *));
-struct omap_dss_device *dss_alloc_and_init_device(struct device *parent);
-int dss_add_device(struct omap_dss_device *dssdev);
-void dss_unregister_device(struct omap_dss_device *dssdev);
-void dss_unregister_child_devices(struct device *parent);
-void dss_put_device(struct omap_dss_device *dssdev);
-void dss_copy_device_pdata(struct omap_dss_device *dst,
- const struct omap_dss_device *src);
-
/* display */
int dss_suspend_all_devices(void);
int dss_resume_all_devices(void);
diff --git a/include/video/omapdss.h b/include/video/omapdss.h
index ca04b56..763b11b 100644
--- a/include/video/omapdss.h
+++ b/include/video/omapdss.h
@@ -703,10 +703,6 @@ struct omapdss_dsi_ops {
};
struct omap_dss_device {
- /* old device, to be removed */
- struct device old_dev;
-
- /* new device, pointer to panel device */
struct device *dev;
struct module *owner;
@@ -808,8 +804,6 @@ struct omap_dss_hdmi_data
};
struct omap_dss_driver {
- struct device_driver driver;
-
int (*probe)(struct omap_dss_device *);
void (*remove)(struct omap_dss_device *);
--
1.8.1.2
^ permalink raw reply related
* [PATCH 14/15] OMAPDSS: rename omap_dss_device's 'output' to 'src'
From: Tomi Valkeinen @ 2013-08-29 13:31 UTC (permalink / raw)
To: linux-omap, linux-fbdev; +Cc: Archit Taneja, Tomi Valkeinen
In-Reply-To: <1377783120-14001-1-git-send-email-tomi.valkeinen@ti.com>
In the old panel device model we had "outputs", which were the encoders
inside OMAP DSS block, and panel devices (omap_dss_device). The panel
devices had a reference to the source of the video data, i.e. reference
to an "output", in a field named "output".
That was somewhat confusing even in the old panel device model, but even
more so with the panel device model where we can have longer chains of
display entities.
This patch renames the "output" field to "src", which much better tells
what the field points to.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
drivers/gpu/drm/omapdrm/omap_encoder.c | 2 +-
drivers/video/omap2/displays-new/encoder-tfp410.c | 4 ++--
drivers/video/omap2/displays-new/encoder-tpd12s015.c | 4 ++--
drivers/video/omap2/dss/output.c | 8 ++++----
include/video/omapdss.h | 4 ++--
5 files changed, 11 insertions(+), 11 deletions(-)
diff --git a/drivers/gpu/drm/omapdrm/omap_encoder.c b/drivers/gpu/drm/omapdrm/omap_encoder.c
index c29451b..6a12e89 100644
--- a/drivers/gpu/drm/omapdrm/omap_encoder.c
+++ b/drivers/gpu/drm/omapdrm/omap_encoder.c
@@ -133,7 +133,7 @@ int omap_encoder_update(struct drm_encoder *encoder,
struct omap_dss_driver *dssdrv = dssdev->driver;
int ret;
- dssdev->output->manager = mgr;
+ dssdev->src->manager = mgr;
if (dssdrv->check_timings) {
ret = dssdrv->check_timings(dssdev, timings);
diff --git a/drivers/video/omap2/displays-new/encoder-tfp410.c b/drivers/video/omap2/displays-new/encoder-tfp410.c
index a04f658..454f771 100644
--- a/drivers/video/omap2/displays-new/encoder-tfp410.c
+++ b/drivers/video/omap2/displays-new/encoder-tfp410.c
@@ -43,7 +43,7 @@ static int tfp410_connect(struct omap_dss_device *dssdev,
if (r)
return r;
- dst->output = dssdev;
+ dst->src = dssdev;
dssdev->device = dst;
return 0;
@@ -63,7 +63,7 @@ static void tfp410_disconnect(struct omap_dss_device *dssdev,
if (dst != dssdev->device)
return;
- dst->output = NULL;
+ dst->src = NULL;
dssdev->device = NULL;
in->ops.dpi->disconnect(in, &ddata->dssdev);
diff --git a/drivers/video/omap2/displays-new/encoder-tpd12s015.c b/drivers/video/omap2/displays-new/encoder-tpd12s015.c
index ce0e010..a3d2991 100644
--- a/drivers/video/omap2/displays-new/encoder-tpd12s015.c
+++ b/drivers/video/omap2/displays-new/encoder-tpd12s015.c
@@ -66,7 +66,7 @@ static int tpd_connect(struct omap_dss_device *dssdev,
if (r)
return r;
- dst->output = dssdev;
+ dst->src = dssdev;
dssdev->device = dst;
INIT_COMPLETION(ddata->hpd_completion);
@@ -102,7 +102,7 @@ static void tpd_disconnect(struct omap_dss_device *dssdev,
gpio_set_value_cansleep(ddata->ct_cp_hpd_gpio, 0);
- dst->output = NULL;
+ dst->src = NULL;
dssdev->device = NULL;
in->ops.hdmi->disconnect(in, &ddata->dssdev);
diff --git a/drivers/video/omap2/dss/output.c b/drivers/video/omap2/dss/output.c
index 3f5c0a7..15f47af 100644
--- a/drivers/video/omap2/dss/output.c
+++ b/drivers/video/omap2/dss/output.c
@@ -48,7 +48,7 @@ int omapdss_output_set_device(struct omap_dss_device *out,
}
out->device = dssdev;
- dssdev->output = out;
+ dssdev->src = out;
mutex_unlock(&output_lock);
@@ -79,7 +79,7 @@ int omapdss_output_unset_device(struct omap_dss_device *out)
goto err;
}
- out->device->output = NULL;
+ out->device->src = NULL;
out->device = NULL;
mutex_unlock(&output_lock);
@@ -146,8 +146,8 @@ EXPORT_SYMBOL(omap_dss_find_output_by_node);
struct omap_dss_device *omapdss_find_output_from_display(struct omap_dss_device *dssdev)
{
- while (dssdev->output)
- dssdev = dssdev->output;
+ while (dssdev->src)
+ dssdev = dssdev->src;
if (dssdev->id != 0)
return omap_dss_get_device(dssdev);
diff --git a/include/video/omapdss.h b/include/video/omapdss.h
index 763b11b..5fa81dd 100644
--- a/include/video/omapdss.h
+++ b/include/video/omapdss.h
@@ -774,7 +774,7 @@ struct omap_dss_device {
enum omap_display_caps caps;
- struct omap_dss_device *output;
+ struct omap_dss_device *src;
enum omap_dss_display_state state;
@@ -1011,7 +1011,7 @@ void dss_mgr_unregister_framedone_handler(struct omap_overlay_manager *mgr,
static inline bool omapdss_device_is_connected(struct omap_dss_device *dssdev)
{
- return dssdev->output;
+ return dssdev->src;
}
static inline bool omapdss_device_is_enabled(struct omap_dss_device *dssdev)
--
1.8.1.2
^ permalink raw reply related
* [PATCH 15/15] OMAPDSS: rename omap_dss_device's 'device' field to 'dst'
From: Tomi Valkeinen @ 2013-08-29 13:32 UTC (permalink / raw)
To: linux-omap, linux-fbdev; +Cc: Archit Taneja, Tomi Valkeinen
In-Reply-To: <1377783120-14001-1-git-send-email-tomi.valkeinen@ti.com>
In the old panel device model we had omap_dss_output entities,
representing the encoders in the DSS block. This entity had "device"
field, which pointed to the panel that was using the omap_dss_output.
With the new panel device model, the omap_dss_output is integrated into
omap_dss_device, which now represents a "display entity". Thus the "device"
field, now in omap_dss_device, points to the next entity in the display
entity-chain.
This patch renames the "device" field to "dst", which much better tells
what the field points to.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
drivers/video/omap2/displays-new/encoder-tfp410.c | 10 +++++-----
drivers/video/omap2/displays-new/encoder-tpd12s015.c | 10 +++++-----
drivers/video/omap2/dss/apply.c | 4 ++--
drivers/video/omap2/dss/dpi.c | 4 ++--
drivers/video/omap2/dss/dsi.c | 4 ++--
drivers/video/omap2/dss/hdmi.c | 4 ++--
drivers/video/omap2/dss/output.c | 16 ++++++++--------
drivers/video/omap2/dss/sdi.c | 4 ++--
drivers/video/omap2/dss/venc.c | 4 ++--
include/video/omapdss.h | 2 +-
10 files changed, 31 insertions(+), 31 deletions(-)
diff --git a/drivers/video/omap2/displays-new/encoder-tfp410.c b/drivers/video/omap2/displays-new/encoder-tfp410.c
index 454f771..4a291e7 100644
--- a/drivers/video/omap2/displays-new/encoder-tfp410.c
+++ b/drivers/video/omap2/displays-new/encoder-tfp410.c
@@ -44,7 +44,7 @@ static int tfp410_connect(struct omap_dss_device *dssdev,
return r;
dst->src = dssdev;
- dssdev->device = dst;
+ dssdev->dst = dst;
return 0;
}
@@ -59,12 +59,12 @@ static void tfp410_disconnect(struct omap_dss_device *dssdev,
if (!omapdss_device_is_connected(dssdev))
return;
- WARN_ON(dst != dssdev->device);
- if (dst != dssdev->device)
+ WARN_ON(dst != dssdev->dst);
+ if (dst != dssdev->dst)
return;
dst->src = NULL;
- dssdev->device = NULL;
+ dssdev->dst = NULL;
in->ops.dpi->disconnect(in, &ddata->dssdev);
}
@@ -244,7 +244,7 @@ static int __exit tfp410_remove(struct platform_device *pdev)
WARN_ON(omapdss_device_is_connected(dssdev));
if (omapdss_device_is_connected(dssdev))
- tfp410_disconnect(dssdev, dssdev->device);
+ tfp410_disconnect(dssdev, dssdev->dst);
omap_dss_put_device(in);
diff --git a/drivers/video/omap2/displays-new/encoder-tpd12s015.c b/drivers/video/omap2/displays-new/encoder-tpd12s015.c
index a3d2991..798ef20 100644
--- a/drivers/video/omap2/displays-new/encoder-tpd12s015.c
+++ b/drivers/video/omap2/displays-new/encoder-tpd12s015.c
@@ -67,7 +67,7 @@ static int tpd_connect(struct omap_dss_device *dssdev,
return r;
dst->src = dssdev;
- dssdev->device = dst;
+ dssdev->dst = dst;
INIT_COMPLETION(ddata->hpd_completion);
@@ -95,15 +95,15 @@ static void tpd_disconnect(struct omap_dss_device *dssdev,
struct panel_drv_data *ddata = to_panel_data(dssdev);
struct omap_dss_device *in = ddata->in;
- WARN_ON(dst != dssdev->device);
+ WARN_ON(dst != dssdev->dst);
- if (dst != dssdev->device)
+ if (dst != dssdev->dst)
return;
gpio_set_value_cansleep(ddata->ct_cp_hpd_gpio, 0);
dst->src = NULL;
- dssdev->device = NULL;
+ dssdev->dst = NULL;
in->ops.hdmi->disconnect(in, &ddata->dssdev);
}
@@ -372,7 +372,7 @@ static int __exit tpd_remove(struct platform_device *pdev)
WARN_ON(omapdss_device_is_connected(dssdev));
if (omapdss_device_is_connected(dssdev))
- tpd_disconnect(dssdev, dssdev->device);
+ tpd_disconnect(dssdev, dssdev->dst);
omap_dss_put_device(in);
diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c
index d6212d63..60758db 100644
--- a/drivers/video/omap2/dss/apply.c
+++ b/drivers/video/omap2/dss/apply.c
@@ -428,8 +428,8 @@ static struct omap_dss_device *dss_mgr_get_device(struct omap_overlay_manager *m
if (dssdev = NULL)
return NULL;
- while (dssdev->device)
- dssdev = dssdev->device;
+ while (dssdev->dst)
+ dssdev = dssdev->dst;
if (dssdev->driver)
return dssdev;
diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c
index b268d04..bd48cde 100644
--- a/drivers/video/omap2/dss/dpi.c
+++ b/drivers/video/omap2/dss/dpi.c
@@ -643,9 +643,9 @@ static int dpi_connect(struct omap_dss_device *dssdev,
static void dpi_disconnect(struct omap_dss_device *dssdev,
struct omap_dss_device *dst)
{
- WARN_ON(dst != dssdev->device);
+ WARN_ON(dst != dssdev->dst);
- if (dst != dssdev->device)
+ if (dst != dssdev->dst)
return;
omapdss_output_unset_device(dssdev);
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index 3daaf7e..a598b58 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -5264,9 +5264,9 @@ static int dsi_connect(struct omap_dss_device *dssdev,
static void dsi_disconnect(struct omap_dss_device *dssdev,
struct omap_dss_device *dst)
{
- WARN_ON(dst != dssdev->device);
+ WARN_ON(dst != dssdev->dst);
- if (dst != dssdev->device)
+ if (dst != dssdev->dst)
return;
omapdss_output_unset_device(dssdev);
diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c
index 0b8e4de..75f3c74 100644
--- a/drivers/video/omap2/dss/hdmi.c
+++ b/drivers/video/omap2/dss/hdmi.c
@@ -900,9 +900,9 @@ static int hdmi_connect(struct omap_dss_device *dssdev,
static void hdmi_disconnect(struct omap_dss_device *dssdev,
struct omap_dss_device *dst)
{
- WARN_ON(dst != dssdev->device);
+ WARN_ON(dst != dssdev->dst);
- if (dst != dssdev->device)
+ if (dst != dssdev->dst)
return;
omapdss_output_unset_device(dssdev);
diff --git a/drivers/video/omap2/dss/output.c b/drivers/video/omap2/dss/output.c
index 15f47af..2ab3afa 100644
--- a/drivers/video/omap2/dss/output.c
+++ b/drivers/video/omap2/dss/output.c
@@ -34,9 +34,9 @@ int omapdss_output_set_device(struct omap_dss_device *out,
mutex_lock(&output_lock);
- if (out->device) {
+ if (out->dst) {
DSSERR("output already has device %s connected to it\n",
- out->device->name);
+ out->dst->name);
r = -EINVAL;
goto err;
}
@@ -47,7 +47,7 @@ int omapdss_output_set_device(struct omap_dss_device *out,
goto err;
}
- out->device = dssdev;
+ out->dst = dssdev;
dssdev->src = out;
mutex_unlock(&output_lock);
@@ -66,21 +66,21 @@ int omapdss_output_unset_device(struct omap_dss_device *out)
mutex_lock(&output_lock);
- if (!out->device) {
+ if (!out->dst) {
DSSERR("output doesn't have a device connected to it\n");
r = -EINVAL;
goto err;
}
- if (out->device->state != OMAP_DSS_DISPLAY_DISABLED) {
+ if (out->dst->state != OMAP_DSS_DISPLAY_DISABLED) {
DSSERR("device %s is not disabled, cannot unset device\n",
- out->device->name);
+ out->dst->name);
r = -EINVAL;
goto err;
}
- out->device->src = NULL;
- out->device = NULL;
+ out->dst->src = NULL;
+ out->dst = NULL;
mutex_unlock(&output_lock);
diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c
index b327688..ccc569a 100644
--- a/drivers/video/omap2/dss/sdi.c
+++ b/drivers/video/omap2/dss/sdi.c
@@ -306,9 +306,9 @@ static int sdi_connect(struct omap_dss_device *dssdev,
static void sdi_disconnect(struct omap_dss_device *dssdev,
struct omap_dss_device *dst)
{
- WARN_ON(dst != dssdev->device);
+ WARN_ON(dst != dssdev->dst);
- if (dst != dssdev->device)
+ if (dst != dssdev->dst)
return;
omapdss_output_unset_device(dssdev);
diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c
index 0d8ccde..5f88ac4 100644
--- a/drivers/video/omap2/dss/venc.c
+++ b/drivers/video/omap2/dss/venc.c
@@ -753,9 +753,9 @@ static int venc_connect(struct omap_dss_device *dssdev,
static void venc_disconnect(struct omap_dss_device *dssdev,
struct omap_dss_device *dst)
{
- WARN_ON(dst != dssdev->device);
+ WARN_ON(dst != dssdev->dst);
- if (dst != dssdev->device)
+ if (dst != dssdev->dst)
return;
omapdss_output_unset_device(dssdev);
diff --git a/include/video/omapdss.h b/include/video/omapdss.h
index 5fa81dd..3d7c51a 100644
--- a/include/video/omapdss.h
+++ b/include/video/omapdss.h
@@ -793,7 +793,7 @@ struct omap_dss_device {
/* dynamic fields */
struct omap_overlay_manager *manager;
- struct omap_dss_device *device;
+ struct omap_dss_device *dst;
};
struct omap_dss_hdmi_data
--
1.8.1.2
^ permalink raw reply related
* Re: [PATCH 06/15] OMAPDSS: remove all old panel drivers
From: Tomi Valkeinen @ 2013-08-29 14:06 UTC (permalink / raw)
To: Archit Taneja; +Cc: linux-omap, linux-fbdev
In-Reply-To: <521F53F0.4030203@ti.com>
[-- Attachment #1: Type: text/plain, Size: 887 bytes --]
Hi,
On 29/08/13 17:00, Archit Taneja wrote:
> On Thursday 29 August 2013 07:01 PM, Tomi Valkeinen wrote:
>> The board files now use the new panel drivers, making the old panel
>> drivers obsolete.
>>
>> Remove the old panel drivers, Kconfig and Makefile entries, and the
>> panels' platform data structs.
>
> Can we convert the picodlp driver to the new panel driver model, and
> report it as broken for now?
(please cut your quotes a bit, you just included some thousands of lines
of code there =).
We could, but I'm not sure what would be the point. The new picodlp
would be (more or less) totally new driver, so we would still end up
removing the old driver. We can as well add it later if we manage to get
it working.
The RFBI case is a bit different, as there we just changed the current
driver a bit and we didn't create a totally new one.
Tomi
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 901 bytes --]
^ permalink raw reply
* Re: [PATCH 06/15] OMAPDSS: remove all old panel drivers
From: Archit Taneja @ 2013-08-29 14:20 UTC (permalink / raw)
To: Tomi Valkeinen; +Cc: linux-omap, linux-fbdev
In-Reply-To: <521F555C.8090802@ti.com>
On Thursday 29 August 2013 07:36 PM, Tomi Valkeinen wrote:
> Hi,
>
> On 29/08/13 17:00, Archit Taneja wrote:
>> On Thursday 29 August 2013 07:01 PM, Tomi Valkeinen wrote:
>>> The board files now use the new panel drivers, making the old panel
>>> drivers obsolete.
>>>
>>> Remove the old panel drivers, Kconfig and Makefile entries, and the
>>> panels' platform data structs.
>>
>> Can we convert the picodlp driver to the new panel driver model, and
>> report it as broken for now?
>
> (please cut your quotes a bit, you just included some thousands of lines
> of code there =).
Oops, sure, will try to remember.
>
> We could, but I'm not sure what would be the point. The new picodlp
> would be (more or less) totally new driver, so we would still end up
> removing the old driver. We can as well add it later if we manage to get
> it working.
Okay. Let's do that then.
Archit
^ permalink raw reply
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