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.c126
1 files changed, 95 insertions, 31 deletions
diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c
index 56748cf8760e..4af136a04e53 100644
--- a/drivers/video/omap2/dss/dpi.c
+++ b/drivers/video/omap2/dss/dpi.c
@@ -49,34 +49,53 @@ static struct {
49 struct omap_dss_output output; 49 struct omap_dss_output output;
50} dpi; 50} dpi;
51 51
52static struct platform_device *dpi_get_dsidev(enum omap_dss_clk_source clk) 52static struct platform_device *dpi_get_dsidev(enum omap_channel channel)
53{ 53{
54 int dsi_module; 54 /*
55 55 * XXX we can't currently use DSI PLL for DPI with OMAP3, as the DSI PLL
56 dsi_module = clk == OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC ? 0 : 1; 56 * would also be used for DISPC fclk. Meaning, when the DPI output is
57 * disabled, DISPC clock will be disabled, and TV out will stop.
58 */
59 switch (omapdss_get_version()) {
60 case OMAPDSS_VER_OMAP24xx:
61 case OMAPDSS_VER_OMAP34xx_ES1:
62 case OMAPDSS_VER_OMAP34xx_ES3:
63 case OMAPDSS_VER_OMAP3630:
64 case OMAPDSS_VER_AM35xx:
65 return NULL;
66 default:
67 break;
68 }
57 69
58 return dsi_get_dsidev_from_id(dsi_module); 70 switch (channel) {
71 case OMAP_DSS_CHANNEL_LCD:
72 return dsi_get_dsidev_from_id(0);
73 case OMAP_DSS_CHANNEL_LCD2:
74 return dsi_get_dsidev_from_id(1);
75 default:
76 return NULL;
77 }
59} 78}
60 79
61static bool dpi_use_dsi_pll(struct omap_dss_device *dssdev) 80static enum omap_dss_clk_source dpi_get_alt_clk_src(enum omap_channel channel)
62{ 81{
63 if (dssdev->clocks.dispc.dispc_fclk_src == 82 switch (channel) {
64 OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC || 83 case OMAP_DSS_CHANNEL_LCD:
65 dssdev->clocks.dispc.dispc_fclk_src == 84 return OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC;
66 OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC || 85 case OMAP_DSS_CHANNEL_LCD2:
67 dssdev->clocks.dispc.channel.lcd_clk_src == 86 return OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC;
68 OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC || 87 default:
69 dssdev->clocks.dispc.channel.lcd_clk_src == 88 /* this shouldn't happen */
70 OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC) 89 WARN_ON(1);
71 return true; 90 return OMAP_DSS_CLK_SRC_FCK;
72 else 91 }
73 return false;
74} 92}
75 93
76static int dpi_set_dsi_clk(struct omap_dss_device *dssdev, 94static int dpi_set_dsi_clk(struct omap_dss_device *dssdev,
77 unsigned long pck_req, unsigned long *fck, int *lck_div, 95 unsigned long pck_req, unsigned long *fck, int *lck_div,
78 int *pck_div) 96 int *pck_div)
79{ 97{
98 struct omap_overlay_manager *mgr = dssdev->output->manager;
80 struct dsi_clock_info dsi_cinfo; 99 struct dsi_clock_info dsi_cinfo;
81 struct dispc_clock_info dispc_cinfo; 100 struct dispc_clock_info dispc_cinfo;
82 int r; 101 int r;
@@ -90,7 +109,8 @@ static int dpi_set_dsi_clk(struct omap_dss_device *dssdev,
90 if (r) 109 if (r)
91 return r; 110 return r;
92 111
93 dss_select_dispc_clk_source(dssdev->clocks.dispc.dispc_fclk_src); 112 dss_select_lcd_clk_source(mgr->id,
113 dpi_get_alt_clk_src(mgr->id));
94 114
95 dpi.mgr_config.clock_info = dispc_cinfo; 115 dpi.mgr_config.clock_info = dispc_cinfo;
96 116
@@ -135,7 +155,7 @@ static int dpi_set_mode(struct omap_dss_device *dssdev)
135 unsigned long pck; 155 unsigned long pck;
136 int r = 0; 156 int r = 0;
137 157
138 if (dpi_use_dsi_pll(dssdev)) 158 if (dpi.dsidev)
139 r = dpi_set_dsi_clk(dssdev, t->pixel_clock * 1000, &fck, 159 r = dpi_set_dsi_clk(dssdev, t->pixel_clock * 1000, &fck,
140 &lck_div, &pck_div); 160 &lck_div, &pck_div);
141 else 161 else
@@ -214,7 +234,7 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
214 if (r) 234 if (r)
215 goto err_src_sel; 235 goto err_src_sel;
216 236
217 if (dpi_use_dsi_pll(dssdev)) { 237 if (dpi.dsidev) {
218 r = dsi_runtime_get(dpi.dsidev); 238 r = dsi_runtime_get(dpi.dsidev);
219 if (r) 239 if (r)
220 goto err_get_dsi; 240 goto err_get_dsi;
@@ -242,10 +262,10 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
242 262
243err_mgr_enable: 263err_mgr_enable:
244err_set_mode: 264err_set_mode:
245 if (dpi_use_dsi_pll(dssdev)) 265 if (dpi.dsidev)
246 dsi_pll_uninit(dpi.dsidev, true); 266 dsi_pll_uninit(dpi.dsidev, true);
247err_dsi_pll_init: 267err_dsi_pll_init:
248 if (dpi_use_dsi_pll(dssdev)) 268 if (dpi.dsidev)
249 dsi_runtime_put(dpi.dsidev); 269 dsi_runtime_put(dpi.dsidev);
250err_get_dsi: 270err_get_dsi:
251err_src_sel: 271err_src_sel:
@@ -271,8 +291,8 @@ void omapdss_dpi_display_disable(struct omap_dss_device *dssdev)
271 291
272 dss_mgr_disable(mgr); 292 dss_mgr_disable(mgr);
273 293
274 if (dpi_use_dsi_pll(dssdev)) { 294 if (dpi.dsidev) {
275 dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK); 295 dss_select_lcd_clk_source(mgr->id, OMAP_DSS_CLK_SRC_FCK);
276 dsi_pll_uninit(dpi.dsidev, true); 296 dsi_pll_uninit(dpi.dsidev, true);
277 dsi_runtime_put(dpi.dsidev); 297 dsi_runtime_put(dpi.dsidev);
278 } 298 }
@@ -311,13 +331,13 @@ int dpi_check_timings(struct omap_dss_device *dssdev,
311 unsigned long pck; 331 unsigned long pck;
312 struct dispc_clock_info dispc_cinfo; 332 struct dispc_clock_info dispc_cinfo;
313 333
314 if (dss_mgr_check_timings(mgr, timings)) 334 if (mgr && !dispc_mgr_timings_ok(mgr->id, timings))
315 return -EINVAL; 335 return -EINVAL;
316 336
317 if (timings->pixel_clock == 0) 337 if (timings->pixel_clock == 0)
318 return -EINVAL; 338 return -EINVAL;
319 339
320 if (dpi_use_dsi_pll(dssdev)) { 340 if (dpi.dsidev) {
321 struct dsi_clock_info dsi_cinfo; 341 struct dsi_clock_info dsi_cinfo;
322 r = dsi_pll_calc_clock_div_pck(dpi.dsidev, 342 r = dsi_pll_calc_clock_div_pck(dpi.dsidev,
323 timings->pixel_clock * 1000, 343 timings->pixel_clock * 1000,
@@ -359,8 +379,32 @@ void omapdss_dpi_set_data_lines(struct omap_dss_device *dssdev, int data_lines)
359} 379}
360EXPORT_SYMBOL(omapdss_dpi_set_data_lines); 380EXPORT_SYMBOL(omapdss_dpi_set_data_lines);
361 381
382static int __init dpi_verify_dsi_pll(struct platform_device *dsidev)
383{
384 int r;
385
386 /* do initial setup with the PLL to see if it is operational */
387
388 r = dsi_runtime_get(dsidev);
389 if (r)
390 return r;
391
392 r = dsi_pll_init(dsidev, 0, 1);
393 if (r) {
394 dsi_runtime_put(dsidev);
395 return r;
396 }
397
398 dsi_pll_uninit(dsidev, true);
399 dsi_runtime_put(dsidev);
400
401 return 0;
402}
403
362static int __init dpi_init_display(struct omap_dss_device *dssdev) 404static int __init dpi_init_display(struct omap_dss_device *dssdev)
363{ 405{
406 struct platform_device *dsidev;
407
364 DSSDBG("init_display\n"); 408 DSSDBG("init_display\n");
365 409
366 if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI) && 410 if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI) &&
@@ -377,19 +421,30 @@ static int __init dpi_init_display(struct omap_dss_device *dssdev)
377 dpi.vdds_dsi_reg = vdds_dsi; 421 dpi.vdds_dsi_reg = vdds_dsi;
378 } 422 }
379 423
380 if (dpi_use_dsi_pll(dssdev)) { 424 /*
381 enum omap_dss_clk_source dispc_fclk_src = 425 * XXX We shouldn't need dssdev->channel for this. The dsi pll clock
382 dssdev->clocks.dispc.dispc_fclk_src; 426 * source for DPI is SoC integration detail, not something that should
383 dpi.dsidev = dpi_get_dsidev(dispc_fclk_src); 427 * be configured in the dssdev
428 */
429 dsidev = dpi_get_dsidev(dssdev->channel);
430
431 if (dsidev && dpi_verify_dsi_pll(dsidev)) {
432 dsidev = NULL;
433 DSSWARN("DSI PLL not operational\n");
384 } 434 }
385 435
436 if (dsidev)
437 DSSDBG("using DSI PLL for DPI clock\n");
438
439 dpi.dsidev = dsidev;
440
386 return 0; 441 return 0;
387} 442}
388 443
389static struct omap_dss_device * __init dpi_find_dssdev(struct platform_device *pdev) 444static struct omap_dss_device * __init dpi_find_dssdev(struct platform_device *pdev)
390{ 445{
391 struct omap_dss_board_info *pdata = pdev->dev.platform_data; 446 struct omap_dss_board_info *pdata = pdev->dev.platform_data;
392 const char *def_disp_name = dss_get_default_display_name(); 447 const char *def_disp_name = omapdss_get_default_display_name();
393 struct omap_dss_device *def_dssdev; 448 struct omap_dss_device *def_dssdev;
394 int i; 449 int i;
395 450
@@ -438,9 +493,18 @@ static void __init dpi_probe_pdata(struct platform_device *dpidev)
438 return; 493 return;
439 } 494 }
440 495
496 r = omapdss_output_set_device(&dpi.output, dssdev);
497 if (r) {
498 DSSERR("failed to connect output to new device: %s\n",
499 dssdev->name);
500 dss_put_device(dssdev);
501 return;
502 }
503
441 r = dss_add_device(dssdev); 504 r = dss_add_device(dssdev);
442 if (r) { 505 if (r) {
443 DSSERR("device %s register failed: %d\n", dssdev->name, r); 506 DSSERR("device %s register failed: %d\n", dssdev->name, r);
507 omapdss_output_unset_device(&dpi.output);
444 dss_put_device(dssdev); 508 dss_put_device(dssdev);
445 return; 509 return;
446 } 510 }