]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - drivers/video/mxc/mxc_dispdrv.c
video: mxc: use proper data structures to eliminate type casts
[karo-tx-linux.git] / drivers / video / mxc / mxc_dispdrv.c
1 /*
2  * Copyright (C) 2011-2013 Freescale Semiconductor, Inc. All Rights Reserved.
3  */
4
5 /*
6  * The code contained herein is licensed under the GNU General Public
7  * License. You may obtain a copy of the GNU General Public License
8  * Version 2 or later at the following locations:
9  *
10  * http://www.opensource.org/licenses/gpl-license.html
11  * http://www.gnu.org/copyleft/gpl.html
12  */
13
14 /*!
15  * @file mxc_dispdrv.c
16  * @brief mxc display driver framework.
17  *
18  * A display device driver could call mxc_dispdrv_register(drv) in its dev_probe() function.
19  * Move all dev_probe() things into mxc_dispdrv_driver->init(), init() function should init
20  * and feedback setting;
21  * Necessary deferred operations can be done in mxc_dispdrv_driver->post_init(),
22  * after dev_id and disp_id pass usage check;
23  * Move all dev_remove() things into mxc_dispdrv_driver->deinit();
24  * Move all dev_suspend() things into fb_notifier for SUSPEND, if there is;
25  * Move all dev_resume() things into fb_notifier for RESUME, if there is;
26  *
27  * ipuv3 fb driver could call mxc_dispdrv_gethandle(name, setting) before a fb
28  * need be added, with fbi param passing by setting, after
29  * mxc_dispdrv_gethandle() return, FB driver should get the basic setting
30  * about fbi info and ipuv3-hw (ipu_id and disp_id).
31  *
32  * @ingroup Framebuffer
33  */
34
35 #include <linux/kernel.h>
36 #include <linux/module.h>
37 #include <linux/list.h>
38 #include <linux/mutex.h>
39 #include <linux/slab.h>
40 #include <linux/err.h>
41 #include <linux/string.h>
42 #include "mxc_dispdrv.h"
43
44 static LIST_HEAD(dispdrv_list);
45 static DEFINE_MUTEX(dispdrv_lock);
46
47 struct mxc_dispdrv_entry {
48         struct mxc_dispdrv_handle handle;
49         bool active;
50         void *priv;
51         struct list_head list;
52 };
53
54 struct mxc_dispdrv_handle *mxc_dispdrv_register(struct mxc_dispdrv_driver *drv)
55 {
56         struct mxc_dispdrv_entry *new;
57
58         mutex_lock(&dispdrv_lock);
59
60         new = kzalloc(sizeof(struct mxc_dispdrv_entry), GFP_KERNEL);
61         if (!new) {
62                 mutex_unlock(&dispdrv_lock);
63                 return ERR_PTR(-ENOMEM);
64         }
65
66         new->handle.drv = drv;
67         list_add_tail(&new->list, &dispdrv_list);
68
69         mutex_unlock(&dispdrv_lock);
70
71         return &new->handle;
72 }
73 EXPORT_SYMBOL_GPL(mxc_dispdrv_register);
74
75 static inline struct mxc_dispdrv_entry *to_dispdrv_entry(
76         struct mxc_dispdrv_handle *handle)
77 {
78         return container_of(handle, struct mxc_dispdrv_entry, handle);
79 }
80
81 int mxc_dispdrv_unregister(struct mxc_dispdrv_handle *handle)
82 {
83         struct mxc_dispdrv_entry *entry = to_dispdrv_entry(handle);
84
85         if (entry) {
86                 mutex_lock(&dispdrv_lock);
87                 list_del(&entry->list);
88                 mutex_unlock(&dispdrv_lock);
89                 kfree(entry);
90                 return 0;
91         } else
92                 return -EINVAL;
93 }
94 EXPORT_SYMBOL_GPL(mxc_dispdrv_unregister);
95
96 struct mxc_dispdrv_handle *mxc_dispdrv_gethandle(char *name,
97         struct mxc_dispdrv_setting *setting)
98 {
99         int ret;
100         struct mxc_dispdrv_entry *entry;
101         struct mxc_dispdrv_handle *handle = ERR_PTR(-ENODEV);
102
103         mutex_lock(&dispdrv_lock);
104         list_for_each_entry(entry, &dispdrv_list, list) {
105                 struct mxc_dispdrv_handle *h = &entry->handle;
106
107                 if (strcmp(h->drv->name, name) == 0 &&
108                         h->drv->init) {
109                         ret = h->drv->init(h, setting);
110                         if (ret >= 0) {
111                                 entry->active = true;
112                                 handle = h;
113                                 break;
114                         }
115                 }
116         }
117         mutex_unlock(&dispdrv_lock);
118
119         return handle;
120 }
121 EXPORT_SYMBOL_GPL(mxc_dispdrv_gethandle);
122
123 void mxc_dispdrv_puthandle(struct mxc_dispdrv_handle *handle)
124 {
125         struct mxc_dispdrv_entry *entry = to_dispdrv_entry(handle);
126
127         mutex_lock(&dispdrv_lock);
128         if (entry && entry->active && handle->drv->deinit) {
129                 handle->drv->deinit(handle);
130                 entry->active = false;
131         }
132         mutex_unlock(&dispdrv_lock);
133
134 }
135 EXPORT_SYMBOL_GPL(mxc_dispdrv_puthandle);
136
137 int mxc_dispdrv_setdata(struct mxc_dispdrv_handle *handle, void *data)
138 {
139         struct mxc_dispdrv_entry *entry = to_dispdrv_entry(handle);
140
141         if (entry) {
142                 entry->priv = data;
143                 return 0;
144         } else
145                 return -EINVAL;
146 }
147 EXPORT_SYMBOL_GPL(mxc_dispdrv_setdata);
148
149 void *mxc_dispdrv_getdata(struct mxc_dispdrv_handle *handle)
150 {
151         struct mxc_dispdrv_entry *entry = to_dispdrv_entry(handle);
152
153         if (entry) {
154                 return entry->priv;
155         } else
156                 return ERR_PTR(-EINVAL);
157 }
158 EXPORT_SYMBOL_GPL(mxc_dispdrv_getdata);