aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>2016-02-16 08:49:39 -0500
committerMauro Carvalho Chehab <mchehab@s-opensource.com>2016-06-17 07:02:48 -0400
commit1e6af546ee66b2870c5c21f4430910a27c26b5bb (patch)
tree6e643324e6aab05a03068868c8d29ff906db28d4
parent7b49235e83b2347caf4bc66dd0154cb799bd7405 (diff)
[media] v4l: vsp1: Implement runtime PM support
Replace the manual refcount and clock management code by runtime PM. Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
-rw-r--r--drivers/media/platform/vsp1/vsp1.h3
-rw-r--r--drivers/media/platform/vsp1/vsp1_drv.c101
-rw-r--r--drivers/media/platform/vsp1/vsp1_pipe.c2
3 files changed, 53 insertions, 53 deletions
diff --git a/drivers/media/platform/vsp1/vsp1.h b/drivers/media/platform/vsp1/vsp1.h
index 46738b6c5f72..9e09bce43cf3 100644
--- a/drivers/media/platform/vsp1/vsp1.h
+++ b/drivers/media/platform/vsp1/vsp1.h
@@ -64,9 +64,6 @@ struct vsp1_device {
64 void __iomem *mmio; 64 void __iomem *mmio;
65 struct clk *clock; 65 struct clk *clock;
66 66
67 struct mutex lock;
68 int ref_count;
69
70 struct vsp1_bru *bru; 67 struct vsp1_bru *bru;
71 struct vsp1_hsit *hsi; 68 struct vsp1_hsit *hsi;
72 struct vsp1_hsit *hst; 69 struct vsp1_hsit *hst;
diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c
index e2d779fac0eb..d6abc7f1216a 100644
--- a/drivers/media/platform/vsp1/vsp1_drv.c
+++ b/drivers/media/platform/vsp1/vsp1_drv.c
@@ -19,6 +19,7 @@
19#include <linux/of.h> 19#include <linux/of.h>
20#include <linux/of_device.h> 20#include <linux/of_device.h>
21#include <linux/platform_device.h> 21#include <linux/platform_device.h>
22#include <linux/pm_runtime.h>
22#include <linux/videodev2.h> 23#include <linux/videodev2.h>
23 24
24#include <media/v4l2-subdev.h> 25#include <media/v4l2-subdev.h>
@@ -462,35 +463,16 @@ static int vsp1_device_init(struct vsp1_device *vsp1)
462/* 463/*
463 * vsp1_device_get - Acquire the VSP1 device 464 * vsp1_device_get - Acquire the VSP1 device
464 * 465 *
465 * Increment the VSP1 reference count and initialize the device if the first 466 * Make sure the device is not suspended and initialize it if needed.
466 * reference is taken.
467 * 467 *
468 * Return 0 on success or a negative error code otherwise. 468 * Return 0 on success or a negative error code otherwise.
469 */ 469 */
470int vsp1_device_get(struct vsp1_device *vsp1) 470int vsp1_device_get(struct vsp1_device *vsp1)
471{ 471{
472 int ret = 0; 472 int ret;
473
474 mutex_lock(&vsp1->lock);
475 if (vsp1->ref_count > 0)
476 goto done;
477
478 ret = clk_prepare_enable(vsp1->clock);
479 if (ret < 0)
480 goto done;
481
482 ret = vsp1_device_init(vsp1);
483 if (ret < 0) {
484 clk_disable_unprepare(vsp1->clock);
485 goto done;
486 }
487
488done:
489 if (!ret)
490 vsp1->ref_count++;
491 473
492 mutex_unlock(&vsp1->lock); 474 ret = pm_runtime_get_sync(vsp1->dev);
493 return ret; 475 return ret < 0 ? ret : 0;
494} 476}
495 477
496/* 478/*
@@ -501,12 +483,7 @@ done:
501 */ 483 */
502void vsp1_device_put(struct vsp1_device *vsp1) 484void vsp1_device_put(struct vsp1_device *vsp1)
503{ 485{
504 mutex_lock(&vsp1->lock); 486 pm_runtime_put_sync(vsp1->dev);
505
506 if (--vsp1->ref_count == 0)
507 clk_disable_unprepare(vsp1->clock);
508
509 mutex_unlock(&vsp1->lock);
510} 487}
511 488
512/* ----------------------------------------------------------------------------- 489/* -----------------------------------------------------------------------------
@@ -518,37 +495,55 @@ static int vsp1_pm_suspend(struct device *dev)
518{ 495{
519 struct vsp1_device *vsp1 = dev_get_drvdata(dev); 496 struct vsp1_device *vsp1 = dev_get_drvdata(dev);
520 497
521 WARN_ON(mutex_is_locked(&vsp1->lock)); 498 vsp1_pipelines_suspend(vsp1);
499 pm_runtime_force_suspend(vsp1->dev);
522 500
523 if (vsp1->ref_count == 0) 501 return 0;
524 return 0; 502}
525 503
526 vsp1_pipelines_suspend(vsp1); 504static int vsp1_pm_resume(struct device *dev)
505{
506 struct vsp1_device *vsp1 = dev_get_drvdata(dev);
527 507
528 clk_disable_unprepare(vsp1->clock); 508 pm_runtime_force_resume(vsp1->dev);
509 vsp1_pipelines_resume(vsp1);
529 510
530 return 0; 511 return 0;
531} 512}
513#endif
532 514
533static int vsp1_pm_resume(struct device *dev) 515static int vsp1_pm_runtime_suspend(struct device *dev)
534{ 516{
535 struct vsp1_device *vsp1 = dev_get_drvdata(dev); 517 struct vsp1_device *vsp1 = dev_get_drvdata(dev);
536 518
537 WARN_ON(mutex_is_locked(&vsp1->lock)); 519 clk_disable_unprepare(vsp1->clock);
538 520
539 if (vsp1->ref_count == 0) 521 return 0;
540 return 0; 522}
541 523
542 clk_prepare_enable(vsp1->clock); 524static int vsp1_pm_runtime_resume(struct device *dev)
525{
526 struct vsp1_device *vsp1 = dev_get_drvdata(dev);
527 int ret;
543 528
544 vsp1_pipelines_resume(vsp1); 529 ret = clk_prepare_enable(vsp1->clock);
530 if (ret < 0)
531 return ret;
532
533 if (vsp1->info) {
534 ret = vsp1_device_init(vsp1);
535 if (ret < 0) {
536 clk_disable_unprepare(vsp1->clock);
537 return ret;
538 }
539 }
545 540
546 return 0; 541 return 0;
547} 542}
548#endif
549 543
550static const struct dev_pm_ops vsp1_pm_ops = { 544static const struct dev_pm_ops vsp1_pm_ops = {
551 SET_SYSTEM_SLEEP_PM_OPS(vsp1_pm_suspend, vsp1_pm_resume) 545 SET_SYSTEM_SLEEP_PM_OPS(vsp1_pm_suspend, vsp1_pm_resume)
546 SET_RUNTIME_PM_OPS(vsp1_pm_runtime_suspend, vsp1_pm_runtime_resume, NULL)
552}; 547};
553 548
554/* ----------------------------------------------------------------------------- 549/* -----------------------------------------------------------------------------
@@ -640,10 +635,11 @@ static int vsp1_probe(struct platform_device *pdev)
640 return -ENOMEM; 635 return -ENOMEM;
641 636
642 vsp1->dev = &pdev->dev; 637 vsp1->dev = &pdev->dev;
643 mutex_init(&vsp1->lock);
644 INIT_LIST_HEAD(&vsp1->entities); 638 INIT_LIST_HEAD(&vsp1->entities);
645 INIT_LIST_HEAD(&vsp1->videos); 639 INIT_LIST_HEAD(&vsp1->videos);
646 640
641 platform_set_drvdata(pdev, vsp1);
642
647 /* I/O, IRQ and clock resources */ 643 /* I/O, IRQ and clock resources */
648 io = platform_get_resource(pdev, IORESOURCE_MEM, 0); 644 io = platform_get_resource(pdev, IORESOURCE_MEM, 0);
649 vsp1->mmio = devm_ioremap_resource(&pdev->dev, io); 645 vsp1->mmio = devm_ioremap_resource(&pdev->dev, io);
@@ -670,12 +666,14 @@ static int vsp1_probe(struct platform_device *pdev)
670 } 666 }
671 667
672 /* Configure device parameters based on the version register. */ 668 /* Configure device parameters based on the version register. */
673 ret = clk_prepare_enable(vsp1->clock); 669 pm_runtime_enable(&pdev->dev);
670
671 ret = pm_runtime_get_sync(&pdev->dev);
674 if (ret < 0) 672 if (ret < 0)
675 return ret; 673 goto done;
676 674
677 version = vsp1_read(vsp1, VI6_IP_VERSION); 675 version = vsp1_read(vsp1, VI6_IP_VERSION);
678 clk_disable_unprepare(vsp1->clock); 676 pm_runtime_put_sync(&pdev->dev);
679 677
680 for (i = 0; i < ARRAY_SIZE(vsp1_device_infos); ++i) { 678 for (i = 0; i < ARRAY_SIZE(vsp1_device_infos); ++i) {
681 if ((version & VI6_IP_VERSION_MODEL_MASK) == 679 if ((version & VI6_IP_VERSION_MODEL_MASK) ==
@@ -687,7 +685,8 @@ static int vsp1_probe(struct platform_device *pdev)
687 685
688 if (!vsp1->info) { 686 if (!vsp1->info) {
689 dev_err(&pdev->dev, "unsupported IP version 0x%08x\n", version); 687 dev_err(&pdev->dev, "unsupported IP version 0x%08x\n", version);
690 return -ENXIO; 688 ret = -ENXIO;
689 goto done;
691 } 690 }
692 691
693 dev_dbg(&pdev->dev, "IP version 0x%08x\n", version); 692 dev_dbg(&pdev->dev, "IP version 0x%08x\n", version);
@@ -696,12 +695,14 @@ static int vsp1_probe(struct platform_device *pdev)
696 ret = vsp1_create_entities(vsp1); 695 ret = vsp1_create_entities(vsp1);
697 if (ret < 0) { 696 if (ret < 0) {
698 dev_err(&pdev->dev, "failed to create entities\n"); 697 dev_err(&pdev->dev, "failed to create entities\n");
699 return ret; 698 goto done;
700 } 699 }
701 700
702 platform_set_drvdata(pdev, vsp1); 701done:
702 if (ret)
703 pm_runtime_disable(&pdev->dev);
703 704
704 return 0; 705 return ret;
705} 706}
706 707
707static int vsp1_remove(struct platform_device *pdev) 708static int vsp1_remove(struct platform_device *pdev)
@@ -710,6 +711,8 @@ static int vsp1_remove(struct platform_device *pdev)
710 711
711 vsp1_destroy_entities(vsp1); 712 vsp1_destroy_entities(vsp1);
712 713
714 pm_runtime_disable(&pdev->dev);
715
713 return 0; 716 return 0;
714} 717}
715 718
diff --git a/drivers/media/platform/vsp1/vsp1_pipe.c b/drivers/media/platform/vsp1/vsp1_pipe.c
index 4f3b4a1d028a..0c1dc80eb304 100644
--- a/drivers/media/platform/vsp1/vsp1_pipe.c
+++ b/drivers/media/platform/vsp1/vsp1_pipe.c
@@ -383,7 +383,7 @@ void vsp1_pipelines_resume(struct vsp1_device *vsp1)
383{ 383{
384 unsigned int i; 384 unsigned int i;
385 385
386 /* Resume pipeline all running pipelines. */ 386 /* Resume all running pipelines. */
387 for (i = 0; i < vsp1->info->wpf_count; ++i) { 387 for (i = 0; i < vsp1->info->wpf_count; ++i) {
388 struct vsp1_rwpf *wpf = vsp1->wpf[i]; 388 struct vsp1_rwpf *wpf = vsp1->wpf[i];
389 struct vsp1_pipeline *pipe; 389 struct vsp1_pipeline *pipe;