1 // SPDX-License-Identifier: GPL-2.0-only
3 * linux/drivers/video/omap2/dss/display.c
5 * Copyright (C) 2009 Nokia Corporation
6 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
8 * Some code and ideas taken from drivers/video/omap/ driver
12 #define DSS_SUBSYS_NAME "DISPLAY"
14 #include <linux/kernel.h>
15 #include <linux/module.h>
16 #include <linux/jiffies.h>
17 #include <linux/platform_device.h>
20 #include <video/omapfb_dss.h>
22 #include "dss_features.h"
24 void omapdss_default_get_resolution(struct omap_dss_device
*dssdev
,
27 *xres
= dssdev
->panel
.timings
.x_res
;
28 *yres
= dssdev
->panel
.timings
.y_res
;
30 EXPORT_SYMBOL(omapdss_default_get_resolution
);
32 int omapdss_default_get_recommended_bpp(struct omap_dss_device
*dssdev
)
34 switch (dssdev
->type
) {
35 case OMAP_DISPLAY_TYPE_DPI
:
36 if (dssdev
->phy
.dpi
.data_lines
== 24)
41 case OMAP_DISPLAY_TYPE_DBI
:
42 if (dssdev
->ctrl
.pixel_size
== 24)
46 case OMAP_DISPLAY_TYPE_DSI
:
47 if (dsi_get_pixel_size(dssdev
->panel
.dsi_pix_fmt
) > 16)
51 case OMAP_DISPLAY_TYPE_VENC
:
52 case OMAP_DISPLAY_TYPE_SDI
:
53 case OMAP_DISPLAY_TYPE_HDMI
:
54 case OMAP_DISPLAY_TYPE_DVI
:
61 EXPORT_SYMBOL(omapdss_default_get_recommended_bpp
);
63 void omapdss_default_get_timings(struct omap_dss_device
*dssdev
,
64 struct omap_video_timings
*timings
)
66 *timings
= dssdev
->panel
.timings
;
68 EXPORT_SYMBOL(omapdss_default_get_timings
);
70 int dss_suspend_all_devices(void)
72 struct omap_dss_device
*dssdev
= NULL
;
74 for_each_dss_dev(dssdev
) {
78 if (dssdev
->state
== OMAP_DSS_DISPLAY_ACTIVE
) {
79 dssdev
->driver
->disable(dssdev
);
80 dssdev
->activate_after_resume
= true;
82 dssdev
->activate_after_resume
= false;
89 int dss_resume_all_devices(void)
91 struct omap_dss_device
*dssdev
= NULL
;
93 for_each_dss_dev(dssdev
) {
97 if (dssdev
->activate_after_resume
) {
98 dssdev
->driver
->enable(dssdev
);
99 dssdev
->activate_after_resume
= false;
106 void dss_disable_all_devices(void)
108 struct omap_dss_device
*dssdev
= NULL
;
110 for_each_dss_dev(dssdev
) {
114 if (dssdev
->state
== OMAP_DSS_DISPLAY_ACTIVE
)
115 dssdev
->driver
->disable(dssdev
);
119 static LIST_HEAD(panel_list
);
120 static DEFINE_MUTEX(panel_list_mutex
);
121 static int disp_num_counter
;
123 int omapdss_register_display(struct omap_dss_device
*dssdev
)
125 struct omap_dss_driver
*drv
= dssdev
->driver
;
129 * Note: this presumes all the displays are either using DT or non-DT,
130 * which normally should be the case. This also presumes that all
131 * displays either have an DT alias, or none has.
134 if (dssdev
->dev
->of_node
) {
135 id
= of_alias_get_id(dssdev
->dev
->of_node
, "display");
138 id
= disp_num_counter
++;
140 id
= disp_num_counter
++;
143 snprintf(dssdev
->alias
, sizeof(dssdev
->alias
), "display%d", id
);
145 /* Use 'label' property for name, if it exists */
146 if (dssdev
->dev
->of_node
)
147 of_property_read_string(dssdev
->dev
->of_node
, "label",
150 if (dssdev
->name
== NULL
)
151 dssdev
->name
= dssdev
->alias
;
153 if (drv
&& drv
->get_resolution
== NULL
)
154 drv
->get_resolution
= omapdss_default_get_resolution
;
155 if (drv
&& drv
->get_recommended_bpp
== NULL
)
156 drv
->get_recommended_bpp
= omapdss_default_get_recommended_bpp
;
157 if (drv
&& drv
->get_timings
== NULL
)
158 drv
->get_timings
= omapdss_default_get_timings
;
160 mutex_lock(&panel_list_mutex
);
161 list_add_tail(&dssdev
->panel_list
, &panel_list
);
162 mutex_unlock(&panel_list_mutex
);
165 EXPORT_SYMBOL(omapdss_register_display
);
167 void omapdss_unregister_display(struct omap_dss_device
*dssdev
)
169 mutex_lock(&panel_list_mutex
);
170 list_del(&dssdev
->panel_list
);
171 mutex_unlock(&panel_list_mutex
);
173 EXPORT_SYMBOL(omapdss_unregister_display
);
175 struct omap_dss_device
*omap_dss_get_device(struct omap_dss_device
*dssdev
)
177 if (!try_module_get(dssdev
->owner
))
180 if (get_device(dssdev
->dev
) == NULL
) {
181 module_put(dssdev
->owner
);
187 EXPORT_SYMBOL(omap_dss_get_device
);
189 void omap_dss_put_device(struct omap_dss_device
*dssdev
)
191 put_device(dssdev
->dev
);
192 module_put(dssdev
->owner
);
194 EXPORT_SYMBOL(omap_dss_put_device
);
197 * ref count of the found device is incremented.
198 * ref count of from-device is decremented.
200 struct omap_dss_device
*omap_dss_get_next_device(struct omap_dss_device
*from
)
203 struct omap_dss_device
*dssdev
;
205 mutex_lock(&panel_list_mutex
);
207 if (list_empty(&panel_list
)) {
213 dssdev
= list_first_entry(&panel_list
, struct omap_dss_device
,
215 omap_dss_get_device(dssdev
);
219 omap_dss_put_device(from
);
221 list_for_each(l
, &panel_list
) {
222 dssdev
= list_entry(l
, struct omap_dss_device
, panel_list
);
223 if (dssdev
== from
) {
224 if (list_is_last(l
, &panel_list
)) {
229 dssdev
= list_entry(l
->next
, struct omap_dss_device
,
231 omap_dss_get_device(dssdev
);
236 WARN(1, "'from' dssdev not found\n");
240 mutex_unlock(&panel_list_mutex
);
243 EXPORT_SYMBOL(omap_dss_get_next_device
);
245 struct omap_dss_device
*omap_dss_find_device(void *data
,
246 int (*match
)(struct omap_dss_device
*dssdev
, void *data
))
248 struct omap_dss_device
*dssdev
= NULL
;
250 while ((dssdev
= omap_dss_get_next_device(dssdev
)) != NULL
) {
251 if (match(dssdev
, data
))
257 EXPORT_SYMBOL(omap_dss_find_device
);
259 void videomode_to_omap_video_timings(const struct videomode
*vm
,
260 struct omap_video_timings
*ovt
)
262 memset(ovt
, 0, sizeof(*ovt
));
264 ovt
->pixelclock
= vm
->pixelclock
;
265 ovt
->x_res
= vm
->hactive
;
266 ovt
->hbp
= vm
->hback_porch
;
267 ovt
->hfp
= vm
->hfront_porch
;
268 ovt
->hsw
= vm
->hsync_len
;
269 ovt
->y_res
= vm
->vactive
;
270 ovt
->vbp
= vm
->vback_porch
;
271 ovt
->vfp
= vm
->vfront_porch
;
272 ovt
->vsw
= vm
->vsync_len
;
274 ovt
->vsync_level
= vm
->flags
& DISPLAY_FLAGS_VSYNC_HIGH
?
275 OMAPDSS_SIG_ACTIVE_HIGH
:
276 OMAPDSS_SIG_ACTIVE_LOW
;
277 ovt
->hsync_level
= vm
->flags
& DISPLAY_FLAGS_HSYNC_HIGH
?
278 OMAPDSS_SIG_ACTIVE_HIGH
:
279 OMAPDSS_SIG_ACTIVE_LOW
;
280 ovt
->de_level
= vm
->flags
& DISPLAY_FLAGS_DE_HIGH
?
281 OMAPDSS_SIG_ACTIVE_HIGH
:
282 OMAPDSS_SIG_ACTIVE_LOW
;
283 ovt
->data_pclk_edge
= vm
->flags
& DISPLAY_FLAGS_PIXDATA_POSEDGE
?
284 OMAPDSS_DRIVE_SIG_RISING_EDGE
:
285 OMAPDSS_DRIVE_SIG_FALLING_EDGE
;
287 ovt
->sync_pclk_edge
= ovt
->data_pclk_edge
;
289 EXPORT_SYMBOL(videomode_to_omap_video_timings
);
291 void omap_video_timings_to_videomode(const struct omap_video_timings
*ovt
,
292 struct videomode
*vm
)
294 memset(vm
, 0, sizeof(*vm
));
296 vm
->pixelclock
= ovt
->pixelclock
;
298 vm
->hactive
= ovt
->x_res
;
299 vm
->hback_porch
= ovt
->hbp
;
300 vm
->hfront_porch
= ovt
->hfp
;
301 vm
->hsync_len
= ovt
->hsw
;
302 vm
->vactive
= ovt
->y_res
;
303 vm
->vback_porch
= ovt
->vbp
;
304 vm
->vfront_porch
= ovt
->vfp
;
305 vm
->vsync_len
= ovt
->vsw
;
307 if (ovt
->hsync_level
== OMAPDSS_SIG_ACTIVE_HIGH
)
308 vm
->flags
|= DISPLAY_FLAGS_HSYNC_HIGH
;
310 vm
->flags
|= DISPLAY_FLAGS_HSYNC_LOW
;
312 if (ovt
->vsync_level
== OMAPDSS_SIG_ACTIVE_HIGH
)
313 vm
->flags
|= DISPLAY_FLAGS_VSYNC_HIGH
;
315 vm
->flags
|= DISPLAY_FLAGS_VSYNC_LOW
;
317 if (ovt
->de_level
== OMAPDSS_SIG_ACTIVE_HIGH
)
318 vm
->flags
|= DISPLAY_FLAGS_DE_HIGH
;
320 vm
->flags
|= DISPLAY_FLAGS_DE_LOW
;
322 if (ovt
->data_pclk_edge
== OMAPDSS_DRIVE_SIG_RISING_EDGE
)
323 vm
->flags
|= DISPLAY_FLAGS_PIXDATA_POSEDGE
;
325 vm
->flags
|= DISPLAY_FLAGS_PIXDATA_NEGEDGE
;
327 EXPORT_SYMBOL(omap_video_timings_to_videomode
);