aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/omap2/dss/dpi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/omap2/dss/dpi.c')
-rw-r--r--drivers/video/omap2/dss/dpi.c181
1 files changed, 138 insertions, 43 deletions
diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c
index 3266be23fc0d..56748cf8760e 100644
--- a/drivers/video/omap2/dss/dpi.c
+++ b/drivers/video/omap2/dss/dpi.c
@@ -29,17 +29,24 @@
29#include <linux/errno.h> 29#include <linux/errno.h>
30#include <linux/platform_device.h> 30#include <linux/platform_device.h>
31#include <linux/regulator/consumer.h> 31#include <linux/regulator/consumer.h>
32#include <linux/string.h>
32 33
33#include <video/omapdss.h> 34#include <video/omapdss.h>
34#include <plat/cpu.h>
35 35
36#include "dss.h" 36#include "dss.h"
37#include "dss_features.h"
37 38
38static struct { 39static struct {
39 struct regulator *vdds_dsi_reg; 40 struct regulator *vdds_dsi_reg;
40 struct platform_device *dsidev; 41 struct platform_device *dsidev;
41 42
43 struct mutex lock;
44
45 struct omap_video_timings timings;
42 struct dss_lcd_mgr_config mgr_config; 46 struct dss_lcd_mgr_config mgr_config;
47 int data_lines;
48
49 struct omap_dss_output output;
43} dpi; 50} dpi;
44 51
45static struct platform_device *dpi_get_dsidev(enum omap_dss_clk_source clk) 52static struct platform_device *dpi_get_dsidev(enum omap_dss_clk_source clk)
@@ -121,7 +128,8 @@ static int dpi_set_dispc_clk(struct omap_dss_device *dssdev,
121 128
122static int dpi_set_mode(struct omap_dss_device *dssdev) 129static int dpi_set_mode(struct omap_dss_device *dssdev)
123{ 130{
124 struct omap_video_timings *t = &dssdev->panel.timings; 131 struct omap_video_timings *t = &dpi.timings;
132 struct omap_overlay_manager *mgr = dssdev->output->manager;
125 int lck_div = 0, pck_div = 0; 133 int lck_div = 0, pck_div = 0;
126 unsigned long fck = 0; 134 unsigned long fck = 0;
127 unsigned long pck; 135 unsigned long pck;
@@ -146,37 +154,44 @@ static int dpi_set_mode(struct omap_dss_device *dssdev)
146 t->pixel_clock = pck; 154 t->pixel_clock = pck;
147 } 155 }
148 156
149 dss_mgr_set_timings(dssdev->manager, t); 157 dss_mgr_set_timings(mgr, t);
150 158
151 return 0; 159 return 0;
152} 160}
153 161
154static void dpi_config_lcd_manager(struct omap_dss_device *dssdev) 162static void dpi_config_lcd_manager(struct omap_dss_device *dssdev)
155{ 163{
164 struct omap_overlay_manager *mgr = dssdev->output->manager;
165
156 dpi.mgr_config.io_pad_mode = DSS_IO_PAD_MODE_BYPASS; 166 dpi.mgr_config.io_pad_mode = DSS_IO_PAD_MODE_BYPASS;
157 167
158 dpi.mgr_config.stallmode = false; 168 dpi.mgr_config.stallmode = false;
159 dpi.mgr_config.fifohandcheck = false; 169 dpi.mgr_config.fifohandcheck = false;
160 170
161 dpi.mgr_config.video_port_width = dssdev->phy.dpi.data_lines; 171 dpi.mgr_config.video_port_width = dpi.data_lines;
162 172
163 dpi.mgr_config.lcden_sig_polarity = 0; 173 dpi.mgr_config.lcden_sig_polarity = 0;
164 174
165 dss_mgr_set_lcd_config(dssdev->manager, &dpi.mgr_config); 175 dss_mgr_set_lcd_config(mgr, &dpi.mgr_config);
166} 176}
167 177
168int omapdss_dpi_display_enable(struct omap_dss_device *dssdev) 178int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
169{ 179{
180 struct omap_dss_output *out = dssdev->output;
170 int r; 181 int r;
171 182
172 if (cpu_is_omap34xx() && !dpi.vdds_dsi_reg) { 183 mutex_lock(&dpi.lock);
184
185 if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI) && !dpi.vdds_dsi_reg) {
173 DSSERR("no VDSS_DSI regulator\n"); 186 DSSERR("no VDSS_DSI regulator\n");
174 return -ENODEV; 187 r = -ENODEV;
188 goto err_no_reg;
175 } 189 }
176 190
177 if (dssdev->manager == NULL) { 191 if (out == NULL || out->manager == NULL) {
178 DSSERR("failed to enable display: no manager\n"); 192 DSSERR("failed to enable display: no output/manager\n");
179 return -ENODEV; 193 r = -ENODEV;
194 goto err_no_out_mgr;
180 } 195 }
181 196
182 r = omap_dss_start_device(dssdev); 197 r = omap_dss_start_device(dssdev);
@@ -185,7 +200,7 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
185 goto err_start_dev; 200 goto err_start_dev;
186 } 201 }
187 202
188 if (cpu_is_omap34xx()) { 203 if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI)) {
189 r = regulator_enable(dpi.vdds_dsi_reg); 204 r = regulator_enable(dpi.vdds_dsi_reg);
190 if (r) 205 if (r)
191 goto err_reg_enable; 206 goto err_reg_enable;
@@ -195,6 +210,10 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
195 if (r) 210 if (r)
196 goto err_get_dispc; 211 goto err_get_dispc;
197 212
213 r = dss_dpi_select_source(dssdev->channel);
214 if (r)
215 goto err_src_sel;
216
198 if (dpi_use_dsi_pll(dssdev)) { 217 if (dpi_use_dsi_pll(dssdev)) {
199 r = dsi_runtime_get(dpi.dsidev); 218 r = dsi_runtime_get(dpi.dsidev);
200 if (r) 219 if (r)
@@ -213,10 +232,12 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
213 232
214 mdelay(2); 233 mdelay(2);
215 234
216 r = dss_mgr_enable(dssdev->manager); 235 r = dss_mgr_enable(out->manager);
217 if (r) 236 if (r)
218 goto err_mgr_enable; 237 goto err_mgr_enable;
219 238
239 mutex_unlock(&dpi.lock);
240
220 return 0; 241 return 0;
221 242
222err_mgr_enable: 243err_mgr_enable:
@@ -227,20 +248,28 @@ err_dsi_pll_init:
227 if (dpi_use_dsi_pll(dssdev)) 248 if (dpi_use_dsi_pll(dssdev))
228 dsi_runtime_put(dpi.dsidev); 249 dsi_runtime_put(dpi.dsidev);
229err_get_dsi: 250err_get_dsi:
251err_src_sel:
230 dispc_runtime_put(); 252 dispc_runtime_put();
231err_get_dispc: 253err_get_dispc:
232 if (cpu_is_omap34xx()) 254 if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI))
233 regulator_disable(dpi.vdds_dsi_reg); 255 regulator_disable(dpi.vdds_dsi_reg);
234err_reg_enable: 256err_reg_enable:
235 omap_dss_stop_device(dssdev); 257 omap_dss_stop_device(dssdev);
236err_start_dev: 258err_start_dev:
259err_no_out_mgr:
260err_no_reg:
261 mutex_unlock(&dpi.lock);
237 return r; 262 return r;
238} 263}
239EXPORT_SYMBOL(omapdss_dpi_display_enable); 264EXPORT_SYMBOL(omapdss_dpi_display_enable);
240 265
241void omapdss_dpi_display_disable(struct omap_dss_device *dssdev) 266void omapdss_dpi_display_disable(struct omap_dss_device *dssdev)
242{ 267{
243 dss_mgr_disable(dssdev->manager); 268 struct omap_overlay_manager *mgr = dssdev->output->manager;
269
270 mutex_lock(&dpi.lock);
271
272 dss_mgr_disable(mgr);
244 273
245 if (dpi_use_dsi_pll(dssdev)) { 274 if (dpi_use_dsi_pll(dssdev)) {
246 dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK); 275 dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
@@ -250,44 +279,39 @@ void omapdss_dpi_display_disable(struct omap_dss_device *dssdev)
250 279
251 dispc_runtime_put(); 280 dispc_runtime_put();
252 281
253 if (cpu_is_omap34xx()) 282 if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI))
254 regulator_disable(dpi.vdds_dsi_reg); 283 regulator_disable(dpi.vdds_dsi_reg);
255 284
256 omap_dss_stop_device(dssdev); 285 omap_dss_stop_device(dssdev);
286
287 mutex_unlock(&dpi.lock);
257} 288}
258EXPORT_SYMBOL(omapdss_dpi_display_disable); 289EXPORT_SYMBOL(omapdss_dpi_display_disable);
259 290
260void dpi_set_timings(struct omap_dss_device *dssdev, 291void omapdss_dpi_set_timings(struct omap_dss_device *dssdev,
261 struct omap_video_timings *timings) 292 struct omap_video_timings *timings)
262{ 293{
263 int r;
264
265 DSSDBG("dpi_set_timings\n"); 294 DSSDBG("dpi_set_timings\n");
266 dssdev->panel.timings = *timings;
267 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
268 r = dispc_runtime_get();
269 if (r)
270 return;
271 295
272 dpi_set_mode(dssdev); 296 mutex_lock(&dpi.lock);
273 297
274 dispc_runtime_put(); 298 dpi.timings = *timings;
275 } else { 299
276 dss_mgr_set_timings(dssdev->manager, timings); 300 mutex_unlock(&dpi.lock);
277 }
278} 301}
279EXPORT_SYMBOL(dpi_set_timings); 302EXPORT_SYMBOL(omapdss_dpi_set_timings);
280 303
281int dpi_check_timings(struct omap_dss_device *dssdev, 304int dpi_check_timings(struct omap_dss_device *dssdev,
282 struct omap_video_timings *timings) 305 struct omap_video_timings *timings)
283{ 306{
284 int r; 307 int r;
308 struct omap_overlay_manager *mgr = dssdev->output->manager;
285 int lck_div, pck_div; 309 int lck_div, pck_div;
286 unsigned long fck; 310 unsigned long fck;
287 unsigned long pck; 311 unsigned long pck;
288 struct dispc_clock_info dispc_cinfo; 312 struct dispc_clock_info dispc_cinfo;
289 313
290 if (dss_mgr_check_timings(dssdev->manager, timings)) 314 if (dss_mgr_check_timings(mgr, timings))
291 return -EINVAL; 315 return -EINVAL;
292 316
293 if (timings->pixel_clock == 0) 317 if (timings->pixel_clock == 0)
@@ -325,11 +349,22 @@ int dpi_check_timings(struct omap_dss_device *dssdev,
325} 349}
326EXPORT_SYMBOL(dpi_check_timings); 350EXPORT_SYMBOL(dpi_check_timings);
327 351
352void omapdss_dpi_set_data_lines(struct omap_dss_device *dssdev, int data_lines)
353{
354 mutex_lock(&dpi.lock);
355
356 dpi.data_lines = data_lines;
357
358 mutex_unlock(&dpi.lock);
359}
360EXPORT_SYMBOL(omapdss_dpi_set_data_lines);
361
328static int __init dpi_init_display(struct omap_dss_device *dssdev) 362static int __init dpi_init_display(struct omap_dss_device *dssdev)
329{ 363{
330 DSSDBG("init_display\n"); 364 DSSDBG("init_display\n");
331 365
332 if (cpu_is_omap34xx() && dpi.vdds_dsi_reg == NULL) { 366 if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI) &&
367 dpi.vdds_dsi_reg == NULL) {
333 struct regulator *vdds_dsi; 368 struct regulator *vdds_dsi;
334 369
335 vdds_dsi = dss_get_vdds_dsi(); 370 vdds_dsi = dss_get_vdds_dsi();
@@ -351,10 +386,14 @@ static int __init dpi_init_display(struct omap_dss_device *dssdev)
351 return 0; 386 return 0;
352} 387}
353 388
354static void __init dpi_probe_pdata(struct platform_device *pdev) 389static struct omap_dss_device * __init dpi_find_dssdev(struct platform_device *pdev)
355{ 390{
356 struct omap_dss_board_info *pdata = pdev->dev.platform_data; 391 struct omap_dss_board_info *pdata = pdev->dev.platform_data;
357 int i, r; 392 const char *def_disp_name = dss_get_default_display_name();
393 struct omap_dss_device *def_dssdev;
394 int i;
395
396 def_dssdev = NULL;
358 397
359 for (i = 0; i < pdata->num_devices; ++i) { 398 for (i = 0; i < pdata->num_devices; ++i) {
360 struct omap_dss_device *dssdev = pdata->devices[i]; 399 struct omap_dss_device *dssdev = pdata->devices[i];
@@ -362,21 +401,75 @@ static void __init dpi_probe_pdata(struct platform_device *pdev)
362 if (dssdev->type != OMAP_DISPLAY_TYPE_DPI) 401 if (dssdev->type != OMAP_DISPLAY_TYPE_DPI)
363 continue; 402 continue;
364 403
365 r = dpi_init_display(dssdev); 404 if (def_dssdev == NULL)
366 if (r) { 405 def_dssdev = dssdev;
367 DSSERR("device %s init failed: %d\n", dssdev->name, r); 406
368 continue; 407 if (def_disp_name != NULL &&
408 strcmp(dssdev->name, def_disp_name) == 0) {
409 def_dssdev = dssdev;
410 break;
369 } 411 }
412 }
370 413
371 r = omap_dss_register_device(dssdev, &pdev->dev, i); 414 return def_dssdev;
372 if (r) 415}
373 DSSERR("device %s register failed: %d\n", 416
374 dssdev->name, r); 417static void __init dpi_probe_pdata(struct platform_device *dpidev)
418{
419 struct omap_dss_device *plat_dssdev;
420 struct omap_dss_device *dssdev;
421 int r;
422
423 plat_dssdev = dpi_find_dssdev(dpidev);
424
425 if (!plat_dssdev)
426 return;
427
428 dssdev = dss_alloc_and_init_device(&dpidev->dev);
429 if (!dssdev)
430 return;
431
432 dss_copy_device_pdata(dssdev, plat_dssdev);
433
434 r = dpi_init_display(dssdev);
435 if (r) {
436 DSSERR("device %s init failed: %d\n", dssdev->name, r);
437 dss_put_device(dssdev);
438 return;
439 }
440
441 r = dss_add_device(dssdev);
442 if (r) {
443 DSSERR("device %s register failed: %d\n", dssdev->name, r);
444 dss_put_device(dssdev);
445 return;
375 } 446 }
376} 447}
377 448
449static void __init dpi_init_output(struct platform_device *pdev)
450{
451 struct omap_dss_output *out = &dpi.output;
452
453 out->pdev = pdev;
454 out->id = OMAP_DSS_OUTPUT_DPI;
455 out->type = OMAP_DISPLAY_TYPE_DPI;
456
457 dss_register_output(out);
458}
459
460static void __exit dpi_uninit_output(struct platform_device *pdev)
461{
462 struct omap_dss_output *out = &dpi.output;
463
464 dss_unregister_output(out);
465}
466
378static int __init omap_dpi_probe(struct platform_device *pdev) 467static int __init omap_dpi_probe(struct platform_device *pdev)
379{ 468{
469 mutex_init(&dpi.lock);
470
471 dpi_init_output(pdev);
472
380 dpi_probe_pdata(pdev); 473 dpi_probe_pdata(pdev);
381 474
382 return 0; 475 return 0;
@@ -384,7 +477,9 @@ static int __init omap_dpi_probe(struct platform_device *pdev)
384 477
385static int __exit omap_dpi_remove(struct platform_device *pdev) 478static int __exit omap_dpi_remove(struct platform_device *pdev)
386{ 479{
387 omap_dss_unregister_child_devices(&pdev->dev); 480 dss_unregister_child_devices(&pdev->dev);
481
482 dpi_uninit_output(pdev);
388 483
389 return 0; 484 return 0;
390} 485}