]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - drivers/video/omap2/dss/display.c
OMAPDSS: Fix de_level in videomode_to_omap_video_timings()
[karo-tx-linux.git] / drivers / video / omap2 / dss / display.c
1 /*
2  * linux/drivers/video/omap2/dss/display.c
3  *
4  * Copyright (C) 2009 Nokia Corporation
5  * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
6  *
7  * Some code and ideas taken from drivers/video/omap/ driver
8  * by Imre Deak.
9  *
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.
13  *
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
17  * more details.
18  *
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/>.
21  */
22
23 #define DSS_SUBSYS_NAME "DISPLAY"
24
25 #include <linux/kernel.h>
26 #include <linux/module.h>
27 #include <linux/jiffies.h>
28 #include <linux/platform_device.h>
29
30 #include <video/omapdss.h>
31 #include "dss.h"
32 #include "dss_features.h"
33
34 void omapdss_default_get_resolution(struct omap_dss_device *dssdev,
35                         u16 *xres, u16 *yres)
36 {
37         *xres = dssdev->panel.timings.x_res;
38         *yres = dssdev->panel.timings.y_res;
39 }
40 EXPORT_SYMBOL(omapdss_default_get_resolution);
41
42 int omapdss_default_get_recommended_bpp(struct omap_dss_device *dssdev)
43 {
44         switch (dssdev->type) {
45         case OMAP_DISPLAY_TYPE_DPI:
46                 if (dssdev->phy.dpi.data_lines == 24)
47                         return 24;
48                 else
49                         return 16;
50
51         case OMAP_DISPLAY_TYPE_DBI:
52                 if (dssdev->ctrl.pixel_size == 24)
53                         return 24;
54                 else
55                         return 16;
56         case OMAP_DISPLAY_TYPE_DSI:
57                 if (dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt) > 16)
58                         return 24;
59                 else
60                         return 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:
65                 return 24;
66         default:
67                 BUG();
68                 return 0;
69         }
70 }
71 EXPORT_SYMBOL(omapdss_default_get_recommended_bpp);
72
73 void omapdss_default_get_timings(struct omap_dss_device *dssdev,
74                 struct omap_video_timings *timings)
75 {
76         *timings = dssdev->panel.timings;
77 }
78 EXPORT_SYMBOL(omapdss_default_get_timings);
79
80 int dss_suspend_all_devices(void)
81 {
82         struct omap_dss_device *dssdev = NULL;
83
84         for_each_dss_dev(dssdev) {
85                 if (!dssdev->driver)
86                         continue;
87
88                 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
89                         dssdev->driver->disable(dssdev);
90                         dssdev->activate_after_resume = true;
91                 } else {
92                         dssdev->activate_after_resume = false;
93                 }
94         }
95
96         return 0;
97 }
98
99 int dss_resume_all_devices(void)
100 {
101         struct omap_dss_device *dssdev = NULL;
102
103         for_each_dss_dev(dssdev) {
104                 if (!dssdev->driver)
105                         continue;
106
107                 if (dssdev->activate_after_resume) {
108                         dssdev->driver->enable(dssdev);
109                         dssdev->activate_after_resume = false;
110                 }
111         }
112
113         return 0;
114 }
115
116 void dss_disable_all_devices(void)
117 {
118         struct omap_dss_device *dssdev = NULL;
119
120         for_each_dss_dev(dssdev) {
121                 if (!dssdev->driver)
122                         continue;
123
124                 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
125                         dssdev->driver->disable(dssdev);
126         }
127 }
128
129 static LIST_HEAD(panel_list);
130 static DEFINE_MUTEX(panel_list_mutex);
131 static int disp_num_counter;
132
133 int omapdss_register_display(struct omap_dss_device *dssdev)
134 {
135         struct omap_dss_driver *drv = dssdev->driver;
136
137         snprintf(dssdev->alias, sizeof(dssdev->alias),
138                         "display%d", disp_num_counter++);
139
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;
146
147         mutex_lock(&panel_list_mutex);
148         list_add_tail(&dssdev->panel_list, &panel_list);
149         mutex_unlock(&panel_list_mutex);
150         return 0;
151 }
152 EXPORT_SYMBOL(omapdss_register_display);
153
154 void omapdss_unregister_display(struct omap_dss_device *dssdev)
155 {
156         mutex_lock(&panel_list_mutex);
157         list_del(&dssdev->panel_list);
158         mutex_unlock(&panel_list_mutex);
159 }
160 EXPORT_SYMBOL(omapdss_unregister_display);
161
162 struct omap_dss_device *omap_dss_get_device(struct omap_dss_device *dssdev)
163 {
164         if (!try_module_get(dssdev->owner))
165                 return NULL;
166
167         if (get_device(dssdev->dev) == NULL) {
168                 module_put(dssdev->owner);
169                 return NULL;
170         }
171
172         return dssdev;
173 }
174 EXPORT_SYMBOL(omap_dss_get_device);
175
176 void omap_dss_put_device(struct omap_dss_device *dssdev)
177 {
178         put_device(dssdev->dev);
179         module_put(dssdev->owner);
180 }
181 EXPORT_SYMBOL(omap_dss_put_device);
182
183 /*
184  * ref count of the found device is incremented.
185  * ref count of from-device is decremented.
186  */
187 struct omap_dss_device *omap_dss_get_next_device(struct omap_dss_device *from)
188 {
189         struct list_head *l;
190         struct omap_dss_device *dssdev;
191
192         mutex_lock(&panel_list_mutex);
193
194         if (list_empty(&panel_list)) {
195                 dssdev = NULL;
196                 goto out;
197         }
198
199         if (from == NULL) {
200                 dssdev = list_first_entry(&panel_list, struct omap_dss_device,
201                                 panel_list);
202                 omap_dss_get_device(dssdev);
203                 goto out;
204         }
205
206         omap_dss_put_device(from);
207
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)) {
212                                 dssdev = NULL;
213                                 goto out;
214                         }
215
216                         dssdev = list_entry(l->next, struct omap_dss_device,
217                                         panel_list);
218                         omap_dss_get_device(dssdev);
219                         goto out;
220                 }
221         }
222
223         WARN(1, "'from' dssdev not found\n");
224
225         dssdev = NULL;
226 out:
227         mutex_unlock(&panel_list_mutex);
228         return dssdev;
229 }
230 EXPORT_SYMBOL(omap_dss_get_next_device);
231
232 struct omap_dss_device *omap_dss_find_device(void *data,
233                 int (*match)(struct omap_dss_device *dssdev, void *data))
234 {
235         struct omap_dss_device *dssdev = NULL;
236
237         while ((dssdev = omap_dss_get_next_device(dssdev)) != NULL) {
238                 if (match(dssdev, data))
239                         return dssdev;
240         }
241
242         return NULL;
243 }
244 EXPORT_SYMBOL(omap_dss_find_device);
245
246 void videomode_to_omap_video_timings(const struct videomode *vm,
247                 struct omap_video_timings *ovt)
248 {
249         memset(ovt, 0, sizeof(*ovt));
250
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;
260
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_LOW;
270         ovt->data_pclk_edge = vm->flags & DISPLAY_FLAGS_PIXDATA_POSEDGE ?
271                 OMAPDSS_DRIVE_SIG_RISING_EDGE :
272                 OMAPDSS_DRIVE_SIG_FALLING_EDGE;
273
274         ovt->sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES;
275 }
276 EXPORT_SYMBOL(videomode_to_omap_video_timings);
277
278 void omap_video_timings_to_videomode(const struct omap_video_timings *ovt,
279                 struct videomode *vm)
280 {
281         memset(vm, 0, sizeof(*vm));
282
283         vm->pixelclock = ovt->pixel_clock * 1000;
284
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;
293
294         if (ovt->hsync_level == OMAPDSS_SIG_ACTIVE_HIGH)
295                 vm->flags |= DISPLAY_FLAGS_HSYNC_HIGH;
296         else
297                 vm->flags |= DISPLAY_FLAGS_HSYNC_LOW;
298
299         if (ovt->vsync_level == OMAPDSS_SIG_ACTIVE_HIGH)
300                 vm->flags |= DISPLAY_FLAGS_VSYNC_HIGH;
301         else
302                 vm->flags |= DISPLAY_FLAGS_VSYNC_LOW;
303
304         if (ovt->de_level == OMAPDSS_SIG_ACTIVE_HIGH)
305                 vm->flags |= DISPLAY_FLAGS_DE_HIGH;
306         else
307                 vm->flags |= DISPLAY_FLAGS_DE_LOW;
308
309         if (ovt->data_pclk_edge == OMAPDSS_DRIVE_SIG_RISING_EDGE)
310                 vm->flags |= DISPLAY_FLAGS_PIXDATA_POSEDGE;
311         else
312                 vm->flags |= DISPLAY_FLAGS_PIXDATA_NEGEDGE;
313 }
314 EXPORT_SYMBOL(omap_video_timings_to_videomode);