aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/omap2/dss/venc.c
diff options
context:
space:
mode:
authorTomi Valkeinen <tomi.valkeinen@ti.com>2011-05-27 03:52:19 -0400
committerTomi Valkeinen <tomi.valkeinen@ti.com>2011-07-25 03:22:04 -0400
commit4fbafaf371be780ed2cd73a520dfeafa1ea73e24 (patch)
tree50be77c643fe710ce07bfea5e21587f9f5c38ac5 /drivers/video/omap2/dss/venc.c
parentde3050a74e2d2830189ceaa5f5fc05b776518d68 (diff)
OMAP: DSS2: Use PM runtime & HWMOD support
Use PM runtime and HWMOD support to handle enabling and disabling of DSS modules. Each DSS module will have get and put functions which can be used to enable and disable that module. The functions use pm_runtime and hwmod opt-clocks to enable the hardware. Acked-by: Kevin Hilman <khilman@ti.com> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Diffstat (limited to 'drivers/video/omap2/dss/venc.c')
-rw-r--r--drivers/video/omap2/dss/venc.c165
1 files changed, 142 insertions, 23 deletions
diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c
index bf0431f788c1..71e005df1759 100644
--- a/drivers/video/omap2/dss/venc.c
+++ b/drivers/video/omap2/dss/venc.c
@@ -33,6 +33,7 @@
33#include <linux/seq_file.h> 33#include <linux/seq_file.h>
34#include <linux/platform_device.h> 34#include <linux/platform_device.h>
35#include <linux/regulator/consumer.h> 35#include <linux/regulator/consumer.h>
36#include <linux/pm_runtime.h>
36 37
37#include <video/omapdss.h> 38#include <video/omapdss.h>
38#include <plat/cpu.h> 39#include <plat/cpu.h>
@@ -293,6 +294,9 @@ static struct {
293 struct mutex venc_lock; 294 struct mutex venc_lock;
294 u32 wss_data; 295 u32 wss_data;
295 struct regulator *vdda_dac_reg; 296 struct regulator *vdda_dac_reg;
297
298 struct clk *tv_clk;
299 struct clk *tv_dac_clk;
296} venc; 300} venc;
297 301
298static inline void venc_write_reg(int idx, u32 val) 302static inline void venc_write_reg(int idx, u32 val)
@@ -381,17 +385,25 @@ static void venc_reset(void)
381#endif 385#endif
382} 386}
383 387
384static void venc_enable_clocks(int enable) 388static int venc_runtime_get(void)
385{ 389{
386 if (enable) { 390 int r;
387 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_TVFCK); 391
388 if (dss_has_feature(FEAT_VENC_REQUIRES_TV_DAC_CLK)) 392 DSSDBG("venc_runtime_get\n");
389 dss_clk_enable(DSS_CLK_VIDFCK); 393
390 } else { 394 r = pm_runtime_get_sync(&venc.pdev->dev);
391 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_TVFCK); 395 WARN_ON(r < 0);
392 if (dss_has_feature(FEAT_VENC_REQUIRES_TV_DAC_CLK)) 396 return r < 0 ? r : 0;
393 dss_clk_disable(DSS_CLK_VIDFCK); 397}
394 } 398
399static void venc_runtime_put(void)
400{
401 int r;
402
403 DSSDBG("venc_runtime_put\n");
404
405 r = pm_runtime_put(&venc.pdev->dev);
406 WARN_ON(r < 0);
395} 407}
396 408
397static const struct venc_config *venc_timings_to_config( 409static const struct venc_config *venc_timings_to_config(
@@ -410,8 +422,6 @@ static void venc_power_on(struct omap_dss_device *dssdev)
410{ 422{
411 u32 l; 423 u32 l;
412 424
413 venc_enable_clocks(1);
414
415 venc_reset(); 425 venc_reset();
416 venc_write_config(venc_timings_to_config(&dssdev->panel.timings)); 426 venc_write_config(venc_timings_to_config(&dssdev->panel.timings));
417 427
@@ -452,8 +462,6 @@ static void venc_power_off(struct omap_dss_device *dssdev)
452 dssdev->platform_disable(dssdev); 462 dssdev->platform_disable(dssdev);
453 463
454 regulator_disable(venc.vdda_dac_reg); 464 regulator_disable(venc.vdda_dac_reg);
455
456 venc_enable_clocks(0);
457} 465}
458 466
459 467
@@ -491,6 +499,10 @@ static int venc_panel_enable(struct omap_dss_device *dssdev)
491 goto err1; 499 goto err1;
492 } 500 }
493 501
502 r = venc_runtime_get();
503 if (r)
504 goto err1;
505
494 venc_power_on(dssdev); 506 venc_power_on(dssdev);
495 507
496 venc.wss_data = 0; 508 venc.wss_data = 0;
@@ -524,6 +536,8 @@ static void venc_panel_disable(struct omap_dss_device *dssdev)
524 536
525 venc_power_off(dssdev); 537 venc_power_off(dssdev);
526 538
539 venc_runtime_put();
540
527 dssdev->state = OMAP_DSS_DISPLAY_DISABLED; 541 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
528 542
529 omap_dss_stop_device(dssdev); 543 omap_dss_stop_device(dssdev);
@@ -588,6 +602,7 @@ static u32 venc_get_wss(struct omap_dss_device *dssdev)
588static int venc_set_wss(struct omap_dss_device *dssdev, u32 wss) 602static int venc_set_wss(struct omap_dss_device *dssdev, u32 wss)
589{ 603{
590 const struct venc_config *config; 604 const struct venc_config *config;
605 int r;
591 606
592 DSSDBG("venc_set_wss\n"); 607 DSSDBG("venc_set_wss\n");
593 608
@@ -598,16 +613,19 @@ static int venc_set_wss(struct omap_dss_device *dssdev, u32 wss)
598 /* Invert due to VENC_L21_WC_CTL:INV=1 */ 613 /* Invert due to VENC_L21_WC_CTL:INV=1 */
599 venc.wss_data = (wss ^ 0xfffff) << 8; 614 venc.wss_data = (wss ^ 0xfffff) << 8;
600 615
601 venc_enable_clocks(1); 616 r = venc_runtime_get();
617 if (r)
618 goto err;
602 619
603 venc_write_reg(VENC_BSTAMP_WSS_DATA, config->bstamp_wss_data | 620 venc_write_reg(VENC_BSTAMP_WSS_DATA, config->bstamp_wss_data |
604 venc.wss_data); 621 venc.wss_data);
605 622
606 venc_enable_clocks(0); 623 venc_runtime_put();
607 624
625err:
608 mutex_unlock(&venc.venc_lock); 626 mutex_unlock(&venc.venc_lock);
609 627
610 return 0; 628 return r;
611} 629}
612 630
613static struct omap_dss_driver venc_driver = { 631static struct omap_dss_driver venc_driver = {
@@ -660,7 +678,8 @@ void venc_dump_regs(struct seq_file *s)
660{ 678{
661#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, venc_read_reg(r)) 679#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, venc_read_reg(r))
662 680
663 venc_enable_clocks(1); 681 if (venc_runtime_get())
682 return;
664 683
665 DUMPREG(VENC_F_CONTROL); 684 DUMPREG(VENC_F_CONTROL);
666 DUMPREG(VENC_VIDOUT_CTRL); 685 DUMPREG(VENC_VIDOUT_CTRL);
@@ -704,16 +723,53 @@ void venc_dump_regs(struct seq_file *s)
704 DUMPREG(VENC_OUTPUT_CONTROL); 723 DUMPREG(VENC_OUTPUT_CONTROL);
705 DUMPREG(VENC_OUTPUT_TEST); 724 DUMPREG(VENC_OUTPUT_TEST);
706 725
707 venc_enable_clocks(0); 726 venc_runtime_put();
708 727
709#undef DUMPREG 728#undef DUMPREG
710} 729}
711 730
731static int venc_get_clocks(struct platform_device *pdev)
732{
733 struct clk *clk;
734
735 clk = clk_get(&pdev->dev, "fck");
736 if (IS_ERR(clk)) {
737 DSSERR("can't get fck\n");
738 return PTR_ERR(clk);
739 }
740
741 venc.tv_clk = clk;
742
743 if (dss_has_feature(FEAT_VENC_REQUIRES_TV_DAC_CLK)) {
744 clk = clk_get(&pdev->dev, "tv_dac_clk");
745 if (IS_ERR(clk)) {
746 DSSERR("can't get tv_dac_clk\n");
747 clk_put(venc.tv_clk);
748 return PTR_ERR(clk);
749 }
750 } else {
751 clk = NULL;
752 }
753
754 venc.tv_dac_clk = clk;
755
756 return 0;
757}
758
759static void venc_put_clocks(void)
760{
761 if (venc.tv_clk)
762 clk_put(venc.tv_clk);
763 if (venc.tv_dac_clk)
764 clk_put(venc.tv_dac_clk);
765}
766
712/* VENC HW IP initialisation */ 767/* VENC HW IP initialisation */
713static int omap_venchw_probe(struct platform_device *pdev) 768static int omap_venchw_probe(struct platform_device *pdev)
714{ 769{
715 u8 rev_id; 770 u8 rev_id;
716 struct resource *venc_mem; 771 struct resource *venc_mem;
772 int r;
717 773
718 venc.pdev = pdev; 774 venc.pdev = pdev;
719 775
@@ -724,22 +780,40 @@ static int omap_venchw_probe(struct platform_device *pdev)
724 venc_mem = platform_get_resource(venc.pdev, IORESOURCE_MEM, 0); 780 venc_mem = platform_get_resource(venc.pdev, IORESOURCE_MEM, 0);
725 if (!venc_mem) { 781 if (!venc_mem) {
726 DSSERR("can't get IORESOURCE_MEM VENC\n"); 782 DSSERR("can't get IORESOURCE_MEM VENC\n");
727 return -EINVAL; 783 r = -EINVAL;
784 goto err_ioremap;
728 } 785 }
729 venc.base = ioremap(venc_mem->start, resource_size(venc_mem)); 786 venc.base = ioremap(venc_mem->start, resource_size(venc_mem));
730 if (!venc.base) { 787 if (!venc.base) {
731 DSSERR("can't ioremap VENC\n"); 788 DSSERR("can't ioremap VENC\n");
732 return -ENOMEM; 789 r = -ENOMEM;
790 goto err_ioremap;
733 } 791 }
734 792
735 venc_enable_clocks(1); 793 r = venc_get_clocks(pdev);
794 if (r)
795 goto err_get_clk;
796
797 pm_runtime_enable(&pdev->dev);
798
799 r = venc_runtime_get();
800 if (r)
801 goto err_get_venc;
736 802
737 rev_id = (u8)(venc_read_reg(VENC_REV_ID) & 0xff); 803 rev_id = (u8)(venc_read_reg(VENC_REV_ID) & 0xff);
738 dev_dbg(&pdev->dev, "OMAP VENC rev %d\n", rev_id); 804 dev_dbg(&pdev->dev, "OMAP VENC rev %d\n", rev_id);
739 805
740 venc_enable_clocks(0); 806 venc_runtime_put();
741 807
742 return omap_dss_register_driver(&venc_driver); 808 return omap_dss_register_driver(&venc_driver);
809
810err_get_venc:
811 pm_runtime_disable(&pdev->dev);
812 venc_put_clocks();
813err_get_clk:
814 iounmap(venc.base);
815err_ioremap:
816 return r;
743} 817}
744 818
745static int omap_venchw_remove(struct platform_device *pdev) 819static int omap_venchw_remove(struct platform_device *pdev)
@@ -750,16 +824,61 @@ static int omap_venchw_remove(struct platform_device *pdev)
750 } 824 }
751 omap_dss_unregister_driver(&venc_driver); 825 omap_dss_unregister_driver(&venc_driver);
752 826
827 pm_runtime_disable(&pdev->dev);
828 venc_put_clocks();
829
753 iounmap(venc.base); 830 iounmap(venc.base);
754 return 0; 831 return 0;
755} 832}
756 833
834static int venc_runtime_suspend(struct device *dev)
835{
836 if (venc.tv_dac_clk)
837 clk_disable(venc.tv_dac_clk);
838 clk_disable(venc.tv_clk);
839
840 dispc_runtime_put();
841 dss_runtime_put();
842
843 return 0;
844}
845
846static int venc_runtime_resume(struct device *dev)
847{
848 int r;
849
850 r = dss_runtime_get();
851 if (r < 0)
852 goto err_get_dss;
853
854 r = dispc_runtime_get();
855 if (r < 0)
856 goto err_get_dispc;
857
858 clk_enable(venc.tv_clk);
859 if (venc.tv_dac_clk)
860 clk_enable(venc.tv_dac_clk);
861
862 return 0;
863
864err_get_dispc:
865 dss_runtime_put();
866err_get_dss:
867 return r;
868}
869
870static const struct dev_pm_ops venc_pm_ops = {
871 .runtime_suspend = venc_runtime_suspend,
872 .runtime_resume = venc_runtime_resume,
873};
874
757static struct platform_driver omap_venchw_driver = { 875static struct platform_driver omap_venchw_driver = {
758 .probe = omap_venchw_probe, 876 .probe = omap_venchw_probe,
759 .remove = omap_venchw_remove, 877 .remove = omap_venchw_remove,
760 .driver = { 878 .driver = {
761 .name = "omapdss_venc", 879 .name = "omapdss_venc",
762 .owner = THIS_MODULE, 880 .owner = THIS_MODULE,
881 .pm = &venc_pm_ops,
763 }, 882 },
764}; 883};
765 884