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>
31 #include <video/omapfb_dss.h>
33 #include "dss_features.h"
35 void omapdss_default_get_resolution(struct omap_dss_device
*dssdev
,
38 *xres
= dssdev
->panel
.timings
.x_res
;
39 *yres
= dssdev
->panel
.timings
.y_res
;
41 EXPORT_SYMBOL(omapdss_default_get_resolution
);
43 int omapdss_default_get_recommended_bpp(struct omap_dss_device
*dssdev
)
45 switch (dssdev
->type
) {
46 case OMAP_DISPLAY_TYPE_DPI
:
47 if (dssdev
->phy
.dpi
.data_lines
== 24)
52 case OMAP_DISPLAY_TYPE_DBI
:
53 if (dssdev
->ctrl
.pixel_size
== 24)
57 case OMAP_DISPLAY_TYPE_DSI
:
58 if (dsi_get_pixel_size(dssdev
->panel
.dsi_pix_fmt
) > 16)
62 case OMAP_DISPLAY_TYPE_VENC
:
63 case OMAP_DISPLAY_TYPE_SDI
:
64 case OMAP_DISPLAY_TYPE_HDMI
:
65 case OMAP_DISPLAY_TYPE_DVI
:
72 EXPORT_SYMBOL(omapdss_default_get_recommended_bpp
);
74 void omapdss_default_get_timings(struct omap_dss_device
*dssdev
,
75 struct omap_video_timings
*timings
)
77 *timings
= dssdev
->panel
.timings
;
79 EXPORT_SYMBOL(omapdss_default_get_timings
);
81 int dss_suspend_all_devices(void)
83 struct omap_dss_device
*dssdev
= NULL
;
85 for_each_dss_dev(dssdev
) {
89 if (dssdev
->state
== OMAP_DSS_DISPLAY_ACTIVE
) {
90 dssdev
->driver
->disable(dssdev
);
91 dssdev
->activate_after_resume
= true;
93 dssdev
->activate_after_resume
= false;
100 int dss_resume_all_devices(void)
102 struct omap_dss_device
*dssdev
= NULL
;
104 for_each_dss_dev(dssdev
) {
108 if (dssdev
->activate_after_resume
) {
109 dssdev
->driver
->enable(dssdev
);
110 dssdev
->activate_after_resume
= false;
117 void dss_disable_all_devices(void)
119 struct omap_dss_device
*dssdev
= NULL
;
121 for_each_dss_dev(dssdev
) {
125 if (dssdev
->state
== OMAP_DSS_DISPLAY_ACTIVE
)
126 dssdev
->driver
->disable(dssdev
);
130 static LIST_HEAD(panel_list
);
131 static DEFINE_MUTEX(panel_list_mutex
);
132 static int disp_num_counter
;
134 int omapdss_register_display(struct omap_dss_device
*dssdev
)
136 struct omap_dss_driver
*drv
= dssdev
->driver
;
140 * Note: this presumes all the displays are either using DT or non-DT,
141 * which normally should be the case. This also presumes that all
142 * displays either have an DT alias, or none has.
145 if (dssdev
->dev
->of_node
) {
146 id
= of_alias_get_id(dssdev
->dev
->of_node
, "display");
149 id
= disp_num_counter
++;
151 id
= disp_num_counter
++;
154 snprintf(dssdev
->alias
, sizeof(dssdev
->alias
), "display%d", id
);
156 /* Use 'label' property for name, if it exists */
157 if (dssdev
->dev
->of_node
)
158 of_property_read_string(dssdev
->dev
->of_node
, "label",
161 if (dssdev
->name
== NULL
)
162 dssdev
->name
= dssdev
->alias
;
164 if (drv
&& drv
->get_resolution
== NULL
)
165 drv
->get_resolution
= omapdss_default_get_resolution
;
166 if (drv
&& drv
->get_recommended_bpp
== NULL
)
167 drv
->get_recommended_bpp
= omapdss_default_get_recommended_bpp
;
168 if (drv
&& drv
->get_timings
== NULL
)
169 drv
->get_timings
= omapdss_default_get_timings
;
171 mutex_lock(&panel_list_mutex
);
172 list_add_tail(&dssdev
->panel_list
, &panel_list
);
173 mutex_unlock(&panel_list_mutex
);
176 EXPORT_SYMBOL(omapdss_register_display
);
178 void omapdss_unregister_display(struct omap_dss_device
*dssdev
)
180 mutex_lock(&panel_list_mutex
);
181 list_del(&dssdev
->panel_list
);
182 mutex_unlock(&panel_list_mutex
);
184 EXPORT_SYMBOL(omapdss_unregister_display
);
186 struct omap_dss_device
*omap_dss_get_device(struct omap_dss_device
*dssdev
)
188 if (!try_module_get(dssdev
->owner
))
191 if (get_device(dssdev
->dev
) == NULL
) {
192 module_put(dssdev
->owner
);
198 EXPORT_SYMBOL(omap_dss_get_device
);
200 void omap_dss_put_device(struct omap_dss_device
*dssdev
)
202 put_device(dssdev
->dev
);
203 module_put(dssdev
->owner
);
205 EXPORT_SYMBOL(omap_dss_put_device
);
208 * ref count of the found device is incremented.
209 * ref count of from-device is decremented.
211 struct omap_dss_device
*omap_dss_get_next_device(struct omap_dss_device
*from
)
214 struct omap_dss_device
*dssdev
;
216 mutex_lock(&panel_list_mutex
);
218 if (list_empty(&panel_list
)) {
224 dssdev
= list_first_entry(&panel_list
, struct omap_dss_device
,
226 omap_dss_get_device(dssdev
);
230 omap_dss_put_device(from
);
232 list_for_each(l
, &panel_list
) {
233 dssdev
= list_entry(l
, struct omap_dss_device
, panel_list
);
234 if (dssdev
== from
) {
235 if (list_is_last(l
, &panel_list
)) {
240 dssdev
= list_entry(l
->next
, struct omap_dss_device
,
242 omap_dss_get_device(dssdev
);
247 WARN(1, "'from' dssdev not found\n");
251 mutex_unlock(&panel_list_mutex
);
254 EXPORT_SYMBOL(omap_dss_get_next_device
);
256 struct omap_dss_device
*omap_dss_find_device(void *data
,
257 int (*match
)(struct omap_dss_device
*dssdev
, void *data
))
259 struct omap_dss_device
*dssdev
= NULL
;
261 while ((dssdev
= omap_dss_get_next_device(dssdev
)) != NULL
) {
262 if (match(dssdev
, data
))
268 EXPORT_SYMBOL(omap_dss_find_device
);
270 void videomode_to_omap_video_timings(const struct videomode
*vm
,
271 struct omap_video_timings
*ovt
)
273 memset(ovt
, 0, sizeof(*ovt
));
275 ovt
->pixelclock
= vm
->pixelclock
;
276 ovt
->x_res
= vm
->hactive
;
277 ovt
->hbp
= vm
->hback_porch
;
278 ovt
->hfp
= vm
->hfront_porch
;
279 ovt
->hsw
= vm
->hsync_len
;
280 ovt
->y_res
= vm
->vactive
;
281 ovt
->vbp
= vm
->vback_porch
;
282 ovt
->vfp
= vm
->vfront_porch
;
283 ovt
->vsw
= vm
->vsync_len
;
285 ovt
->vsync_level
= vm
->flags
& DISPLAY_FLAGS_VSYNC_HIGH
?
286 OMAPDSS_SIG_ACTIVE_HIGH
:
287 OMAPDSS_SIG_ACTIVE_LOW
;
288 ovt
->hsync_level
= vm
->flags
& DISPLAY_FLAGS_HSYNC_HIGH
?
289 OMAPDSS_SIG_ACTIVE_HIGH
:
290 OMAPDSS_SIG_ACTIVE_LOW
;
291 ovt
->de_level
= vm
->flags
& DISPLAY_FLAGS_DE_HIGH
?
292 OMAPDSS_SIG_ACTIVE_HIGH
:
293 OMAPDSS_SIG_ACTIVE_LOW
;
294 ovt
->data_pclk_edge
= vm
->flags
& DISPLAY_FLAGS_PIXDATA_POSEDGE
?
295 OMAPDSS_DRIVE_SIG_RISING_EDGE
:
296 OMAPDSS_DRIVE_SIG_FALLING_EDGE
;
298 ovt
->sync_pclk_edge
= ovt
->data_pclk_edge
;
300 EXPORT_SYMBOL(videomode_to_omap_video_timings
);
302 void omap_video_timings_to_videomode(const struct omap_video_timings
*ovt
,
303 struct videomode
*vm
)
305 memset(vm
, 0, sizeof(*vm
));
307 vm
->pixelclock
= ovt
->pixelclock
;
309 vm
->hactive
= ovt
->x_res
;
310 vm
->hback_porch
= ovt
->hbp
;
311 vm
->hfront_porch
= ovt
->hfp
;
312 vm
->hsync_len
= ovt
->hsw
;
313 vm
->vactive
= ovt
->y_res
;
314 vm
->vback_porch
= ovt
->vbp
;
315 vm
->vfront_porch
= ovt
->vfp
;
316 vm
->vsync_len
= ovt
->vsw
;
318 if (ovt
->hsync_level
== OMAPDSS_SIG_ACTIVE_HIGH
)
319 vm
->flags
|= DISPLAY_FLAGS_HSYNC_HIGH
;
321 vm
->flags
|= DISPLAY_FLAGS_HSYNC_LOW
;
323 if (ovt
->vsync_level
== OMAPDSS_SIG_ACTIVE_HIGH
)
324 vm
->flags
|= DISPLAY_FLAGS_VSYNC_HIGH
;
326 vm
->flags
|= DISPLAY_FLAGS_VSYNC_LOW
;
328 if (ovt
->de_level
== OMAPDSS_SIG_ACTIVE_HIGH
)
329 vm
->flags
|= DISPLAY_FLAGS_DE_HIGH
;
331 vm
->flags
|= DISPLAY_FLAGS_DE_LOW
;
333 if (ovt
->data_pclk_edge
== OMAPDSS_DRIVE_SIG_RISING_EDGE
)
334 vm
->flags
|= DISPLAY_FLAGS_PIXDATA_POSEDGE
;
336 vm
->flags
|= DISPLAY_FLAGS_PIXDATA_NEGEDGE
;
338 EXPORT_SYMBOL(omap_video_timings_to_videomode
);