diff options
author | Guennadi Liakhovetski <g.liakhovetski@gmx.de> | 2009-08-25 10:46:43 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-09-18 23:18:49 -0400 |
commit | fa48984e36ee73e964eeb994a45de6525114e871 (patch) | |
tree | 733f9fd78a536209456fbc02ceac2792a2b71755 /drivers/media/video/soc_camera.c | |
parent | 0d205b6a09177cd14c109321fb40873418a11f7e (diff) |
V4L/DVB (12519): soc-camera: put pixel format initialisation back in probe, add .put_formats()
The move of format translation initialisation into soc_camera_open() was
temporary for the soc-camera as platform driver intermediate step, put it back
into soc_camera_probe(). Also add a .put_formats() method to
soc_camera_host_ops to free any resources host driver might have allocated in
.get_formats().
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/soc_camera.c')
-rw-r--r-- | drivers/media/video/soc_camera.c | 50 |
1 files changed, 35 insertions, 15 deletions
diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c index 5028023b72aa..aa6614b60d6f 100644 --- a/drivers/media/video/soc_camera.c +++ b/drivers/media/video/soc_camera.c | |||
@@ -211,7 +211,7 @@ static int soc_camera_dqbuf(struct file *file, void *priv, | |||
211 | static int soc_camera_init_user_formats(struct soc_camera_device *icd) | 211 | static int soc_camera_init_user_formats(struct soc_camera_device *icd) |
212 | { | 212 | { |
213 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); | 213 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); |
214 | int i, fmts = 0; | 214 | int i, fmts = 0, ret; |
215 | 215 | ||
216 | if (!ici->ops->get_formats) | 216 | if (!ici->ops->get_formats) |
217 | /* | 217 | /* |
@@ -224,8 +224,12 @@ static int soc_camera_init_user_formats(struct soc_camera_device *icd) | |||
224 | * First pass - only count formats this host-sensor | 224 | * First pass - only count formats this host-sensor |
225 | * configuration can provide | 225 | * configuration can provide |
226 | */ | 226 | */ |
227 | for (i = 0; i < icd->num_formats; i++) | 227 | for (i = 0; i < icd->num_formats; i++) { |
228 | fmts += ici->ops->get_formats(icd, i, NULL); | 228 | ret = ici->ops->get_formats(icd, i, NULL); |
229 | if (ret < 0) | ||
230 | return ret; | ||
231 | fmts += ret; | ||
232 | } | ||
229 | 233 | ||
230 | if (!fmts) | 234 | if (!fmts) |
231 | return -ENXIO; | 235 | return -ENXIO; |
@@ -247,19 +251,32 @@ static int soc_camera_init_user_formats(struct soc_camera_device *icd) | |||
247 | icd->user_formats[i].cam_fmt = icd->formats + i; | 251 | icd->user_formats[i].cam_fmt = icd->formats + i; |
248 | icd->user_formats[i].buswidth = icd->formats[i].depth; | 252 | icd->user_formats[i].buswidth = icd->formats[i].depth; |
249 | } else { | 253 | } else { |
250 | fmts += ici->ops->get_formats(icd, i, | 254 | ret = ici->ops->get_formats(icd, i, |
251 | &icd->user_formats[fmts]); | 255 | &icd->user_formats[fmts]); |
256 | if (ret < 0) | ||
257 | goto egfmt; | ||
258 | fmts += ret; | ||
252 | } | 259 | } |
253 | 260 | ||
254 | icd->current_fmt = icd->user_formats[0].host_fmt; | 261 | icd->current_fmt = icd->user_formats[0].host_fmt; |
255 | 262 | ||
256 | return 0; | 263 | return 0; |
264 | |||
265 | egfmt: | ||
266 | icd->num_user_formats = 0; | ||
267 | vfree(icd->user_formats); | ||
268 | return ret; | ||
257 | } | 269 | } |
258 | 270 | ||
259 | /* Always entered with .video_lock held */ | 271 | /* Always entered with .video_lock held */ |
260 | static void soc_camera_free_user_formats(struct soc_camera_device *icd) | 272 | static void soc_camera_free_user_formats(struct soc_camera_device *icd) |
261 | { | 273 | { |
274 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); | ||
275 | |||
276 | if (ici->ops->put_formats) | ||
277 | ici->ops->put_formats(icd); | ||
262 | icd->current_fmt = NULL; | 278 | icd->current_fmt = NULL; |
279 | icd->num_user_formats = 0; | ||
263 | vfree(icd->user_formats); | 280 | vfree(icd->user_formats); |
264 | icd->user_formats = NULL; | 281 | icd->user_formats = NULL; |
265 | } | 282 | } |
@@ -344,16 +361,11 @@ static int soc_camera_open(struct file *file) | |||
344 | .width = icd->rect_current.width, | 361 | .width = icd->rect_current.width, |
345 | .height = icd->rect_current.height, | 362 | .height = icd->rect_current.height, |
346 | .field = icd->field, | 363 | .field = icd->field, |
364 | .pixelformat = icd->current_fmt->fourcc, | ||
365 | .colorspace = icd->current_fmt->colorspace, | ||
347 | }, | 366 | }, |
348 | }; | 367 | }; |
349 | 368 | ||
350 | ret = soc_camera_init_user_formats(icd); | ||
351 | if (ret < 0) | ||
352 | goto eiufmt; | ||
353 | |||
354 | f.fmt.pix.pixelformat = icd->current_fmt->fourcc; | ||
355 | f.fmt.pix.colorspace = icd->current_fmt->colorspace; | ||
356 | |||
357 | if (icl->power) { | 369 | if (icl->power) { |
358 | ret = icl->power(icd->pdev, 1); | 370 | ret = icl->power(icd->pdev, 1); |
359 | if (ret < 0) | 371 | if (ret < 0) |
@@ -404,8 +416,6 @@ eiciadd: | |||
404 | if (icl->power) | 416 | if (icl->power) |
405 | icl->power(icd->pdev, 0); | 417 | icl->power(icd->pdev, 0); |
406 | epower: | 418 | epower: |
407 | soc_camera_free_user_formats(icd); | ||
408 | eiufmt: | ||
409 | icd->use_count--; | 419 | icd->use_count--; |
410 | mutex_unlock(&icd->video_lock); | 420 | mutex_unlock(&icd->video_lock); |
411 | module_put(ici->ops->owner); | 421 | module_put(ici->ops->owner); |
@@ -431,7 +441,6 @@ static int soc_camera_close(struct file *file) | |||
431 | ici->ops->remove(icd); | 441 | ici->ops->remove(icd); |
432 | if (icl->power) | 442 | if (icl->power) |
433 | icl->power(icd->pdev, 0); | 443 | icl->power(icd->pdev, 0); |
434 | soc_camera_free_user_formats(icd); | ||
435 | } | 444 | } |
436 | 445 | ||
437 | mutex_unlock(&icd->video_lock); | 446 | mutex_unlock(&icd->video_lock); |
@@ -954,6 +963,14 @@ static int soc_camera_probe(struct device *dev) | |||
954 | } | 963 | } |
955 | } | 964 | } |
956 | 965 | ||
966 | /* At this point client .probe() should have run already */ | ||
967 | ret = soc_camera_init_user_formats(icd); | ||
968 | if (ret < 0) | ||
969 | goto eiufmt; | ||
970 | |||
971 | icd->rect_current = icd->rect_max; | ||
972 | icd->field = V4L2_FIELD_ANY; | ||
973 | |||
957 | /* ..._video_start() will create a device node, so we have to protect */ | 974 | /* ..._video_start() will create a device node, so we have to protect */ |
958 | mutex_lock(&icd->video_lock); | 975 | mutex_lock(&icd->video_lock); |
959 | 976 | ||
@@ -978,6 +995,8 @@ static int soc_camera_probe(struct device *dev) | |||
978 | 995 | ||
979 | evidstart: | 996 | evidstart: |
980 | mutex_unlock(&icd->video_lock); | 997 | mutex_unlock(&icd->video_lock); |
998 | soc_camera_free_user_formats(icd); | ||
999 | eiufmt: | ||
981 | if (icl->board_info) { | 1000 | if (icl->board_info) { |
982 | soc_camera_free_i2c(icd); | 1001 | soc_camera_free_i2c(icd); |
983 | } else { | 1002 | } else { |
@@ -1023,6 +1042,7 @@ static int soc_camera_remove(struct device *dev) | |||
1023 | module_put(drv->owner); | 1042 | module_put(drv->owner); |
1024 | } | 1043 | } |
1025 | } | 1044 | } |
1045 | soc_camera_free_user_formats(icd); | ||
1026 | 1046 | ||
1027 | return 0; | 1047 | return 0; |
1028 | } | 1048 | } |