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 /* Note: drv always the first element */
49 struct mxc_dispdrv_driver *drv;
52 struct list_head list;
55 struct mxc_dispdrv_handle *mxc_dispdrv_register(struct mxc_dispdrv_driver *drv)
57 struct mxc_dispdrv_entry *new;
59 mutex_lock(&dispdrv_lock);
61 new = kzalloc(sizeof(struct mxc_dispdrv_entry), GFP_KERNEL);
63 mutex_unlock(&dispdrv_lock);
64 return ERR_PTR(-ENOMEM);
68 list_add_tail(&new->list, &dispdrv_list);
70 mutex_unlock(&dispdrv_lock);
72 return (struct mxc_dispdrv_handle *)new;
74 EXPORT_SYMBOL_GPL(mxc_dispdrv_register);
76 int mxc_dispdrv_unregister(struct mxc_dispdrv_handle *handle)
78 struct mxc_dispdrv_entry *entry = (struct mxc_dispdrv_entry *)handle;
81 mutex_lock(&dispdrv_lock);
82 list_del(&entry->list);
83 mutex_unlock(&dispdrv_lock);
89 EXPORT_SYMBOL_GPL(mxc_dispdrv_unregister);
91 struct mxc_dispdrv_handle *mxc_dispdrv_gethandle(char *name,
92 struct mxc_dispdrv_setting *setting)
95 struct mxc_dispdrv_entry *entry;
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 *)
103 entry->active = true;
109 mutex_unlock(&dispdrv_lock);
111 return found ? (struct mxc_dispdrv_handle *)entry:ERR_PTR(-ENODEV);
113 EXPORT_SYMBOL_GPL(mxc_dispdrv_gethandle);
115 void mxc_dispdrv_puthandle(struct mxc_dispdrv_handle *handle)
117 struct mxc_dispdrv_entry *entry = (struct mxc_dispdrv_entry *)handle;
119 mutex_lock(&dispdrv_lock);
120 if (entry && entry->active && entry->drv->deinit) {
121 entry->drv->deinit(handle);
122 entry->active = false;
124 mutex_unlock(&dispdrv_lock);
127 EXPORT_SYMBOL_GPL(mxc_dispdrv_puthandle);
129 int mxc_dispdrv_setdata(struct mxc_dispdrv_handle *handle, void *data)
131 struct mxc_dispdrv_entry *entry = (struct mxc_dispdrv_entry *)handle;
139 EXPORT_SYMBOL_GPL(mxc_dispdrv_setdata);
141 void *mxc_dispdrv_getdata(struct mxc_dispdrv_handle *handle)
143 struct mxc_dispdrv_entry *entry = (struct mxc_dispdrv_entry *)handle;
148 return ERR_PTR(-EINVAL);
150 EXPORT_SYMBOL_GPL(mxc_dispdrv_getdata);