aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/soc_camera.c
diff options
context:
space:
mode:
authorGuennadi Liakhovetski <g.liakhovetski@gmx.de>2009-08-25 10:46:43 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2009-09-18 23:18:49 -0400
commitfa48984e36ee73e964eeb994a45de6525114e871 (patch)
tree733f9fd78a536209456fbc02ceac2792a2b71755 /drivers/media/video/soc_camera.c
parent0d205b6a09177cd14c109321fb40873418a11f7e (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.c50
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,
211static int soc_camera_init_user_formats(struct soc_camera_device *icd) 211static 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
265egfmt:
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 */
260static void soc_camera_free_user_formats(struct soc_camera_device *icd) 272static 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);
406epower: 418epower:
407 soc_camera_free_user_formats(icd);
408eiufmt:
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
979evidstart: 996evidstart:
980 mutex_unlock(&icd->video_lock); 997 mutex_unlock(&icd->video_lock);
998 soc_camera_free_user_formats(icd);
999eiufmt:
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}