2 * linux/drivers/video/omap2/dss/display.c
4 * Copyright (C) 2009 Nokia Corporation
5 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
7 * Some code and ideas taken from drivers/video/omap/ driver
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License version 2 as published by
12 * the Free Software Foundation.
14 * This program is distributed in the hope that it will be useful, but WITHOUT
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
19 * You should have received a copy of the GNU General Public License along with
20 * this program. If not, see <http://www.gnu.org/licenses/>.
23 #define DSS_SUBSYS_NAME "DISPLAY"
25 #include <linux/kernel.h>
26 #include <linux/module.h>
27 #include <linux/jiffies.h>
28 #include <linux/platform_device.h>
30 #include <video/omapdss.h>
32 #include "dss_features.h"
34 void omapdss_default_get_resolution(struct omap_dss_device
*dssdev
,
37 *xres
= dssdev
->panel
.timings
.x_res
;
38 *yres
= dssdev
->panel
.timings
.y_res
;
40 EXPORT_SYMBOL(omapdss_default_get_resolution
);
42 int omapdss_default_get_recommended_bpp(struct omap_dss_device
*dssdev
)
44 switch (dssdev
->type
) {
45 case OMAP_DISPLAY_TYPE_DPI
:
46 if (dssdev
->phy
.dpi
.data_lines
== 24)
51 case OMAP_DISPLAY_TYPE_DBI
:
52 if (dssdev
->ctrl
.pixel_size
== 24)
56 case OMAP_DISPLAY_TYPE_DSI
:
57 if (dsi_get_pixel_size(dssdev
->panel
.dsi_pix_fmt
) > 16)
61 case OMAP_DISPLAY_TYPE_VENC
:
62 case OMAP_DISPLAY_TYPE_SDI
:
63 case OMAP_DISPLAY_TYPE_HDMI
:
64 case OMAP_DISPLAY_TYPE_DVI
:
71 EXPORT_SYMBOL(omapdss_default_get_recommended_bpp
);
73 void omapdss_default_get_timings(struct omap_dss_device
*dssdev
,
74 struct omap_video_timings
*timings
)
76 *timings
= dssdev
->panel
.timings
;
78 EXPORT_SYMBOL(omapdss_default_get_timings
);
80 int dss_suspend_all_devices(void)
82 struct omap_dss_device
*dssdev
= NULL
;
84 for_each_dss_dev(dssdev
) {
88 if (dssdev
->state
== OMAP_DSS_DISPLAY_ACTIVE
) {
89 dssdev
->driver
->disable(dssdev
);
90 dssdev
->activate_after_resume
= true;
92 dssdev
->activate_after_resume
= false;
99 int dss_resume_all_devices(void)
101 struct omap_dss_device
*dssdev
= NULL
;
103 for_each_dss_dev(dssdev
) {
107 if (dssdev
->activate_after_resume
) {
108 dssdev
->driver
->enable(dssdev
);
109 dssdev
->activate_after_resume
= false;
116 void dss_disable_all_devices(void)
118 struct omap_dss_device
*dssdev
= NULL
;
120 for_each_dss_dev(dssdev
) {
124 if (dssdev
->state
== OMAP_DSS_DISPLAY_ACTIVE
)
125 dssdev
->driver
->disable(dssdev
);
129 static LIST_HEAD(panel_list
);
130 static DEFINE_MUTEX(panel_list_mutex
);
131 static int disp_num_counter
;
133 int omapdss_register_display(struct omap_dss_device
*dssdev
)
135 struct omap_dss_driver
*drv
= dssdev
->driver
;
137 snprintf(dssdev
->alias
, sizeof(dssdev
->alias
),
138 "display%d", disp_num_counter
++);
140 if (drv
&& drv
->get_resolution
== NULL
)
141 drv
->get_resolution
= omapdss_default_get_resolution
;
142 if (drv
&& drv
->get_recommended_bpp
== NULL
)
143 drv
->get_recommended_bpp
= omapdss_default_get_recommended_bpp
;
144 if (drv
&& drv
->get_timings
== NULL
)
145 drv
->get_timings
= omapdss_default_get_timings
;
147 mutex_lock(&panel_list_mutex
);
148 list_add_tail(&dssdev
->panel_list
, &panel_list
);
149 mutex_unlock(&panel_list_mutex
);
152 EXPORT_SYMBOL(omapdss_register_display
);
154 void omapdss_unregister_display(struct omap_dss_device
*dssdev
)
156 mutex_lock(&panel_list_mutex
);
157 list_del(&dssdev
->panel_list
);
158 mutex_unlock(&panel_list_mutex
);
160 EXPORT_SYMBOL(omapdss_unregister_display
);
162 struct omap_dss_device
*omap_dss_get_device(struct omap_dss_device
*dssdev
)
164 if (!try_module_get(dssdev
->owner
))
167 if (get_device(dssdev
->dev
) == NULL
) {
168 module_put(dssdev
->owner
);
174 EXPORT_SYMBOL(omap_dss_get_device
);
176 void omap_dss_put_device(struct omap_dss_device
*dssdev
)
178 put_device(dssdev
->dev
);
179 module_put(dssdev
->owner
);
181 EXPORT_SYMBOL(omap_dss_put_device
);
184 * ref count of the found device is incremented.
185 * ref count of from-device is decremented.
187 struct omap_dss_device
*omap_dss_get_next_device(struct omap_dss_device
*from
)
190 struct omap_dss_device
*dssdev
;
192 mutex_lock(&panel_list_mutex
);
194 if (list_empty(&panel_list
)) {
200 dssdev
= list_first_entry(&panel_list
, struct omap_dss_device
,
202 omap_dss_get_device(dssdev
);
206 omap_dss_put_device(from
);
208 list_for_each(l
, &panel_list
) {
209 dssdev
= list_entry(l
, struct omap_dss_device
, panel_list
);
210 if (dssdev
== from
) {
211 if (list_is_last(l
, &panel_list
)) {
216 dssdev
= list_entry(l
->next
, struct omap_dss_device
,
218 omap_dss_get_device(dssdev
);
223 WARN(1, "'from' dssdev not found\n");
227 mutex_unlock(&panel_list_mutex
);
230 EXPORT_SYMBOL(omap_dss_get_next_device
);
232 struct omap_dss_device
*omap_dss_find_device(void *data
,
233 int (*match
)(struct omap_dss_device
*dssdev
, void *data
))
235 struct omap_dss_device
*dssdev
= NULL
;
237 while ((dssdev
= omap_dss_get_next_device(dssdev
)) != NULL
) {
238 if (match(dssdev
, data
))
244 EXPORT_SYMBOL(omap_dss_find_device
);
246 void videomode_to_omap_video_timings(const struct videomode
*vm
,
247 struct omap_video_timings
*ovt
)
249 memset(ovt
, 0, sizeof(*ovt
));
251 ovt
->pixel_clock
= vm
->pixelclock
/ 1000;
252 ovt
->x_res
= vm
->hactive
;
253 ovt
->hbp
= vm
->hback_porch
;
254 ovt
->hfp
= vm
->hfront_porch
;
255 ovt
->hsw
= vm
->hsync_len
;
256 ovt
->y_res
= vm
->vactive
;
257 ovt
->vbp
= vm
->vback_porch
;
258 ovt
->vfp
= vm
->vfront_porch
;
259 ovt
->vsw
= vm
->vsync_len
;
261 ovt
->vsync_level
= vm
->flags
& DISPLAY_FLAGS_VSYNC_HIGH
?
262 OMAPDSS_SIG_ACTIVE_HIGH
:
263 OMAPDSS_SIG_ACTIVE_LOW
;
264 ovt
->hsync_level
= vm
->flags
& DISPLAY_FLAGS_HSYNC_HIGH
?
265 OMAPDSS_SIG_ACTIVE_HIGH
:
266 OMAPDSS_SIG_ACTIVE_LOW
;
267 ovt
->de_level
= vm
->flags
& DISPLAY_FLAGS_DE_HIGH
?
268 OMAPDSS_SIG_ACTIVE_HIGH
:
269 OMAPDSS_SIG_ACTIVE_HIGH
;
270 ovt
->data_pclk_edge
= vm
->flags
& DISPLAY_FLAGS_PIXDATA_POSEDGE
?
271 OMAPDSS_DRIVE_SIG_RISING_EDGE
:
272 OMAPDSS_DRIVE_SIG_FALLING_EDGE
;
274 ovt
->sync_pclk_edge
= OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES
;
276 EXPORT_SYMBOL(videomode_to_omap_video_timings
);
278 void omap_video_timings_to_videomode(const struct omap_video_timings
*ovt
,
279 struct videomode
*vm
)
281 memset(vm
, 0, sizeof(*vm
));
283 vm
->pixelclock
= ovt
->pixel_clock
* 1000;
285 vm
->hactive
= ovt
->x_res
;
286 vm
->hback_porch
= ovt
->hbp
;
287 vm
->hfront_porch
= ovt
->hfp
;
288 vm
->hsync_len
= ovt
->hsw
;
289 vm
->vactive
= ovt
->y_res
;
290 vm
->vback_porch
= ovt
->vbp
;
291 vm
->vfront_porch
= ovt
->vfp
;
292 vm
->vsync_len
= ovt
->vsw
;
294 if (ovt
->hsync_level
== OMAPDSS_SIG_ACTIVE_HIGH
)
295 vm
->flags
|= DISPLAY_FLAGS_HSYNC_HIGH
;
297 vm
->flags
|= DISPLAY_FLAGS_HSYNC_LOW
;
299 if (ovt
->vsync_level
== OMAPDSS_SIG_ACTIVE_HIGH
)
300 vm
->flags
|= DISPLAY_FLAGS_VSYNC_HIGH
;
302 vm
->flags
|= DISPLAY_FLAGS_VSYNC_LOW
;
304 if (ovt
->de_level
== OMAPDSS_SIG_ACTIVE_HIGH
)
305 vm
->flags
|= DISPLAY_FLAGS_DE_HIGH
;
307 vm
->flags
|= DISPLAY_FLAGS_DE_LOW
;
309 if (ovt
->data_pclk_edge
== OMAPDSS_DRIVE_SIG_RISING_EDGE
)
310 vm
->flags
|= DISPLAY_FLAGS_PIXDATA_POSEDGE
;
312 vm
->flags
|= DISPLAY_FLAGS_PIXDATA_NEGEDGE
;
314 EXPORT_SYMBOL(omap_video_timings_to_videomode
);