2 * Copyright (C) 2011-2013 Freescale Semiconductor, Inc. All Rights Reserved.
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:
10 * http://www.opensource.org/licenses/gpl-license.html
11 * http://www.gnu.org/copyleft/gpl.html
16 * @brief mxc display driver framework.
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;
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).
32 * @ingroup Framebuffer
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"
44 static LIST_HEAD(dispdrv_list);
45 static DEFINE_MUTEX(dispdrv_lock);
47 struct mxc_dispdrv_entry {
48 struct mxc_dispdrv_handle handle;
51 struct list_head list;
54 struct mxc_dispdrv_handle *mxc_dispdrv_register(struct mxc_dispdrv_driver *drv)
56 struct mxc_dispdrv_entry *new;
58 mutex_lock(&dispdrv_lock);
60 new = kzalloc(sizeof(struct mxc_dispdrv_entry), GFP_KERNEL);
62 mutex_unlock(&dispdrv_lock);
63 return ERR_PTR(-ENOMEM);
66 new->handle.drv = drv;
67 list_add_tail(&new->list, &dispdrv_list);
69 mutex_unlock(&dispdrv_lock);
73 EXPORT_SYMBOL_GPL(mxc_dispdrv_register);
75 static inline struct mxc_dispdrv_entry *to_dispdrv_entry(
76 struct mxc_dispdrv_handle *handle)
78 return container_of(handle, struct mxc_dispdrv_entry, handle);
81 int mxc_dispdrv_unregister(struct mxc_dispdrv_handle *handle)
83 struct mxc_dispdrv_entry *entry = to_dispdrv_entry(handle);
86 mutex_lock(&dispdrv_lock);
87 list_del(&entry->list);
88 mutex_unlock(&dispdrv_lock);
94 EXPORT_SYMBOL_GPL(mxc_dispdrv_unregister);
96 struct mxc_dispdrv_handle *mxc_dispdrv_gethandle(char *name,
97 struct mxc_dispdrv_setting *setting)
100 struct mxc_dispdrv_entry *entry;
101 struct mxc_dispdrv_handle *handle = ERR_PTR(-ENODEV);
103 mutex_lock(&dispdrv_lock);
104 list_for_each_entry(entry, &dispdrv_list, list) {
105 struct mxc_dispdrv_handle *h = &entry->handle;
107 if (strcmp(h->drv->name, name) == 0 &&
109 ret = h->drv->init(h, setting);
111 entry->active = true;
117 mutex_unlock(&dispdrv_lock);
121 EXPORT_SYMBOL_GPL(mxc_dispdrv_gethandle);
123 void mxc_dispdrv_puthandle(struct mxc_dispdrv_handle *handle)
125 struct mxc_dispdrv_entry *entry = to_dispdrv_entry(handle);
127 mutex_lock(&dispdrv_lock);
128 if (entry && entry->active && handle->drv->deinit) {
129 handle->drv->deinit(handle);
130 entry->active = false;
132 mutex_unlock(&dispdrv_lock);
135 EXPORT_SYMBOL_GPL(mxc_dispdrv_puthandle);
137 int mxc_dispdrv_setdata(struct mxc_dispdrv_handle *handle, void *data)
139 struct mxc_dispdrv_entry *entry = to_dispdrv_entry(handle);
147 EXPORT_SYMBOL_GPL(mxc_dispdrv_setdata);
149 void *mxc_dispdrv_getdata(struct mxc_dispdrv_handle *handle)
151 struct mxc_dispdrv_entry *entry = to_dispdrv_entry(handle);
156 return ERR_PTR(-EINVAL);
158 EXPORT_SYMBOL_GPL(mxc_dispdrv_getdata);