diff options
author | Hans Verkuil <hans.verkuil@cisco.com> | 2013-03-15 10:56:46 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2013-03-25 07:44:37 -0400 |
commit | 6a2e65d54ebb1284c4d234ec606e4eccab7eb812 (patch) | |
tree | 9e92a6487fdc5f3e32bacf958412c9213a72cc64 | |
parent | 941604977c00ebeb6324348ece84d2140b190754 (diff) |
[media] solo6x10: move global fields in solo_dev_fh to solo_dev
All fields in solo_dev_fh do not belong there since they refer to global
properties. After moving all these fields to solo_dev the solo_dev_fh
struct can be removed completely.
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r-- | drivers/staging/media/solo6x10/solo6x10.h | 7 | ||||
-rw-r--r-- | drivers/staging/media/solo6x10/v4l2.c | 231 |
2 files changed, 101 insertions, 137 deletions
diff --git a/drivers/staging/media/solo6x10/solo6x10.h b/drivers/staging/media/solo6x10/solo6x10.h index 4035c072fb47..830359f3bb16 100644 --- a/drivers/staging/media/solo6x10/solo6x10.h +++ b/drivers/staging/media/solo6x10/solo6x10.h | |||
@@ -250,6 +250,13 @@ struct solo_dev { | |||
250 | void *vh_buf; | 250 | void *vh_buf; |
251 | dma_addr_t vh_dma; | 251 | dma_addr_t vh_dma; |
252 | int vh_size; | 252 | int vh_size; |
253 | |||
254 | /* Buffer handling */ | ||
255 | struct videobuf_queue vidq; | ||
256 | struct task_struct *kthread; | ||
257 | spinlock_t slock; | ||
258 | int old_write; | ||
259 | struct list_head vidq_active; | ||
253 | }; | 260 | }; |
254 | 261 | ||
255 | static inline u32 solo_reg_read(struct solo_dev *solo_dev, int reg) | 262 | static inline u32 solo_reg_read(struct solo_dev *solo_dev, int reg) |
diff --git a/drivers/staging/media/solo6x10/v4l2.c b/drivers/staging/media/solo6x10/v4l2.c index a6889490561b..13b7640d8cac 100644 --- a/drivers/staging/media/solo6x10/v4l2.c +++ b/drivers/staging/media/solo6x10/v4l2.c | |||
@@ -44,17 +44,6 @@ | |||
44 | 44 | ||
45 | #define MIN_VID_BUFFERS 2 | 45 | #define MIN_VID_BUFFERS 2 |
46 | 46 | ||
47 | /* Simple file handle */ | ||
48 | struct solo_filehandle { | ||
49 | struct v4l2_fh fh; | ||
50 | struct solo_dev *solo_dev; | ||
51 | struct videobuf_queue vidq; | ||
52 | struct task_struct *kthread; | ||
53 | spinlock_t slock; | ||
54 | int old_write; | ||
55 | struct list_head vidq_active; | ||
56 | }; | ||
57 | |||
58 | static inline void erase_on(struct solo_dev *solo_dev) | 47 | static inline void erase_on(struct solo_dev *solo_dev) |
59 | { | 48 | { |
60 | solo_reg_write(solo_dev, SOLO_VO_DISP_ERASE, SOLO_VO_DISP_ERASE_ON); | 49 | solo_reg_write(solo_dev, SOLO_VO_DISP_ERASE, SOLO_VO_DISP_ERASE_ON); |
@@ -202,10 +191,9 @@ static int solo_v4l2_set_ch(struct solo_dev *solo_dev, u8 ch) | |||
202 | return 0; | 191 | return 0; |
203 | } | 192 | } |
204 | 193 | ||
205 | static void solo_fillbuf(struct solo_filehandle *fh, | 194 | static void solo_fillbuf(struct solo_dev *solo_dev, |
206 | struct videobuf_buffer *vb) | 195 | struct videobuf_buffer *vb) |
207 | { | 196 | { |
208 | struct solo_dev *solo_dev = fh->solo_dev; | ||
209 | dma_addr_t vbuf; | 197 | dma_addr_t vbuf; |
210 | unsigned int fdma_addr; | 198 | unsigned int fdma_addr; |
211 | int error = -1; | 199 | int error = -1; |
@@ -216,7 +204,7 @@ static void solo_fillbuf(struct solo_filehandle *fh, | |||
216 | goto finish_buf; | 204 | goto finish_buf; |
217 | 205 | ||
218 | if (erase_off(solo_dev)) { | 206 | if (erase_off(solo_dev)) { |
219 | void *p = videobuf_queue_to_vaddr(&fh->vidq, vb); | 207 | void *p = videobuf_queue_to_vaddr(&solo_dev->vidq, vb); |
220 | int image_size = solo_image_size(solo_dev); | 208 | int image_size = solo_image_size(solo_dev); |
221 | for (i = 0; i < image_size; i += 2) { | 209 | for (i = 0; i < image_size; i += 2) { |
222 | ((u8 *)p)[i] = 0x80; | 210 | ((u8 *)p)[i] = 0x80; |
@@ -224,7 +212,7 @@ static void solo_fillbuf(struct solo_filehandle *fh, | |||
224 | } | 212 | } |
225 | error = 0; | 213 | error = 0; |
226 | } else { | 214 | } else { |
227 | fdma_addr = SOLO_DISP_EXT_ADDR + (fh->old_write * | 215 | fdma_addr = SOLO_DISP_EXT_ADDR + (solo_dev->old_write * |
228 | (SOLO_HW_BPL * solo_vlines(solo_dev))); | 216 | (SOLO_HW_BPL * solo_vlines(solo_dev))); |
229 | 217 | ||
230 | error = solo_p2m_dma_t(solo_dev, 0, vbuf, fdma_addr, | 218 | error = solo_p2m_dma_t(solo_dev, 0, vbuf, fdma_addr, |
@@ -243,7 +231,7 @@ finish_buf: | |||
243 | wake_up(&vb->done); | 231 | wake_up(&vb->done); |
244 | } | 232 | } |
245 | 233 | ||
246 | static void solo_thread_try(struct solo_filehandle *fh) | 234 | static void solo_thread_try(struct solo_dev *solo_dev) |
247 | { | 235 | { |
248 | struct videobuf_buffer *vb; | 236 | struct videobuf_buffer *vb; |
249 | 237 | ||
@@ -253,38 +241,37 @@ static void solo_thread_try(struct solo_filehandle *fh) | |||
253 | unsigned int cur_write; | 241 | unsigned int cur_write; |
254 | 242 | ||
255 | cur_write = SOLO_VI_STATUS0_PAGE( | 243 | cur_write = SOLO_VI_STATUS0_PAGE( |
256 | solo_reg_read(fh->solo_dev, SOLO_VI_STATUS0)); | 244 | solo_reg_read(solo_dev, SOLO_VI_STATUS0)); |
257 | if (cur_write == fh->old_write) | 245 | if (cur_write == solo_dev->old_write) |
258 | return; | 246 | return; |
259 | 247 | ||
260 | spin_lock(&fh->slock); | 248 | spin_lock(&solo_dev->slock); |
261 | 249 | ||
262 | if (list_empty(&fh->vidq_active)) | 250 | if (list_empty(&solo_dev->vidq_active)) |
263 | break; | 251 | break; |
264 | 252 | ||
265 | vb = list_first_entry(&fh->vidq_active, struct videobuf_buffer, | 253 | vb = list_first_entry(&solo_dev->vidq_active, struct videobuf_buffer, |
266 | queue); | 254 | queue); |
267 | 255 | ||
268 | if (!waitqueue_active(&vb->done)) | 256 | if (!waitqueue_active(&vb->done)) |
269 | break; | 257 | break; |
270 | 258 | ||
271 | fh->old_write = cur_write; | 259 | solo_dev->old_write = cur_write; |
272 | list_del(&vb->queue); | 260 | list_del(&vb->queue); |
273 | vb->state = VIDEOBUF_ACTIVE; | 261 | vb->state = VIDEOBUF_ACTIVE; |
274 | 262 | ||
275 | spin_unlock(&fh->slock); | 263 | spin_unlock(&solo_dev->slock); |
276 | 264 | ||
277 | solo_fillbuf(fh, vb); | 265 | solo_fillbuf(solo_dev, vb); |
278 | } | 266 | } |
279 | 267 | ||
280 | assert_spin_locked(&fh->slock); | 268 | assert_spin_locked(&solo_dev->slock); |
281 | spin_unlock(&fh->slock); | 269 | spin_unlock(&solo_dev->slock); |
282 | } | 270 | } |
283 | 271 | ||
284 | static int solo_thread(void *data) | 272 | static int solo_thread(void *data) |
285 | { | 273 | { |
286 | struct solo_filehandle *fh = data; | 274 | struct solo_dev *solo_dev = data; |
287 | struct solo_dev *solo_dev = fh->solo_dev; | ||
288 | DECLARE_WAITQUEUE(wait, current); | 275 | DECLARE_WAITQUEUE(wait, current); |
289 | 276 | ||
290 | set_freezable(); | 277 | set_freezable(); |
@@ -294,7 +281,7 @@ static int solo_thread(void *data) | |||
294 | long timeout = schedule_timeout_interruptible(HZ); | 281 | long timeout = schedule_timeout_interruptible(HZ); |
295 | if (timeout == -ERESTARTSYS || kthread_should_stop()) | 282 | if (timeout == -ERESTARTSYS || kthread_should_stop()) |
296 | break; | 283 | break; |
297 | solo_thread_try(fh); | 284 | solo_thread_try(solo_dev); |
298 | try_to_freeze(); | 285 | try_to_freeze(); |
299 | } | 286 | } |
300 | 287 | ||
@@ -303,40 +290,39 @@ static int solo_thread(void *data) | |||
303 | return 0; | 290 | return 0; |
304 | } | 291 | } |
305 | 292 | ||
306 | static int solo_start_thread(struct solo_filehandle *fh) | 293 | static int solo_start_thread(struct solo_dev *solo_dev) |
307 | { | 294 | { |
308 | int ret = 0; | 295 | int ret = 0; |
309 | 296 | ||
310 | if (atomic_inc_return(&fh->solo_dev->disp_users) == 1) | 297 | if (atomic_inc_return(&solo_dev->disp_users) == 1) |
311 | solo_irq_on(fh->solo_dev, SOLO_IRQ_VIDEO_IN); | 298 | solo_irq_on(solo_dev, SOLO_IRQ_VIDEO_IN); |
312 | 299 | ||
313 | fh->kthread = kthread_run(solo_thread, fh, SOLO6X10_NAME "_disp"); | 300 | solo_dev->kthread = kthread_run(solo_thread, solo_dev, SOLO6X10_NAME "_disp"); |
314 | 301 | ||
315 | if (IS_ERR(fh->kthread)) { | 302 | if (IS_ERR(solo_dev->kthread)) { |
316 | ret = PTR_ERR(fh->kthread); | 303 | ret = PTR_ERR(solo_dev->kthread); |
317 | fh->kthread = NULL; | 304 | solo_dev->kthread = NULL; |
318 | } | 305 | } |
319 | 306 | ||
320 | return ret; | 307 | return ret; |
321 | } | 308 | } |
322 | 309 | ||
323 | static void solo_stop_thread(struct solo_filehandle *fh) | 310 | static void solo_stop_thread(struct solo_dev *solo_dev) |
324 | { | 311 | { |
325 | if (!fh->kthread) | 312 | if (!solo_dev->kthread) |
326 | return; | 313 | return; |
327 | 314 | ||
328 | kthread_stop(fh->kthread); | 315 | kthread_stop(solo_dev->kthread); |
329 | fh->kthread = NULL; | 316 | solo_dev->kthread = NULL; |
330 | 317 | ||
331 | if (atomic_dec_return(&fh->solo_dev->disp_users) == 0) | 318 | if (atomic_dec_return(&solo_dev->disp_users) == 0) |
332 | solo_irq_off(fh->solo_dev, SOLO_IRQ_VIDEO_IN); | 319 | solo_irq_off(solo_dev, SOLO_IRQ_VIDEO_IN); |
333 | } | 320 | } |
334 | 321 | ||
335 | static int solo_buf_setup(struct videobuf_queue *vq, unsigned int *count, | 322 | static int solo_buf_setup(struct videobuf_queue *vq, unsigned int *count, |
336 | unsigned int *size) | 323 | unsigned int *size) |
337 | { | 324 | { |
338 | struct solo_filehandle *fh = vq->priv_data; | 325 | struct solo_dev *solo_dev = vq->priv_data; |
339 | struct solo_dev *solo_dev = fh->solo_dev; | ||
340 | 326 | ||
341 | *size = solo_image_size(solo_dev); | 327 | *size = solo_image_size(solo_dev); |
342 | 328 | ||
@@ -349,8 +335,7 @@ static int solo_buf_setup(struct videobuf_queue *vq, unsigned int *count, | |||
349 | static int solo_buf_prepare(struct videobuf_queue *vq, | 335 | static int solo_buf_prepare(struct videobuf_queue *vq, |
350 | struct videobuf_buffer *vb, enum v4l2_field field) | 336 | struct videobuf_buffer *vb, enum v4l2_field field) |
351 | { | 337 | { |
352 | struct solo_filehandle *fh = vq->priv_data; | 338 | struct solo_dev *solo_dev = vq->priv_data; |
353 | struct solo_dev *solo_dev = fh->solo_dev; | ||
354 | 339 | ||
355 | vb->size = solo_image_size(solo_dev); | 340 | vb->size = solo_image_size(solo_dev); |
356 | if (vb->baddr != 0 && vb->bsize < vb->size) | 341 | if (vb->baddr != 0 && vb->bsize < vb->size) |
@@ -378,11 +363,10 @@ static int solo_buf_prepare(struct videobuf_queue *vq, | |||
378 | static void solo_buf_queue(struct videobuf_queue *vq, | 363 | static void solo_buf_queue(struct videobuf_queue *vq, |
379 | struct videobuf_buffer *vb) | 364 | struct videobuf_buffer *vb) |
380 | { | 365 | { |
381 | struct solo_filehandle *fh = vq->priv_data; | 366 | struct solo_dev *solo_dev = vq->priv_data; |
382 | struct solo_dev *solo_dev = fh->solo_dev; | ||
383 | 367 | ||
384 | vb->state = VIDEOBUF_QUEUED; | 368 | vb->state = VIDEOBUF_QUEUED; |
385 | list_add_tail(&vb->queue, &fh->vidq_active); | 369 | list_add_tail(&vb->queue, &solo_dev->vidq_active); |
386 | wake_up_interruptible(&solo_dev->disp_thread_wait); | 370 | wake_up_interruptible(&solo_dev->disp_thread_wait); |
387 | } | 371 | } |
388 | 372 | ||
@@ -403,84 +387,45 @@ static const struct videobuf_queue_ops solo_video_qops = { | |||
403 | static unsigned int solo_v4l2_poll(struct file *file, | 387 | static unsigned int solo_v4l2_poll(struct file *file, |
404 | struct poll_table_struct *wait) | 388 | struct poll_table_struct *wait) |
405 | { | 389 | { |
406 | struct solo_filehandle *fh = file->private_data; | 390 | struct solo_dev *solo_dev = video_drvdata(file); |
407 | unsigned long req_events = poll_requested_events(wait); | 391 | unsigned long req_events = poll_requested_events(wait); |
408 | unsigned res = v4l2_ctrl_poll(file, wait); | 392 | unsigned res = v4l2_ctrl_poll(file, wait); |
409 | 393 | ||
410 | if (!(req_events & (POLLIN | POLLRDNORM))) | 394 | if (!(req_events & (POLLIN | POLLRDNORM))) |
411 | return res; | 395 | return res; |
412 | return res | videobuf_poll_stream(file, &fh->vidq, wait); | 396 | return res | videobuf_poll_stream(file, &solo_dev->vidq, wait); |
413 | } | 397 | } |
414 | 398 | ||
415 | static int solo_v4l2_mmap(struct file *file, struct vm_area_struct *vma) | 399 | static int solo_v4l2_mmap(struct file *file, struct vm_area_struct *vma) |
416 | { | 400 | { |
417 | struct solo_filehandle *fh = file->private_data; | ||
418 | |||
419 | return videobuf_mmap_mapper(&fh->vidq, vma); | ||
420 | } | ||
421 | |||
422 | static int solo_v4l2_open(struct file *file) | ||
423 | { | ||
424 | struct solo_dev *solo_dev = video_drvdata(file); | 401 | struct solo_dev *solo_dev = video_drvdata(file); |
425 | struct solo_filehandle *fh; | ||
426 | int ret; | ||
427 | 402 | ||
428 | fh = kzalloc(sizeof(*fh), GFP_KERNEL); | 403 | return videobuf_mmap_mapper(&solo_dev->vidq, vma); |
429 | if (fh == NULL) | ||
430 | return -ENOMEM; | ||
431 | |||
432 | v4l2_fh_init(&fh->fh, video_devdata(file)); | ||
433 | spin_lock_init(&fh->slock); | ||
434 | INIT_LIST_HEAD(&fh->vidq_active); | ||
435 | fh->solo_dev = solo_dev; | ||
436 | file->private_data = fh; | ||
437 | |||
438 | ret = solo_start_thread(fh); | ||
439 | if (ret) { | ||
440 | kfree(fh); | ||
441 | return ret; | ||
442 | } | ||
443 | |||
444 | videobuf_queue_dma_contig_init(&fh->vidq, &solo_video_qops, | ||
445 | &solo_dev->pdev->dev, &fh->slock, | ||
446 | V4L2_BUF_TYPE_VIDEO_CAPTURE, | ||
447 | V4L2_FIELD_INTERLACED, | ||
448 | sizeof(struct videobuf_buffer), | ||
449 | fh, NULL); | ||
450 | v4l2_fh_add(&fh->fh); | ||
451 | return 0; | ||
452 | } | 404 | } |
453 | 405 | ||
454 | static ssize_t solo_v4l2_read(struct file *file, char __user *data, | 406 | static ssize_t solo_v4l2_read(struct file *file, char __user *data, |
455 | size_t count, loff_t *ppos) | 407 | size_t count, loff_t *ppos) |
456 | { | 408 | { |
457 | struct solo_filehandle *fh = file->private_data; | 409 | struct solo_dev *solo_dev = video_drvdata(file); |
458 | 410 | ||
459 | return videobuf_read_stream(&fh->vidq, data, count, ppos, 0, | 411 | return videobuf_read_stream(&solo_dev->vidq, data, count, ppos, 0, |
460 | file->f_flags & O_NONBLOCK); | 412 | file->f_flags & O_NONBLOCK); |
461 | } | 413 | } |
462 | 414 | ||
463 | static int solo_v4l2_release(struct file *file) | 415 | static int solo_v4l2_release(struct file *file) |
464 | { | 416 | { |
465 | struct solo_filehandle *fh = file->private_data; | 417 | struct solo_dev *solo_dev = video_drvdata(file); |
466 | |||
467 | solo_stop_thread(fh); | ||
468 | |||
469 | videobuf_stop(&fh->vidq); | ||
470 | videobuf_mmap_free(&fh->vidq); | ||
471 | |||
472 | v4l2_fh_del(&fh->fh); | ||
473 | v4l2_fh_exit(&fh->fh); | ||
474 | kfree(fh); | ||
475 | 418 | ||
476 | return 0; | 419 | solo_stop_thread(solo_dev); |
420 | videobuf_stop(&solo_dev->vidq); | ||
421 | videobuf_mmap_free(&solo_dev->vidq); | ||
422 | return v4l2_fh_release(file); | ||
477 | } | 423 | } |
478 | 424 | ||
479 | static int solo_querycap(struct file *file, void *priv, | 425 | static int solo_querycap(struct file *file, void *priv, |
480 | struct v4l2_capability *cap) | 426 | struct v4l2_capability *cap) |
481 | { | 427 | { |
482 | struct solo_filehandle *fh = priv; | 428 | struct solo_dev *solo_dev = video_drvdata(file); |
483 | struct solo_dev *solo_dev = fh->solo_dev; | ||
484 | 429 | ||
485 | strcpy(cap->driver, SOLO6X10_NAME); | 430 | strcpy(cap->driver, SOLO6X10_NAME); |
486 | strcpy(cap->card, "Softlogic 6x10"); | 431 | strcpy(cap->card, "Softlogic 6x10"); |
@@ -521,8 +466,7 @@ static int solo_enum_ext_input(struct solo_dev *solo_dev, | |||
521 | static int solo_enum_input(struct file *file, void *priv, | 466 | static int solo_enum_input(struct file *file, void *priv, |
522 | struct v4l2_input *input) | 467 | struct v4l2_input *input) |
523 | { | 468 | { |
524 | struct solo_filehandle *fh = priv; | 469 | struct solo_dev *solo_dev = video_drvdata(file); |
525 | struct solo_dev *solo_dev = fh->solo_dev; | ||
526 | 470 | ||
527 | if (input->index >= solo_dev->nr_chans) { | 471 | if (input->index >= solo_dev->nr_chans) { |
528 | int ret = solo_enum_ext_input(solo_dev, input); | 472 | int ret = solo_enum_ext_input(solo_dev, input); |
@@ -549,11 +493,11 @@ static int solo_enum_input(struct file *file, void *priv, | |||
549 | 493 | ||
550 | static int solo_set_input(struct file *file, void *priv, unsigned int index) | 494 | static int solo_set_input(struct file *file, void *priv, unsigned int index) |
551 | { | 495 | { |
552 | struct solo_filehandle *fh = priv; | 496 | struct solo_dev *solo_dev = video_drvdata(file); |
553 | int ret = solo_v4l2_set_ch(fh->solo_dev, index); | 497 | int ret = solo_v4l2_set_ch(solo_dev, index); |
554 | 498 | ||
555 | if (!ret) { | 499 | if (!ret) { |
556 | while (erase_off(fh->solo_dev)) | 500 | while (erase_off(solo_dev)) |
557 | /* Do nothing */; | 501 | /* Do nothing */; |
558 | } | 502 | } |
559 | 503 | ||
@@ -562,9 +506,9 @@ static int solo_set_input(struct file *file, void *priv, unsigned int index) | |||
562 | 506 | ||
563 | static int solo_get_input(struct file *file, void *priv, unsigned int *index) | 507 | static int solo_get_input(struct file *file, void *priv, unsigned int *index) |
564 | { | 508 | { |
565 | struct solo_filehandle *fh = priv; | 509 | struct solo_dev *solo_dev = video_drvdata(file); |
566 | 510 | ||
567 | *index = fh->solo_dev->cur_disp_ch; | 511 | *index = solo_dev->cur_disp_ch; |
568 | 512 | ||
569 | return 0; | 513 | return 0; |
570 | } | 514 | } |
@@ -584,8 +528,7 @@ static int solo_enum_fmt_cap(struct file *file, void *priv, | |||
584 | static int solo_try_fmt_cap(struct file *file, void *priv, | 528 | static int solo_try_fmt_cap(struct file *file, void *priv, |
585 | struct v4l2_format *f) | 529 | struct v4l2_format *f) |
586 | { | 530 | { |
587 | struct solo_filehandle *fh = priv; | 531 | struct solo_dev *solo_dev = video_drvdata(file); |
588 | struct solo_dev *solo_dev = fh->solo_dev; | ||
589 | struct v4l2_pix_format *pix = &f->fmt.pix; | 532 | struct v4l2_pix_format *pix = &f->fmt.pix; |
590 | int image_size = solo_image_size(solo_dev); | 533 | int image_size = solo_image_size(solo_dev); |
591 | 534 | ||
@@ -605,9 +548,9 @@ static int solo_try_fmt_cap(struct file *file, void *priv, | |||
605 | static int solo_set_fmt_cap(struct file *file, void *priv, | 548 | static int solo_set_fmt_cap(struct file *file, void *priv, |
606 | struct v4l2_format *f) | 549 | struct v4l2_format *f) |
607 | { | 550 | { |
608 | struct solo_filehandle *fh = priv; | 551 | struct solo_dev *solo_dev = video_drvdata(file); |
609 | 552 | ||
610 | if (videobuf_queue_is_busy(&fh->vidq)) | 553 | if (videobuf_queue_is_busy(&solo_dev->vidq)) |
611 | return -EBUSY; | 554 | return -EBUSY; |
612 | 555 | ||
613 | /* For right now, if it doesn't match our running config, | 556 | /* For right now, if it doesn't match our running config, |
@@ -618,8 +561,7 @@ static int solo_set_fmt_cap(struct file *file, void *priv, | |||
618 | static int solo_get_fmt_cap(struct file *file, void *priv, | 561 | static int solo_get_fmt_cap(struct file *file, void *priv, |
619 | struct v4l2_format *f) | 562 | struct v4l2_format *f) |
620 | { | 563 | { |
621 | struct solo_filehandle *fh = priv; | 564 | struct solo_dev *solo_dev = video_drvdata(file); |
622 | struct solo_dev *solo_dev = fh->solo_dev; | ||
623 | struct v4l2_pix_format *pix = &f->fmt.pix; | 565 | struct v4l2_pix_format *pix = &f->fmt.pix; |
624 | 566 | ||
625 | pix->width = solo_dev->video_hsize; | 567 | pix->width = solo_dev->video_hsize; |
@@ -637,51 +579,56 @@ static int solo_get_fmt_cap(struct file *file, void *priv, | |||
637 | static int solo_reqbufs(struct file *file, void *priv, | 579 | static int solo_reqbufs(struct file *file, void *priv, |
638 | struct v4l2_requestbuffers *req) | 580 | struct v4l2_requestbuffers *req) |
639 | { | 581 | { |
640 | struct solo_filehandle *fh = priv; | 582 | struct solo_dev *solo_dev = video_drvdata(file); |
641 | 583 | ||
642 | return videobuf_reqbufs(&fh->vidq, req); | 584 | return videobuf_reqbufs(&solo_dev->vidq, req); |
643 | } | 585 | } |
644 | 586 | ||
645 | static int solo_querybuf(struct file *file, void *priv, | 587 | static int solo_querybuf(struct file *file, void *priv, |
646 | struct v4l2_buffer *buf) | 588 | struct v4l2_buffer *buf) |
647 | { | 589 | { |
648 | struct solo_filehandle *fh = priv; | 590 | struct solo_dev *solo_dev = video_drvdata(file); |
649 | 591 | ||
650 | return videobuf_querybuf(&fh->vidq, buf); | 592 | return videobuf_querybuf(&solo_dev->vidq, buf); |
651 | } | 593 | } |
652 | 594 | ||
653 | static int solo_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) | 595 | static int solo_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) |
654 | { | 596 | { |
655 | struct solo_filehandle *fh = priv; | 597 | struct solo_dev *solo_dev = video_drvdata(file); |
656 | 598 | ||
657 | return videobuf_qbuf(&fh->vidq, buf); | 599 | return videobuf_qbuf(&solo_dev->vidq, buf); |
658 | } | 600 | } |
659 | 601 | ||
660 | static int solo_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf) | 602 | static int solo_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf) |
661 | { | 603 | { |
662 | struct solo_filehandle *fh = priv; | 604 | struct solo_dev *solo_dev = video_drvdata(file); |
663 | 605 | ||
664 | return videobuf_dqbuf(&fh->vidq, buf, file->f_flags & O_NONBLOCK); | 606 | return videobuf_dqbuf(&solo_dev->vidq, buf, file->f_flags & O_NONBLOCK); |
665 | } | 607 | } |
666 | 608 | ||
667 | static int solo_streamon(struct file *file, void *priv, enum v4l2_buf_type i) | 609 | static int solo_streamon(struct file *file, void *priv, enum v4l2_buf_type i) |
668 | { | 610 | { |
669 | struct solo_filehandle *fh = priv; | 611 | struct solo_dev *solo_dev = video_drvdata(file); |
612 | int ret; | ||
670 | 613 | ||
671 | if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE) | 614 | if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE) |
672 | return -EINVAL; | 615 | return -EINVAL; |
673 | 616 | ||
674 | return videobuf_streamon(&fh->vidq); | 617 | ret = solo_start_thread(solo_dev); |
618 | if (ret) | ||
619 | return ret; | ||
620 | |||
621 | return videobuf_streamon(&solo_dev->vidq); | ||
675 | } | 622 | } |
676 | 623 | ||
677 | static int solo_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) | 624 | static int solo_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) |
678 | { | 625 | { |
679 | struct solo_filehandle *fh = priv; | 626 | struct solo_dev *solo_dev = video_drvdata(file); |
680 | 627 | ||
681 | if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE) | 628 | if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE) |
682 | return -EINVAL; | 629 | return -EINVAL; |
683 | 630 | ||
684 | return videobuf_streamoff(&fh->vidq); | 631 | return videobuf_streamoff(&solo_dev->vidq); |
685 | } | 632 | } |
686 | 633 | ||
687 | static int solo_s_std(struct file *file, void *priv, v4l2_std_id i) | 634 | static int solo_s_std(struct file *file, void *priv, v4l2_std_id i) |
@@ -720,7 +667,7 @@ static int solo_s_ctrl(struct v4l2_ctrl *ctrl) | |||
720 | 667 | ||
721 | static const struct v4l2_file_operations solo_v4l2_fops = { | 668 | static const struct v4l2_file_operations solo_v4l2_fops = { |
722 | .owner = THIS_MODULE, | 669 | .owner = THIS_MODULE, |
723 | .open = solo_v4l2_open, | 670 | .open = v4l2_fh_open, |
724 | .release = solo_v4l2_release, | 671 | .release = solo_v4l2_release, |
725 | .read = solo_v4l2_read, | 672 | .read = solo_v4l2_read, |
726 | .poll = solo_v4l2_poll, | 673 | .poll = solo_v4l2_poll, |
@@ -798,21 +745,17 @@ int solo_v4l2_init(struct solo_dev *solo_dev, unsigned nr) | |||
798 | solo_dev->vfd->ctrl_handler = &solo_dev->disp_hdl; | 745 | solo_dev->vfd->ctrl_handler = &solo_dev->disp_hdl; |
799 | set_bit(V4L2_FL_USE_FH_PRIO, &solo_dev->vfd->flags); | 746 | set_bit(V4L2_FL_USE_FH_PRIO, &solo_dev->vfd->flags); |
800 | 747 | ||
801 | ret = video_register_device(solo_dev->vfd, VFL_TYPE_GRABBER, nr); | ||
802 | if (ret < 0) { | ||
803 | video_device_release(solo_dev->vfd); | ||
804 | solo_dev->vfd = NULL; | ||
805 | return ret; | ||
806 | } | ||
807 | |||
808 | video_set_drvdata(solo_dev->vfd, solo_dev); | 748 | video_set_drvdata(solo_dev->vfd, solo_dev); |
809 | 749 | ||
810 | snprintf(solo_dev->vfd->name, sizeof(solo_dev->vfd->name), "%s (%i)", | 750 | spin_lock_init(&solo_dev->slock); |
811 | SOLO6X10_NAME, solo_dev->vfd->num); | 751 | INIT_LIST_HEAD(&solo_dev->vidq_active); |
812 | 752 | ||
813 | dev_info(&solo_dev->pdev->dev, | 753 | videobuf_queue_dma_contig_init(&solo_dev->vidq, &solo_video_qops, |
814 | "Display as /dev/video%d with %d inputs (%d extended)\n", | 754 | &solo_dev->pdev->dev, &solo_dev->slock, |
815 | solo_dev->vfd->num, solo_dev->nr_chans, solo_dev->nr_ext); | 755 | V4L2_BUF_TYPE_VIDEO_CAPTURE, |
756 | V4L2_FIELD_INTERLACED, | ||
757 | sizeof(struct videobuf_buffer), | ||
758 | solo_dev, NULL); | ||
816 | 759 | ||
817 | /* Cycle all the channels and clear */ | 760 | /* Cycle all the channels and clear */ |
818 | for (i = 0; i < solo_dev->nr_chans; i++) { | 761 | for (i = 0; i < solo_dev->nr_chans; i++) { |
@@ -826,6 +769,20 @@ int solo_v4l2_init(struct solo_dev *solo_dev, unsigned nr) | |||
826 | while (erase_off(solo_dev)) | 769 | while (erase_off(solo_dev)) |
827 | /* Do nothing */; | 770 | /* Do nothing */; |
828 | 771 | ||
772 | ret = video_register_device(solo_dev->vfd, VFL_TYPE_GRABBER, nr); | ||
773 | if (ret < 0) { | ||
774 | video_device_release(solo_dev->vfd); | ||
775 | solo_dev->vfd = NULL; | ||
776 | return ret; | ||
777 | } | ||
778 | |||
779 | snprintf(solo_dev->vfd->name, sizeof(solo_dev->vfd->name), "%s (%i)", | ||
780 | SOLO6X10_NAME, solo_dev->vfd->num); | ||
781 | |||
782 | dev_info(&solo_dev->pdev->dev, "Display as /dev/video%d with " | ||
783 | "%d inputs (%d extended)\n", solo_dev->vfd->num, | ||
784 | solo_dev->nr_chans, solo_dev->nr_ext); | ||
785 | |||
829 | return 0; | 786 | return 0; |
830 | } | 787 | } |
831 | 788 | ||