diff options
author | Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> | 2016-02-16 08:49:39 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@s-opensource.com> | 2016-06-17 07:02:48 -0400 |
commit | 1e6af546ee66b2870c5c21f4430910a27c26b5bb (patch) | |
tree | 6e643324e6aab05a03068868c8d29ff906db28d4 | |
parent | 7b49235e83b2347caf4bc66dd0154cb799bd7405 (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.h | 3 | ||||
-rw-r--r-- | drivers/media/platform/vsp1/vsp1_drv.c | 101 | ||||
-rw-r--r-- | drivers/media/platform/vsp1/vsp1_pipe.c | 2 |
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 | */ |
470 | int vsp1_device_get(struct vsp1_device *vsp1) | 470 | int 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 | |||
488 | done: | ||
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 | */ |
502 | void vsp1_device_put(struct vsp1_device *vsp1) | 484 | void 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); | 504 | static 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 | ||
533 | static int vsp1_pm_resume(struct device *dev) | 515 | static 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); | 524 | static 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 | ||
550 | static const struct dev_pm_ops vsp1_pm_ops = { | 544 | static 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); | 701 | done: |
702 | if (ret) | ||
703 | pm_runtime_disable(&pdev->dev); | ||
703 | 704 | ||
704 | return 0; | 705 | return ret; |
705 | } | 706 | } |
706 | 707 | ||
707 | static int vsp1_remove(struct platform_device *pdev) | 708 | static 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; |