diff options
Diffstat (limited to 'drivers/video/omap2/dss/venc.c')
-rw-r--r-- | drivers/video/omap2/dss/venc.c | 133 |
1 files changed, 101 insertions, 32 deletions
diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c index 9c3daf71750c..2b8973931ff4 100644 --- a/drivers/video/omap2/dss/venc.c +++ b/drivers/video/omap2/dss/venc.c | |||
@@ -415,6 +415,7 @@ static const struct venc_config *venc_timings_to_config( | |||
415 | return &venc_config_ntsc_trm; | 415 | return &venc_config_ntsc_trm; |
416 | 416 | ||
417 | BUG(); | 417 | BUG(); |
418 | return NULL; | ||
418 | } | 419 | } |
419 | 420 | ||
420 | static int venc_power_on(struct omap_dss_device *dssdev) | 421 | static int venc_power_on(struct omap_dss_device *dssdev) |
@@ -440,10 +441,11 @@ static int venc_power_on(struct omap_dss_device *dssdev) | |||
440 | 441 | ||
441 | venc_write_reg(VENC_OUTPUT_CONTROL, l); | 442 | venc_write_reg(VENC_OUTPUT_CONTROL, l); |
442 | 443 | ||
443 | dispc_set_digit_size(dssdev->panel.timings.x_res, | 444 | dss_mgr_set_timings(dssdev->manager, &dssdev->panel.timings); |
444 | dssdev->panel.timings.y_res/2); | ||
445 | 445 | ||
446 | regulator_enable(venc.vdda_dac_reg); | 446 | r = regulator_enable(venc.vdda_dac_reg); |
447 | if (r) | ||
448 | goto err; | ||
447 | 449 | ||
448 | if (dssdev->platform_enable) | 450 | if (dssdev->platform_enable) |
449 | dssdev->platform_enable(dssdev); | 451 | dssdev->platform_enable(dssdev); |
@@ -485,16 +487,68 @@ unsigned long venc_get_pixel_clock(void) | |||
485 | return 13500000; | 487 | return 13500000; |
486 | } | 488 | } |
487 | 489 | ||
490 | static ssize_t display_output_type_show(struct device *dev, | ||
491 | struct device_attribute *attr, char *buf) | ||
492 | { | ||
493 | struct omap_dss_device *dssdev = to_dss_device(dev); | ||
494 | const char *ret; | ||
495 | |||
496 | switch (dssdev->phy.venc.type) { | ||
497 | case OMAP_DSS_VENC_TYPE_COMPOSITE: | ||
498 | ret = "composite"; | ||
499 | break; | ||
500 | case OMAP_DSS_VENC_TYPE_SVIDEO: | ||
501 | ret = "svideo"; | ||
502 | break; | ||
503 | default: | ||
504 | return -EINVAL; | ||
505 | } | ||
506 | |||
507 | return snprintf(buf, PAGE_SIZE, "%s\n", ret); | ||
508 | } | ||
509 | |||
510 | static ssize_t display_output_type_store(struct device *dev, | ||
511 | struct device_attribute *attr, const char *buf, size_t size) | ||
512 | { | ||
513 | struct omap_dss_device *dssdev = to_dss_device(dev); | ||
514 | enum omap_dss_venc_type new_type; | ||
515 | |||
516 | if (sysfs_streq("composite", buf)) | ||
517 | new_type = OMAP_DSS_VENC_TYPE_COMPOSITE; | ||
518 | else if (sysfs_streq("svideo", buf)) | ||
519 | new_type = OMAP_DSS_VENC_TYPE_SVIDEO; | ||
520 | else | ||
521 | return -EINVAL; | ||
522 | |||
523 | mutex_lock(&venc.venc_lock); | ||
524 | |||
525 | if (dssdev->phy.venc.type != new_type) { | ||
526 | dssdev->phy.venc.type = new_type; | ||
527 | if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) { | ||
528 | venc_power_off(dssdev); | ||
529 | venc_power_on(dssdev); | ||
530 | } | ||
531 | } | ||
532 | |||
533 | mutex_unlock(&venc.venc_lock); | ||
534 | |||
535 | return size; | ||
536 | } | ||
537 | |||
538 | static DEVICE_ATTR(output_type, S_IRUGO | S_IWUSR, | ||
539 | display_output_type_show, display_output_type_store); | ||
540 | |||
488 | /* driver */ | 541 | /* driver */ |
489 | static int venc_panel_probe(struct omap_dss_device *dssdev) | 542 | static int venc_panel_probe(struct omap_dss_device *dssdev) |
490 | { | 543 | { |
491 | dssdev->panel.timings = omap_dss_pal_timings; | 544 | dssdev->panel.timings = omap_dss_pal_timings; |
492 | 545 | ||
493 | return 0; | 546 | return device_create_file(&dssdev->dev, &dev_attr_output_type); |
494 | } | 547 | } |
495 | 548 | ||
496 | static void venc_panel_remove(struct omap_dss_device *dssdev) | 549 | static void venc_panel_remove(struct omap_dss_device *dssdev) |
497 | { | 550 | { |
551 | device_remove_file(&dssdev->dev, &dev_attr_output_type); | ||
498 | } | 552 | } |
499 | 553 | ||
500 | static int venc_panel_enable(struct omap_dss_device *dssdev) | 554 | static int venc_panel_enable(struct omap_dss_device *dssdev) |
@@ -577,12 +631,6 @@ static int venc_panel_resume(struct omap_dss_device *dssdev) | |||
577 | return venc_panel_enable(dssdev); | 631 | return venc_panel_enable(dssdev); |
578 | } | 632 | } |
579 | 633 | ||
580 | static void venc_get_timings(struct omap_dss_device *dssdev, | ||
581 | struct omap_video_timings *timings) | ||
582 | { | ||
583 | *timings = dssdev->panel.timings; | ||
584 | } | ||
585 | |||
586 | static void venc_set_timings(struct omap_dss_device *dssdev, | 634 | static void venc_set_timings(struct omap_dss_device *dssdev, |
587 | struct omap_video_timings *timings) | 635 | struct omap_video_timings *timings) |
588 | { | 636 | { |
@@ -597,6 +645,8 @@ static void venc_set_timings(struct omap_dss_device *dssdev, | |||
597 | /* turn the venc off and on to get new timings to use */ | 645 | /* turn the venc off and on to get new timings to use */ |
598 | venc_panel_disable(dssdev); | 646 | venc_panel_disable(dssdev); |
599 | venc_panel_enable(dssdev); | 647 | venc_panel_enable(dssdev); |
648 | } else { | ||
649 | dss_mgr_set_timings(dssdev->manager, timings); | ||
600 | } | 650 | } |
601 | } | 651 | } |
602 | 652 | ||
@@ -661,7 +711,6 @@ static struct omap_dss_driver venc_driver = { | |||
661 | .get_resolution = omapdss_default_get_resolution, | 711 | .get_resolution = omapdss_default_get_resolution, |
662 | .get_recommended_bpp = omapdss_default_get_recommended_bpp, | 712 | .get_recommended_bpp = omapdss_default_get_recommended_bpp, |
663 | 713 | ||
664 | .get_timings = venc_get_timings, | ||
665 | .set_timings = venc_set_timings, | 714 | .set_timings = venc_set_timings, |
666 | .check_timings = venc_check_timings, | 715 | .check_timings = venc_check_timings, |
667 | 716 | ||
@@ -675,7 +724,7 @@ static struct omap_dss_driver venc_driver = { | |||
675 | }; | 724 | }; |
676 | /* driver end */ | 725 | /* driver end */ |
677 | 726 | ||
678 | int venc_init_display(struct omap_dss_device *dssdev) | 727 | static int __init venc_init_display(struct omap_dss_device *dssdev) |
679 | { | 728 | { |
680 | DSSDBG("init_display\n"); | 729 | DSSDBG("init_display\n"); |
681 | 730 | ||
@@ -695,7 +744,7 @@ int venc_init_display(struct omap_dss_device *dssdev) | |||
695 | return 0; | 744 | return 0; |
696 | } | 745 | } |
697 | 746 | ||
698 | void venc_dump_regs(struct seq_file *s) | 747 | static void venc_dump_regs(struct seq_file *s) |
699 | { | 748 | { |
700 | #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, venc_read_reg(r)) | 749 | #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, venc_read_reg(r)) |
701 | 750 | ||
@@ -779,8 +828,32 @@ static void venc_put_clocks(void) | |||
779 | clk_put(venc.tv_dac_clk); | 828 | clk_put(venc.tv_dac_clk); |
780 | } | 829 | } |
781 | 830 | ||
831 | static void __init venc_probe_pdata(struct platform_device *pdev) | ||
832 | { | ||
833 | struct omap_dss_board_info *pdata = pdev->dev.platform_data; | ||
834 | int r, i; | ||
835 | |||
836 | for (i = 0; i < pdata->num_devices; ++i) { | ||
837 | struct omap_dss_device *dssdev = pdata->devices[i]; | ||
838 | |||
839 | if (dssdev->type != OMAP_DISPLAY_TYPE_VENC) | ||
840 | continue; | ||
841 | |||
842 | r = venc_init_display(dssdev); | ||
843 | if (r) { | ||
844 | DSSERR("device %s init failed: %d\n", dssdev->name, r); | ||
845 | continue; | ||
846 | } | ||
847 | |||
848 | r = omap_dss_register_device(dssdev, &pdev->dev, i); | ||
849 | if (r) | ||
850 | DSSERR("device %s register failed: %d\n", | ||
851 | dssdev->name, r); | ||
852 | } | ||
853 | } | ||
854 | |||
782 | /* VENC HW IP initialisation */ | 855 | /* VENC HW IP initialisation */ |
783 | static int omap_venchw_probe(struct platform_device *pdev) | 856 | static int __init omap_venchw_probe(struct platform_device *pdev) |
784 | { | 857 | { |
785 | u8 rev_id; | 858 | u8 rev_id; |
786 | struct resource *venc_mem; | 859 | struct resource *venc_mem; |
@@ -824,6 +897,10 @@ static int omap_venchw_probe(struct platform_device *pdev) | |||
824 | if (r) | 897 | if (r) |
825 | goto err_reg_panel_driver; | 898 | goto err_reg_panel_driver; |
826 | 899 | ||
900 | dss_debugfs_create_file("venc", venc_dump_regs); | ||
901 | |||
902 | venc_probe_pdata(pdev); | ||
903 | |||
827 | return 0; | 904 | return 0; |
828 | 905 | ||
829 | err_reg_panel_driver: | 906 | err_reg_panel_driver: |
@@ -833,12 +910,15 @@ err_runtime_get: | |||
833 | return r; | 910 | return r; |
834 | } | 911 | } |
835 | 912 | ||
836 | static int omap_venchw_remove(struct platform_device *pdev) | 913 | static int __exit omap_venchw_remove(struct platform_device *pdev) |
837 | { | 914 | { |
915 | omap_dss_unregister_child_devices(&pdev->dev); | ||
916 | |||
838 | if (venc.vdda_dac_reg != NULL) { | 917 | if (venc.vdda_dac_reg != NULL) { |
839 | regulator_put(venc.vdda_dac_reg); | 918 | regulator_put(venc.vdda_dac_reg); |
840 | venc.vdda_dac_reg = NULL; | 919 | venc.vdda_dac_reg = NULL; |
841 | } | 920 | } |
921 | |||
842 | omap_dss_unregister_driver(&venc_driver); | 922 | omap_dss_unregister_driver(&venc_driver); |
843 | 923 | ||
844 | pm_runtime_disable(&pdev->dev); | 924 | pm_runtime_disable(&pdev->dev); |
@@ -853,7 +933,6 @@ static int venc_runtime_suspend(struct device *dev) | |||
853 | clk_disable(venc.tv_dac_clk); | 933 | clk_disable(venc.tv_dac_clk); |
854 | 934 | ||
855 | dispc_runtime_put(); | 935 | dispc_runtime_put(); |
856 | dss_runtime_put(); | ||
857 | 936 | ||
858 | return 0; | 937 | return 0; |
859 | } | 938 | } |
@@ -862,23 +941,14 @@ static int venc_runtime_resume(struct device *dev) | |||
862 | { | 941 | { |
863 | int r; | 942 | int r; |
864 | 943 | ||
865 | r = dss_runtime_get(); | ||
866 | if (r < 0) | ||
867 | goto err_get_dss; | ||
868 | |||
869 | r = dispc_runtime_get(); | 944 | r = dispc_runtime_get(); |
870 | if (r < 0) | 945 | if (r < 0) |
871 | goto err_get_dispc; | 946 | return r; |
872 | 947 | ||
873 | if (venc.tv_dac_clk) | 948 | if (venc.tv_dac_clk) |
874 | clk_enable(venc.tv_dac_clk); | 949 | clk_enable(venc.tv_dac_clk); |
875 | 950 | ||
876 | return 0; | 951 | return 0; |
877 | |||
878 | err_get_dispc: | ||
879 | dss_runtime_put(); | ||
880 | err_get_dss: | ||
881 | return r; | ||
882 | } | 952 | } |
883 | 953 | ||
884 | static const struct dev_pm_ops venc_pm_ops = { | 954 | static const struct dev_pm_ops venc_pm_ops = { |
@@ -887,8 +957,7 @@ static const struct dev_pm_ops venc_pm_ops = { | |||
887 | }; | 957 | }; |
888 | 958 | ||
889 | static struct platform_driver omap_venchw_driver = { | 959 | static struct platform_driver omap_venchw_driver = { |
890 | .probe = omap_venchw_probe, | 960 | .remove = __exit_p(omap_venchw_remove), |
891 | .remove = omap_venchw_remove, | ||
892 | .driver = { | 961 | .driver = { |
893 | .name = "omapdss_venc", | 962 | .name = "omapdss_venc", |
894 | .owner = THIS_MODULE, | 963 | .owner = THIS_MODULE, |
@@ -896,18 +965,18 @@ static struct platform_driver omap_venchw_driver = { | |||
896 | }, | 965 | }, |
897 | }; | 966 | }; |
898 | 967 | ||
899 | int venc_init_platform_driver(void) | 968 | int __init venc_init_platform_driver(void) |
900 | { | 969 | { |
901 | if (cpu_is_omap44xx()) | 970 | if (cpu_is_omap44xx()) |
902 | return 0; | 971 | return 0; |
903 | 972 | ||
904 | return platform_driver_register(&omap_venchw_driver); | 973 | return platform_driver_probe(&omap_venchw_driver, omap_venchw_probe); |
905 | } | 974 | } |
906 | 975 | ||
907 | void venc_uninit_platform_driver(void) | 976 | void __exit venc_uninit_platform_driver(void) |
908 | { | 977 | { |
909 | if (cpu_is_omap44xx()) | 978 | if (cpu_is_omap44xx()) |
910 | return; | 979 | return; |
911 | 980 | ||
912 | return platform_driver_unregister(&omap_venchw_driver); | 981 | platform_driver_unregister(&omap_venchw_driver); |
913 | } | 982 | } |