aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/pxa_camera.c
diff options
context:
space:
mode:
authorGuennadi Liakhovetski <g.liakhovetski@pengutronix.de>2008-03-07 19:57:18 -0500
committerMauro Carvalho Chehab <mchehab@infradead.org>2008-04-24 13:07:49 -0400
commitad5f2e859d76dccb7eb1aa942171b1a32211efc2 (patch)
tree1716d5c82322d55886de36dddd9535b90dd57630 /drivers/media/video/pxa_camera.c
parent1c659689fe9959c017bfaaa8301243f7d99f1a46 (diff)
V4L/DVB (7336): soc-camera: streamline hardware parameter negotiation
Improve hardware parameter negotiation between the camera host driver and camera drivers. Parameters like horizontal and vertical synchronisation, pixel clock polarity shall be set depending on capabilities of the parties. Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@pengutronix.de> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/video/pxa_camera.c')
-rw-r--r--drivers/media/video/pxa_camera.c156
1 files changed, 113 insertions, 43 deletions
diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c
index a34a193249f6..4756699d16aa 100644
--- a/drivers/media/video/pxa_camera.c
+++ b/drivers/media/video/pxa_camera.c
@@ -581,64 +581,109 @@ static void pxa_camera_remove_device(struct soc_camera_device *icd)
581 pcdev->icd = NULL; 581 pcdev->icd = NULL;
582} 582}
583 583
584static int pxa_camera_set_capture_format(struct soc_camera_device *icd, 584static int test_platform_param(struct pxa_camera_dev *pcdev,
585 __u32 pixfmt, struct v4l2_rect *rect) 585 unsigned char buswidth, unsigned long *flags)
586{ 586{
587 struct soc_camera_host *ici = 587 /*
588 to_soc_camera_host(icd->dev.parent); 588 * Platform specified synchronization and pixel clock polarities are
589 struct pxa_camera_dev *pcdev = ici->priv; 589 * only a recommendation and are only used during probing. The PXA270
590 unsigned int datawidth = 0, dw, bpp; 590 * quick capture interface supports both.
591 u32 cicr0, cicr4 = 0; 591 */
592 int ret; 592 *flags = (pcdev->platform_flags & PXA_CAMERA_MASTER ?
593 SOCAM_MASTER : SOCAM_SLAVE) |
594 SOCAM_HSYNC_ACTIVE_HIGH |
595 SOCAM_HSYNC_ACTIVE_LOW |
596 SOCAM_VSYNC_ACTIVE_HIGH |
597 SOCAM_VSYNC_ACTIVE_LOW |
598 SOCAM_PCLK_SAMPLE_RISING |
599 SOCAM_PCLK_SAMPLE_FALLING;
593 600
594 /* If requested data width is supported by the platform, use it */ 601 /* If requested data width is supported by the platform, use it */
595 switch (icd->cached_datawidth) { 602 switch (buswidth) {
596 case 10: 603 case 10:
597 if (pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_10) 604 if (!(pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_10))
598 datawidth = IS_DATAWIDTH_10; 605 return -EINVAL;
606 *flags |= SOCAM_DATAWIDTH_10;
599 break; 607 break;
600 case 9: 608 case 9:
601 if (pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_9) 609 if (!(pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_9))
602 datawidth = IS_DATAWIDTH_9; 610 return -EINVAL;
611 *flags |= SOCAM_DATAWIDTH_9;
603 break; 612 break;
604 case 8: 613 case 8:
605 if (pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_8) 614 if (!(pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_8))
606 datawidth = IS_DATAWIDTH_8; 615 return -EINVAL;
616 *flags |= SOCAM_DATAWIDTH_8;
607 } 617 }
608 if (!datawidth) 618
619 return 0;
620}
621
622static int pxa_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
623{
624 struct soc_camera_host *ici =
625 to_soc_camera_host(icd->dev.parent);
626 struct pxa_camera_dev *pcdev = ici->priv;
627 unsigned long dw, bpp, bus_flags, camera_flags, common_flags;
628 u32 cicr0, cicr4 = 0;
629 int ret = test_platform_param(pcdev, icd->buswidth, &bus_flags);
630
631 if (ret < 0)
632 return ret;
633
634 camera_flags = icd->ops->query_bus_param(icd);
635
636 common_flags = soc_camera_bus_param_compatible(camera_flags, bus_flags);
637 if (!common_flags)
609 return -EINVAL; 638 return -EINVAL;
610 639
611 ret = icd->ops->set_capture_format(icd, pixfmt, rect, 640 /* Make choises, based on platform preferences */
612 datawidth | 641 if ((common_flags & SOCAM_HSYNC_ACTIVE_HIGH) &&
613 (pcdev->platform_flags & PXA_CAMERA_MASTER ? 642 (common_flags & SOCAM_HSYNC_ACTIVE_LOW)) {
614 IS_MASTER : 0) | 643 if (pcdev->platform_flags & PXA_CAMERA_HSP)
615 (pcdev->platform_flags & PXA_CAMERA_HSP ? 644 common_flags &= ~SOCAM_HSYNC_ACTIVE_HIGH;
616 0 : IS_HSYNC_ACTIVE_HIGH) | 645 else
617 (pcdev->platform_flags & PXA_CAMERA_VSP ? 646 common_flags &= ~SOCAM_HSYNC_ACTIVE_LOW;
618 0 : IS_VSYNC_ACTIVE_HIGH) | 647 }
619 (pcdev->platform_flags & PXA_CAMERA_PCP ? 648
620 0 : IS_PCLK_SAMPLE_RISING)); 649 if ((common_flags & SOCAM_VSYNC_ACTIVE_HIGH) &&
650 (common_flags & SOCAM_VSYNC_ACTIVE_LOW)) {
651 if (pcdev->platform_flags & PXA_CAMERA_VSP)
652 common_flags &= ~SOCAM_VSYNC_ACTIVE_HIGH;
653 else
654 common_flags &= ~SOCAM_VSYNC_ACTIVE_LOW;
655 }
656
657 if ((common_flags & SOCAM_PCLK_SAMPLE_RISING) &&
658 (common_flags & SOCAM_PCLK_SAMPLE_FALLING)) {
659 if (pcdev->platform_flags & PXA_CAMERA_PCP)
660 common_flags &= ~SOCAM_PCLK_SAMPLE_RISING;
661 else
662 common_flags &= ~SOCAM_PCLK_SAMPLE_FALLING;
663 }
664
665 ret = icd->ops->set_bus_param(icd, common_flags);
621 if (ret < 0) 666 if (ret < 0)
622 return ret; 667 return ret;
623 668
624 /* Datawidth is now guaranteed to be equal to one of the three values. 669 /* Datawidth is now guaranteed to be equal to one of the three values.
625 * We fix bit-per-pixel equal to data-width... */ 670 * We fix bit-per-pixel equal to data-width... */
626 switch (datawidth) { 671 switch (common_flags & SOCAM_DATAWIDTH_MASK) {
627 case IS_DATAWIDTH_10: 672 case SOCAM_DATAWIDTH_10:
628 icd->cached_datawidth = 10; 673 icd->buswidth = 10;
629 dw = 4; 674 dw = 4;
630 bpp = 0x40; 675 bpp = 0x40;
631 break; 676 break;
632 case IS_DATAWIDTH_9: 677 case SOCAM_DATAWIDTH_9:
633 icd->cached_datawidth = 9; 678 icd->buswidth = 9;
634 dw = 3; 679 dw = 3;
635 bpp = 0x20; 680 bpp = 0x20;
636 break; 681 break;
637 default: 682 default:
638 /* Actually it can only be 8 now, 683 /* Actually it can only be 8 now,
639 * default is just to silence compiler warnings */ 684 * default is just to silence compiler warnings */
640 case IS_DATAWIDTH_8: 685 case SOCAM_DATAWIDTH_8:
641 icd->cached_datawidth = 8; 686 icd->buswidth = 8;
642 dw = 2; 687 dw = 2;
643 bpp = 0; 688 bpp = 0;
644 } 689 }
@@ -647,19 +692,19 @@ static int pxa_camera_set_capture_format(struct soc_camera_device *icd,
647 cicr4 |= CICR4_PCLK_EN; 692 cicr4 |= CICR4_PCLK_EN;
648 if (pcdev->platform_flags & PXA_CAMERA_MCLK_EN) 693 if (pcdev->platform_flags & PXA_CAMERA_MCLK_EN)
649 cicr4 |= CICR4_MCLK_EN; 694 cicr4 |= CICR4_MCLK_EN;
650 if (pcdev->platform_flags & PXA_CAMERA_PCP) 695 if (common_flags & SOCAM_PCLK_SAMPLE_FALLING)
651 cicr4 |= CICR4_PCP; 696 cicr4 |= CICR4_PCP;
652 if (pcdev->platform_flags & PXA_CAMERA_HSP) 697 if (common_flags & SOCAM_HSYNC_ACTIVE_LOW)
653 cicr4 |= CICR4_HSP; 698 cicr4 |= CICR4_HSP;
654 if (pcdev->platform_flags & PXA_CAMERA_VSP) 699 if (common_flags & SOCAM_VSYNC_ACTIVE_LOW)
655 cicr4 |= CICR4_VSP; 700 cicr4 |= CICR4_VSP;
656 701
657 cicr0 = CICR0; 702 cicr0 = CICR0;
658 if (cicr0 & CICR0_ENB) 703 if (cicr0 & CICR0_ENB)
659 CICR0 = cicr0 & ~CICR0_ENB; 704 CICR0 = cicr0 & ~CICR0_ENB;
660 CICR1 = CICR1_PPL_VAL(rect->width - 1) | bpp | dw; 705 CICR1 = CICR1_PPL_VAL(icd->width - 1) | bpp | dw;
661 CICR2 = 0; 706 CICR2 = 0;
662 CICR3 = CICR3_LPF_VAL(rect->height - 1) | 707 CICR3 = CICR3_LPF_VAL(icd->height - 1) |
663 CICR3_BFW_VAL(min((unsigned short)255, icd->y_skip_top)); 708 CICR3_BFW_VAL(min((unsigned short)255, icd->y_skip_top));
664 CICR4 = mclk_get_divisor(pcdev) | cicr4; 709 CICR4 = mclk_get_divisor(pcdev) | cicr4;
665 710
@@ -671,7 +716,29 @@ static int pxa_camera_set_capture_format(struct soc_camera_device *icd,
671 return 0; 716 return 0;
672} 717}
673 718
674static int pxa_camera_try_fmt_cap(struct soc_camera_host *ici, 719static int pxa_camera_try_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
720{
721 struct soc_camera_host *ici =
722 to_soc_camera_host(icd->dev.parent);
723 struct pxa_camera_dev *pcdev = ici->priv;
724 unsigned long bus_flags, camera_flags;
725 int ret = test_platform_param(pcdev, icd->buswidth, &bus_flags);
726
727 if (ret < 0)
728 return ret;
729
730 camera_flags = icd->ops->query_bus_param(icd);
731
732 return soc_camera_bus_param_compatible(camera_flags, bus_flags) ? 0 : -EINVAL;
733}
734
735static int pxa_camera_set_fmt_cap(struct soc_camera_device *icd,
736 __u32 pixfmt, struct v4l2_rect *rect)
737{
738 return icd->ops->set_fmt_cap(icd, pixfmt, rect);
739}
740
741static int pxa_camera_try_fmt_cap(struct soc_camera_device *icd,
675 struct v4l2_format *f) 742 struct v4l2_format *f)
676{ 743{
677 /* limit to pxa hardware capabilities */ 744 /* limit to pxa hardware capabilities */
@@ -685,7 +752,8 @@ static int pxa_camera_try_fmt_cap(struct soc_camera_host *ici,
685 f->fmt.pix.width = 2048; 752 f->fmt.pix.width = 2048;
686 f->fmt.pix.width &= ~0x01; 753 f->fmt.pix.width &= ~0x01;
687 754
688 return 0; 755 /* limit to sensor capabilities */
756 return icd->ops->try_fmt_cap(icd, f);
689} 757}
690 758
691static int pxa_camera_reqbufs(struct soc_camera_file *icf, 759static int pxa_camera_reqbufs(struct soc_camera_file *icf,
@@ -742,11 +810,13 @@ static struct soc_camera_host pxa_soc_camera_host = {
742 .add = pxa_camera_add_device, 810 .add = pxa_camera_add_device,
743 .remove = pxa_camera_remove_device, 811 .remove = pxa_camera_remove_device,
744 .msize = sizeof(struct pxa_buffer), 812 .msize = sizeof(struct pxa_buffer),
745 .set_capture_format = pxa_camera_set_capture_format, 813 .set_fmt_cap = pxa_camera_set_fmt_cap,
746 .try_fmt_cap = pxa_camera_try_fmt_cap, 814 .try_fmt_cap = pxa_camera_try_fmt_cap,
747 .reqbufs = pxa_camera_reqbufs, 815 .reqbufs = pxa_camera_reqbufs,
748 .poll = pxa_camera_poll, 816 .poll = pxa_camera_poll,
749 .querycap = pxa_camera_querycap, 817 .querycap = pxa_camera_querycap,
818 .try_bus_param = pxa_camera_try_bus_param,
819 .set_bus_param = pxa_camera_set_bus_param,
750}; 820};
751 821
752static int pxa_camera_probe(struct platform_device *pdev) 822static int pxa_camera_probe(struct platform_device *pdev)
@@ -782,8 +852,8 @@ static int pxa_camera_probe(struct platform_device *pdev)
782 852
783 pcdev->pdata = pdev->dev.platform_data; 853 pcdev->pdata = pdev->dev.platform_data;
784 pcdev->platform_flags = pcdev->pdata->flags; 854 pcdev->platform_flags = pcdev->pdata->flags;
785 if (!pcdev->platform_flags & (PXA_CAMERA_DATAWIDTH_8 | 855 if (!(pcdev->platform_flags & (PXA_CAMERA_DATAWIDTH_8 |
786 PXA_CAMERA_DATAWIDTH_9 | PXA_CAMERA_DATAWIDTH_10)) { 856 PXA_CAMERA_DATAWIDTH_9 | PXA_CAMERA_DATAWIDTH_10))) {
787 /* Platform hasn't set available data widths. This is bad. 857 /* Platform hasn't set available data widths. This is bad.
788 * Warn and use a default. */ 858 * Warn and use a default. */
789 dev_warn(&pdev->dev, "WARNING! Platform hasn't set available " 859 dev_warn(&pdev->dev, "WARNING! Platform hasn't set available "