diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/media/video/sh_mobile_ceu_camera.c | 42 |
1 files changed, 36 insertions, 6 deletions
diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c index 9c8b7c7b89ee..edb6ec3d2bcd 100644 --- a/drivers/media/video/sh_mobile_ceu_camera.c +++ b/drivers/media/video/sh_mobile_ceu_camera.c | |||
@@ -153,6 +153,40 @@ static u32 ceu_read(struct sh_mobile_ceu_dev *priv, unsigned long reg_offs) | |||
153 | return ioread32(priv->base + reg_offs); | 153 | return ioread32(priv->base + reg_offs); |
154 | } | 154 | } |
155 | 155 | ||
156 | static int sh_mobile_ceu_soft_reset(struct sh_mobile_ceu_dev *pcdev) | ||
157 | { | ||
158 | int i, success = 0; | ||
159 | struct soc_camera_device *icd = pcdev->icd; | ||
160 | |||
161 | ceu_write(pcdev, CAPSR, 1 << 16); /* reset */ | ||
162 | |||
163 | /* wait CSTSR.CPTON bit */ | ||
164 | for (i = 0; i < 1000; i++) { | ||
165 | if (!(ceu_read(pcdev, CSTSR) & 1)) { | ||
166 | success++; | ||
167 | break; | ||
168 | } | ||
169 | udelay(1); | ||
170 | } | ||
171 | |||
172 | /* wait CAPSR.CPKIL bit */ | ||
173 | for (i = 0; i < 1000; i++) { | ||
174 | if (!(ceu_read(pcdev, CAPSR) & (1 << 16))) { | ||
175 | success++; | ||
176 | break; | ||
177 | } | ||
178 | udelay(1); | ||
179 | } | ||
180 | |||
181 | |||
182 | if (2 != success) { | ||
183 | dev_warn(&icd->dev, "soft reset time out\n"); | ||
184 | return -EIO; | ||
185 | } | ||
186 | |||
187 | return 0; | ||
188 | } | ||
189 | |||
156 | /* | 190 | /* |
157 | * Videobuf operations | 191 | * Videobuf operations |
158 | */ | 192 | */ |
@@ -407,13 +441,9 @@ static int sh_mobile_ceu_add_device(struct soc_camera_device *icd) | |||
407 | 441 | ||
408 | pm_runtime_get_sync(ici->v4l2_dev.dev); | 442 | pm_runtime_get_sync(ici->v4l2_dev.dev); |
409 | 443 | ||
410 | ceu_write(pcdev, CAPSR, 1 << 16); /* reset */ | ||
411 | while (ceu_read(pcdev, CSTSR) & 1) | ||
412 | msleep(1); | ||
413 | |||
414 | pcdev->icd = icd; | 444 | pcdev->icd = icd; |
415 | 445 | ||
416 | return 0; | 446 | return sh_mobile_ceu_soft_reset(pcdev); |
417 | } | 447 | } |
418 | 448 | ||
419 | /* Called with .video_lock held */ | 449 | /* Called with .video_lock held */ |
@@ -427,7 +457,7 @@ static void sh_mobile_ceu_remove_device(struct soc_camera_device *icd) | |||
427 | 457 | ||
428 | /* disable capture, disable interrupts */ | 458 | /* disable capture, disable interrupts */ |
429 | ceu_write(pcdev, CEIER, 0); | 459 | ceu_write(pcdev, CEIER, 0); |
430 | ceu_write(pcdev, CAPSR, 1 << 16); /* reset */ | 460 | sh_mobile_ceu_soft_reset(pcdev); |
431 | 461 | ||
432 | /* make sure active buffer is canceled */ | 462 | /* make sure active buffer is canceled */ |
433 | spin_lock_irqsave(&pcdev->lock, flags); | 463 | spin_lock_irqsave(&pcdev->lock, flags); |