]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - drivers/video/mxc/mxc_dispdrv.c
KARO: cleanup after merge of Freescale 3.10.17 stuff
[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         /* Note: drv always the first element */
49         struct mxc_dispdrv_driver *drv;
50         bool active;
51         void *priv;
52         struct list_head list;
53 };
54
55 struct mxc_dispdrv_handle *mxc_dispdrv_register(struct mxc_dispdrv_driver *drv)
56 {
57         struct mxc_dispdrv_entry *new;
58
59         mutex_lock(&dispdrv_lock);
60
61         new = kzalloc(sizeof(struct mxc_dispdrv_entry), GFP_KERNEL);
62         if (!new) {
63                 mutex_unlock(&dispdrv_lock);
64                 return ERR_PTR(-ENOMEM);
65         }
66
67         new->drv = drv;
68         list_add_tail(&new->list, &dispdrv_list);
69
70         mutex_unlock(&dispdrv_lock);
71
72         return (struct mxc_dispdrv_handle *)new;
73 }
74 EXPORT_SYMBOL_GPL(mxc_dispdrv_register);
75
76 int mxc_dispdrv_unregister(struct mxc_dispdrv_handle *handle)
77 {
78         struct mxc_dispdrv_entry *entry = (struct mxc_dispdrv_entry *)handle;
79
80         if (entry) {
81                 mutex_lock(&dispdrv_lock);
82                 list_del(&entry->list);
83                 mutex_unlock(&dispdrv_lock);
84                 kfree(entry);
85                 return 0;
86         } else
87                 return -EINVAL;
88 }
89 EXPORT_SYMBOL_GPL(mxc_dispdrv_unregister);
90
91 struct mxc_dispdrv_handle *mxc_dispdrv_gethandle(char *name,
92         struct mxc_dispdrv_setting *setting)
93 {
94         int ret, found = 0;
95         struct mxc_dispdrv_entry *entry;
96
97         mutex_lock(&dispdrv_lock);
98         list_for_each_entry(entry, &dispdrv_list, list) {
99                 if (!strcmp(entry->drv->name, name) && (entry->drv->init)) {
100                         ret = entry->drv->init((struct mxc_dispdrv_handle *)
101                                 entry, setting);
102                         if (ret >= 0) {
103                                 entry->active = true;
104                                 found = 1;
105                                 break;
106                         }
107                 }
108         }
109         mutex_unlock(&dispdrv_lock);
110
111         return found ? (struct mxc_dispdrv_handle *)entry:ERR_PTR(-ENODEV);
112 }
113 EXPORT_SYMBOL_GPL(mxc_dispdrv_gethandle);
114
115 void mxc_dispdrv_puthandle(struct mxc_dispdrv_handle *handle)
116 {
117         struct mxc_dispdrv_entry *entry = (struct mxc_dispdrv_entry *)handle;
118
119         mutex_lock(&dispdrv_lock);
120         if (entry && entry->active && entry->drv->deinit) {
121                 entry->drv->deinit(handle);
122                 entry->active = false;
123         }
124         mutex_unlock(&dispdrv_lock);
125
126 }
127 EXPORT_SYMBOL_GPL(mxc_dispdrv_puthandle);
128
129 int mxc_dispdrv_setdata(struct mxc_dispdrv_handle *handle, void *data)
130 {
131         struct mxc_dispdrv_entry *entry = (struct mxc_dispdrv_entry *)handle;
132
133         if (entry) {
134                 entry->priv = data;
135                 return 0;
136         } else
137                 return -EINVAL;
138 }
139 EXPORT_SYMBOL_GPL(mxc_dispdrv_setdata);
140
141 void *mxc_dispdrv_getdata(struct mxc_dispdrv_handle *handle)
142 {
143         struct mxc_dispdrv_entry *entry = (struct mxc_dispdrv_entry *)handle;
144
145         if (entry) {
146                 return entry->priv;
147         } else
148                 return ERR_PTR(-EINVAL);
149 }
150 EXPORT_SYMBOL_GPL(mxc_dispdrv_getdata);