aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorZhou Zhu <zzhu3@marvell.com>2013-02-21 19:42:11 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2013-02-21 20:22:17 -0500
commit59393bb94c103fca48c29348d2415cc67d772045 (patch)
treea9baad541380644bee104d48e714e4aae3e8c959 /drivers
parentc289ba2d26cf872570ba23fceee8d80ae64be351 (diff)
video: mmp display subsystem
Add mmp display subsystem to support Marvell MMP display controllers. This subsystem contains 4 parts: --fb folder --core.c --hw folder --panel folder 1. fb folder contains implementation of fb. fb get path and overlay from common interface and operates on these structures. 2. core.c provides common interface for a hardware abstraction. Major parts of this interface are: a) Path: path is a output device connected to a panel or HDMI TV. Main operations of the path is set/get timing/output color. fb operates output device through path structure. b) Ovly: Ovly is a buffer shown on the path. Ovly describes frame buffer and its source/destination size, offset, input color, buffer address, z-order, and so on. Each fb device maps to one overlay. 3. hw folder contains implementation of hardware operations defined by core.c. It registers paths for fb use. 4. panel folder contains implementation of panels. It's connected to path. Panel drivers would also regiester panels and linked to path when probe. Signed-off-by: Zhou Zhu <zzhu3@marvell.com> Signed-off-by: Lisa Du <cldu@marvell.com> Cc: Guoqing Li <ligq@marvell.com> Acked-by: Haojian Zhuang <haojian.zhuang@gmail.com> Cc: Florian Tobias Schandinat <FlorianSchandinat@gmx.de> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/video/Kconfig1
-rw-r--r--drivers/video/Makefile1
-rw-r--r--drivers/video/mmp/Kconfig5
-rw-r--r--drivers/video/mmp/Makefile1
-rw-r--r--drivers/video/mmp/core.c258
5 files changed, 266 insertions, 0 deletions
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index a913997c7b75..6c2c991af6fa 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -2431,6 +2431,7 @@ config FB_PUV3_UNIGFX
2431source "drivers/video/omap/Kconfig" 2431source "drivers/video/omap/Kconfig"
2432source "drivers/video/omap2/Kconfig" 2432source "drivers/video/omap2/Kconfig"
2433source "drivers/video/exynos/Kconfig" 2433source "drivers/video/exynos/Kconfig"
2434source "drivers/video/mmp/Kconfig"
2434source "drivers/video/backlight/Kconfig" 2435source "drivers/video/backlight/Kconfig"
2435 2436
2436if VT 2437if VT
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 3363f674237f..0577f834fdcd 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -106,6 +106,7 @@ obj-$(CONFIG_FB_ASILIANT) += asiliantfb.o
106obj-$(CONFIG_FB_PXA) += pxafb.o 106obj-$(CONFIG_FB_PXA) += pxafb.o
107obj-$(CONFIG_FB_PXA168) += pxa168fb.o 107obj-$(CONFIG_FB_PXA168) += pxa168fb.o
108obj-$(CONFIG_PXA3XX_GCU) += pxa3xx-gcu.o 108obj-$(CONFIG_PXA3XX_GCU) += pxa3xx-gcu.o
109obj-$(CONFIG_MMP_DISP) += mmp/
109obj-$(CONFIG_FB_W100) += w100fb.o 110obj-$(CONFIG_FB_W100) += w100fb.o
110obj-$(CONFIG_FB_TMIO) += tmiofb.o 111obj-$(CONFIG_FB_TMIO) += tmiofb.o
111obj-$(CONFIG_FB_AU1100) += au1100fb.o 112obj-$(CONFIG_FB_AU1100) += au1100fb.o
diff --git a/drivers/video/mmp/Kconfig b/drivers/video/mmp/Kconfig
new file mode 100644
index 000000000000..055433624526
--- /dev/null
+++ b/drivers/video/mmp/Kconfig
@@ -0,0 +1,5 @@
1menuconfig MMP_DISP
2 tristate "Marvell MMP Display Subsystem support"
3 depends on CPU_PXA910 || CPU_MMP2 || CPU_MMP3 || CPU_PXA988
4 help
5 Marvell Display Subsystem support.
diff --git a/drivers/video/mmp/Makefile b/drivers/video/mmp/Makefile
new file mode 100644
index 000000000000..820eb10ac2dd
--- /dev/null
+++ b/drivers/video/mmp/Makefile
@@ -0,0 +1 @@
obj-y += core.o
diff --git a/drivers/video/mmp/core.c b/drivers/video/mmp/core.c
new file mode 100644
index 000000000000..9ed83419038b
--- /dev/null
+++ b/drivers/video/mmp/core.c
@@ -0,0 +1,258 @@
1/*
2 * linux/drivers/video/mmp/common.c
3 * This driver is a common framework for Marvell Display Controller
4 *
5 * Copyright (C) 2012 Marvell Technology Group Ltd.
6 * Authors: Zhou Zhu <zzhu3@marvell.com>
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful, but WITHOUT
14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 * more details.
17 *
18 * You should have received a copy of the GNU General Public License along with
19 * this program. If not, see <http://www.gnu.org/licenses/>.
20 *
21 */
22
23#include <linux/slab.h>
24#include <linux/dma-mapping.h>
25#include <linux/export.h>
26#include <video/mmp_disp.h>
27
28static struct mmp_overlay *path_get_overlay(struct mmp_path *path,
29 int overlay_id)
30{
31 if (path && overlay_id < path->overlay_num)
32 return &path->overlays[overlay_id];
33 return 0;
34}
35
36static int path_check_status(struct mmp_path *path)
37{
38 int i;
39 for (i = 0; i < path->overlay_num; i++)
40 if (path->overlays[i].status)
41 return 1;
42
43 return 0;
44}
45
46/*
47 * Get modelist write pointer of modelist.
48 * It also returns modelist number
49 * this function fetches modelist from phy/panel:
50 * for HDMI/parallel or dsi to hdmi cases, get from phy
51 * or get from panel
52 */
53static int path_get_modelist(struct mmp_path *path,
54 struct mmp_mode **modelist)
55{
56 BUG_ON(!path || !modelist);
57
58 if (path->panel && path->panel->get_modelist)
59 return path->panel->get_modelist(path->panel, modelist);
60
61 return 0;
62}
63
64/*
65 * panel list is used to pair panel/path when path/panel registered
66 * path list is used for both buffer driver and platdriver
67 * plat driver do path register/unregister
68 * panel driver do panel register/unregister
69 * buffer driver get registered path
70 */
71static LIST_HEAD(panel_list);
72static LIST_HEAD(path_list);
73static DEFINE_MUTEX(disp_lock);
74
75/*
76 * mmp_register_panel - register panel to panel_list and connect to path
77 * @p: panel to be registered
78 *
79 * this function provides interface for panel drivers to register panel
80 * to panel_list and connect to path which matchs panel->plat_path_name.
81 * no error returns when no matching path is found as path register after
82 * panel register is permitted.
83 */
84void mmp_register_panel(struct mmp_panel *panel)
85{
86 struct mmp_path *path;
87
88 mutex_lock(&disp_lock);
89
90 /* add */
91 list_add_tail(&panel->node, &panel_list);
92
93 /* try to register to path */
94 list_for_each_entry(path, &path_list, node) {
95 if (!strcmp(panel->plat_path_name, path->name)) {
96 dev_info(panel->dev, "connect to path %s\n",
97 path->name);
98 path->panel = panel;
99 break;
100 }
101 }
102
103 mutex_unlock(&disp_lock);
104}
105EXPORT_SYMBOL_GPL(mmp_register_panel);
106
107/*
108 * mmp_unregister_panel - unregister panel from panel_list and disconnect
109 * @p: panel to be unregistered
110 *
111 * this function provides interface for panel drivers to unregister panel
112 * from panel_list and disconnect from path.
113 */
114void mmp_unregister_panel(struct mmp_panel *panel)
115{
116 struct mmp_path *path;
117
118 mutex_lock(&disp_lock);
119 list_del(&panel->node);
120
121 list_for_each_entry(path, &path_list, node) {
122 if (path->panel && path->panel == panel) {
123 dev_info(panel->dev, "disconnect from path %s\n",
124 path->name);
125 path->panel = NULL;
126 break;
127 }
128 }
129 mutex_unlock(&disp_lock);
130}
131EXPORT_SYMBOL_GPL(mmp_unregister_panel);
132
133/*
134 * mmp_get_path - get path by name
135 * @p: path name
136 *
137 * this function checks path name in path_list and return matching path
138 * return NULL if no matching path
139 */
140struct mmp_path *mmp_get_path(const char *name)
141{
142 struct mmp_path *path;
143 int found = 0;
144
145 mutex_lock(&disp_lock);
146 list_for_each_entry(path, &path_list, node) {
147 if (!strcmp(name, path->name)) {
148 found = 1;
149 break;
150 }
151 }
152 mutex_unlock(&disp_lock);
153
154 return found ? path : NULL;
155}
156EXPORT_SYMBOL_GPL(mmp_get_path);
157
158/*
159 * mmp_register_path - init and register path by path_info
160 * @p: path info provided by display controller
161 *
162 * this function init by path info and register path to path_list
163 * this function also try to connect path with panel by name
164 */
165struct mmp_path *mmp_register_path(struct mmp_path_info *info)
166{
167 int i;
168 size_t size;
169 struct mmp_path *path = NULL;
170 struct mmp_panel *panel;
171
172 size = sizeof(struct mmp_path)
173 + sizeof(struct mmp_overlay) * info->overlay_num;
174 path = kzalloc(size, GFP_KERNEL);
175 if (!path)
176 goto failed;
177
178 /* path set */
179 mutex_init(&path->access_ok);
180 path->dev = info->dev;
181 path->id = info->id;
182 path->name = info->name;
183 path->output_type = info->output_type;
184 path->overlay_num = info->overlay_num;
185 path->plat_data = info->plat_data;
186 path->ops.set_mode = info->set_mode;
187
188 mutex_lock(&disp_lock);
189 /* get panel */
190 list_for_each_entry(panel, &panel_list, node) {
191 if (!strcmp(info->name, panel->plat_path_name)) {
192 dev_info(path->dev, "get panel %s\n", panel->name);
193 path->panel = panel;
194 break;
195 }
196 }
197
198 dev_info(path->dev, "register %s, overlay_num %d\n",
199 path->name, path->overlay_num);
200
201 /* default op set: if already set by driver, never cover it */
202 if (!path->ops.check_status)
203 path->ops.check_status = path_check_status;
204 if (!path->ops.get_overlay)
205 path->ops.get_overlay = path_get_overlay;
206 if (!path->ops.get_modelist)
207 path->ops.get_modelist = path_get_modelist;
208
209 /* step3: init overlays */
210 for (i = 0; i < path->overlay_num; i++) {
211 path->overlays[i].path = path;
212 path->overlays[i].id = i;
213 mutex_init(&path->overlays[i].access_ok);
214 path->overlays[i].ops = info->overlay_ops;
215 }
216
217 /* add to pathlist */
218 list_add_tail(&path->node, &path_list);
219
220 mutex_unlock(&disp_lock);
221 return path;
222
223failed:
224 kfree(path);
225 mutex_unlock(&disp_lock);
226 return NULL;
227}
228EXPORT_SYMBOL_GPL(mmp_register_path);
229
230/*
231 * mmp_unregister_path - unregister and destory path
232 * @p: path to be destoried.
233 *
234 * this function registers path and destorys it.
235 */
236void mmp_unregister_path(struct mmp_path *path)
237{
238 int i;
239
240 if (!path)
241 return;
242
243 mutex_lock(&disp_lock);
244 /* del from pathlist */
245 list_del(&path->node);
246
247 /* deinit overlays */
248 for (i = 0; i < path->overlay_num; i++)
249 mutex_destroy(&path->overlays[i].access_ok);
250
251 mutex_destroy(&path->access_ok);
252
253 kfree(path);
254 mutex_unlock(&disp_lock);
255
256 dev_info(path->dev, "de-register %s\n", path->name);
257}
258EXPORT_SYMBOL_GPL(mmp_unregister_path);