OMAPDSS: manage output-dssdev connection in output drivers
[platform/adaptation/renesas_rcar/renesas_kernel.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                 return 24;
65         default:
66                 BUG();
67                 return 0;
68         }
69 }
70 EXPORT_SYMBOL(omapdss_default_get_recommended_bpp);
71
72 void omapdss_default_get_timings(struct omap_dss_device *dssdev,
73                 struct omap_video_timings *timings)
74 {
75         *timings = dssdev->panel.timings;
76 }
77 EXPORT_SYMBOL(omapdss_default_get_timings);
78
79 int dss_init_device(struct platform_device *pdev,
80                 struct omap_dss_device *dssdev)
81 {
82         int r;
83
84         r = display_init_sysfs(pdev, dssdev);
85         if (r) {
86                 omapdss_output_unset_device(dssdev->output);
87                 return r;
88         }
89
90         return 0;
91 }
92
93 void dss_uninit_device(struct platform_device *pdev,
94                 struct omap_dss_device *dssdev)
95 {
96         display_uninit_sysfs(pdev, dssdev);
97 }
98
99 static int dss_suspend_device(struct device *dev, void *data)
100 {
101         struct omap_dss_device *dssdev = to_dss_device(dev);
102
103         if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
104                 dssdev->activate_after_resume = false;
105                 return 0;
106         }
107
108         dssdev->driver->disable(dssdev);
109
110         dssdev->activate_after_resume = true;
111
112         return 0;
113 }
114
115 int dss_suspend_all_devices(void)
116 {
117         int r;
118         struct bus_type *bus = dss_get_bus();
119
120         r = bus_for_each_dev(bus, NULL, NULL, dss_suspend_device);
121         if (r) {
122                 /* resume all displays that were suspended */
123                 dss_resume_all_devices();
124                 return r;
125         }
126
127         return 0;
128 }
129
130 static int dss_resume_device(struct device *dev, void *data)
131 {
132         int r;
133         struct omap_dss_device *dssdev = to_dss_device(dev);
134
135         if (dssdev->activate_after_resume) {
136                 r = dssdev->driver->enable(dssdev);
137                 if (r)
138                         return r;
139         }
140
141         dssdev->activate_after_resume = false;
142
143         return 0;
144 }
145
146 int dss_resume_all_devices(void)
147 {
148         struct bus_type *bus = dss_get_bus();
149
150         return bus_for_each_dev(bus, NULL, NULL, dss_resume_device);
151 }
152
153 static int dss_disable_device(struct device *dev, void *data)
154 {
155         struct omap_dss_device *dssdev = to_dss_device(dev);
156
157         if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED)
158                 dssdev->driver->disable(dssdev);
159
160         return 0;
161 }
162
163 void dss_disable_all_devices(void)
164 {
165         struct bus_type *bus = dss_get_bus();
166         bus_for_each_dev(bus, NULL, NULL, dss_disable_device);
167 }
168
169
170 void omap_dss_get_device(struct omap_dss_device *dssdev)
171 {
172         get_device(&dssdev->dev);
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 }
180 EXPORT_SYMBOL(omap_dss_put_device);
181
182 /* ref count of the found device is incremented. ref count
183  * of from-device is decremented. */
184 struct omap_dss_device *omap_dss_get_next_device(struct omap_dss_device *from)
185 {
186         struct device *dev;
187         struct device *dev_start = NULL;
188         struct omap_dss_device *dssdev = NULL;
189
190         int match(struct device *dev, void *data)
191         {
192                 return 1;
193         }
194
195         if (from)
196                 dev_start = &from->dev;
197         dev = bus_find_device(dss_get_bus(), dev_start, NULL, match);
198         if (dev)
199                 dssdev = to_dss_device(dev);
200         if (from)
201                 put_device(&from->dev);
202
203         return dssdev;
204 }
205 EXPORT_SYMBOL(omap_dss_get_next_device);
206
207 struct omap_dss_device *omap_dss_find_device(void *data,
208                 int (*match)(struct omap_dss_device *dssdev, void *data))
209 {
210         struct omap_dss_device *dssdev = NULL;
211
212         while ((dssdev = omap_dss_get_next_device(dssdev)) != NULL) {
213                 if (match(dssdev, data))
214                         return dssdev;
215         }
216
217         return NULL;
218 }
219 EXPORT_SYMBOL(omap_dss_find_device);
220
221 int omap_dss_start_device(struct omap_dss_device *dssdev)
222 {
223         if (!dssdev->driver) {
224                 DSSDBG("no driver\n");
225                 return -ENODEV;
226         }
227
228         if (!try_module_get(dssdev->dev.driver->owner)) {
229                 return -ENODEV;
230         }
231
232         return 0;
233 }
234 EXPORT_SYMBOL(omap_dss_start_device);
235
236 void omap_dss_stop_device(struct omap_dss_device *dssdev)
237 {
238         module_put(dssdev->dev.driver->owner);
239 }
240 EXPORT_SYMBOL(omap_dss_stop_device);
241