diff options
Diffstat (limited to 'drivers/media/video/atmel-isi.c')
-rw-r--r-- | drivers/media/video/atmel-isi.c | 142 |
1 files changed, 76 insertions, 66 deletions
diff --git a/drivers/media/video/atmel-isi.c b/drivers/media/video/atmel-isi.c index 774715d2f84..8c775c59e12 100644 --- a/drivers/media/video/atmel-isi.c +++ b/drivers/media/video/atmel-isi.c | |||
@@ -94,6 +94,7 @@ struct atmel_isi { | |||
94 | unsigned int irq; | 94 | unsigned int irq; |
95 | 95 | ||
96 | struct isi_platform_data *pdata; | 96 | struct isi_platform_data *pdata; |
97 | u16 width_flags; /* max 12 bits */ | ||
97 | 98 | ||
98 | struct list_head video_buffer_list; | 99 | struct list_head video_buffer_list; |
99 | struct frame_buffer *active; | 100 | struct frame_buffer *active; |
@@ -248,9 +249,9 @@ static int atmel_isi_wait_status(struct atmel_isi *isi, int wait_reset) | |||
248 | /* ------------------------------------------------------------------ | 249 | /* ------------------------------------------------------------------ |
249 | Videobuf operations | 250 | Videobuf operations |
250 | ------------------------------------------------------------------*/ | 251 | ------------------------------------------------------------------*/ |
251 | static int queue_setup(struct vb2_queue *vq, unsigned int *nbuffers, | 252 | static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt, |
252 | unsigned int *nplanes, unsigned int sizes[], | 253 | unsigned int *nbuffers, unsigned int *nplanes, |
253 | void *alloc_ctxs[]) | 254 | unsigned int sizes[], void *alloc_ctxs[]) |
254 | { | 255 | { |
255 | struct soc_camera_device *icd = soc_camera_from_vb2q(vq); | 256 | struct soc_camera_device *icd = soc_camera_from_vb2q(vq); |
256 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); | 257 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); |
@@ -647,50 +648,42 @@ static bool isi_camera_packing_supported(const struct soc_mbus_pixelfmt *fmt) | |||
647 | fmt->packing == SOC_MBUS_PACKING_EXTEND16); | 648 | fmt->packing == SOC_MBUS_PACKING_EXTEND16); |
648 | } | 649 | } |
649 | 650 | ||
650 | static unsigned long make_bus_param(struct atmel_isi *isi) | 651 | #define ISI_BUS_PARAM (V4L2_MBUS_MASTER | \ |
651 | { | 652 | V4L2_MBUS_HSYNC_ACTIVE_HIGH | \ |
652 | unsigned long flags; | 653 | V4L2_MBUS_HSYNC_ACTIVE_LOW | \ |
653 | /* | 654 | V4L2_MBUS_VSYNC_ACTIVE_HIGH | \ |
654 | * Platform specified synchronization and pixel clock polarities are | 655 | V4L2_MBUS_VSYNC_ACTIVE_LOW | \ |
655 | * only a recommendation and are only used during probing. Atmel ISI | 656 | V4L2_MBUS_PCLK_SAMPLE_RISING | \ |
656 | * camera interface only works in master mode, i.e., uses HSYNC and | 657 | V4L2_MBUS_PCLK_SAMPLE_FALLING | \ |
657 | * VSYNC signals from the sensor | 658 | V4L2_MBUS_DATA_ACTIVE_HIGH) |
658 | */ | ||
659 | flags = SOCAM_MASTER | | ||
660 | SOCAM_HSYNC_ACTIVE_HIGH | | ||
661 | SOCAM_HSYNC_ACTIVE_LOW | | ||
662 | SOCAM_VSYNC_ACTIVE_HIGH | | ||
663 | SOCAM_VSYNC_ACTIVE_LOW | | ||
664 | SOCAM_PCLK_SAMPLE_RISING | | ||
665 | SOCAM_PCLK_SAMPLE_FALLING | | ||
666 | SOCAM_DATA_ACTIVE_HIGH; | ||
667 | |||
668 | if (isi->pdata->data_width_flags & ISI_DATAWIDTH_10) | ||
669 | flags |= SOCAM_DATAWIDTH_10; | ||
670 | |||
671 | if (isi->pdata->data_width_flags & ISI_DATAWIDTH_8) | ||
672 | flags |= SOCAM_DATAWIDTH_8; | ||
673 | |||
674 | if (flags & SOCAM_DATAWIDTH_MASK) | ||
675 | return flags; | ||
676 | |||
677 | return 0; | ||
678 | } | ||
679 | 659 | ||
680 | static int isi_camera_try_bus_param(struct soc_camera_device *icd, | 660 | static int isi_camera_try_bus_param(struct soc_camera_device *icd, |
681 | unsigned char buswidth) | 661 | unsigned char buswidth) |
682 | { | 662 | { |
663 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); | ||
683 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); | 664 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); |
684 | struct atmel_isi *isi = ici->priv; | 665 | struct atmel_isi *isi = ici->priv; |
685 | unsigned long camera_flags; | 666 | struct v4l2_mbus_config cfg = {.type = V4L2_MBUS_PARALLEL,}; |
667 | unsigned long common_flags; | ||
686 | int ret; | 668 | int ret; |
687 | 669 | ||
688 | camera_flags = icd->ops->query_bus_param(icd); | 670 | ret = v4l2_subdev_call(sd, video, g_mbus_config, &cfg); |
689 | ret = soc_camera_bus_param_compatible(camera_flags, | 671 | if (!ret) { |
690 | make_bus_param(isi)); | 672 | common_flags = soc_mbus_config_compatible(&cfg, |
691 | if (!ret) | 673 | ISI_BUS_PARAM); |
692 | return -EINVAL; | 674 | if (!common_flags) { |
693 | return 0; | 675 | dev_warn(icd->parent, |
676 | "Flags incompatible: camera 0x%x, host 0x%x\n", | ||
677 | cfg.flags, ISI_BUS_PARAM); | ||
678 | return -EINVAL; | ||
679 | } | ||
680 | } else if (ret != -ENOIOCTLCMD) { | ||
681 | return ret; | ||
682 | } | ||
683 | |||
684 | if ((1 << (buswidth - 1)) & isi->width_flags) | ||
685 | return 0; | ||
686 | return -EINVAL; | ||
694 | } | 687 | } |
695 | 688 | ||
696 | 689 | ||
@@ -812,59 +805,71 @@ static int isi_camera_querycap(struct soc_camera_host *ici, | |||
812 | 805 | ||
813 | static int isi_camera_set_bus_param(struct soc_camera_device *icd, u32 pixfmt) | 806 | static int isi_camera_set_bus_param(struct soc_camera_device *icd, u32 pixfmt) |
814 | { | 807 | { |
808 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); | ||
815 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); | 809 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); |
816 | struct atmel_isi *isi = ici->priv; | 810 | struct atmel_isi *isi = ici->priv; |
817 | unsigned long bus_flags, camera_flags, common_flags; | 811 | struct v4l2_mbus_config cfg = {.type = V4L2_MBUS_PARALLEL,}; |
812 | unsigned long common_flags; | ||
818 | int ret; | 813 | int ret; |
819 | u32 cfg1 = 0; | 814 | u32 cfg1 = 0; |
820 | 815 | ||
821 | camera_flags = icd->ops->query_bus_param(icd); | 816 | ret = v4l2_subdev_call(sd, video, g_mbus_config, &cfg); |
822 | 817 | if (!ret) { | |
823 | bus_flags = make_bus_param(isi); | 818 | common_flags = soc_mbus_config_compatible(&cfg, |
824 | common_flags = soc_camera_bus_param_compatible(camera_flags, bus_flags); | 819 | ISI_BUS_PARAM); |
825 | dev_dbg(icd->parent, "Flags cam: 0x%lx host: 0x%lx common: 0x%lx\n", | 820 | if (!common_flags) { |
826 | camera_flags, bus_flags, common_flags); | 821 | dev_warn(icd->parent, |
827 | if (!common_flags) | 822 | "Flags incompatible: camera 0x%x, host 0x%x\n", |
828 | return -EINVAL; | 823 | cfg.flags, ISI_BUS_PARAM); |
824 | return -EINVAL; | ||
825 | } | ||
826 | } else if (ret != -ENOIOCTLCMD) { | ||
827 | return ret; | ||
828 | } else { | ||
829 | common_flags = ISI_BUS_PARAM; | ||
830 | } | ||
831 | dev_dbg(icd->parent, "Flags cam: 0x%x host: 0x%x common: 0x%lx\n", | ||
832 | cfg.flags, ISI_BUS_PARAM, common_flags); | ||
829 | 833 | ||
830 | /* Make choises, based on platform preferences */ | 834 | /* Make choises, based on platform preferences */ |
831 | if ((common_flags & SOCAM_HSYNC_ACTIVE_HIGH) && | 835 | if ((common_flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH) && |
832 | (common_flags & SOCAM_HSYNC_ACTIVE_LOW)) { | 836 | (common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)) { |
833 | if (isi->pdata->hsync_act_low) | 837 | if (isi->pdata->hsync_act_low) |
834 | common_flags &= ~SOCAM_HSYNC_ACTIVE_HIGH; | 838 | common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_HIGH; |
835 | else | 839 | else |
836 | common_flags &= ~SOCAM_HSYNC_ACTIVE_LOW; | 840 | common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_LOW; |
837 | } | 841 | } |
838 | 842 | ||
839 | if ((common_flags & SOCAM_VSYNC_ACTIVE_HIGH) && | 843 | if ((common_flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH) && |
840 | (common_flags & SOCAM_VSYNC_ACTIVE_LOW)) { | 844 | (common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)) { |
841 | if (isi->pdata->vsync_act_low) | 845 | if (isi->pdata->vsync_act_low) |
842 | common_flags &= ~SOCAM_VSYNC_ACTIVE_HIGH; | 846 | common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_HIGH; |
843 | else | 847 | else |
844 | common_flags &= ~SOCAM_VSYNC_ACTIVE_LOW; | 848 | common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_LOW; |
845 | } | 849 | } |
846 | 850 | ||
847 | if ((common_flags & SOCAM_PCLK_SAMPLE_RISING) && | 851 | if ((common_flags & V4L2_MBUS_PCLK_SAMPLE_RISING) && |
848 | (common_flags & SOCAM_PCLK_SAMPLE_FALLING)) { | 852 | (common_flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)) { |
849 | if (isi->pdata->pclk_act_falling) | 853 | if (isi->pdata->pclk_act_falling) |
850 | common_flags &= ~SOCAM_PCLK_SAMPLE_RISING; | 854 | common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_RISING; |
851 | else | 855 | else |
852 | common_flags &= ~SOCAM_PCLK_SAMPLE_FALLING; | 856 | common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_FALLING; |
853 | } | 857 | } |
854 | 858 | ||
855 | ret = icd->ops->set_bus_param(icd, common_flags); | 859 | cfg.flags = common_flags; |
856 | if (ret < 0) { | 860 | ret = v4l2_subdev_call(sd, video, s_mbus_config, &cfg); |
857 | dev_dbg(icd->parent, "Camera set_bus_param(%lx) returned %d\n", | 861 | if (ret < 0 && ret != -ENOIOCTLCMD) { |
862 | dev_dbg(icd->parent, "camera s_mbus_config(0x%lx) returned %d\n", | ||
858 | common_flags, ret); | 863 | common_flags, ret); |
859 | return ret; | 864 | return ret; |
860 | } | 865 | } |
861 | 866 | ||
862 | /* set bus param for ISI */ | 867 | /* set bus param for ISI */ |
863 | if (common_flags & SOCAM_HSYNC_ACTIVE_LOW) | 868 | if (common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW) |
864 | cfg1 |= ISI_CFG1_HSYNC_POL_ACTIVE_LOW; | 869 | cfg1 |= ISI_CFG1_HSYNC_POL_ACTIVE_LOW; |
865 | if (common_flags & SOCAM_VSYNC_ACTIVE_LOW) | 870 | if (common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW) |
866 | cfg1 |= ISI_CFG1_VSYNC_POL_ACTIVE_LOW; | 871 | cfg1 |= ISI_CFG1_VSYNC_POL_ACTIVE_LOW; |
867 | if (common_flags & SOCAM_PCLK_SAMPLE_FALLING) | 872 | if (common_flags & V4L2_MBUS_PCLK_SAMPLE_FALLING) |
868 | cfg1 |= ISI_CFG1_PIXCLK_POL_ACTIVE_FALLING; | 873 | cfg1 |= ISI_CFG1_PIXCLK_POL_ACTIVE_FALLING; |
869 | 874 | ||
870 | if (isi->pdata->has_emb_sync) | 875 | if (isi->pdata->has_emb_sync) |
@@ -983,6 +988,11 @@ static int __devinit atmel_isi_probe(struct platform_device *pdev) | |||
983 | goto err_ioremap; | 988 | goto err_ioremap; |
984 | } | 989 | } |
985 | 990 | ||
991 | if (pdata->data_width_flags & ISI_DATAWIDTH_8) | ||
992 | isi->width_flags = 1 << 7; | ||
993 | if (pdata->data_width_flags & ISI_DATAWIDTH_10) | ||
994 | isi->width_flags |= 1 << 9; | ||
995 | |||
986 | isi_writel(isi, ISI_CTRL, ISI_CTRL_DIS); | 996 | isi_writel(isi, ISI_CTRL, ISI_CTRL_DIS); |
987 | 997 | ||
988 | irq = platform_get_irq(pdev, 0); | 998 | irq = platform_get_irq(pdev, 0); |