aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/s5p-fimc/mipi-csis.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/s5p-fimc/mipi-csis.c')
-rw-r--r--drivers/media/video/s5p-fimc/mipi-csis.c90
1 files changed, 48 insertions, 42 deletions
diff --git a/drivers/media/video/s5p-fimc/mipi-csis.c b/drivers/media/video/s5p-fimc/mipi-csis.c
index ef056d6605c..59d79bc2f58 100644
--- a/drivers/media/video/s5p-fimc/mipi-csis.c
+++ b/drivers/media/video/s5p-fimc/mipi-csis.c
@@ -81,6 +81,12 @@ static char *csi_clock_name[] = {
81}; 81};
82#define NUM_CSIS_CLOCKS ARRAY_SIZE(csi_clock_name) 82#define NUM_CSIS_CLOCKS ARRAY_SIZE(csi_clock_name)
83 83
84static const char * const csis_supply_name[] = {
85 "vdd11", /* 1.1V or 1.2V (s5pc100) MIPI CSI suppply */
86 "vdd18", /* VDD 1.8V and MIPI CSI PLL supply */
87};
88#define CSIS_NUM_SUPPLIES ARRAY_SIZE(csis_supply_name)
89
84enum { 90enum {
85 ST_POWERED = 1, 91 ST_POWERED = 1,
86 ST_STREAMING = 2, 92 ST_STREAMING = 2,
@@ -109,9 +115,9 @@ struct csis_state {
109 struct platform_device *pdev; 115 struct platform_device *pdev;
110 struct resource *regs_res; 116 struct resource *regs_res;
111 void __iomem *regs; 117 void __iomem *regs;
118 struct regulator_bulk_data supplies[CSIS_NUM_SUPPLIES];
112 struct clk *clock[NUM_CSIS_CLOCKS]; 119 struct clk *clock[NUM_CSIS_CLOCKS];
113 int irq; 120 int irq;
114 struct regulator *supply;
115 u32 flags; 121 u32 flags;
116 const struct csis_pix_format *csis_fmt; 122 const struct csis_pix_format *csis_fmt;
117 struct v4l2_mbus_framefmt format; 123 struct v4l2_mbus_framefmt format;
@@ -460,6 +466,7 @@ static int __devinit s5pcsis_probe(struct platform_device *pdev)
460 struct resource *regs_res; 466 struct resource *regs_res;
461 struct csis_state *state; 467 struct csis_state *state;
462 int ret = -ENOMEM; 468 int ret = -ENOMEM;
469 int i;
463 470
464 state = kzalloc(sizeof(*state), GFP_KERNEL); 471 state = kzalloc(sizeof(*state), GFP_KERNEL);
465 if (!state) 472 if (!state)
@@ -519,14 +526,13 @@ static int __devinit s5pcsis_probe(struct platform_device *pdev)
519 goto e_clkput; 526 goto e_clkput;
520 } 527 }
521 528
522 if (!pdata->fixed_phy_vdd) { 529 for (i = 0; i < CSIS_NUM_SUPPLIES; i++)
523 state->supply = regulator_get(&pdev->dev, "vdd"); 530 state->supplies[i].supply = csis_supply_name[i];
524 if (IS_ERR(state->supply)) { 531
525 ret = PTR_ERR(state->supply); 532 ret = regulator_bulk_get(&pdev->dev, CSIS_NUM_SUPPLIES,
526 state->supply = NULL; 533 state->supplies);
527 goto e_clkput; 534 if (ret)
528 } 535 goto e_clkput;
529 }
530 536
531 ret = request_irq(state->irq, s5pcsis_irq_handler, 0, 537 ret = request_irq(state->irq, s5pcsis_irq_handler, 0,
532 dev_name(&pdev->dev), state); 538 dev_name(&pdev->dev), state);
@@ -553,7 +559,6 @@ static int __devinit s5pcsis_probe(struct platform_device *pdev)
553 /* .. and a pointer to the subdev. */ 559 /* .. and a pointer to the subdev. */
554 platform_set_drvdata(pdev, &state->sd); 560 platform_set_drvdata(pdev, &state->sd);
555 561
556 state->flags = ST_SUSPENDED;
557 pm_runtime_enable(&pdev->dev); 562 pm_runtime_enable(&pdev->dev);
558 563
559 return 0; 564 return 0;
@@ -561,8 +566,7 @@ static int __devinit s5pcsis_probe(struct platform_device *pdev)
561e_irqfree: 566e_irqfree:
562 free_irq(state->irq, state); 567 free_irq(state->irq, state);
563e_regput: 568e_regput:
564 if (state->supply) 569 regulator_bulk_free(CSIS_NUM_SUPPLIES, state->supplies);
565 regulator_put(state->supply);
566e_clkput: 570e_clkput:
567 clk_disable(state->clock[CSIS_CLK_MUX]); 571 clk_disable(state->clock[CSIS_CLK_MUX]);
568 s5pcsis_clk_put(state); 572 s5pcsis_clk_put(state);
@@ -575,7 +579,7 @@ e_free:
575 return ret; 579 return ret;
576} 580}
577 581
578static int s5pcsis_suspend(struct device *dev) 582static int s5pcsis_pm_suspend(struct device *dev, bool runtime)
579{ 583{
580 struct s5p_platform_mipi_csis *pdata = dev->platform_data; 584 struct s5p_platform_mipi_csis *pdata = dev->platform_data;
581 struct platform_device *pdev = to_platform_device(dev); 585 struct platform_device *pdev = to_platform_device(dev);
@@ -592,21 +596,21 @@ static int s5pcsis_suspend(struct device *dev)
592 ret = pdata->phy_enable(state->pdev, false); 596 ret = pdata->phy_enable(state->pdev, false);
593 if (ret) 597 if (ret)
594 goto unlock; 598 goto unlock;
595 if (state->supply) { 599 ret = regulator_bulk_disable(CSIS_NUM_SUPPLIES,
596 ret = regulator_disable(state->supply); 600 state->supplies);
597 if (ret) 601 if (ret)
598 goto unlock; 602 goto unlock;
599 }
600 clk_disable(state->clock[CSIS_CLK_GATE]); 603 clk_disable(state->clock[CSIS_CLK_GATE]);
601 state->flags &= ~ST_POWERED; 604 state->flags &= ~ST_POWERED;
605 if (!runtime)
606 state->flags |= ST_SUSPENDED;
602 } 607 }
603 state->flags |= ST_SUSPENDED;
604 unlock: 608 unlock:
605 mutex_unlock(&state->lock); 609 mutex_unlock(&state->lock);
606 return ret ? -EAGAIN : 0; 610 return ret ? -EAGAIN : 0;
607} 611}
608 612
609static int s5pcsis_resume(struct device *dev) 613static int s5pcsis_pm_resume(struct device *dev, bool runtime)
610{ 614{
611 struct s5p_platform_mipi_csis *pdata = dev->platform_data; 615 struct s5p_platform_mipi_csis *pdata = dev->platform_data;
612 struct platform_device *pdev = to_platform_device(dev); 616 struct platform_device *pdev = to_platform_device(dev);
@@ -618,20 +622,20 @@ static int s5pcsis_resume(struct device *dev)
618 __func__, state->flags); 622 __func__, state->flags);
619 623
620 mutex_lock(&state->lock); 624 mutex_lock(&state->lock);
621 if (!(state->flags & ST_SUSPENDED)) 625 if (!runtime && !(state->flags & ST_SUSPENDED))
622 goto unlock; 626 goto unlock;
623 627
624 if (!(state->flags & ST_POWERED)) { 628 if (!(state->flags & ST_POWERED)) {
625 if (state->supply) 629 ret = regulator_bulk_enable(CSIS_NUM_SUPPLIES,
626 ret = regulator_enable(state->supply); 630 state->supplies);
627 if (ret) 631 if (ret)
628 goto unlock; 632 goto unlock;
629
630 ret = pdata->phy_enable(state->pdev, true); 633 ret = pdata->phy_enable(state->pdev, true);
631 if (!ret) { 634 if (!ret) {
632 state->flags |= ST_POWERED; 635 state->flags |= ST_POWERED;
633 } else if (state->supply) { 636 } else {
634 regulator_disable(state->supply); 637 regulator_bulk_disable(CSIS_NUM_SUPPLIES,
638 state->supplies);
635 goto unlock; 639 goto unlock;
636 } 640 }
637 clk_enable(state->clock[CSIS_CLK_GATE]); 641 clk_enable(state->clock[CSIS_CLK_GATE]);
@@ -646,24 +650,26 @@ static int s5pcsis_resume(struct device *dev)
646} 650}
647 651
648#ifdef CONFIG_PM_SLEEP 652#ifdef CONFIG_PM_SLEEP
649static int s5pcsis_pm_suspend(struct device *dev) 653static int s5pcsis_suspend(struct device *dev)
650{ 654{
651 return s5pcsis_suspend(dev); 655 return s5pcsis_pm_suspend(dev, false);
652} 656}
653 657
654static int s5pcsis_pm_resume(struct device *dev) 658static int s5pcsis_resume(struct device *dev)
655{ 659{
656 int ret; 660 return s5pcsis_pm_resume(dev, false);
657 661}
658 ret = s5pcsis_resume(dev); 662#endif
659 663
660 if (!ret) { 664#ifdef CONFIG_PM_RUNTIME
661 pm_runtime_disable(dev); 665static int s5pcsis_runtime_suspend(struct device *dev)
662 ret = pm_runtime_set_active(dev); 666{
663 pm_runtime_enable(dev); 667 return s5pcsis_pm_suspend(dev, true);
664 } 668}
665 669
666 return ret; 670static int s5pcsis_runtime_resume(struct device *dev)
671{
672 return s5pcsis_pm_resume(dev, true);
667} 673}
668#endif 674#endif
669 675
@@ -679,8 +685,7 @@ static int __devexit s5pcsis_remove(struct platform_device *pdev)
679 pm_runtime_set_suspended(&pdev->dev); 685 pm_runtime_set_suspended(&pdev->dev);
680 686
681 s5pcsis_clk_put(state); 687 s5pcsis_clk_put(state);
682 if (state->supply) 688 regulator_bulk_free(CSIS_NUM_SUPPLIES, state->supplies);
683 regulator_put(state->supply);
684 689
685 media_entity_cleanup(&state->sd.entity); 690 media_entity_cleanup(&state->sd.entity);
686 free_irq(state->irq, state); 691 free_irq(state->irq, state);
@@ -692,8 +697,9 @@ static int __devexit s5pcsis_remove(struct platform_device *pdev)
692} 697}
693 698
694static const struct dev_pm_ops s5pcsis_pm_ops = { 699static const struct dev_pm_ops s5pcsis_pm_ops = {
695 SET_RUNTIME_PM_OPS(s5pcsis_suspend, s5pcsis_resume, NULL) 700 SET_RUNTIME_PM_OPS(s5pcsis_runtime_suspend, s5pcsis_runtime_resume,
696 SET_SYSTEM_SLEEP_PM_OPS(s5pcsis_pm_suspend, s5pcsis_pm_resume) 701 NULL)
702 SET_SYSTEM_SLEEP_PM_OPS(s5pcsis_suspend, s5pcsis_resume)
697}; 703};
698 704
699static struct platform_driver s5pcsis_driver = { 705static struct platform_driver s5pcsis_driver = {