diff options
Diffstat (limited to 'drivers/video/omap2/dss/dpi.c')
-rw-r--r-- | drivers/video/omap2/dss/dpi.c | 181 |
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 | ||
38 | static struct { | 39 | static 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 | ||
45 | static struct platform_device *dpi_get_dsidev(enum omap_dss_clk_source clk) | 52 | static 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 | ||
122 | static int dpi_set_mode(struct omap_dss_device *dssdev) | 129 | static 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 | ||
154 | static void dpi_config_lcd_manager(struct omap_dss_device *dssdev) | 162 | static 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 | ||
168 | int omapdss_dpi_display_enable(struct omap_dss_device *dssdev) | 178 | int 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 | ||
222 | err_mgr_enable: | 243 | err_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); |
229 | err_get_dsi: | 250 | err_get_dsi: |
251 | err_src_sel: | ||
230 | dispc_runtime_put(); | 252 | dispc_runtime_put(); |
231 | err_get_dispc: | 253 | err_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); |
234 | err_reg_enable: | 256 | err_reg_enable: |
235 | omap_dss_stop_device(dssdev); | 257 | omap_dss_stop_device(dssdev); |
236 | err_start_dev: | 258 | err_start_dev: |
259 | err_no_out_mgr: | ||
260 | err_no_reg: | ||
261 | mutex_unlock(&dpi.lock); | ||
237 | return r; | 262 | return r; |
238 | } | 263 | } |
239 | EXPORT_SYMBOL(omapdss_dpi_display_enable); | 264 | EXPORT_SYMBOL(omapdss_dpi_display_enable); |
240 | 265 | ||
241 | void omapdss_dpi_display_disable(struct omap_dss_device *dssdev) | 266 | void 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 | } |
258 | EXPORT_SYMBOL(omapdss_dpi_display_disable); | 289 | EXPORT_SYMBOL(omapdss_dpi_display_disable); |
259 | 290 | ||
260 | void dpi_set_timings(struct omap_dss_device *dssdev, | 291 | void 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 | } |
279 | EXPORT_SYMBOL(dpi_set_timings); | 302 | EXPORT_SYMBOL(omapdss_dpi_set_timings); |
280 | 303 | ||
281 | int dpi_check_timings(struct omap_dss_device *dssdev, | 304 | int 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 | } |
326 | EXPORT_SYMBOL(dpi_check_timings); | 350 | EXPORT_SYMBOL(dpi_check_timings); |
327 | 351 | ||
352 | void 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 | } | ||
360 | EXPORT_SYMBOL(omapdss_dpi_set_data_lines); | ||
361 | |||
328 | static int __init dpi_init_display(struct omap_dss_device *dssdev) | 362 | static 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 | ||
354 | static void __init dpi_probe_pdata(struct platform_device *pdev) | 389 | static 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); | 417 | static 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 | ||
449 | static 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 | |||
460 | static 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 | |||
378 | static int __init omap_dpi_probe(struct platform_device *pdev) | 467 | static 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 | ||
385 | static int __exit omap_dpi_remove(struct platform_device *pdev) | 478 | static 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 | } |