aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/soc_camera.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/soc_camera.c')
-rw-r--r--drivers/media/video/soc_camera.c389
1 files changed, 274 insertions, 115 deletions
diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c
index 66ebe5956a87..90077cb4fe66 100644
--- a/drivers/media/video/soc_camera.c
+++ b/drivers/media/video/soc_camera.c
@@ -33,10 +33,9 @@
33static LIST_HEAD(hosts); 33static LIST_HEAD(hosts);
34static LIST_HEAD(devices); 34static LIST_HEAD(devices);
35static DEFINE_MUTEX(list_lock); 35static DEFINE_MUTEX(list_lock);
36static DEFINE_MUTEX(video_lock);
37 36
38const static struct soc_camera_data_format* 37const struct soc_camera_data_format *soc_camera_format_by_fourcc(
39format_by_fourcc(struct soc_camera_device *icd, unsigned int fourcc) 38 struct soc_camera_device *icd, unsigned int fourcc)
40{ 39{
41 unsigned int i; 40 unsigned int i;
42 41
@@ -45,67 +44,87 @@ format_by_fourcc(struct soc_camera_device *icd, unsigned int fourcc)
45 return icd->formats + i; 44 return icd->formats + i;
46 return NULL; 45 return NULL;
47} 46}
47EXPORT_SYMBOL(soc_camera_format_by_fourcc);
48 48
49static int soc_camera_try_fmt_vid_cap(struct file *file, void *priv, 49const struct soc_camera_format_xlate *soc_camera_xlate_by_fourcc(
50 struct v4l2_format *f) 50 struct soc_camera_device *icd, unsigned int fourcc)
51{ 51{
52 struct soc_camera_file *icf = file->private_data; 52 unsigned int i;
53 struct soc_camera_device *icd = icf->icd;
54 struct soc_camera_host *ici =
55 to_soc_camera_host(icd->dev.parent);
56 enum v4l2_field field;
57 const struct soc_camera_data_format *fmt;
58 int ret;
59 53
60 WARN_ON(priv != file->private_data); 54 for (i = 0; i < icd->num_user_formats; i++)
55 if (icd->user_formats[i].host_fmt->fourcc == fourcc)
56 return icd->user_formats + i;
57 return NULL;
58}
59EXPORT_SYMBOL(soc_camera_xlate_by_fourcc);
61 60
62 fmt = format_by_fourcc(icd, f->fmt.pix.pixelformat); 61/**
63 if (!fmt) { 62 * soc_camera_apply_sensor_flags() - apply platform SOCAM_SENSOR_INVERT_* flags
64 dev_dbg(&icd->dev, "invalid format 0x%08x\n", 63 * @icl: camera platform parameters
65 f->fmt.pix.pixelformat); 64 * @flags: flags to be inverted according to platform configuration
66 return -EINVAL; 65 * @return: resulting flags
67 } 66 */
67unsigned long soc_camera_apply_sensor_flags(struct soc_camera_link *icl,
68 unsigned long flags)
69{
70 unsigned long f;
68 71
69 dev_dbg(&icd->dev, "fmt: 0x%08x\n", fmt->fourcc); 72 /* If only one of the two polarities is supported, switch to the opposite */
73 if (icl->flags & SOCAM_SENSOR_INVERT_HSYNC) {
74 f = flags & (SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_LOW);
75 if (f == SOCAM_HSYNC_ACTIVE_HIGH || f == SOCAM_HSYNC_ACTIVE_LOW)
76 flags ^= SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_LOW;
77 }
70 78
71 field = f->fmt.pix.field; 79 if (icl->flags & SOCAM_SENSOR_INVERT_VSYNC) {
80 f = flags & (SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_LOW);
81 if (f == SOCAM_VSYNC_ACTIVE_HIGH || f == SOCAM_VSYNC_ACTIVE_LOW)
82 flags ^= SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_LOW;
83 }
72 84
73 if (field == V4L2_FIELD_ANY) { 85 if (icl->flags & SOCAM_SENSOR_INVERT_PCLK) {
74 field = V4L2_FIELD_NONE; 86 f = flags & (SOCAM_PCLK_SAMPLE_RISING | SOCAM_PCLK_SAMPLE_FALLING);
75 } else if (V4L2_FIELD_NONE != field) { 87 if (f == SOCAM_PCLK_SAMPLE_RISING || f == SOCAM_PCLK_SAMPLE_FALLING)
76 dev_err(&icd->dev, "Field type invalid.\n"); 88 flags ^= SOCAM_PCLK_SAMPLE_RISING | SOCAM_PCLK_SAMPLE_FALLING;
77 return -EINVAL;
78 } 89 }
79 90
80 /* test physical bus parameters */ 91 return flags;
81 ret = ici->ops->try_bus_param(icd, f->fmt.pix.pixelformat); 92}
82 if (ret) 93EXPORT_SYMBOL(soc_camera_apply_sensor_flags);
83 return ret;
84 94
85 /* limit format to hardware capabilities */ 95static int soc_camera_try_fmt_vid_cap(struct file *file, void *priv,
86 ret = ici->ops->try_fmt_cap(icd, f); 96 struct v4l2_format *f)
97{
98 struct soc_camera_file *icf = file->private_data;
99 struct soc_camera_device *icd = icf->icd;
100 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
87 101
88 /* calculate missing fields */ 102 WARN_ON(priv != file->private_data);
89 f->fmt.pix.field = field;
90 f->fmt.pix.bytesperline =
91 (f->fmt.pix.width * fmt->depth) >> 3;
92 f->fmt.pix.sizeimage =
93 f->fmt.pix.height * f->fmt.pix.bytesperline;
94 103
95 return ret; 104 /* limit format to hardware capabilities */
105 return ici->ops->try_fmt(icd, f);
96} 106}
97 107
98static int soc_camera_enum_input(struct file *file, void *priv, 108static int soc_camera_enum_input(struct file *file, void *priv,
99 struct v4l2_input *inp) 109 struct v4l2_input *inp)
100{ 110{
111 struct soc_camera_file *icf = file->private_data;
112 struct soc_camera_device *icd = icf->icd;
113 int ret = 0;
114
101 if (inp->index != 0) 115 if (inp->index != 0)
102 return -EINVAL; 116 return -EINVAL;
103 117
104 inp->type = V4L2_INPUT_TYPE_CAMERA; 118 if (icd->ops->enum_input)
105 inp->std = V4L2_STD_UNKNOWN; 119 ret = icd->ops->enum_input(icd, inp);
106 strcpy(inp->name, "Camera"); 120 else {
121 /* default is camera */
122 inp->type = V4L2_INPUT_TYPE_CAMERA;
123 inp->std = V4L2_STD_UNKNOWN;
124 strcpy(inp->name, "Camera");
125 }
107 126
108 return 0; 127 return ret;
109} 128}
110 129
111static int soc_camera_g_input(struct file *file, void *priv, unsigned int *i) 130static int soc_camera_g_input(struct file *file, void *priv, unsigned int *i)
@@ -125,7 +144,14 @@ static int soc_camera_s_input(struct file *file, void *priv, unsigned int i)
125 144
126static int soc_camera_s_std(struct file *file, void *priv, v4l2_std_id *a) 145static int soc_camera_s_std(struct file *file, void *priv, v4l2_std_id *a)
127{ 146{
128 return 0; 147 struct soc_camera_file *icf = file->private_data;
148 struct soc_camera_device *icd = icf->icd;
149 int ret = 0;
150
151 if (icd->ops->set_std)
152 ret = icd->ops->set_std(icd, a);
153
154 return ret;
129} 155}
130 156
131static int soc_camera_reqbufs(struct file *file, void *priv, 157static int soc_camera_reqbufs(struct file *file, void *priv,
@@ -134,8 +160,7 @@ static int soc_camera_reqbufs(struct file *file, void *priv,
134 int ret; 160 int ret;
135 struct soc_camera_file *icf = file->private_data; 161 struct soc_camera_file *icf = file->private_data;
136 struct soc_camera_device *icd = icf->icd; 162 struct soc_camera_device *icd = icf->icd;
137 struct soc_camera_host *ici = 163 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
138 to_soc_camera_host(icd->dev.parent);
139 164
140 WARN_ON(priv != file->private_data); 165 WARN_ON(priv != file->private_data);
141 166
@@ -178,6 +203,59 @@ static int soc_camera_dqbuf(struct file *file, void *priv,
178 return videobuf_dqbuf(&icf->vb_vidq, p, file->f_flags & O_NONBLOCK); 203 return videobuf_dqbuf(&icf->vb_vidq, p, file->f_flags & O_NONBLOCK);
179} 204}
180 205
206static int soc_camera_init_user_formats(struct soc_camera_device *icd)
207{
208 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
209 int i, fmts = 0;
210
211 if (!ici->ops->get_formats)
212 /*
213 * Fallback mode - the host will have to serve all
214 * sensor-provided formats one-to-one to the user
215 */
216 fmts = icd->num_formats;
217 else
218 /*
219 * First pass - only count formats this host-sensor
220 * configuration can provide
221 */
222 for (i = 0; i < icd->num_formats; i++)
223 fmts += ici->ops->get_formats(icd, i, NULL);
224
225 if (!fmts)
226 return -ENXIO;
227
228 icd->user_formats =
229 vmalloc(fmts * sizeof(struct soc_camera_format_xlate));
230 if (!icd->user_formats)
231 return -ENOMEM;
232
233 icd->num_user_formats = fmts;
234 fmts = 0;
235
236 dev_dbg(&icd->dev, "Found %d supported formats.\n", fmts);
237
238 /* Second pass - actually fill data formats */
239 for (i = 0; i < icd->num_formats; i++)
240 if (!ici->ops->get_formats) {
241 icd->user_formats[i].host_fmt = icd->formats + i;
242 icd->user_formats[i].cam_fmt = icd->formats + i;
243 icd->user_formats[i].buswidth = icd->formats[i].depth;
244 } else {
245 fmts += ici->ops->get_formats(icd, i,
246 &icd->user_formats[fmts]);
247 }
248
249 icd->current_fmt = icd->user_formats[0].host_fmt;
250
251 return 0;
252}
253
254static void soc_camera_free_user_formats(struct soc_camera_device *icd)
255{
256 vfree(icd->user_formats);
257}
258
181static int soc_camera_open(struct inode *inode, struct file *file) 259static int soc_camera_open(struct inode *inode, struct file *file)
182{ 260{
183 struct video_device *vdev; 261 struct video_device *vdev;
@@ -190,8 +268,10 @@ static int soc_camera_open(struct inode *inode, struct file *file)
190 if (!icf) 268 if (!icf)
191 return -ENOMEM; 269 return -ENOMEM;
192 270
193 /* Protect against icd->remove() until we module_get() both drivers. */ 271 /*
194 mutex_lock(&video_lock); 272 * It is safe to dereference these pointers now as long as a user has
273 * the video device open - we are protected by the held cdev reference.
274 */
195 275
196 vdev = video_devdata(file); 276 vdev = video_devdata(file);
197 icd = container_of(vdev->parent, struct soc_camera_device, dev); 277 icd = container_of(vdev->parent, struct soc_camera_device, dev);
@@ -209,20 +289,25 @@ static int soc_camera_open(struct inode *inode, struct file *file)
209 goto emgi; 289 goto emgi;
210 } 290 }
211 291
292 /* Protect against icd->remove() until we module_get() both drivers. */
293 mutex_lock(&icd->video_lock);
294
212 icf->icd = icd; 295 icf->icd = icd;
213 icd->use_count++; 296 icd->use_count++;
214 297
215 /* Now we really have to activate the camera */ 298 /* Now we really have to activate the camera */
216 if (icd->use_count == 1) { 299 if (icd->use_count == 1) {
300 ret = soc_camera_init_user_formats(icd);
301 if (ret < 0)
302 goto eiufmt;
217 ret = ici->ops->add(icd); 303 ret = ici->ops->add(icd);
218 if (ret < 0) { 304 if (ret < 0) {
219 dev_err(&icd->dev, "Couldn't activate the camera: %d\n", ret); 305 dev_err(&icd->dev, "Couldn't activate the camera: %d\n", ret);
220 icd->use_count--;
221 goto eiciadd; 306 goto eiciadd;
222 } 307 }
223 } 308 }
224 309
225 mutex_unlock(&video_lock); 310 mutex_unlock(&icd->video_lock);
226 311
227 file->private_data = icf; 312 file->private_data = icf;
228 dev_dbg(&icd->dev, "camera device open\n"); 313 dev_dbg(&icd->dev, "camera device open\n");
@@ -231,13 +316,16 @@ static int soc_camera_open(struct inode *inode, struct file *file)
231 316
232 return 0; 317 return 0;
233 318
234 /* All errors are entered with the video_lock held */ 319 /* First two errors are entered with the .video_lock held */
235eiciadd: 320eiciadd:
321 soc_camera_free_user_formats(icd);
322eiufmt:
323 icd->use_count--;
324 mutex_unlock(&icd->video_lock);
236 module_put(ici->ops->owner); 325 module_put(ici->ops->owner);
237emgi: 326emgi:
238 module_put(icd->ops->owner); 327 module_put(icd->ops->owner);
239emgd: 328emgd:
240 mutex_unlock(&video_lock);
241 vfree(icf); 329 vfree(icf);
242 return ret; 330 return ret;
243} 331}
@@ -249,13 +337,16 @@ static int soc_camera_close(struct inode *inode, struct file *file)
249 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); 337 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
250 struct video_device *vdev = icd->vdev; 338 struct video_device *vdev = icd->vdev;
251 339
252 mutex_lock(&video_lock); 340 mutex_lock(&icd->video_lock);
253 icd->use_count--; 341 icd->use_count--;
254 if (!icd->use_count) 342 if (!icd->use_count) {
255 ici->ops->remove(icd); 343 ici->ops->remove(icd);
344 soc_camera_free_user_formats(icd);
345 }
346 mutex_unlock(&icd->video_lock);
347
256 module_put(icd->ops->owner); 348 module_put(icd->ops->owner);
257 module_put(ici->ops->owner); 349 module_put(ici->ops->owner);
258 mutex_unlock(&video_lock);
259 350
260 vfree(icf); 351 vfree(icf);
261 352
@@ -265,7 +356,7 @@ static int soc_camera_close(struct inode *inode, struct file *file)
265} 356}
266 357
267static ssize_t soc_camera_read(struct file *file, char __user *buf, 358static ssize_t soc_camera_read(struct file *file, char __user *buf,
268 size_t count, loff_t *ppos) 359 size_t count, loff_t *ppos)
269{ 360{
270 struct soc_camera_file *icf = file->private_data; 361 struct soc_camera_file *icf = file->private_data;
271 struct soc_camera_device *icd = icf->icd; 362 struct soc_camera_device *icd = icf->icd;
@@ -299,8 +390,7 @@ static unsigned int soc_camera_poll(struct file *file, poll_table *pt)
299{ 390{
300 struct soc_camera_file *icf = file->private_data; 391 struct soc_camera_file *icf = file->private_data;
301 struct soc_camera_device *icd = icf->icd; 392 struct soc_camera_device *icd = icf->icd;
302 struct soc_camera_host *ici = 393 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
303 to_soc_camera_host(icd->dev.parent);
304 394
305 if (list_empty(&icf->vb_vidq.stream)) { 395 if (list_empty(&icf->vb_vidq.stream)) {
306 dev_err(&icd->dev, "Trying to poll with no queued buffers!\n"); 396 dev_err(&icd->dev, "Trying to poll with no queued buffers!\n");
@@ -310,7 +400,6 @@ static unsigned int soc_camera_poll(struct file *file, poll_table *pt)
310 return ici->ops->poll(file, pt); 400 return ici->ops->poll(file, pt);
311} 401}
312 402
313
314static struct file_operations soc_camera_fops = { 403static struct file_operations soc_camera_fops = {
315 .owner = THIS_MODULE, 404 .owner = THIS_MODULE,
316 .open = soc_camera_open, 405 .open = soc_camera_open,
@@ -322,44 +411,50 @@ static struct file_operations soc_camera_fops = {
322 .llseek = no_llseek, 411 .llseek = no_llseek,
323}; 412};
324 413
325
326static int soc_camera_s_fmt_vid_cap(struct file *file, void *priv, 414static int soc_camera_s_fmt_vid_cap(struct file *file, void *priv,
327 struct v4l2_format *f) 415 struct v4l2_format *f)
328{ 416{
329 struct soc_camera_file *icf = file->private_data; 417 struct soc_camera_file *icf = file->private_data;
330 struct soc_camera_device *icd = icf->icd; 418 struct soc_camera_device *icd = icf->icd;
331 struct soc_camera_host *ici = 419 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
332 to_soc_camera_host(icd->dev.parent); 420 struct v4l2_pix_format *pix = &f->fmt.pix;
421 __u32 pixfmt = pix->pixelformat;
333 int ret; 422 int ret;
334 struct v4l2_rect rect; 423 struct v4l2_rect rect;
335 const static struct soc_camera_data_format *data_fmt;
336 424
337 WARN_ON(priv != file->private_data); 425 WARN_ON(priv != file->private_data);
338 426
339 data_fmt = format_by_fourcc(icd, f->fmt.pix.pixelformat); 427 ret = soc_camera_try_fmt_vid_cap(file, priv, f);
340 if (!data_fmt)
341 return -EINVAL;
342
343 /* buswidth may be further adjusted by the ici */
344 icd->buswidth = data_fmt->depth;
345
346 ret = soc_camera_try_fmt_vid_cap(file, icf, f);
347 if (ret < 0) 428 if (ret < 0)
348 return ret; 429 return ret;
349 430
431 mutex_lock(&icf->vb_vidq.vb_lock);
432
433 if (videobuf_queue_is_busy(&icf->vb_vidq)) {
434 dev_err(&icd->dev, "S_FMT denied: queue busy\n");
435 ret = -EBUSY;
436 goto unlock;
437 }
438
350 rect.left = icd->x_current; 439 rect.left = icd->x_current;
351 rect.top = icd->y_current; 440 rect.top = icd->y_current;
352 rect.width = f->fmt.pix.width; 441 rect.width = pix->width;
353 rect.height = f->fmt.pix.height; 442 rect.height = pix->height;
354 ret = ici->ops->set_fmt_cap(icd, f->fmt.pix.pixelformat, &rect); 443 ret = ici->ops->set_fmt(icd, pix->pixelformat, &rect);
355 if (ret < 0) 444 if (ret < 0) {
356 return ret; 445 goto unlock;
446 } else if (!icd->current_fmt ||
447 icd->current_fmt->fourcc != pixfmt) {
448 dev_err(&ici->dev,
449 "Host driver hasn't set up current format correctly!\n");
450 ret = -EINVAL;
451 goto unlock;
452 }
357 453
358 icd->current_fmt = data_fmt;
359 icd->width = rect.width; 454 icd->width = rect.width;
360 icd->height = rect.height; 455 icd->height = rect.height;
361 icf->vb_vidq.field = f->fmt.pix.field; 456 icf->vb_vidq.field = pix->field;
362 if (V4L2_BUF_TYPE_VIDEO_CAPTURE != f->type) 457 if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
363 dev_warn(&icd->dev, "Attention! Wrong buf-type %d\n", 458 dev_warn(&icd->dev, "Attention! Wrong buf-type %d\n",
364 f->type); 459 f->type);
365 460
@@ -367,11 +462,16 @@ static int soc_camera_s_fmt_vid_cap(struct file *file, void *priv,
367 icd->width, icd->height); 462 icd->width, icd->height);
368 463
369 /* set physical bus parameters */ 464 /* set physical bus parameters */
370 return ici->ops->set_bus_param(icd, f->fmt.pix.pixelformat); 465 ret = ici->ops->set_bus_param(icd, pixfmt);
466
467unlock:
468 mutex_unlock(&icf->vb_vidq.vb_lock);
469
470 return ret;
371} 471}
372 472
373static int soc_camera_enum_fmt_vid_cap(struct file *file, void *priv, 473static int soc_camera_enum_fmt_vid_cap(struct file *file, void *priv,
374 struct v4l2_fmtdesc *f) 474 struct v4l2_fmtdesc *f)
375{ 475{
376 struct soc_camera_file *icf = file->private_data; 476 struct soc_camera_file *icf = file->private_data;
377 struct soc_camera_device *icd = icf->icd; 477 struct soc_camera_device *icd = icf->icd;
@@ -379,10 +479,10 @@ static int soc_camera_enum_fmt_vid_cap(struct file *file, void *priv,
379 479
380 WARN_ON(priv != file->private_data); 480 WARN_ON(priv != file->private_data);
381 481
382 if (f->index >= icd->num_formats) 482 if (f->index >= icd->num_user_formats)
383 return -EINVAL; 483 return -EINVAL;
384 484
385 format = &icd->formats[f->index]; 485 format = icd->user_formats[f->index].host_fmt;
386 486
387 strlcpy(f->description, format->name, sizeof(f->description)); 487 strlcpy(f->description, format->name, sizeof(f->description));
388 f->pixelformat = format->fourcc; 488 f->pixelformat = format->fourcc;
@@ -390,21 +490,21 @@ static int soc_camera_enum_fmt_vid_cap(struct file *file, void *priv,
390} 490}
391 491
392static int soc_camera_g_fmt_vid_cap(struct file *file, void *priv, 492static int soc_camera_g_fmt_vid_cap(struct file *file, void *priv,
393 struct v4l2_format *f) 493 struct v4l2_format *f)
394{ 494{
395 struct soc_camera_file *icf = file->private_data; 495 struct soc_camera_file *icf = file->private_data;
396 struct soc_camera_device *icd = icf->icd; 496 struct soc_camera_device *icd = icf->icd;
497 struct v4l2_pix_format *pix = &f->fmt.pix;
397 498
398 WARN_ON(priv != file->private_data); 499 WARN_ON(priv != file->private_data);
399 500
400 f->fmt.pix.width = icd->width; 501 pix->width = icd->width;
401 f->fmt.pix.height = icd->height; 502 pix->height = icd->height;
402 f->fmt.pix.field = icf->vb_vidq.field; 503 pix->field = icf->vb_vidq.field;
403 f->fmt.pix.pixelformat = icd->current_fmt->fourcc; 504 pix->pixelformat = icd->current_fmt->fourcc;
404 f->fmt.pix.bytesperline = 505 pix->bytesperline = pix->width *
405 (f->fmt.pix.width * icd->current_fmt->depth) >> 3; 506 DIV_ROUND_UP(icd->current_fmt->depth, 8);
406 f->fmt.pix.sizeimage = 507 pix->sizeimage = pix->height * pix->bytesperline;
407 f->fmt.pix.height * f->fmt.pix.bytesperline;
408 dev_dbg(&icd->dev, "current_fmt->fourcc: 0x%08x\n", 508 dev_dbg(&icd->dev, "current_fmt->fourcc: 0x%08x\n",
409 icd->current_fmt->fourcc); 509 icd->current_fmt->fourcc);
410 return 0; 510 return 0;
@@ -415,8 +515,7 @@ static int soc_camera_querycap(struct file *file, void *priv,
415{ 515{
416 struct soc_camera_file *icf = file->private_data; 516 struct soc_camera_file *icf = file->private_data;
417 struct soc_camera_device *icd = icf->icd; 517 struct soc_camera_device *icd = icf->icd;
418 struct soc_camera_host *ici = 518 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
419 to_soc_camera_host(icd->dev.parent);
420 519
421 WARN_ON(priv != file->private_data); 520 WARN_ON(priv != file->private_data);
422 521
@@ -429,6 +528,7 @@ static int soc_camera_streamon(struct file *file, void *priv,
429{ 528{
430 struct soc_camera_file *icf = file->private_data; 529 struct soc_camera_file *icf = file->private_data;
431 struct soc_camera_device *icd = icf->icd; 530 struct soc_camera_device *icd = icf->icd;
531 int ret;
432 532
433 WARN_ON(priv != file->private_data); 533 WARN_ON(priv != file->private_data);
434 534
@@ -437,10 +537,16 @@ static int soc_camera_streamon(struct file *file, void *priv,
437 if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE) 537 if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE)
438 return -EINVAL; 538 return -EINVAL;
439 539
540 mutex_lock(&icd->video_lock);
541
440 icd->ops->start_capture(icd); 542 icd->ops->start_capture(icd);
441 543
442 /* This calls buf_queue from host driver's videobuf_queue_ops */ 544 /* This calls buf_queue from host driver's videobuf_queue_ops */
443 return videobuf_streamon(&icf->vb_vidq); 545 ret = videobuf_streamon(&icf->vb_vidq);
546
547 mutex_unlock(&icd->video_lock);
548
549 return ret;
444} 550}
445 551
446static int soc_camera_streamoff(struct file *file, void *priv, 552static int soc_camera_streamoff(struct file *file, void *priv,
@@ -456,12 +562,16 @@ static int soc_camera_streamoff(struct file *file, void *priv,
456 if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE) 562 if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE)
457 return -EINVAL; 563 return -EINVAL;
458 564
565 mutex_lock(&icd->video_lock);
566
459 /* This calls buf_release from host driver's videobuf_queue_ops for all 567 /* This calls buf_release from host driver's videobuf_queue_ops for all
460 * remaining buffers. When the last buffer is freed, stop capture */ 568 * remaining buffers. When the last buffer is freed, stop capture */
461 videobuf_streamoff(&icf->vb_vidq); 569 videobuf_streamoff(&icf->vb_vidq);
462 570
463 icd->ops->stop_capture(icd); 571 icd->ops->stop_capture(icd);
464 572
573 mutex_unlock(&icd->video_lock);
574
465 return 0; 575 return 0;
466} 576}
467 577
@@ -567,14 +677,16 @@ static int soc_camera_s_crop(struct file *file, void *fh,
567{ 677{
568 struct soc_camera_file *icf = file->private_data; 678 struct soc_camera_file *icf = file->private_data;
569 struct soc_camera_device *icd = icf->icd; 679 struct soc_camera_device *icd = icf->icd;
570 struct soc_camera_host *ici = 680 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
571 to_soc_camera_host(icd->dev.parent);
572 int ret; 681 int ret;
573 682
574 if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) 683 if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
575 return -EINVAL; 684 return -EINVAL;
576 685
577 ret = ici->ops->set_fmt_cap(icd, 0, &a->c); 686 /* Cropping is allowed during a running capture, guard consistency */
687 mutex_lock(&icf->vb_vidq.vb_lock);
688
689 ret = ici->ops->set_fmt(icd, 0, &a->c);
578 if (!ret) { 690 if (!ret) {
579 icd->width = a->c.width; 691 icd->width = a->c.width;
580 icd->height = a->c.height; 692 icd->height = a->c.height;
@@ -582,6 +694,8 @@ static int soc_camera_s_crop(struct file *file, void *fh,
582 icd->y_current = a->c.top; 694 icd->y_current = a->c.top;
583 } 695 }
584 696
697 mutex_unlock(&icf->vb_vidq.vb_lock);
698
585 return ret; 699 return ret;
586} 700}
587 701
@@ -692,18 +806,35 @@ static int scan_add_device(struct soc_camera_device *icd)
692static int soc_camera_probe(struct device *dev) 806static int soc_camera_probe(struct device *dev)
693{ 807{
694 struct soc_camera_device *icd = to_soc_camera_dev(dev); 808 struct soc_camera_device *icd = to_soc_camera_dev(dev);
695 struct soc_camera_host *ici = 809 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
696 to_soc_camera_host(icd->dev.parent);
697 int ret; 810 int ret;
698 811
699 if (!icd->ops->probe) 812 /*
700 return -ENODEV; 813 * Possible race scenario:
814 * modprobe <camera-host-driver> triggers __func__
815 * at this moment respective <camera-sensor-driver> gets rmmod'ed
816 * to protect take module references.
817 */
818
819 if (!try_module_get(icd->ops->owner)) {
820 dev_err(&icd->dev, "Couldn't lock sensor driver.\n");
821 ret = -EINVAL;
822 goto emgd;
823 }
824
825 if (!try_module_get(ici->ops->owner)) {
826 dev_err(&icd->dev, "Couldn't lock capture bus driver.\n");
827 ret = -EINVAL;
828 goto emgi;
829 }
830
831 mutex_lock(&icd->video_lock);
701 832
702 /* We only call ->add() here to activate and probe the camera. 833 /* We only call ->add() here to activate and probe the camera.
703 * We shall ->remove() and deactivate it immediately afterwards. */ 834 * We shall ->remove() and deactivate it immediately afterwards. */
704 ret = ici->ops->add(icd); 835 ret = ici->ops->add(icd);
705 if (ret < 0) 836 if (ret < 0)
706 return ret; 837 goto eiadd;
707 838
708 ret = icd->ops->probe(icd); 839 ret = icd->ops->probe(icd);
709 if (ret >= 0) { 840 if (ret >= 0) {
@@ -717,6 +848,12 @@ static int soc_camera_probe(struct device *dev)
717 } 848 }
718 ici->ops->remove(icd); 849 ici->ops->remove(icd);
719 850
851eiadd:
852 mutex_unlock(&icd->video_lock);
853 module_put(ici->ops->owner);
854emgi:
855 module_put(icd->ops->owner);
856emgd:
720 return ret; 857 return ret;
721} 858}
722 859
@@ -779,11 +916,20 @@ int soc_camera_host_register(struct soc_camera_host *ici)
779 int ret; 916 int ret;
780 struct soc_camera_host *ix; 917 struct soc_camera_host *ix;
781 918
782 if (!ici->ops->init_videobuf || !ici->ops->add || !ici->ops->remove) 919 if (!ici || !ici->ops ||
920 !ici->ops->try_fmt ||
921 !ici->ops->set_fmt ||
922 !ici->ops->set_bus_param ||
923 !ici->ops->querycap ||
924 !ici->ops->init_videobuf ||
925 !ici->ops->reqbufs ||
926 !ici->ops->add ||
927 !ici->ops->remove ||
928 !ici->ops->poll)
783 return -EINVAL; 929 return -EINVAL;
784 930
785 /* Number might be equal to the platform device ID */ 931 /* Number might be equal to the platform device ID */
786 sprintf(ici->dev.bus_id, "camera_host%d", ici->nr); 932 dev_set_name(&ici->dev, "camera_host%d", ici->nr);
787 933
788 mutex_lock(&list_lock); 934 mutex_lock(&list_lock);
789 list_for_each_entry(ix, &hosts, list) { 935 list_for_each_entry(ix, &hosts, list) {
@@ -847,7 +993,16 @@ int soc_camera_device_register(struct soc_camera_device *icd)
847 struct soc_camera_device *ix; 993 struct soc_camera_device *ix;
848 int num = -1, i; 994 int num = -1, i;
849 995
850 if (!icd) 996 if (!icd || !icd->ops ||
997 !icd->ops->probe ||
998 !icd->ops->init ||
999 !icd->ops->release ||
1000 !icd->ops->start_capture ||
1001 !icd->ops->stop_capture ||
1002 !icd->ops->set_fmt ||
1003 !icd->ops->try_fmt ||
1004 !icd->ops->query_bus_param ||
1005 !icd->ops->set_bus_param)
851 return -EINVAL; 1006 return -EINVAL;
852 1007
853 for (i = 0; i < 256 && num < 0; i++) { 1008 for (i = 0; i < 256 && num < 0; i++) {
@@ -867,10 +1022,12 @@ int soc_camera_device_register(struct soc_camera_device *icd)
867 1022
868 icd->devnum = num; 1023 icd->devnum = num;
869 icd->dev.bus = &soc_camera_bus_type; 1024 icd->dev.bus = &soc_camera_bus_type;
870 snprintf(icd->dev.bus_id, sizeof(icd->dev.bus_id), 1025 dev_set_name(&icd->dev, "%u-%u", icd->iface, icd->devnum);
871 "%u-%u", icd->iface, icd->devnum);
872 1026
873 icd->dev.release = dummy_release; 1027 icd->dev.release = dummy_release;
1028 icd->use_count = 0;
1029 icd->host_priv = NULL;
1030 mutex_init(&icd->video_lock);
874 1031
875 return scan_add_device(icd); 1032 return scan_add_device(icd);
876} 1033}
@@ -917,6 +1074,10 @@ static const struct v4l2_ioctl_ops soc_camera_ioctl_ops = {
917#endif 1074#endif
918}; 1075};
919 1076
1077/*
1078 * Usually called from the struct soc_camera_ops .probe() method, i.e., from
1079 * soc_camera_probe() above with .video_lock held
1080 */
920int soc_camera_video_start(struct soc_camera_device *icd) 1081int soc_camera_video_start(struct soc_camera_device *icd)
921{ 1082{
922 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); 1083 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
@@ -932,7 +1093,7 @@ int soc_camera_video_start(struct soc_camera_device *icd)
932 dev_dbg(&ici->dev, "Allocated video_device %p\n", vdev); 1093 dev_dbg(&ici->dev, "Allocated video_device %p\n", vdev);
933 1094
934 strlcpy(vdev->name, ici->drv_name, sizeof(vdev->name)); 1095 strlcpy(vdev->name, ici->drv_name, sizeof(vdev->name));
935 /* Maybe better &ici->dev */ 1096
936 vdev->parent = &icd->dev; 1097 vdev->parent = &icd->dev;
937 vdev->current_norm = V4L2_STD_UNKNOWN; 1098 vdev->current_norm = V4L2_STD_UNKNOWN;
938 vdev->fops = &soc_camera_fops; 1099 vdev->fops = &soc_camera_fops;
@@ -941,8 +1102,6 @@ int soc_camera_video_start(struct soc_camera_device *icd)
941 vdev->minor = -1; 1102 vdev->minor = -1;
942 vdev->tvnorms = V4L2_STD_UNKNOWN, 1103 vdev->tvnorms = V4L2_STD_UNKNOWN,
943 1104
944 icd->current_fmt = &icd->formats[0];
945
946 err = video_register_device(vdev, VFL_TYPE_GRABBER, vdev->minor); 1105 err = video_register_device(vdev, VFL_TYPE_GRABBER, vdev->minor);
947 if (err < 0) { 1106 if (err < 0) {
948 dev_err(vdev->parent, "video_register_device failed\n"); 1107 dev_err(vdev->parent, "video_register_device failed\n");
@@ -968,10 +1127,10 @@ void soc_camera_video_stop(struct soc_camera_device *icd)
968 if (!icd->dev.parent || !vdev) 1127 if (!icd->dev.parent || !vdev)
969 return; 1128 return;
970 1129
971 mutex_lock(&video_lock); 1130 mutex_lock(&icd->video_lock);
972 video_unregister_device(vdev); 1131 video_unregister_device(vdev);
973 icd->vdev = NULL; 1132 icd->vdev = NULL;
974 mutex_unlock(&video_lock); 1133 mutex_unlock(&icd->video_lock);
975} 1134}
976EXPORT_SYMBOL(soc_camera_video_stop); 1135EXPORT_SYMBOL(soc_camera_video_stop);
977 1136