diff options
author | Sylwester Nawrocki <s.nawrocki@samsung.com> | 2010-12-27 13:34:43 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2011-03-21 19:31:39 -0400 |
commit | a25be18dfb6e1b172498a9f6c9793d67057000b0 (patch) | |
tree | c824969740de62c2ddc9e80bc689d72ff73ae1a9 /drivers/media/video/s5p-fimc/fimc-capture.c | |
parent | ac75934cc644051dc1b33b234448ea4a0990f31f (diff) |
[media] s5p-fimc: Add control of the external sensor clock
Manage the camera sensor clock in the host driver rather than
leaving this task for sensor drivers. The clock frequency
must be passed in the sensor's and host driver's platform data.
Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/s5p-fimc/fimc-capture.c')
-rw-r--r-- | drivers/media/video/s5p-fimc/fimc-capture.c | 45 |
1 files changed, 31 insertions, 14 deletions
diff --git a/drivers/media/video/s5p-fimc/fimc-capture.c b/drivers/media/video/s5p-fimc/fimc-capture.c index c6689a24c85b..03ddf5d6164f 100644 --- a/drivers/media/video/s5p-fimc/fimc-capture.c +++ b/drivers/media/video/s5p-fimc/fimc-capture.c | |||
@@ -113,26 +113,43 @@ static int fimc_subdev_attach(struct fimc_dev *fimc, int index) | |||
113 | return -ENODEV; | 113 | return -ENODEV; |
114 | } | 114 | } |
115 | 115 | ||
116 | static int fimc_isp_subdev_init(struct fimc_dev *fimc, int index) | 116 | static int fimc_isp_subdev_init(struct fimc_dev *fimc, unsigned int index) |
117 | { | 117 | { |
118 | struct s5p_fimc_isp_info *isp_info; | 118 | struct s5p_fimc_isp_info *isp_info; |
119 | int ret; | 119 | int ret; |
120 | 120 | ||
121 | if (index >= FIMC_MAX_CAMIF_CLIENTS) | ||
122 | return -EINVAL; | ||
123 | |||
124 | isp_info = fimc->pdata->isp_info[index]; | ||
125 | if (!isp_info) | ||
126 | return -EINVAL; | ||
127 | |||
128 | if (isp_info->clk_frequency) | ||
129 | clk_set_rate(fimc->clock[CLK_CAM], isp_info->clk_frequency); | ||
130 | |||
131 | ret = clk_enable(fimc->clock[CLK_CAM]); | ||
132 | if (ret) | ||
133 | return ret; | ||
134 | |||
121 | ret = fimc_subdev_attach(fimc, index); | 135 | ret = fimc_subdev_attach(fimc, index); |
122 | if (ret) | 136 | if (ret) |
123 | return ret; | 137 | return ret; |
124 | 138 | ||
125 | isp_info = fimc->pdata->isp_info[fimc->vid_cap.input_index]; | ||
126 | ret = fimc_hw_set_camera_polarity(fimc, isp_info); | 139 | ret = fimc_hw_set_camera_polarity(fimc, isp_info); |
127 | if (!ret) { | 140 | if (ret) |
128 | ret = v4l2_subdev_call(fimc->vid_cap.sd, core, | 141 | return ret; |
129 | s_power, 1); | 142 | |
130 | if (!ret) | 143 | ret = v4l2_subdev_call(fimc->vid_cap.sd, core, s_power, 1); |
131 | return ret; | 144 | if (!ret) |
132 | } | 145 | return ret; |
133 | 146 | ||
147 | /* enabling power failed so unregister subdev */ | ||
134 | fimc_subdev_unregister(fimc); | 148 | fimc_subdev_unregister(fimc); |
135 | err("ISP initialization failed: %d", ret); | 149 | |
150 | v4l2_err(&fimc->vid_cap.v4l2_dev, "ISP initialization failed: %d\n", | ||
151 | ret); | ||
152 | |||
136 | return ret; | 153 | return ret; |
137 | } | 154 | } |
138 | 155 | ||
@@ -190,10 +207,7 @@ static int fimc_stop_capture(struct fimc_dev *fimc) | |||
190 | test_bit(ST_CAPT_SHUT, &fimc->state), | 207 | test_bit(ST_CAPT_SHUT, &fimc->state), |
191 | FIMC_SHUTDOWN_TIMEOUT); | 208 | FIMC_SHUTDOWN_TIMEOUT); |
192 | 209 | ||
193 | ret = v4l2_subdev_call(cap->sd, video, s_stream, 0); | 210 | v4l2_subdev_call(cap->sd, video, s_stream, 0); |
194 | |||
195 | if (ret && ret != -ENOIOCTLCMD) | ||
196 | v4l2_err(&fimc->vid_cap.v4l2_dev, "s_stream(0) failed\n"); | ||
197 | 211 | ||
198 | spin_lock_irqsave(&fimc->slock, flags); | 212 | spin_lock_irqsave(&fimc->slock, flags); |
199 | fimc->state &= ~(1 << ST_CAPT_RUN | 1 << ST_CAPT_PEND | | 213 | fimc->state &= ~(1 << ST_CAPT_RUN | 1 << ST_CAPT_PEND | |
@@ -408,7 +422,7 @@ static int fimc_capture_open(struct file *file) | |||
408 | return -EBUSY; | 422 | return -EBUSY; |
409 | 423 | ||
410 | if (++fimc->vid_cap.refcnt == 1) { | 424 | if (++fimc->vid_cap.refcnt == 1) { |
411 | ret = fimc_isp_subdev_init(fimc, -1); | 425 | ret = fimc_isp_subdev_init(fimc, 0); |
412 | if (ret) { | 426 | if (ret) { |
413 | fimc->vid_cap.refcnt--; | 427 | fimc->vid_cap.refcnt--; |
414 | return -EIO; | 428 | return -EIO; |
@@ -433,6 +447,7 @@ static int fimc_capture_close(struct file *file) | |||
433 | v4l2_err(&fimc->vid_cap.v4l2_dev, "releasing ISP\n"); | 447 | v4l2_err(&fimc->vid_cap.v4l2_dev, "releasing ISP\n"); |
434 | 448 | ||
435 | v4l2_subdev_call(fimc->vid_cap.sd, core, s_power, 0); | 449 | v4l2_subdev_call(fimc->vid_cap.sd, core, s_power, 0); |
450 | clk_disable(fimc->clock[CLK_CAM]); | ||
436 | fimc_subdev_unregister(fimc); | 451 | fimc_subdev_unregister(fimc); |
437 | } | 452 | } |
438 | 453 | ||
@@ -604,6 +619,8 @@ static int fimc_cap_s_input(struct file *file, void *priv, | |||
604 | int ret = v4l2_subdev_call(fimc->vid_cap.sd, core, s_power, 0); | 619 | int ret = v4l2_subdev_call(fimc->vid_cap.sd, core, s_power, 0); |
605 | if (ret) | 620 | if (ret) |
606 | err("s_power failed: %d", ret); | 621 | err("s_power failed: %d", ret); |
622 | |||
623 | clk_disable(fimc->clock[CLK_CAM]); | ||
607 | } | 624 | } |
608 | 625 | ||
609 | /* Release the attached sensor subdevice. */ | 626 | /* Release the attached sensor subdevice. */ |