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>
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 static LIST_HEAD(panel_list
);
82 static DEFINE_MUTEX(panel_list_mutex
);
83 static int disp_num_counter
;
85 int omapdss_register_display(struct omap_dss_device
*dssdev
)
87 struct omap_dss_driver
*drv
= dssdev
->driver
;
91 * Note: this presumes all the displays are either using DT or non-DT,
92 * which normally should be the case. This also presumes that all
93 * displays either have an DT alias, or none has.
96 if (dssdev
->dev
->of_node
) {
97 id
= of_alias_get_id(dssdev
->dev
->of_node
, "display");
100 id
= disp_num_counter
++;
102 id
= disp_num_counter
++;
105 snprintf(dssdev
->alias
, sizeof(dssdev
->alias
), "display%d", id
);
107 /* Use 'label' property for name, if it exists */
108 if (dssdev
->dev
->of_node
)
109 of_property_read_string(dssdev
->dev
->of_node
, "label",
112 if (dssdev
->name
== NULL
)
113 dssdev
->name
= dssdev
->alias
;
115 if (drv
&& drv
->get_resolution
== NULL
)
116 drv
->get_resolution
= omapdss_default_get_resolution
;
117 if (drv
&& drv
->get_recommended_bpp
== NULL
)
118 drv
->get_recommended_bpp
= omapdss_default_get_recommended_bpp
;
119 if (drv
&& drv
->get_timings
== NULL
)
120 drv
->get_timings
= omapdss_default_get_timings
;
122 mutex_lock(&panel_list_mutex
);
123 list_add_tail(&dssdev
->panel_list
, &panel_list
);
124 mutex_unlock(&panel_list_mutex
);
127 EXPORT_SYMBOL(omapdss_register_display
);
129 void omapdss_unregister_display(struct omap_dss_device
*dssdev
)
131 mutex_lock(&panel_list_mutex
);
132 list_del(&dssdev
->panel_list
);
133 mutex_unlock(&panel_list_mutex
);
135 EXPORT_SYMBOL(omapdss_unregister_display
);
137 struct omap_dss_device
*omap_dss_get_device(struct omap_dss_device
*dssdev
)
139 if (!try_module_get(dssdev
->owner
))
142 if (get_device(dssdev
->dev
) == NULL
) {
143 module_put(dssdev
->owner
);
149 EXPORT_SYMBOL(omap_dss_get_device
);
151 void omap_dss_put_device(struct omap_dss_device
*dssdev
)
153 put_device(dssdev
->dev
);
154 module_put(dssdev
->owner
);
156 EXPORT_SYMBOL(omap_dss_put_device
);
159 * ref count of the found device is incremented.
160 * ref count of from-device is decremented.
162 struct omap_dss_device
*omap_dss_get_next_device(struct omap_dss_device
*from
)
165 struct omap_dss_device
*dssdev
;
167 mutex_lock(&panel_list_mutex
);
169 if (list_empty(&panel_list
)) {
175 dssdev
= list_first_entry(&panel_list
, struct omap_dss_device
,
177 omap_dss_get_device(dssdev
);
181 omap_dss_put_device(from
);
183 list_for_each(l
, &panel_list
) {
184 dssdev
= list_entry(l
, struct omap_dss_device
, panel_list
);
185 if (dssdev
== from
) {
186 if (list_is_last(l
, &panel_list
)) {
191 dssdev
= list_entry(l
->next
, struct omap_dss_device
,
193 omap_dss_get_device(dssdev
);
198 WARN(1, "'from' dssdev not found\n");
202 mutex_unlock(&panel_list_mutex
);
205 EXPORT_SYMBOL(omap_dss_get_next_device
);
207 struct omap_dss_device
*omap_dss_find_device(void *data
,
208 int (*match
)(struct omap_dss_device
*dssdev
, void *data
))
210 struct omap_dss_device
*dssdev
= NULL
;
212 while ((dssdev
= omap_dss_get_next_device(dssdev
)) != NULL
) {
213 if (match(dssdev
, data
))
219 EXPORT_SYMBOL(omap_dss_find_device
);
221 void videomode_to_omap_video_timings(const struct videomode
*vm
,
222 struct omap_video_timings
*ovt
)
224 memset(ovt
, 0, sizeof(*ovt
));
226 ovt
->pixelclock
= vm
->pixelclock
;
227 ovt
->x_res
= vm
->hactive
;
228 ovt
->hbp
= vm
->hback_porch
;
229 ovt
->hfp
= vm
->hfront_porch
;
230 ovt
->hsw
= vm
->hsync_len
;
231 ovt
->y_res
= vm
->vactive
;
232 ovt
->vbp
= vm
->vback_porch
;
233 ovt
->vfp
= vm
->vfront_porch
;
234 ovt
->vsw
= vm
->vsync_len
;
236 ovt
->vsync_level
= vm
->flags
& DISPLAY_FLAGS_VSYNC_HIGH
?
237 OMAPDSS_SIG_ACTIVE_HIGH
:
238 OMAPDSS_SIG_ACTIVE_LOW
;
239 ovt
->hsync_level
= vm
->flags
& DISPLAY_FLAGS_HSYNC_HIGH
?
240 OMAPDSS_SIG_ACTIVE_HIGH
:
241 OMAPDSS_SIG_ACTIVE_LOW
;
242 ovt
->de_level
= vm
->flags
& DISPLAY_FLAGS_DE_HIGH
?
243 OMAPDSS_SIG_ACTIVE_HIGH
:
244 OMAPDSS_SIG_ACTIVE_LOW
;
245 ovt
->data_pclk_edge
= vm
->flags
& DISPLAY_FLAGS_PIXDATA_POSEDGE
?
246 OMAPDSS_DRIVE_SIG_RISING_EDGE
:
247 OMAPDSS_DRIVE_SIG_FALLING_EDGE
;
249 ovt
->sync_pclk_edge
= ovt
->data_pclk_edge
;
251 EXPORT_SYMBOL(videomode_to_omap_video_timings
);
253 void omap_video_timings_to_videomode(const struct omap_video_timings
*ovt
,
254 struct videomode
*vm
)
256 memset(vm
, 0, sizeof(*vm
));
258 vm
->pixelclock
= ovt
->pixelclock
;
260 vm
->hactive
= ovt
->x_res
;
261 vm
->hback_porch
= ovt
->hbp
;
262 vm
->hfront_porch
= ovt
->hfp
;
263 vm
->hsync_len
= ovt
->hsw
;
264 vm
->vactive
= ovt
->y_res
;
265 vm
->vback_porch
= ovt
->vbp
;
266 vm
->vfront_porch
= ovt
->vfp
;
267 vm
->vsync_len
= ovt
->vsw
;
269 if (ovt
->hsync_level
== OMAPDSS_SIG_ACTIVE_HIGH
)
270 vm
->flags
|= DISPLAY_FLAGS_HSYNC_HIGH
;
272 vm
->flags
|= DISPLAY_FLAGS_HSYNC_LOW
;
274 if (ovt
->vsync_level
== OMAPDSS_SIG_ACTIVE_HIGH
)
275 vm
->flags
|= DISPLAY_FLAGS_VSYNC_HIGH
;
277 vm
->flags
|= DISPLAY_FLAGS_VSYNC_LOW
;
279 if (ovt
->de_level
== OMAPDSS_SIG_ACTIVE_HIGH
)
280 vm
->flags
|= DISPLAY_FLAGS_DE_HIGH
;
282 vm
->flags
|= DISPLAY_FLAGS_DE_LOW
;
284 if (ovt
->data_pclk_edge
== OMAPDSS_DRIVE_SIG_RISING_EDGE
)
285 vm
->flags
|= DISPLAY_FLAGS_PIXDATA_POSEDGE
;
287 vm
->flags
|= DISPLAY_FLAGS_PIXDATA_NEGEDGE
;
289 EXPORT_SYMBOL(omap_video_timings_to_videomode
);