Commit fa48984e authored by Guennadi Liakhovetski's avatar Guennadi Liakhovetski Committed by Mauro Carvalho Chehab

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: default avatarGuennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 0d205b6a
...@@ -211,7 +211,7 @@ static int soc_camera_dqbuf(struct file *file, void *priv, ...@@ -211,7 +211,7 @@ static int soc_camera_dqbuf(struct file *file, void *priv,
static int soc_camera_init_user_formats(struct soc_camera_device *icd) static int soc_camera_init_user_formats(struct soc_camera_device *icd)
{ {
struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
int i, fmts = 0; int i, fmts = 0, ret;
if (!ici->ops->get_formats) if (!ici->ops->get_formats)
/* /*
...@@ -224,8 +224,12 @@ static int soc_camera_init_user_formats(struct soc_camera_device *icd) ...@@ -224,8 +224,12 @@ static int soc_camera_init_user_formats(struct soc_camera_device *icd)
* First pass - only count formats this host-sensor * First pass - only count formats this host-sensor
* configuration can provide * configuration can provide
*/ */
for (i = 0; i < icd->num_formats; i++) for (i = 0; i < icd->num_formats; i++) {
fmts += ici->ops->get_formats(icd, i, NULL); ret = ici->ops->get_formats(icd, i, NULL);
if (ret < 0)
return ret;
fmts += ret;
}
if (!fmts) if (!fmts)
return -ENXIO; return -ENXIO;
...@@ -247,19 +251,32 @@ static int soc_camera_init_user_formats(struct soc_camera_device *icd) ...@@ -247,19 +251,32 @@ static int soc_camera_init_user_formats(struct soc_camera_device *icd)
icd->user_formats[i].cam_fmt = icd->formats + i; icd->user_formats[i].cam_fmt = icd->formats + i;
icd->user_formats[i].buswidth = icd->formats[i].depth; icd->user_formats[i].buswidth = icd->formats[i].depth;
} else { } else {
fmts += ici->ops->get_formats(icd, i, ret = ici->ops->get_formats(icd, i,
&icd->user_formats[fmts]); &icd->user_formats[fmts]);
if (ret < 0)
goto egfmt;
fmts += ret;
} }
icd->current_fmt = icd->user_formats[0].host_fmt; icd->current_fmt = icd->user_formats[0].host_fmt;
return 0; return 0;
egfmt:
icd->num_user_formats = 0;
vfree(icd->user_formats);
return ret;
} }
/* Always entered with .video_lock held */ /* Always entered with .video_lock held */
static void soc_camera_free_user_formats(struct soc_camera_device *icd) static void soc_camera_free_user_formats(struct soc_camera_device *icd)
{ {
struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
if (ici->ops->put_formats)
ici->ops->put_formats(icd);
icd->current_fmt = NULL; icd->current_fmt = NULL;
icd->num_user_formats = 0;
vfree(icd->user_formats); vfree(icd->user_formats);
icd->user_formats = NULL; icd->user_formats = NULL;
} }
...@@ -344,16 +361,11 @@ static int soc_camera_open(struct file *file) ...@@ -344,16 +361,11 @@ static int soc_camera_open(struct file *file)
.width = icd->rect_current.width, .width = icd->rect_current.width,
.height = icd->rect_current.height, .height = icd->rect_current.height,
.field = icd->field, .field = icd->field,
.pixelformat = icd->current_fmt->fourcc,
.colorspace = icd->current_fmt->colorspace,
}, },
}; };
ret = soc_camera_init_user_formats(icd);
if (ret < 0)
goto eiufmt;
f.fmt.pix.pixelformat = icd->current_fmt->fourcc;
f.fmt.pix.colorspace = icd->current_fmt->colorspace;
if (icl->power) { if (icl->power) {
ret = icl->power(icd->pdev, 1); ret = icl->power(icd->pdev, 1);
if (ret < 0) if (ret < 0)
...@@ -404,8 +416,6 @@ static int soc_camera_open(struct file *file) ...@@ -404,8 +416,6 @@ static int soc_camera_open(struct file *file)
if (icl->power) if (icl->power)
icl->power(icd->pdev, 0); icl->power(icd->pdev, 0);
epower: epower:
soc_camera_free_user_formats(icd);
eiufmt:
icd->use_count--; icd->use_count--;
mutex_unlock(&icd->video_lock); mutex_unlock(&icd->video_lock);
module_put(ici->ops->owner); module_put(ici->ops->owner);
...@@ -431,7 +441,6 @@ static int soc_camera_close(struct file *file) ...@@ -431,7 +441,6 @@ static int soc_camera_close(struct file *file)
ici->ops->remove(icd); ici->ops->remove(icd);
if (icl->power) if (icl->power)
icl->power(icd->pdev, 0); icl->power(icd->pdev, 0);
soc_camera_free_user_formats(icd);
} }
mutex_unlock(&icd->video_lock); mutex_unlock(&icd->video_lock);
...@@ -954,6 +963,14 @@ static int soc_camera_probe(struct device *dev) ...@@ -954,6 +963,14 @@ static int soc_camera_probe(struct device *dev)
} }
} }
/* At this point client .probe() should have run already */
ret = soc_camera_init_user_formats(icd);
if (ret < 0)
goto eiufmt;
icd->rect_current = icd->rect_max;
icd->field = V4L2_FIELD_ANY;
/* ..._video_start() will create a device node, so we have to protect */ /* ..._video_start() will create a device node, so we have to protect */
mutex_lock(&icd->video_lock); mutex_lock(&icd->video_lock);
...@@ -978,6 +995,8 @@ static int soc_camera_probe(struct device *dev) ...@@ -978,6 +995,8 @@ static int soc_camera_probe(struct device *dev)
evidstart: evidstart:
mutex_unlock(&icd->video_lock); mutex_unlock(&icd->video_lock);
soc_camera_free_user_formats(icd);
eiufmt:
if (icl->board_info) { if (icl->board_info) {
soc_camera_free_i2c(icd); soc_camera_free_i2c(icd);
} else { } else {
...@@ -1023,6 +1042,7 @@ static int soc_camera_remove(struct device *dev) ...@@ -1023,6 +1042,7 @@ static int soc_camera_remove(struct device *dev)
module_put(drv->owner); module_put(drv->owner);
} }
} }
soc_camera_free_user_formats(icd);
return 0; return 0;
} }
......
...@@ -67,8 +67,15 @@ struct soc_camera_host_ops { ...@@ -67,8 +67,15 @@ struct soc_camera_host_ops {
void (*remove)(struct soc_camera_device *); void (*remove)(struct soc_camera_device *);
int (*suspend)(struct soc_camera_device *, pm_message_t); int (*suspend)(struct soc_camera_device *, pm_message_t);
int (*resume)(struct soc_camera_device *); int (*resume)(struct soc_camera_device *);
/*
* .get_formats() is called for each client device format, but
* .put_formats() is only called once. Further, if any of the calls to
* .get_formats() fail, .put_formats() will not be called at all, the
* failing .get_formats() must then clean up internally.
*/
int (*get_formats)(struct soc_camera_device *, int, int (*get_formats)(struct soc_camera_device *, int,
struct soc_camera_format_xlate *); struct soc_camera_format_xlate *);
void (*put_formats)(struct soc_camera_device *);
int (*set_crop)(struct soc_camera_device *, struct v4l2_rect *); int (*set_crop)(struct soc_camera_device *, struct v4l2_rect *);
int (*set_fmt)(struct soc_camera_device *, struct v4l2_format *); int (*set_fmt)(struct soc_camera_device *, struct v4l2_format *);
int (*try_fmt)(struct soc_camera_device *, struct v4l2_format *); int (*try_fmt)(struct soc_camera_device *, struct v4l2_format *);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment