diff options
Diffstat (limited to 'drivers/media/video/atmel-isi.c')
-rw-r--r-- | drivers/media/video/atmel-isi.c | 35 |
1 files changed, 31 insertions, 4 deletions
diff --git a/drivers/media/video/atmel-isi.c b/drivers/media/video/atmel-isi.c index 8c775c59e120..9fe4519176a4 100644 --- a/drivers/media/video/atmel-isi.c +++ b/drivers/media/video/atmel-isi.c | |||
@@ -90,7 +90,10 @@ struct atmel_isi { | |||
90 | struct isi_dma_desc dma_desc[MAX_BUFFER_NUM]; | 90 | struct isi_dma_desc dma_desc[MAX_BUFFER_NUM]; |
91 | 91 | ||
92 | struct completion complete; | 92 | struct completion complete; |
93 | /* ISI peripherial clock */ | ||
93 | struct clk *pclk; | 94 | struct clk *pclk; |
95 | /* ISI_MCK, feed to camera sensor to generate pixel clock */ | ||
96 | struct clk *mck; | ||
94 | unsigned int irq; | 97 | unsigned int irq; |
95 | 98 | ||
96 | struct isi_platform_data *pdata; | 99 | struct isi_platform_data *pdata; |
@@ -766,6 +769,12 @@ static int isi_camera_add_device(struct soc_camera_device *icd) | |||
766 | if (ret) | 769 | if (ret) |
767 | return ret; | 770 | return ret; |
768 | 771 | ||
772 | ret = clk_enable(isi->mck); | ||
773 | if (ret) { | ||
774 | clk_disable(isi->pclk); | ||
775 | return ret; | ||
776 | } | ||
777 | |||
769 | isi->icd = icd; | 778 | isi->icd = icd; |
770 | dev_dbg(icd->parent, "Atmel ISI Camera driver attached to camera %d\n", | 779 | dev_dbg(icd->parent, "Atmel ISI Camera driver attached to camera %d\n", |
771 | icd->devnum); | 780 | icd->devnum); |
@@ -779,6 +788,7 @@ static void isi_camera_remove_device(struct soc_camera_device *icd) | |||
779 | 788 | ||
780 | BUG_ON(icd != isi->icd); | 789 | BUG_ON(icd != isi->icd); |
781 | 790 | ||
791 | clk_disable(isi->mck); | ||
782 | clk_disable(isi->pclk); | 792 | clk_disable(isi->pclk); |
783 | isi->icd = NULL; | 793 | isi->icd = NULL; |
784 | 794 | ||
@@ -803,7 +813,7 @@ static int isi_camera_querycap(struct soc_camera_host *ici, | |||
803 | return 0; | 813 | return 0; |
804 | } | 814 | } |
805 | 815 | ||
806 | static int isi_camera_set_bus_param(struct soc_camera_device *icd, u32 pixfmt) | 816 | static int isi_camera_set_bus_param(struct soc_camera_device *icd) |
807 | { | 817 | { |
808 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); | 818 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); |
809 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); | 819 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); |
@@ -874,7 +884,7 @@ static int isi_camera_set_bus_param(struct soc_camera_device *icd, u32 pixfmt) | |||
874 | 884 | ||
875 | if (isi->pdata->has_emb_sync) | 885 | if (isi->pdata->has_emb_sync) |
876 | cfg1 |= ISI_CFG1_EMB_SYNC; | 886 | cfg1 |= ISI_CFG1_EMB_SYNC; |
877 | if (isi->pdata->isi_full_mode) | 887 | if (isi->pdata->full_mode) |
878 | cfg1 |= ISI_CFG1_FULL_MODE; | 888 | cfg1 |= ISI_CFG1_FULL_MODE; |
879 | 889 | ||
880 | isi_writel(isi, ISI_CTRL, ISI_CTRL_DIS); | 890 | isi_writel(isi, ISI_CTRL, ISI_CTRL_DIS); |
@@ -912,6 +922,7 @@ static int __devexit atmel_isi_remove(struct platform_device *pdev) | |||
912 | isi->fb_descriptors_phys); | 922 | isi->fb_descriptors_phys); |
913 | 923 | ||
914 | iounmap(isi->regs); | 924 | iounmap(isi->regs); |
925 | clk_put(isi->mck); | ||
915 | clk_put(isi->pclk); | 926 | clk_put(isi->pclk); |
916 | kfree(isi); | 927 | kfree(isi); |
917 | 928 | ||
@@ -930,7 +941,7 @@ static int __devinit atmel_isi_probe(struct platform_device *pdev) | |||
930 | struct isi_platform_data *pdata; | 941 | struct isi_platform_data *pdata; |
931 | 942 | ||
932 | pdata = dev->platform_data; | 943 | pdata = dev->platform_data; |
933 | if (!pdata || !pdata->data_width_flags) { | 944 | if (!pdata || !pdata->data_width_flags || !pdata->mck_hz) { |
934 | dev_err(&pdev->dev, | 945 | dev_err(&pdev->dev, |
935 | "No config available for Atmel ISI\n"); | 946 | "No config available for Atmel ISI\n"); |
936 | return -EINVAL; | 947 | return -EINVAL; |
@@ -959,6 +970,19 @@ static int __devinit atmel_isi_probe(struct platform_device *pdev) | |||
959 | INIT_LIST_HEAD(&isi->video_buffer_list); | 970 | INIT_LIST_HEAD(&isi->video_buffer_list); |
960 | INIT_LIST_HEAD(&isi->dma_desc_head); | 971 | INIT_LIST_HEAD(&isi->dma_desc_head); |
961 | 972 | ||
973 | /* Get ISI_MCK, provided by programmable clock or external clock */ | ||
974 | isi->mck = clk_get(dev, "isi_mck"); | ||
975 | if (IS_ERR(isi->mck)) { | ||
976 | dev_err(dev, "Failed to get isi_mck\n"); | ||
977 | ret = PTR_ERR(isi->mck); | ||
978 | goto err_clk_get; | ||
979 | } | ||
980 | |||
981 | /* Set ISI_MCK's frequency, it should be faster than pixel clock */ | ||
982 | ret = clk_set_rate(isi->mck, pdata->mck_hz); | ||
983 | if (ret < 0) | ||
984 | goto err_set_mck_rate; | ||
985 | |||
962 | isi->p_fb_descriptors = dma_alloc_coherent(&pdev->dev, | 986 | isi->p_fb_descriptors = dma_alloc_coherent(&pdev->dev, |
963 | sizeof(struct fbd) * MAX_BUFFER_NUM, | 987 | sizeof(struct fbd) * MAX_BUFFER_NUM, |
964 | &isi->fb_descriptors_phys, | 988 | &isi->fb_descriptors_phys, |
@@ -1034,9 +1058,12 @@ err_alloc_ctx: | |||
1034 | isi->p_fb_descriptors, | 1058 | isi->p_fb_descriptors, |
1035 | isi->fb_descriptors_phys); | 1059 | isi->fb_descriptors_phys); |
1036 | err_alloc_descriptors: | 1060 | err_alloc_descriptors: |
1061 | err_set_mck_rate: | ||
1062 | clk_put(isi->mck); | ||
1063 | err_clk_get: | ||
1037 | kfree(isi); | 1064 | kfree(isi); |
1038 | err_alloc_isi: | 1065 | err_alloc_isi: |
1039 | clk_put(isi->pclk); | 1066 | clk_put(pclk); |
1040 | 1067 | ||
1041 | return ret; | 1068 | return ret; |
1042 | } | 1069 | } |