1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33#include <linux/module.h>
34#include <linux/delay.h>
35#include <linux/slab.h>
36
37#include <plat/panel-generic-dpi.h>
38
39struct panel_config {
40 struct omap_video_timings timings;
41
42 int acbi;
43
44 int acb;
45
46 enum omap_panel_config config;
47
48 int power_on_delay;
49 int power_off_delay;
50
51
52
53
54
55 const char *name;
56};
57
58
59static struct panel_config generic_dpi_panels[] = {
60
61 {
62 {
63 .x_res = 640,
64 .y_res = 480,
65
66 .pixel_clock = 23500,
67
68 .hfp = 48,
69 .hsw = 32,
70 .hbp = 80,
71
72 .vfp = 3,
73 .vsw = 4,
74 .vbp = 7,
75 },
76 .acbi = 0x0,
77 .acb = 0x0,
78 .config = OMAP_DSS_LCD_TFT,
79 .power_on_delay = 0,
80 .power_off_delay = 0,
81 .name = "generic",
82 },
83
84
85 {
86 {
87 .x_res = 480,
88 .y_res = 272,
89
90 .pixel_clock = 9000,
91
92 .hsw = 42,
93 .hfp = 3,
94 .hbp = 2,
95
96 .vsw = 11,
97 .vfp = 3,
98 .vbp = 2,
99 },
100 .acbi = 0x0,
101 .acb = 0x0,
102 .config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
103 OMAP_DSS_LCD_IHS | OMAP_DSS_LCD_IEO,
104 .power_on_delay = 50,
105 .power_off_delay = 100,
106 .name = "sharp_lq",
107 },
108
109
110 {
111 {
112 .x_res = 480,
113 .y_res = 640,
114
115 .pixel_clock = 19200,
116
117 .hsw = 2,
118 .hfp = 1,
119 .hbp = 28,
120
121 .vsw = 1,
122 .vfp = 1,
123 .vbp = 1,
124 },
125 .acbi = 0x0,
126 .acb = 0x28,
127 .config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
128 OMAP_DSS_LCD_IHS,
129 .power_on_delay = 50,
130 .power_off_delay = 100,
131 .name = "sharp_ls",
132 },
133
134
135 {
136 {
137 .x_res = 480,
138 .y_res = 640,
139
140 .pixel_clock = 26000,
141
142 .hfp = 104,
143 .hsw = 8,
144 .hbp = 8,
145
146 .vfp = 4,
147 .vsw = 2,
148 .vbp = 2,
149 },
150 .acbi = 0x0,
151 .acb = 0x0,
152 .config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
153 OMAP_DSS_LCD_IHS | OMAP_DSS_LCD_IPC |
154 OMAP_DSS_LCD_ONOFF,
155 .power_on_delay = 0,
156 .power_off_delay = 0,
157 .name = "toppoly_tdo35s",
158 },
159};
160
161struct panel_drv_data {
162
163 struct omap_dss_device *dssdev;
164
165 struct panel_config *panel_config;
166};
167
168static inline struct panel_generic_dpi_data
169*get_panel_data(const struct omap_dss_device *dssdev)
170{
171 return (struct panel_generic_dpi_data *) dssdev->data;
172}
173
174static int generic_dpi_panel_power_on(struct omap_dss_device *dssdev)
175{
176 int r;
177 struct panel_generic_dpi_data *panel_data = get_panel_data(dssdev);
178 struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
179 struct panel_config *panel_config = drv_data->panel_config;
180
181 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
182 return 0;
183
184 r = omapdss_dpi_display_enable(dssdev);
185 if (r)
186 goto err0;
187
188
189 if (panel_config->power_on_delay)
190 msleep(panel_config->power_on_delay);
191
192 if (panel_data->platform_enable) {
193 r = panel_data->platform_enable(dssdev);
194 if (r)
195 goto err1;
196 }
197
198 return 0;
199err1:
200 omapdss_dpi_display_disable(dssdev);
201err0:
202 return r;
203}
204
205static void generic_dpi_panel_power_off(struct omap_dss_device *dssdev)
206{
207 struct panel_generic_dpi_data *panel_data = get_panel_data(dssdev);
208 struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
209 struct panel_config *panel_config = drv_data->panel_config;
210
211 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
212 return;
213
214 if (panel_data->platform_disable)
215 panel_data->platform_disable(dssdev);
216
217
218 if (panel_config->power_off_delay)
219 msleep(panel_config->power_off_delay);
220
221 omapdss_dpi_display_disable(dssdev);
222}
223
224static int generic_dpi_panel_probe(struct omap_dss_device *dssdev)
225{
226 struct panel_generic_dpi_data *panel_data = get_panel_data(dssdev);
227 struct panel_config *panel_config = NULL;
228 struct panel_drv_data *drv_data = NULL;
229 int i;
230
231 dev_dbg(&dssdev->dev, "probe\n");
232
233 if (!panel_data || !panel_data->name)
234 return -EINVAL;
235
236 for (i = 0; i < ARRAY_SIZE(generic_dpi_panels); i++) {
237 if (strcmp(panel_data->name, generic_dpi_panels[i].name) == 0) {
238 panel_config = &generic_dpi_panels[i];
239 break;
240 }
241 }
242
243 if (!panel_config)
244 return -EINVAL;
245
246 dssdev->panel.config = panel_config->config;
247 dssdev->panel.timings = panel_config->timings;
248 dssdev->panel.acb = panel_config->acb;
249 dssdev->panel.acbi = panel_config->acbi;
250
251 drv_data = kzalloc(sizeof(*drv_data), GFP_KERNEL);
252 if (!drv_data)
253 return -ENOMEM;
254
255 drv_data->dssdev = dssdev;
256 drv_data->panel_config = panel_config;
257
258 dev_set_drvdata(&dssdev->dev, drv_data);
259
260 return 0;
261}
262
263static void generic_dpi_panel_remove(struct omap_dss_device *dssdev)
264{
265 struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
266
267 dev_dbg(&dssdev->dev, "remove\n");
268
269 kfree(drv_data);
270
271 dev_set_drvdata(&dssdev->dev, NULL);
272}
273
274static int generic_dpi_panel_enable(struct omap_dss_device *dssdev)
275{
276 int r = 0;
277
278 r = generic_dpi_panel_power_on(dssdev);
279 if (r)
280 return r;
281
282 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
283
284 return 0;
285}
286
287static void generic_dpi_panel_disable(struct omap_dss_device *dssdev)
288{
289 generic_dpi_panel_power_off(dssdev);
290
291 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
292}
293
294static int generic_dpi_panel_suspend(struct omap_dss_device *dssdev)
295{
296 generic_dpi_panel_power_off(dssdev);
297
298 dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
299
300 return 0;
301}
302
303static int generic_dpi_panel_resume(struct omap_dss_device *dssdev)
304{
305 int r = 0;
306
307 r = generic_dpi_panel_power_on(dssdev);
308 if (r)
309 return r;
310
311 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
312
313 return 0;
314}
315
316static void generic_dpi_panel_set_timings(struct omap_dss_device *dssdev,
317 struct omap_video_timings *timings)
318{
319 dpi_set_timings(dssdev, timings);
320}
321
322static void generic_dpi_panel_get_timings(struct omap_dss_device *dssdev,
323 struct omap_video_timings *timings)
324{
325 *timings = dssdev->panel.timings;
326}
327
328static int generic_dpi_panel_check_timings(struct omap_dss_device *dssdev,
329 struct omap_video_timings *timings)
330{
331 return dpi_check_timings(dssdev, timings);
332}
333
334static struct omap_dss_driver dpi_driver = {
335 .probe = generic_dpi_panel_probe,
336 .remove = generic_dpi_panel_remove,
337
338 .enable = generic_dpi_panel_enable,
339 .disable = generic_dpi_panel_disable,
340 .suspend = generic_dpi_panel_suspend,
341 .resume = generic_dpi_panel_resume,
342
343 .set_timings = generic_dpi_panel_set_timings,
344 .get_timings = generic_dpi_panel_get_timings,
345 .check_timings = generic_dpi_panel_check_timings,
346
347 .driver = {
348 .name = "generic_dpi_panel",
349 .owner = THIS_MODULE,
350 },
351};
352
353static int __init generic_dpi_panel_drv_init(void)
354{
355 return omap_dss_register_driver(&dpi_driver);
356}
357
358static void __exit generic_dpi_panel_drv_exit(void)
359{
360 omap_dss_unregister_driver(&dpi_driver);
361}
362
363module_init(generic_dpi_panel_drv_init);
364module_exit(generic_dpi_panel_drv_exit);
365MODULE_LICENSE("GPL");
366