diff options
-rw-r--r-- | drivers/media/video/sh_mobile_ceu_camera.c | 41 |
1 files changed, 25 insertions, 16 deletions
diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c index e86878deea71..61c47b824083 100644 --- a/drivers/media/video/sh_mobile_ceu_camera.c +++ b/drivers/media/video/sh_mobile_ceu_camera.c | |||
@@ -30,7 +30,7 @@ | |||
30 | #include <linux/device.h> | 30 | #include <linux/device.h> |
31 | #include <linux/platform_device.h> | 31 | #include <linux/platform_device.h> |
32 | #include <linux/videodev2.h> | 32 | #include <linux/videodev2.h> |
33 | #include <linux/clk.h> | 33 | #include <linux/pm_runtime.h> |
34 | 34 | ||
35 | #include <media/v4l2-common.h> | 35 | #include <media/v4l2-common.h> |
36 | #include <media/v4l2-dev.h> | 36 | #include <media/v4l2-dev.h> |
@@ -86,7 +86,6 @@ struct sh_mobile_ceu_dev { | |||
86 | 86 | ||
87 | unsigned int irq; | 87 | unsigned int irq; |
88 | void __iomem *base; | 88 | void __iomem *base; |
89 | struct clk *clk; | ||
90 | unsigned long video_limit; | 89 | unsigned long video_limit; |
91 | 90 | ||
92 | /* lock used to protect videobuf */ | 91 | /* lock used to protect videobuf */ |
@@ -361,7 +360,7 @@ static int sh_mobile_ceu_add_device(struct soc_camera_device *icd) | |||
361 | if (ret) | 360 | if (ret) |
362 | goto err; | 361 | goto err; |
363 | 362 | ||
364 | clk_enable(pcdev->clk); | 363 | pm_runtime_get_sync(ici->dev); |
365 | 364 | ||
366 | ceu_write(pcdev, CAPSR, 1 << 16); /* reset */ | 365 | ceu_write(pcdev, CAPSR, 1 << 16); /* reset */ |
367 | while (ceu_read(pcdev, CSTSR) & 1) | 366 | while (ceu_read(pcdev, CSTSR) & 1) |
@@ -395,7 +394,7 @@ static void sh_mobile_ceu_remove_device(struct soc_camera_device *icd) | |||
395 | } | 394 | } |
396 | spin_unlock_irqrestore(&pcdev->lock, flags); | 395 | spin_unlock_irqrestore(&pcdev->lock, flags); |
397 | 396 | ||
398 | clk_disable(pcdev->clk); | 397 | pm_runtime_put_sync(ici->dev); |
399 | 398 | ||
400 | icd->ops->release(icd); | 399 | icd->ops->release(icd); |
401 | 400 | ||
@@ -798,7 +797,6 @@ static int sh_mobile_ceu_probe(struct platform_device *pdev) | |||
798 | struct sh_mobile_ceu_dev *pcdev; | 797 | struct sh_mobile_ceu_dev *pcdev; |
799 | struct resource *res; | 798 | struct resource *res; |
800 | void __iomem *base; | 799 | void __iomem *base; |
801 | char clk_name[8]; | ||
802 | unsigned int irq; | 800 | unsigned int irq; |
803 | int err = 0; | 801 | int err = 0; |
804 | 802 | ||
@@ -862,13 +860,9 @@ static int sh_mobile_ceu_probe(struct platform_device *pdev) | |||
862 | goto exit_release_mem; | 860 | goto exit_release_mem; |
863 | } | 861 | } |
864 | 862 | ||
865 | snprintf(clk_name, sizeof(clk_name), "ceu%d", pdev->id); | 863 | pm_suspend_ignore_children(&pdev->dev, true); |
866 | pcdev->clk = clk_get(&pdev->dev, clk_name); | 864 | pm_runtime_enable(&pdev->dev); |
867 | if (IS_ERR(pcdev->clk)) { | 865 | pm_runtime_resume(&pdev->dev); |
868 | dev_err(&pdev->dev, "cannot get clock \"%s\"\n", clk_name); | ||
869 | err = PTR_ERR(pcdev->clk); | ||
870 | goto exit_free_irq; | ||
871 | } | ||
872 | 866 | ||
873 | pcdev->ici.priv = pcdev; | 867 | pcdev->ici.priv = pcdev; |
874 | pcdev->ici.dev = &pdev->dev; | 868 | pcdev->ici.dev = &pdev->dev; |
@@ -878,12 +872,10 @@ static int sh_mobile_ceu_probe(struct platform_device *pdev) | |||
878 | 872 | ||
879 | err = soc_camera_host_register(&pcdev->ici); | 873 | err = soc_camera_host_register(&pcdev->ici); |
880 | if (err) | 874 | if (err) |
881 | goto exit_free_clk; | 875 | goto exit_free_irq; |
882 | 876 | ||
883 | return 0; | 877 | return 0; |
884 | 878 | ||
885 | exit_free_clk: | ||
886 | clk_put(pcdev->clk); | ||
887 | exit_free_irq: | 879 | exit_free_irq: |
888 | free_irq(pcdev->irq, pcdev); | 880 | free_irq(pcdev->irq, pcdev); |
889 | exit_release_mem: | 881 | exit_release_mem: |
@@ -904,7 +896,6 @@ static int sh_mobile_ceu_remove(struct platform_device *pdev) | |||
904 | struct sh_mobile_ceu_dev, ici); | 896 | struct sh_mobile_ceu_dev, ici); |
905 | 897 | ||
906 | soc_camera_host_unregister(soc_host); | 898 | soc_camera_host_unregister(soc_host); |
907 | clk_put(pcdev->clk); | ||
908 | free_irq(pcdev->irq, pcdev); | 899 | free_irq(pcdev->irq, pcdev); |
909 | if (platform_get_resource(pdev, IORESOURCE_MEM, 1)) | 900 | if (platform_get_resource(pdev, IORESOURCE_MEM, 1)) |
910 | dma_release_declared_memory(&pdev->dev); | 901 | dma_release_declared_memory(&pdev->dev); |
@@ -913,9 +904,27 @@ static int sh_mobile_ceu_remove(struct platform_device *pdev) | |||
913 | return 0; | 904 | return 0; |
914 | } | 905 | } |
915 | 906 | ||
907 | static int sh_mobile_ceu_runtime_nop(struct device *dev) | ||
908 | { | ||
909 | /* Runtime PM callback shared between ->runtime_suspend() | ||
910 | * and ->runtime_resume(). Simply returns success. | ||
911 | * | ||
912 | * This driver re-initializes all registers after | ||
913 | * pm_runtime_get_sync() anyway so there is no need | ||
914 | * to save and restore registers here. | ||
915 | */ | ||
916 | return 0; | ||
917 | } | ||
918 | |||
919 | static struct dev_pm_ops sh_mobile_ceu_dev_pm_ops = { | ||
920 | .runtime_suspend = sh_mobile_ceu_runtime_nop, | ||
921 | .runtime_resume = sh_mobile_ceu_runtime_nop, | ||
922 | }; | ||
923 | |||
916 | static struct platform_driver sh_mobile_ceu_driver = { | 924 | static struct platform_driver sh_mobile_ceu_driver = { |
917 | .driver = { | 925 | .driver = { |
918 | .name = "sh_mobile_ceu", | 926 | .name = "sh_mobile_ceu", |
927 | .pm = &sh_mobile_ceu_dev_pm_ops, | ||
919 | }, | 928 | }, |
920 | .probe = sh_mobile_ceu_probe, | 929 | .probe = sh_mobile_ceu_probe, |
921 | .remove = sh_mobile_ceu_remove, | 930 | .remove = sh_mobile_ceu_remove, |