diff options
Diffstat (limited to 'drivers/media/video/omap/omap_vout.c')
-rw-r--r-- | drivers/media/video/omap/omap_vout.c | 645 |
1 files changed, 141 insertions, 504 deletions
diff --git a/drivers/media/video/omap/omap_vout.c b/drivers/media/video/omap/omap_vout.c index a647894d3a71..b5ef36222440 100644 --- a/drivers/media/video/omap/omap_vout.c +++ b/drivers/media/video/omap/omap_vout.c | |||
@@ -35,28 +35,26 @@ | |||
35 | #include <linux/sched.h> | 35 | #include <linux/sched.h> |
36 | #include <linux/types.h> | 36 | #include <linux/types.h> |
37 | #include <linux/platform_device.h> | 37 | #include <linux/platform_device.h> |
38 | #include <linux/dma-mapping.h> | ||
39 | #include <linux/irq.h> | 38 | #include <linux/irq.h> |
40 | #include <linux/videodev2.h> | 39 | #include <linux/videodev2.h> |
41 | #include <linux/slab.h> | 40 | #include <linux/dma-mapping.h> |
42 | 41 | ||
43 | #include <media/videobuf-dma-contig.h> | 42 | #include <media/videobuf-dma-contig.h> |
44 | #include <media/v4l2-device.h> | 43 | #include <media/v4l2-device.h> |
45 | #include <media/v4l2-ioctl.h> | 44 | #include <media/v4l2-ioctl.h> |
46 | 45 | ||
47 | #include <plat/dma.h> | 46 | #include <plat/dma.h> |
48 | #include <plat/vram.h> | ||
49 | #include <plat/vrfb.h> | 47 | #include <plat/vrfb.h> |
50 | #include <video/omapdss.h> | 48 | #include <video/omapdss.h> |
51 | 49 | ||
52 | #include "omap_voutlib.h" | 50 | #include "omap_voutlib.h" |
53 | #include "omap_voutdef.h" | 51 | #include "omap_voutdef.h" |
52 | #include "omap_vout_vrfb.h" | ||
54 | 53 | ||
55 | MODULE_AUTHOR("Texas Instruments"); | 54 | MODULE_AUTHOR("Texas Instruments"); |
56 | MODULE_DESCRIPTION("OMAP Video for Linux Video out driver"); | 55 | MODULE_DESCRIPTION("OMAP Video for Linux Video out driver"); |
57 | MODULE_LICENSE("GPL"); | 56 | MODULE_LICENSE("GPL"); |
58 | 57 | ||
59 | |||
60 | /* Driver Configuration macros */ | 58 | /* Driver Configuration macros */ |
61 | #define VOUT_NAME "omap_vout" | 59 | #define VOUT_NAME "omap_vout" |
62 | 60 | ||
@@ -65,31 +63,6 @@ enum omap_vout_channels { | |||
65 | OMAP_VIDEO2, | 63 | OMAP_VIDEO2, |
66 | }; | 64 | }; |
67 | 65 | ||
68 | enum dma_channel_state { | ||
69 | DMA_CHAN_NOT_ALLOTED, | ||
70 | DMA_CHAN_ALLOTED, | ||
71 | }; | ||
72 | |||
73 | #define QQVGA_WIDTH 160 | ||
74 | #define QQVGA_HEIGHT 120 | ||
75 | |||
76 | /* Max Resolution supported by the driver */ | ||
77 | #define VID_MAX_WIDTH 1280 /* Largest width */ | ||
78 | #define VID_MAX_HEIGHT 720 /* Largest height */ | ||
79 | |||
80 | /* Mimimum requirement is 2x2 for DSS */ | ||
81 | #define VID_MIN_WIDTH 2 | ||
82 | #define VID_MIN_HEIGHT 2 | ||
83 | |||
84 | /* 2048 x 2048 is max res supported by OMAP display controller */ | ||
85 | #define MAX_PIXELS_PER_LINE 2048 | ||
86 | |||
87 | #define VRFB_TX_TIMEOUT 1000 | ||
88 | #define VRFB_NUM_BUFS 4 | ||
89 | |||
90 | /* Max buffer size tobe allocated during init */ | ||
91 | #define OMAP_VOUT_MAX_BUF_SIZE (VID_MAX_WIDTH*VID_MAX_HEIGHT*4) | ||
92 | |||
93 | static struct videobuf_queue_ops video_vbq_ops; | 66 | static struct videobuf_queue_ops video_vbq_ops; |
94 | /* Variables configurable through module params*/ | 67 | /* Variables configurable through module params*/ |
95 | static u32 video1_numbuffers = 3; | 68 | static u32 video1_numbuffers = 3; |
@@ -172,84 +145,6 @@ static const struct v4l2_fmtdesc omap_formats[] = { | |||
172 | #define NUM_OUTPUT_FORMATS (ARRAY_SIZE(omap_formats)) | 145 | #define NUM_OUTPUT_FORMATS (ARRAY_SIZE(omap_formats)) |
173 | 146 | ||
174 | /* | 147 | /* |
175 | * Allocate buffers | ||
176 | */ | ||
177 | static unsigned long omap_vout_alloc_buffer(u32 buf_size, u32 *phys_addr) | ||
178 | { | ||
179 | u32 order, size; | ||
180 | unsigned long virt_addr, addr; | ||
181 | |||
182 | size = PAGE_ALIGN(buf_size); | ||
183 | order = get_order(size); | ||
184 | virt_addr = __get_free_pages(GFP_KERNEL | GFP_DMA, order); | ||
185 | addr = virt_addr; | ||
186 | |||
187 | if (virt_addr) { | ||
188 | while (size > 0) { | ||
189 | SetPageReserved(virt_to_page(addr)); | ||
190 | addr += PAGE_SIZE; | ||
191 | size -= PAGE_SIZE; | ||
192 | } | ||
193 | } | ||
194 | *phys_addr = (u32) virt_to_phys((void *) virt_addr); | ||
195 | return virt_addr; | ||
196 | } | ||
197 | |||
198 | /* | ||
199 | * Free buffers | ||
200 | */ | ||
201 | static void omap_vout_free_buffer(unsigned long virtaddr, u32 buf_size) | ||
202 | { | ||
203 | u32 order, size; | ||
204 | unsigned long addr = virtaddr; | ||
205 | |||
206 | size = PAGE_ALIGN(buf_size); | ||
207 | order = get_order(size); | ||
208 | |||
209 | while (size > 0) { | ||
210 | ClearPageReserved(virt_to_page(addr)); | ||
211 | addr += PAGE_SIZE; | ||
212 | size -= PAGE_SIZE; | ||
213 | } | ||
214 | free_pages((unsigned long) virtaddr, order); | ||
215 | } | ||
216 | |||
217 | /* | ||
218 | * Function for allocating video buffers | ||
219 | */ | ||
220 | static int omap_vout_allocate_vrfb_buffers(struct omap_vout_device *vout, | ||
221 | unsigned int *count, int startindex) | ||
222 | { | ||
223 | int i, j; | ||
224 | |||
225 | for (i = 0; i < *count; i++) { | ||
226 | if (!vout->smsshado_virt_addr[i]) { | ||
227 | vout->smsshado_virt_addr[i] = | ||
228 | omap_vout_alloc_buffer(vout->smsshado_size, | ||
229 | &vout->smsshado_phy_addr[i]); | ||
230 | } | ||
231 | if (!vout->smsshado_virt_addr[i] && startindex != -1) { | ||
232 | if (V4L2_MEMORY_MMAP == vout->memory && i >= startindex) | ||
233 | break; | ||
234 | } | ||
235 | if (!vout->smsshado_virt_addr[i]) { | ||
236 | for (j = 0; j < i; j++) { | ||
237 | omap_vout_free_buffer( | ||
238 | vout->smsshado_virt_addr[j], | ||
239 | vout->smsshado_size); | ||
240 | vout->smsshado_virt_addr[j] = 0; | ||
241 | vout->smsshado_phy_addr[j] = 0; | ||
242 | } | ||
243 | *count = 0; | ||
244 | return -ENOMEM; | ||
245 | } | ||
246 | memset((void *) vout->smsshado_virt_addr[i], 0, | ||
247 | vout->smsshado_size); | ||
248 | } | ||
249 | return 0; | ||
250 | } | ||
251 | |||
252 | /* | ||
253 | * Try format | 148 | * Try format |
254 | */ | 149 | */ |
255 | static int omap_vout_try_format(struct v4l2_pix_format *pix) | 150 | static int omap_vout_try_format(struct v4l2_pix_format *pix) |
@@ -342,73 +237,9 @@ static u32 omap_vout_uservirt_to_phys(u32 virtp) | |||
342 | } | 237 | } |
343 | 238 | ||
344 | /* | 239 | /* |
345 | * Wakes up the application once the DMA transfer to VRFB space is completed. | ||
346 | */ | ||
347 | static void omap_vout_vrfb_dma_tx_callback(int lch, u16 ch_status, void *data) | ||
348 | { | ||
349 | struct vid_vrfb_dma *t = (struct vid_vrfb_dma *) data; | ||
350 | |||
351 | t->tx_status = 1; | ||
352 | wake_up_interruptible(&t->wait); | ||
353 | } | ||
354 | |||
355 | /* | ||
356 | * Release the VRFB context once the module exits | ||
357 | */ | ||
358 | static void omap_vout_release_vrfb(struct omap_vout_device *vout) | ||
359 | { | ||
360 | int i; | ||
361 | |||
362 | for (i = 0; i < VRFB_NUM_BUFS; i++) | ||
363 | omap_vrfb_release_ctx(&vout->vrfb_context[i]); | ||
364 | |||
365 | if (vout->vrfb_dma_tx.req_status == DMA_CHAN_ALLOTED) { | ||
366 | vout->vrfb_dma_tx.req_status = DMA_CHAN_NOT_ALLOTED; | ||
367 | omap_free_dma(vout->vrfb_dma_tx.dma_ch); | ||
368 | } | ||
369 | } | ||
370 | |||
371 | /* | ||
372 | * Return true if rotation is 90 or 270 | ||
373 | */ | ||
374 | static inline int rotate_90_or_270(const struct omap_vout_device *vout) | ||
375 | { | ||
376 | return (vout->rotation == dss_rotation_90_degree || | ||
377 | vout->rotation == dss_rotation_270_degree); | ||
378 | } | ||
379 | |||
380 | /* | ||
381 | * Return true if rotation is enabled | ||
382 | */ | ||
383 | static inline int rotation_enabled(const struct omap_vout_device *vout) | ||
384 | { | ||
385 | return vout->rotation || vout->mirror; | ||
386 | } | ||
387 | |||
388 | /* | ||
389 | * Reverse the rotation degree if mirroring is enabled | ||
390 | */ | ||
391 | static inline int calc_rotation(const struct omap_vout_device *vout) | ||
392 | { | ||
393 | if (!vout->mirror) | ||
394 | return vout->rotation; | ||
395 | |||
396 | switch (vout->rotation) { | ||
397 | case dss_rotation_90_degree: | ||
398 | return dss_rotation_270_degree; | ||
399 | case dss_rotation_270_degree: | ||
400 | return dss_rotation_90_degree; | ||
401 | case dss_rotation_180_degree: | ||
402 | return dss_rotation_0_degree; | ||
403 | default: | ||
404 | return dss_rotation_180_degree; | ||
405 | } | ||
406 | } | ||
407 | |||
408 | /* | ||
409 | * Free the V4L2 buffers | 240 | * Free the V4L2 buffers |
410 | */ | 241 | */ |
411 | static void omap_vout_free_buffers(struct omap_vout_device *vout) | 242 | void omap_vout_free_buffers(struct omap_vout_device *vout) |
412 | { | 243 | { |
413 | int i, numbuffers; | 244 | int i, numbuffers; |
414 | 245 | ||
@@ -425,52 +256,6 @@ static void omap_vout_free_buffers(struct omap_vout_device *vout) | |||
425 | } | 256 | } |
426 | 257 | ||
427 | /* | 258 | /* |
428 | * Free VRFB buffers | ||
429 | */ | ||
430 | static void omap_vout_free_vrfb_buffers(struct omap_vout_device *vout) | ||
431 | { | ||
432 | int j; | ||
433 | |||
434 | for (j = 0; j < VRFB_NUM_BUFS; j++) { | ||
435 | omap_vout_free_buffer(vout->smsshado_virt_addr[j], | ||
436 | vout->smsshado_size); | ||
437 | vout->smsshado_virt_addr[j] = 0; | ||
438 | vout->smsshado_phy_addr[j] = 0; | ||
439 | } | ||
440 | } | ||
441 | |||
442 | /* | ||
443 | * Allocate the buffers for the VRFB space. Data is copied from V4L2 | ||
444 | * buffers to the VRFB buffers using the DMA engine. | ||
445 | */ | ||
446 | static int omap_vout_vrfb_buffer_setup(struct omap_vout_device *vout, | ||
447 | unsigned int *count, unsigned int startindex) | ||
448 | { | ||
449 | int i; | ||
450 | bool yuv_mode; | ||
451 | |||
452 | /* Allocate the VRFB buffers only if the buffers are not | ||
453 | * allocated during init time. | ||
454 | */ | ||
455 | if ((rotation_enabled(vout)) && !vout->vrfb_static_allocation) | ||
456 | if (omap_vout_allocate_vrfb_buffers(vout, count, startindex)) | ||
457 | return -ENOMEM; | ||
458 | |||
459 | if (vout->dss_mode == OMAP_DSS_COLOR_YUV2 || | ||
460 | vout->dss_mode == OMAP_DSS_COLOR_UYVY) | ||
461 | yuv_mode = true; | ||
462 | else | ||
463 | yuv_mode = false; | ||
464 | |||
465 | for (i = 0; i < *count; i++) | ||
466 | omap_vrfb_setup(&vout->vrfb_context[i], | ||
467 | vout->smsshado_phy_addr[i], vout->pix.width, | ||
468 | vout->pix.height, vout->bpp, yuv_mode); | ||
469 | |||
470 | return 0; | ||
471 | } | ||
472 | |||
473 | /* | ||
474 | * Convert V4L2 rotation to DSS rotation | 259 | * Convert V4L2 rotation to DSS rotation |
475 | * V4L2 understand 0, 90, 180, 270. | 260 | * V4L2 understand 0, 90, 180, 270. |
476 | * Convert to 0, 1, 2 and 3 respectively for DSS | 261 | * Convert to 0, 1, 2 and 3 respectively for DSS |
@@ -499,124 +284,38 @@ static int v4l2_rot_to_dss_rot(int v4l2_rotation, | |||
499 | return ret; | 284 | return ret; |
500 | } | 285 | } |
501 | 286 | ||
502 | /* | ||
503 | * Calculate the buffer offsets from which the streaming should | ||
504 | * start. This offset calculation is mainly required because of | ||
505 | * the VRFB 32 pixels alignment with rotation. | ||
506 | */ | ||
507 | static int omap_vout_calculate_offset(struct omap_vout_device *vout) | 287 | static int omap_vout_calculate_offset(struct omap_vout_device *vout) |
508 | { | 288 | { |
509 | struct omap_overlay *ovl; | ||
510 | enum dss_rotation rotation; | ||
511 | struct omapvideo_info *ovid; | 289 | struct omapvideo_info *ovid; |
512 | bool mirroring = vout->mirror; | ||
513 | struct omap_dss_device *cur_display; | ||
514 | struct v4l2_rect *crop = &vout->crop; | 290 | struct v4l2_rect *crop = &vout->crop; |
515 | struct v4l2_pix_format *pix = &vout->pix; | 291 | struct v4l2_pix_format *pix = &vout->pix; |
516 | int *cropped_offset = &vout->cropped_offset; | 292 | int *cropped_offset = &vout->cropped_offset; |
517 | int vr_ps = 1, ps = 2, temp_ps = 2; | 293 | int ps = 2, line_length = 0; |
518 | int offset = 0, ctop = 0, cleft = 0, line_length = 0; | ||
519 | 294 | ||
520 | ovid = &vout->vid_info; | 295 | ovid = &vout->vid_info; |
521 | ovl = ovid->overlays[0]; | ||
522 | /* get the display device attached to the overlay */ | ||
523 | if (!ovl->manager || !ovl->manager->device) | ||
524 | return -1; | ||
525 | 296 | ||
526 | cur_display = ovl->manager->device; | 297 | if (ovid->rotation_type == VOUT_ROT_VRFB) { |
527 | rotation = calc_rotation(vout); | 298 | omap_vout_calculate_vrfb_offset(vout); |
299 | } else { | ||
300 | vout->line_length = line_length = pix->width; | ||
528 | 301 | ||
529 | if (V4L2_PIX_FMT_YUYV == pix->pixelformat || | 302 | if (V4L2_PIX_FMT_YUYV == pix->pixelformat || |
530 | V4L2_PIX_FMT_UYVY == pix->pixelformat) { | 303 | V4L2_PIX_FMT_UYVY == pix->pixelformat) |
531 | if (rotation_enabled(vout)) { | 304 | ps = 2; |
532 | /* | 305 | else if (V4L2_PIX_FMT_RGB32 == pix->pixelformat) |
533 | * ps - Actual pixel size for YUYV/UYVY for | ||
534 | * VRFB/Mirroring is 4 bytes | ||
535 | * vr_ps - Virtually pixel size for YUYV/UYVY is | ||
536 | * 2 bytes | ||
537 | */ | ||
538 | ps = 4; | 306 | ps = 4; |
539 | vr_ps = 2; | 307 | else if (V4L2_PIX_FMT_RGB24 == pix->pixelformat) |
540 | } else { | 308 | ps = 3; |
541 | ps = 2; /* otherwise the pixel size is 2 byte */ | ||
542 | } | ||
543 | } else if (V4L2_PIX_FMT_RGB32 == pix->pixelformat) { | ||
544 | ps = 4; | ||
545 | } else if (V4L2_PIX_FMT_RGB24 == pix->pixelformat) { | ||
546 | ps = 3; | ||
547 | } | ||
548 | vout->ps = ps; | ||
549 | vout->vr_ps = vr_ps; | ||
550 | |||
551 | if (rotation_enabled(vout)) { | ||
552 | line_length = MAX_PIXELS_PER_LINE; | ||
553 | ctop = (pix->height - crop->height) - crop->top; | ||
554 | cleft = (pix->width - crop->width) - crop->left; | ||
555 | } else { | ||
556 | line_length = pix->width; | ||
557 | } | ||
558 | vout->line_length = line_length; | ||
559 | switch (rotation) { | ||
560 | case dss_rotation_90_degree: | ||
561 | offset = vout->vrfb_context[0].yoffset * | ||
562 | vout->vrfb_context[0].bytespp; | ||
563 | temp_ps = ps / vr_ps; | ||
564 | if (mirroring == 0) { | ||
565 | *cropped_offset = offset + line_length * | ||
566 | temp_ps * cleft + crop->top * temp_ps; | ||
567 | } else { | ||
568 | *cropped_offset = offset + line_length * temp_ps * | ||
569 | cleft + crop->top * temp_ps + (line_length * | ||
570 | ((crop->width / (vr_ps)) - 1) * ps); | ||
571 | } | ||
572 | break; | ||
573 | case dss_rotation_180_degree: | ||
574 | offset = ((MAX_PIXELS_PER_LINE * vout->vrfb_context[0].yoffset * | ||
575 | vout->vrfb_context[0].bytespp) + | ||
576 | (vout->vrfb_context[0].xoffset * | ||
577 | vout->vrfb_context[0].bytespp)); | ||
578 | if (mirroring == 0) { | ||
579 | *cropped_offset = offset + (line_length * ps * ctop) + | ||
580 | (cleft / vr_ps) * ps; | ||
581 | 309 | ||
582 | } else { | 310 | vout->ps = ps; |
583 | *cropped_offset = offset + (line_length * ps * ctop) + | 311 | |
584 | (cleft / vr_ps) * ps + (line_length * | 312 | *cropped_offset = (line_length * ps) * |
585 | (crop->height - 1) * ps); | 313 | crop->top + crop->left * ps; |
586 | } | ||
587 | break; | ||
588 | case dss_rotation_270_degree: | ||
589 | offset = MAX_PIXELS_PER_LINE * vout->vrfb_context[0].xoffset * | ||
590 | vout->vrfb_context[0].bytespp; | ||
591 | temp_ps = ps / vr_ps; | ||
592 | if (mirroring == 0) { | ||
593 | *cropped_offset = offset + line_length * | ||
594 | temp_ps * crop->left + ctop * ps; | ||
595 | } else { | ||
596 | *cropped_offset = offset + line_length * | ||
597 | temp_ps * crop->left + ctop * ps + | ||
598 | (line_length * ((crop->width / vr_ps) - 1) * | ||
599 | ps); | ||
600 | } | ||
601 | break; | ||
602 | case dss_rotation_0_degree: | ||
603 | if (mirroring == 0) { | ||
604 | *cropped_offset = (line_length * ps) * | ||
605 | crop->top + (crop->left / vr_ps) * ps; | ||
606 | } else { | ||
607 | *cropped_offset = (line_length * ps) * | ||
608 | crop->top + (crop->left / vr_ps) * ps + | ||
609 | (line_length * (crop->height - 1) * ps); | ||
610 | } | ||
611 | break; | ||
612 | default: | ||
613 | *cropped_offset = (line_length * ps * crop->top) / | ||
614 | vr_ps + (crop->left * ps) / vr_ps + | ||
615 | ((crop->width / vr_ps) - 1) * ps; | ||
616 | break; | ||
617 | } | 314 | } |
315 | |||
618 | v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev, "%s Offset:%x\n", | 316 | v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev, "%s Offset:%x\n", |
619 | __func__, *cropped_offset); | 317 | __func__, vout->cropped_offset); |
318 | |||
620 | return 0; | 319 | return 0; |
621 | } | 320 | } |
622 | 321 | ||
@@ -664,7 +363,7 @@ static int video_mode_to_dss_mode(struct omap_vout_device *vout) | |||
664 | /* | 363 | /* |
665 | * Setup the overlay | 364 | * Setup the overlay |
666 | */ | 365 | */ |
667 | int omapvid_setup_overlay(struct omap_vout_device *vout, | 366 | static int omapvid_setup_overlay(struct omap_vout_device *vout, |
668 | struct omap_overlay *ovl, int posx, int posy, int outw, | 367 | struct omap_overlay *ovl, int posx, int posy, int outw, |
669 | int outh, u32 addr) | 368 | int outh, u32 addr) |
670 | { | 369 | { |
@@ -687,7 +386,7 @@ int omapvid_setup_overlay(struct omap_vout_device *vout, | |||
687 | /* Setup the input plane parameters according to | 386 | /* Setup the input plane parameters according to |
688 | * rotation value selected. | 387 | * rotation value selected. |
689 | */ | 388 | */ |
690 | if (rotate_90_or_270(vout)) { | 389 | if (is_rotation_90_or_270(vout)) { |
691 | cropheight = vout->crop.width; | 390 | cropheight = vout->crop.width; |
692 | cropwidth = vout->crop.height; | 391 | cropwidth = vout->crop.height; |
693 | pixheight = vout->pix.width; | 392 | pixheight = vout->pix.width; |
@@ -711,7 +410,7 @@ int omapvid_setup_overlay(struct omap_vout_device *vout, | |||
711 | info.out_width = outw; | 410 | info.out_width = outw; |
712 | info.out_height = outh; | 411 | info.out_height = outh; |
713 | info.global_alpha = vout->win.global_alpha; | 412 | info.global_alpha = vout->win.global_alpha; |
714 | if (!rotation_enabled(vout)) { | 413 | if (!is_rotation_enabled(vout)) { |
715 | info.rotation = 0; | 414 | info.rotation = 0; |
716 | info.rotation_type = OMAP_DSS_ROT_DMA; | 415 | info.rotation_type = OMAP_DSS_ROT_DMA; |
717 | info.screen_width = pixwidth; | 416 | info.screen_width = pixwidth; |
@@ -744,7 +443,7 @@ setup_ovl_err: | |||
744 | /* | 443 | /* |
745 | * Initialize the overlay structure | 444 | * Initialize the overlay structure |
746 | */ | 445 | */ |
747 | int omapvid_init(struct omap_vout_device *vout, u32 addr) | 446 | static int omapvid_init(struct omap_vout_device *vout, u32 addr) |
748 | { | 447 | { |
749 | int ret = 0, i; | 448 | int ret = 0, i; |
750 | struct v4l2_window *win; | 449 | struct v4l2_window *win; |
@@ -809,7 +508,7 @@ omapvid_init_err: | |||
809 | /* | 508 | /* |
810 | * Apply the changes set the go bit of DSS | 509 | * Apply the changes set the go bit of DSS |
811 | */ | 510 | */ |
812 | int omapvid_apply_changes(struct omap_vout_device *vout) | 511 | static int omapvid_apply_changes(struct omap_vout_device *vout) |
813 | { | 512 | { |
814 | int i; | 513 | int i; |
815 | struct omap_overlay *ovl; | 514 | struct omap_overlay *ovl; |
@@ -825,7 +524,7 @@ int omapvid_apply_changes(struct omap_vout_device *vout) | |||
825 | return 0; | 524 | return 0; |
826 | } | 525 | } |
827 | 526 | ||
828 | void omap_vout_isr(void *arg, unsigned int irqstatus) | 527 | static void omap_vout_isr(void *arg, unsigned int irqstatus) |
829 | { | 528 | { |
830 | int ret; | 529 | int ret; |
831 | u32 addr, fid; | 530 | u32 addr, fid; |
@@ -848,10 +547,20 @@ void omap_vout_isr(void *arg, unsigned int irqstatus) | |||
848 | 547 | ||
849 | spin_lock(&vout->vbq_lock); | 548 | spin_lock(&vout->vbq_lock); |
850 | do_gettimeofday(&timevalue); | 549 | do_gettimeofday(&timevalue); |
851 | if (cur_display->type == OMAP_DISPLAY_TYPE_DPI) { | ||
852 | if (!(irqstatus & DISPC_IRQ_VSYNC)) | ||
853 | goto vout_isr_err; | ||
854 | 550 | ||
551 | if (cur_display->type != OMAP_DISPLAY_TYPE_VENC) { | ||
552 | switch (cur_display->type) { | ||
553 | case OMAP_DISPLAY_TYPE_DPI: | ||
554 | if (!(irqstatus & (DISPC_IRQ_VSYNC | DISPC_IRQ_VSYNC2))) | ||
555 | goto vout_isr_err; | ||
556 | break; | ||
557 | case OMAP_DISPLAY_TYPE_HDMI: | ||
558 | if (!(irqstatus & DISPC_IRQ_EVSYNC_EVEN)) | ||
559 | goto vout_isr_err; | ||
560 | break; | ||
561 | default: | ||
562 | goto vout_isr_err; | ||
563 | } | ||
855 | if (!vout->first_int && (vout->cur_frm != vout->next_frm)) { | 564 | if (!vout->first_int && (vout->cur_frm != vout->next_frm)) { |
856 | vout->cur_frm->ts = timevalue; | 565 | vout->cur_frm->ts = timevalue; |
857 | vout->cur_frm->state = VIDEOBUF_DONE; | 566 | vout->cur_frm->state = VIDEOBUF_DONE; |
@@ -875,7 +584,7 @@ void omap_vout_isr(void *arg, unsigned int irqstatus) | |||
875 | ret = omapvid_init(vout, addr); | 584 | ret = omapvid_init(vout, addr); |
876 | if (ret) | 585 | if (ret) |
877 | printk(KERN_ERR VOUT_NAME | 586 | printk(KERN_ERR VOUT_NAME |
878 | "failed to set overlay info\n"); | 587 | "failed to set overlay info\n"); |
879 | /* Enable the pipeline and set the Go bit */ | 588 | /* Enable the pipeline and set the Go bit */ |
880 | ret = omapvid_apply_changes(vout); | 589 | ret = omapvid_apply_changes(vout); |
881 | if (ret) | 590 | if (ret) |
@@ -954,6 +663,7 @@ static int omap_vout_buffer_setup(struct videobuf_queue *q, unsigned int *count, | |||
954 | int startindex = 0, i, j; | 663 | int startindex = 0, i, j; |
955 | u32 phy_addr = 0, virt_addr = 0; | 664 | u32 phy_addr = 0, virt_addr = 0; |
956 | struct omap_vout_device *vout = q->priv_data; | 665 | struct omap_vout_device *vout = q->priv_data; |
666 | struct omapvideo_info *ovid = &vout->vid_info; | ||
957 | 667 | ||
958 | if (!vout) | 668 | if (!vout) |
959 | return -EINVAL; | 669 | return -EINVAL; |
@@ -966,13 +676,10 @@ static int omap_vout_buffer_setup(struct videobuf_queue *q, unsigned int *count, | |||
966 | if (V4L2_MEMORY_MMAP == vout->memory && *count < startindex) | 676 | if (V4L2_MEMORY_MMAP == vout->memory && *count < startindex) |
967 | *count = startindex; | 677 | *count = startindex; |
968 | 678 | ||
969 | if ((rotation_enabled(vout)) && *count > VRFB_NUM_BUFS) | 679 | if (ovid->rotation_type == VOUT_ROT_VRFB) { |
970 | *count = VRFB_NUM_BUFS; | ||
971 | |||
972 | /* If rotation is enabled, allocate memory for VRFB space also */ | ||
973 | if (rotation_enabled(vout)) | ||
974 | if (omap_vout_vrfb_buffer_setup(vout, count, startindex)) | 680 | if (omap_vout_vrfb_buffer_setup(vout, count, startindex)) |
975 | return -ENOMEM; | 681 | return -ENOMEM; |
682 | } | ||
976 | 683 | ||
977 | if (V4L2_MEMORY_MMAP != vout->memory) | 684 | if (V4L2_MEMORY_MMAP != vout->memory) |
978 | return 0; | 685 | return 0; |
@@ -996,8 +703,11 @@ static int omap_vout_buffer_setup(struct videobuf_queue *q, unsigned int *count, | |||
996 | virt_addr = omap_vout_alloc_buffer(vout->buffer_size, | 703 | virt_addr = omap_vout_alloc_buffer(vout->buffer_size, |
997 | &phy_addr); | 704 | &phy_addr); |
998 | if (!virt_addr) { | 705 | if (!virt_addr) { |
999 | if (!rotation_enabled(vout)) | 706 | if (ovid->rotation_type == VOUT_ROT_NONE) { |
1000 | break; | 707 | break; |
708 | } else { | ||
709 | if (!is_rotation_enabled(vout)) | ||
710 | break; | ||
1001 | /* Free the VRFB buffers if no space for V4L2 buffers */ | 711 | /* Free the VRFB buffers if no space for V4L2 buffers */ |
1002 | for (j = i; j < *count; j++) { | 712 | for (j = i; j < *count; j++) { |
1003 | omap_vout_free_buffer( | 713 | omap_vout_free_buffer( |
@@ -1005,6 +715,7 @@ static int omap_vout_buffer_setup(struct videobuf_queue *q, unsigned int *count, | |||
1005 | vout->smsshado_size); | 715 | vout->smsshado_size); |
1006 | vout->smsshado_virt_addr[j] = 0; | 716 | vout->smsshado_virt_addr[j] = 0; |
1007 | vout->smsshado_phy_addr[j] = 0; | 717 | vout->smsshado_phy_addr[j] = 0; |
718 | } | ||
1008 | } | 719 | } |
1009 | } | 720 | } |
1010 | vout->buf_virt_addr[i] = virt_addr; | 721 | vout->buf_virt_addr[i] = virt_addr; |
@@ -1017,9 +728,9 @@ static int omap_vout_buffer_setup(struct videobuf_queue *q, unsigned int *count, | |||
1017 | 728 | ||
1018 | /* | 729 | /* |
1019 | * Free the V4L2 buffers additionally allocated than default | 730 | * Free the V4L2 buffers additionally allocated than default |
1020 | * number of buffers and free all the VRFB buffers | 731 | * number of buffers |
1021 | */ | 732 | */ |
1022 | static void omap_vout_free_allbuffers(struct omap_vout_device *vout) | 733 | static void omap_vout_free_extra_buffers(struct omap_vout_device *vout) |
1023 | { | 734 | { |
1024 | int num_buffers = 0, i; | 735 | int num_buffers = 0, i; |
1025 | 736 | ||
@@ -1034,20 +745,6 @@ static void omap_vout_free_allbuffers(struct omap_vout_device *vout) | |||
1034 | vout->buf_virt_addr[i] = 0; | 745 | vout->buf_virt_addr[i] = 0; |
1035 | vout->buf_phy_addr[i] = 0; | 746 | vout->buf_phy_addr[i] = 0; |
1036 | } | 747 | } |
1037 | /* Free the VRFB buffers only if they are allocated | ||
1038 | * during reqbufs. Don't free if init time allocated | ||
1039 | */ | ||
1040 | if (!vout->vrfb_static_allocation) { | ||
1041 | for (i = 0; i < VRFB_NUM_BUFS; i++) { | ||
1042 | if (vout->smsshado_virt_addr[i]) { | ||
1043 | omap_vout_free_buffer( | ||
1044 | vout->smsshado_virt_addr[i], | ||
1045 | vout->smsshado_size); | ||
1046 | vout->smsshado_virt_addr[i] = 0; | ||
1047 | vout->smsshado_phy_addr[i] = 0; | ||
1048 | } | ||
1049 | } | ||
1050 | } | ||
1051 | vout->buffer_allocated = num_buffers; | 748 | vout->buffer_allocated = num_buffers; |
1052 | } | 749 | } |
1053 | 750 | ||
@@ -1059,16 +756,11 @@ static void omap_vout_free_allbuffers(struct omap_vout_device *vout) | |||
1059 | * buffer into VRFB memory space before giving it to the DSS. | 756 | * buffer into VRFB memory space before giving it to the DSS. |
1060 | */ | 757 | */ |
1061 | static int omap_vout_buffer_prepare(struct videobuf_queue *q, | 758 | static int omap_vout_buffer_prepare(struct videobuf_queue *q, |
1062 | struct videobuf_buffer *vb, | 759 | struct videobuf_buffer *vb, |
1063 | enum v4l2_field field) | 760 | enum v4l2_field field) |
1064 | { | 761 | { |
1065 | dma_addr_t dmabuf; | ||
1066 | struct vid_vrfb_dma *tx; | ||
1067 | enum dss_rotation rotation; | ||
1068 | struct omap_vout_device *vout = q->priv_data; | 762 | struct omap_vout_device *vout = q->priv_data; |
1069 | u32 dest_frame_index = 0, src_element_index = 0; | 763 | struct omapvideo_info *ovid = &vout->vid_info; |
1070 | u32 dest_element_index = 0, src_frame_index = 0; | ||
1071 | u32 elem_count = 0, frame_count = 0, pixsize = 2; | ||
1072 | 764 | ||
1073 | if (VIDEOBUF_NEEDS_INIT == vb->state) { | 765 | if (VIDEOBUF_NEEDS_INIT == vb->state) { |
1074 | vb->width = vout->pix.width; | 766 | vb->width = vout->pix.width; |
@@ -1087,66 +779,24 @@ static int omap_vout_buffer_prepare(struct videobuf_queue *q, | |||
1087 | vout->queued_buf_addr[vb->i] = (u8 *) | 779 | vout->queued_buf_addr[vb->i] = (u8 *) |
1088 | omap_vout_uservirt_to_phys(vb->baddr); | 780 | omap_vout_uservirt_to_phys(vb->baddr); |
1089 | } else { | 781 | } else { |
1090 | vout->queued_buf_addr[vb->i] = (u8 *)vout->buf_phy_addr[vb->i]; | 782 | u32 addr, dma_addr; |
1091 | } | 783 | unsigned long size; |
1092 | 784 | ||
1093 | if (!rotation_enabled(vout)) | 785 | addr = (unsigned long) vout->buf_virt_addr[vb->i]; |
1094 | return 0; | 786 | size = (unsigned long) vb->size; |
1095 | 787 | ||
1096 | dmabuf = vout->buf_phy_addr[vb->i]; | 788 | dma_addr = dma_map_single(vout->vid_dev->v4l2_dev.dev, (void *) addr, |
1097 | /* If rotation is enabled, copy input buffer into VRFB | 789 | size, DMA_TO_DEVICE); |
1098 | * memory space using DMA. We are copying input buffer | 790 | if (dma_mapping_error(vout->vid_dev->v4l2_dev.dev, dma_addr)) |
1099 | * into VRFB memory space of desired angle and DSS will | 791 | v4l2_err(&vout->vid_dev->v4l2_dev, "dma_map_single failed\n"); |
1100 | * read image VRFB memory for 0 degree angle | ||
1101 | */ | ||
1102 | pixsize = vout->bpp * vout->vrfb_bpp; | ||
1103 | /* | ||
1104 | * DMA transfer in double index mode | ||
1105 | */ | ||
1106 | 792 | ||
1107 | /* Frame index */ | 793 | vout->queued_buf_addr[vb->i] = (u8 *)vout->buf_phy_addr[vb->i]; |
1108 | dest_frame_index = ((MAX_PIXELS_PER_LINE * pixsize) - | ||
1109 | (vout->pix.width * vout->bpp)) + 1; | ||
1110 | |||
1111 | /* Source and destination parameters */ | ||
1112 | src_element_index = 0; | ||
1113 | src_frame_index = 0; | ||
1114 | dest_element_index = 1; | ||
1115 | /* Number of elements per frame */ | ||
1116 | elem_count = vout->pix.width * vout->bpp; | ||
1117 | frame_count = vout->pix.height; | ||
1118 | tx = &vout->vrfb_dma_tx; | ||
1119 | tx->tx_status = 0; | ||
1120 | omap_set_dma_transfer_params(tx->dma_ch, OMAP_DMA_DATA_TYPE_S32, | ||
1121 | (elem_count / 4), frame_count, OMAP_DMA_SYNC_ELEMENT, | ||
1122 | tx->dev_id, 0x0); | ||
1123 | /* src_port required only for OMAP1 */ | ||
1124 | omap_set_dma_src_params(tx->dma_ch, 0, OMAP_DMA_AMODE_POST_INC, | ||
1125 | dmabuf, src_element_index, src_frame_index); | ||
1126 | /*set dma source burst mode for VRFB */ | ||
1127 | omap_set_dma_src_burst_mode(tx->dma_ch, OMAP_DMA_DATA_BURST_16); | ||
1128 | rotation = calc_rotation(vout); | ||
1129 | |||
1130 | /* dest_port required only for OMAP1 */ | ||
1131 | omap_set_dma_dest_params(tx->dma_ch, 0, OMAP_DMA_AMODE_DOUBLE_IDX, | ||
1132 | vout->vrfb_context[vb->i].paddr[0], dest_element_index, | ||
1133 | dest_frame_index); | ||
1134 | /*set dma dest burst mode for VRFB */ | ||
1135 | omap_set_dma_dest_burst_mode(tx->dma_ch, OMAP_DMA_DATA_BURST_16); | ||
1136 | omap_dma_set_global_params(DMA_DEFAULT_ARB_RATE, 0x20, 0); | ||
1137 | |||
1138 | omap_start_dma(tx->dma_ch); | ||
1139 | interruptible_sleep_on_timeout(&tx->wait, VRFB_TX_TIMEOUT); | ||
1140 | |||
1141 | if (tx->tx_status == 0) { | ||
1142 | omap_stop_dma(tx->dma_ch); | ||
1143 | return -EINVAL; | ||
1144 | } | 794 | } |
1145 | /* Store buffers physical address into an array. Addresses | 795 | |
1146 | * from this array will be used to configure DSS */ | 796 | if (ovid->rotation_type == VOUT_ROT_VRFB) |
1147 | vout->queued_buf_addr[vb->i] = (u8 *) | 797 | return omap_vout_prepare_vrfb(vout, vb); |
1148 | vout->vrfb_context[vb->i].paddr[rotation]; | 798 | else |
1149 | return 0; | 799 | return 0; |
1150 | } | 800 | } |
1151 | 801 | ||
1152 | /* | 802 | /* |
@@ -1298,7 +948,15 @@ static int omap_vout_release(struct file *file) | |||
1298 | "Unable to apply changes\n"); | 948 | "Unable to apply changes\n"); |
1299 | 949 | ||
1300 | /* Free all buffers */ | 950 | /* Free all buffers */ |
1301 | omap_vout_free_allbuffers(vout); | 951 | omap_vout_free_extra_buffers(vout); |
952 | |||
953 | /* Free the VRFB buffers only if they are allocated | ||
954 | * during reqbufs. Don't free if init time allocated | ||
955 | */ | ||
956 | if (ovid->rotation_type == VOUT_ROT_VRFB) { | ||
957 | if (!vout->vrfb_static_allocation) | ||
958 | omap_vout_free_vrfb_buffers(vout); | ||
959 | } | ||
1302 | videobuf_mmap_free(q); | 960 | videobuf_mmap_free(q); |
1303 | 961 | ||
1304 | /* Even if apply changes fails we should continue | 962 | /* Even if apply changes fails we should continue |
@@ -1307,7 +965,7 @@ static int omap_vout_release(struct file *file) | |||
1307 | u32 mask = 0; | 965 | u32 mask = 0; |
1308 | 966 | ||
1309 | mask = DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_EVEN | | 967 | mask = DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_EVEN | |
1310 | DISPC_IRQ_EVSYNC_ODD; | 968 | DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_VSYNC2; |
1311 | omap_dispc_unregister_isr(omap_vout_isr, vout, mask); | 969 | omap_dispc_unregister_isr(omap_vout_isr, vout, mask); |
1312 | vout->streaming = 0; | 970 | vout->streaming = 0; |
1313 | 971 | ||
@@ -1383,10 +1041,7 @@ static int vidioc_enum_fmt_vid_out(struct file *file, void *fh, | |||
1383 | struct v4l2_fmtdesc *fmt) | 1041 | struct v4l2_fmtdesc *fmt) |
1384 | { | 1042 | { |
1385 | int index = fmt->index; | 1043 | int index = fmt->index; |
1386 | enum v4l2_buf_type type = fmt->type; | ||
1387 | 1044 | ||
1388 | fmt->index = index; | ||
1389 | fmt->type = type; | ||
1390 | if (index >= NUM_OUTPUT_FORMATS) | 1045 | if (index >= NUM_OUTPUT_FORMATS) |
1391 | return -EINVAL; | 1046 | return -EINVAL; |
1392 | 1047 | ||
@@ -1457,7 +1112,7 @@ static int vidioc_s_fmt_vid_out(struct file *file, void *fh, | |||
1457 | 1112 | ||
1458 | /* We dont support RGB24-packed mode if vrfb rotation | 1113 | /* We dont support RGB24-packed mode if vrfb rotation |
1459 | * is enabled*/ | 1114 | * is enabled*/ |
1460 | if ((rotation_enabled(vout)) && | 1115 | if ((is_rotation_enabled(vout)) && |
1461 | f->fmt.pix.pixelformat == V4L2_PIX_FMT_RGB24) { | 1116 | f->fmt.pix.pixelformat == V4L2_PIX_FMT_RGB24) { |
1462 | ret = -EINVAL; | 1117 | ret = -EINVAL; |
1463 | goto s_fmt_vid_out_exit; | 1118 | goto s_fmt_vid_out_exit; |
@@ -1465,7 +1120,7 @@ static int vidioc_s_fmt_vid_out(struct file *file, void *fh, | |||
1465 | 1120 | ||
1466 | /* get the framebuffer parameters */ | 1121 | /* get the framebuffer parameters */ |
1467 | 1122 | ||
1468 | if (rotate_90_or_270(vout)) { | 1123 | if (is_rotation_90_or_270(vout)) { |
1469 | vout->fbuf.fmt.height = timing->x_res; | 1124 | vout->fbuf.fmt.height = timing->x_res; |
1470 | vout->fbuf.fmt.width = timing->y_res; | 1125 | vout->fbuf.fmt.width = timing->y_res; |
1471 | } else { | 1126 | } else { |
@@ -1555,10 +1210,7 @@ static int vidioc_enum_fmt_vid_overlay(struct file *file, void *fh, | |||
1555 | struct v4l2_fmtdesc *fmt) | 1210 | struct v4l2_fmtdesc *fmt) |
1556 | { | 1211 | { |
1557 | int index = fmt->index; | 1212 | int index = fmt->index; |
1558 | enum v4l2_buf_type type = fmt->type; | ||
1559 | 1213 | ||
1560 | fmt->index = index; | ||
1561 | fmt->type = type; | ||
1562 | if (index >= NUM_OUTPUT_FORMATS) | 1214 | if (index >= NUM_OUTPUT_FORMATS) |
1563 | return -EINVAL; | 1215 | return -EINVAL; |
1564 | 1216 | ||
@@ -1645,7 +1297,7 @@ static int vidioc_s_crop(struct file *file, void *fh, struct v4l2_crop *crop) | |||
1645 | /* get the display device attached to the overlay */ | 1297 | /* get the display device attached to the overlay */ |
1646 | timing = &ovl->manager->device->panel.timings; | 1298 | timing = &ovl->manager->device->panel.timings; |
1647 | 1299 | ||
1648 | if (rotate_90_or_270(vout)) { | 1300 | if (is_rotation_90_or_270(vout)) { |
1649 | vout->fbuf.fmt.height = timing->x_res; | 1301 | vout->fbuf.fmt.height = timing->x_res; |
1650 | vout->fbuf.fmt.width = timing->y_res; | 1302 | vout->fbuf.fmt.width = timing->y_res; |
1651 | } else { | 1303 | } else { |
@@ -1725,9 +1377,17 @@ static int vidioc_s_ctrl(struct file *file, void *fh, struct v4l2_control *a) | |||
1725 | switch (a->id) { | 1377 | switch (a->id) { |
1726 | case V4L2_CID_ROTATE: | 1378 | case V4L2_CID_ROTATE: |
1727 | { | 1379 | { |
1380 | struct omapvideo_info *ovid; | ||
1728 | int rotation = a->value; | 1381 | int rotation = a->value; |
1729 | 1382 | ||
1383 | ovid = &vout->vid_info; | ||
1384 | |||
1730 | mutex_lock(&vout->lock); | 1385 | mutex_lock(&vout->lock); |
1386 | if (rotation && ovid->rotation_type == VOUT_ROT_NONE) { | ||
1387 | mutex_unlock(&vout->lock); | ||
1388 | ret = -ERANGE; | ||
1389 | break; | ||
1390 | } | ||
1731 | 1391 | ||
1732 | if (rotation && vout->pix.pixelformat == V4L2_PIX_FMT_RGB24) { | 1392 | if (rotation && vout->pix.pixelformat == V4L2_PIX_FMT_RGB24) { |
1733 | mutex_unlock(&vout->lock); | 1393 | mutex_unlock(&vout->lock); |
@@ -1783,6 +1443,11 @@ static int vidioc_s_ctrl(struct file *file, void *fh, struct v4l2_control *a) | |||
1783 | ovl = ovid->overlays[0]; | 1443 | ovl = ovid->overlays[0]; |
1784 | 1444 | ||
1785 | mutex_lock(&vout->lock); | 1445 | mutex_lock(&vout->lock); |
1446 | if (mirror && ovid->rotation_type == VOUT_ROT_NONE) { | ||
1447 | mutex_unlock(&vout->lock); | ||
1448 | ret = -ERANGE; | ||
1449 | break; | ||
1450 | } | ||
1786 | 1451 | ||
1787 | if (mirror && vout->pix.pixelformat == V4L2_PIX_FMT_RGB24) { | 1452 | if (mirror && vout->pix.pixelformat == V4L2_PIX_FMT_RGB24) { |
1788 | mutex_unlock(&vout->lock); | 1453 | mutex_unlock(&vout->lock); |
@@ -1893,7 +1558,7 @@ static int vidioc_qbuf(struct file *file, void *fh, | |||
1893 | } | 1558 | } |
1894 | } | 1559 | } |
1895 | 1560 | ||
1896 | if ((rotation_enabled(vout)) && | 1561 | if ((is_rotation_enabled(vout)) && |
1897 | vout->vrfb_dma_tx.req_status == DMA_CHAN_NOT_ALLOTED) { | 1562 | vout->vrfb_dma_tx.req_status == DMA_CHAN_NOT_ALLOTED) { |
1898 | v4l2_warn(&vout->vid_dev->v4l2_dev, | 1563 | v4l2_warn(&vout->vid_dev->v4l2_dev, |
1899 | "DMA Channel not allocated for Rotation\n"); | 1564 | "DMA Channel not allocated for Rotation\n"); |
@@ -1908,15 +1573,28 @@ static int vidioc_dqbuf(struct file *file, void *fh, struct v4l2_buffer *b) | |||
1908 | struct omap_vout_device *vout = fh; | 1573 | struct omap_vout_device *vout = fh; |
1909 | struct videobuf_queue *q = &vout->vbq; | 1574 | struct videobuf_queue *q = &vout->vbq; |
1910 | 1575 | ||
1576 | int ret; | ||
1577 | u32 addr; | ||
1578 | unsigned long size; | ||
1579 | struct videobuf_buffer *vb; | ||
1580 | |||
1581 | vb = q->bufs[b->index]; | ||
1582 | |||
1911 | if (!vout->streaming) | 1583 | if (!vout->streaming) |
1912 | return -EINVAL; | 1584 | return -EINVAL; |
1913 | 1585 | ||
1914 | if (file->f_flags & O_NONBLOCK) | 1586 | if (file->f_flags & O_NONBLOCK) |
1915 | /* Call videobuf_dqbuf for non blocking mode */ | 1587 | /* Call videobuf_dqbuf for non blocking mode */ |
1916 | return videobuf_dqbuf(q, (struct v4l2_buffer *)b, 1); | 1588 | ret = videobuf_dqbuf(q, (struct v4l2_buffer *)b, 1); |
1917 | else | 1589 | else |
1918 | /* Call videobuf_dqbuf for blocking mode */ | 1590 | /* Call videobuf_dqbuf for blocking mode */ |
1919 | return videobuf_dqbuf(q, (struct v4l2_buffer *)b, 0); | 1591 | ret = videobuf_dqbuf(q, (struct v4l2_buffer *)b, 0); |
1592 | |||
1593 | addr = (unsigned long) vout->buf_phy_addr[vb->i]; | ||
1594 | size = (unsigned long) vb->size; | ||
1595 | dma_unmap_single(vout->vid_dev->v4l2_dev.dev, addr, | ||
1596 | size, DMA_TO_DEVICE); | ||
1597 | return ret; | ||
1920 | } | 1598 | } |
1921 | 1599 | ||
1922 | static int vidioc_streamon(struct file *file, void *fh, enum v4l2_buf_type i) | 1600 | static int vidioc_streamon(struct file *file, void *fh, enum v4l2_buf_type i) |
@@ -1965,7 +1643,8 @@ static int vidioc_streamon(struct file *file, void *fh, enum v4l2_buf_type i) | |||
1965 | addr = (unsigned long) vout->queued_buf_addr[vout->cur_frm->i] | 1643 | addr = (unsigned long) vout->queued_buf_addr[vout->cur_frm->i] |
1966 | + vout->cropped_offset; | 1644 | + vout->cropped_offset; |
1967 | 1645 | ||
1968 | mask = DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD; | 1646 | mask = DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD |
1647 | | DISPC_IRQ_VSYNC2; | ||
1969 | 1648 | ||
1970 | omap_dispc_register_isr(omap_vout_isr, vout, mask); | 1649 | omap_dispc_register_isr(omap_vout_isr, vout, mask); |
1971 | 1650 | ||
@@ -2015,7 +1694,8 @@ static int vidioc_streamoff(struct file *file, void *fh, enum v4l2_buf_type i) | |||
2015 | return -EINVAL; | 1694 | return -EINVAL; |
2016 | 1695 | ||
2017 | vout->streaming = 0; | 1696 | vout->streaming = 0; |
2018 | mask = DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD; | 1697 | mask = DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD |
1698 | | DISPC_IRQ_VSYNC2; | ||
2019 | 1699 | ||
2020 | omap_dispc_unregister_isr(omap_vout_isr, vout, mask); | 1700 | omap_dispc_unregister_isr(omap_vout_isr, vout, mask); |
2021 | 1701 | ||
@@ -2228,7 +1908,8 @@ static int __init omap_vout_setup_video_data(struct omap_vout_device *vout) | |||
2228 | vout->mirror = 0; | 1908 | vout->mirror = 0; |
2229 | vout->control[2].id = V4L2_CID_HFLIP; | 1909 | vout->control[2].id = V4L2_CID_HFLIP; |
2230 | vout->control[2].value = 0; | 1910 | vout->control[2].value = 0; |
2231 | vout->vrfb_bpp = 2; | 1911 | if (vout->vid_info.rotation_type == VOUT_ROT_VRFB) |
1912 | vout->vrfb_bpp = 2; | ||
2232 | 1913 | ||
2233 | control[1].id = V4L2_CID_BG_COLOR; | 1914 | control[1].id = V4L2_CID_BG_COLOR; |
2234 | control[1].value = 0; | 1915 | control[1].value = 0; |
@@ -2260,17 +1941,15 @@ static int __init omap_vout_setup_video_bufs(struct platform_device *pdev, | |||
2260 | int vid_num) | 1941 | int vid_num) |
2261 | { | 1942 | { |
2262 | u32 numbuffers; | 1943 | u32 numbuffers; |
2263 | int ret = 0, i, j; | 1944 | int ret = 0, i; |
2264 | int image_width, image_height; | 1945 | struct omapvideo_info *ovid; |
2265 | struct video_device *vfd; | ||
2266 | struct omap_vout_device *vout; | 1946 | struct omap_vout_device *vout; |
2267 | int static_vrfb_allocation = 0, vrfb_num_bufs = VRFB_NUM_BUFS; | ||
2268 | struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev); | 1947 | struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev); |
2269 | struct omap2video_device *vid_dev = | 1948 | struct omap2video_device *vid_dev = |
2270 | container_of(v4l2_dev, struct omap2video_device, v4l2_dev); | 1949 | container_of(v4l2_dev, struct omap2video_device, v4l2_dev); |
2271 | 1950 | ||
2272 | vout = vid_dev->vouts[vid_num]; | 1951 | vout = vid_dev->vouts[vid_num]; |
2273 | vfd = vout->vfd; | 1952 | ovid = &vout->vid_info; |
2274 | 1953 | ||
2275 | numbuffers = (vid_num == 0) ? video1_numbuffers : video2_numbuffers; | 1954 | numbuffers = (vid_num == 0) ? video1_numbuffers : video2_numbuffers; |
2276 | vout->buffer_size = (vid_num == 0) ? video1_bufsize : video2_bufsize; | 1955 | vout->buffer_size = (vid_num == 0) ? video1_bufsize : video2_bufsize; |
@@ -2287,66 +1966,16 @@ static int __init omap_vout_setup_video_bufs(struct platform_device *pdev, | |||
2287 | } | 1966 | } |
2288 | } | 1967 | } |
2289 | 1968 | ||
2290 | for (i = 0; i < VRFB_NUM_BUFS; i++) { | ||
2291 | if (omap_vrfb_request_ctx(&vout->vrfb_context[i])) { | ||
2292 | dev_info(&pdev->dev, ": VRFB allocation failed\n"); | ||
2293 | for (j = 0; j < i; j++) | ||
2294 | omap_vrfb_release_ctx(&vout->vrfb_context[j]); | ||
2295 | ret = -ENOMEM; | ||
2296 | goto free_buffers; | ||
2297 | } | ||
2298 | } | ||
2299 | vout->cropped_offset = 0; | 1969 | vout->cropped_offset = 0; |
2300 | 1970 | ||
2301 | /* Calculate VRFB memory size */ | 1971 | if (ovid->rotation_type == VOUT_ROT_VRFB) { |
2302 | /* allocate for worst case size */ | 1972 | int static_vrfb_allocation = (vid_num == 0) ? |
2303 | image_width = VID_MAX_WIDTH / TILE_SIZE; | 1973 | vid1_static_vrfb_alloc : vid2_static_vrfb_alloc; |
2304 | if (VID_MAX_WIDTH % TILE_SIZE) | 1974 | ret = omap_vout_setup_vrfb_bufs(pdev, vid_num, |
2305 | image_width++; | 1975 | static_vrfb_allocation); |
2306 | |||
2307 | image_width = image_width * TILE_SIZE; | ||
2308 | image_height = VID_MAX_HEIGHT / TILE_SIZE; | ||
2309 | |||
2310 | if (VID_MAX_HEIGHT % TILE_SIZE) | ||
2311 | image_height++; | ||
2312 | |||
2313 | image_height = image_height * TILE_SIZE; | ||
2314 | vout->smsshado_size = PAGE_ALIGN(image_width * image_height * 2 * 2); | ||
2315 | |||
2316 | /* | ||
2317 | * Request and Initialize DMA, for DMA based VRFB transfer | ||
2318 | */ | ||
2319 | vout->vrfb_dma_tx.dev_id = OMAP_DMA_NO_DEVICE; | ||
2320 | vout->vrfb_dma_tx.dma_ch = -1; | ||
2321 | vout->vrfb_dma_tx.req_status = DMA_CHAN_ALLOTED; | ||
2322 | ret = omap_request_dma(vout->vrfb_dma_tx.dev_id, "VRFB DMA TX", | ||
2323 | omap_vout_vrfb_dma_tx_callback, | ||
2324 | (void *) &vout->vrfb_dma_tx, &vout->vrfb_dma_tx.dma_ch); | ||
2325 | if (ret < 0) { | ||
2326 | vout->vrfb_dma_tx.req_status = DMA_CHAN_NOT_ALLOTED; | ||
2327 | dev_info(&pdev->dev, ": failed to allocate DMA Channel for" | ||
2328 | " video%d\n", vfd->minor); | ||
2329 | } | ||
2330 | init_waitqueue_head(&vout->vrfb_dma_tx.wait); | ||
2331 | |||
2332 | /* Allocate VRFB buffers if selected through bootargs */ | ||
2333 | static_vrfb_allocation = (vid_num == 0) ? | ||
2334 | vid1_static_vrfb_alloc : vid2_static_vrfb_alloc; | ||
2335 | |||
2336 | /* statically allocated the VRFB buffer is done through | ||
2337 | commands line aruments */ | ||
2338 | if (static_vrfb_allocation) { | ||
2339 | if (omap_vout_allocate_vrfb_buffers(vout, &vrfb_num_bufs, -1)) { | ||
2340 | ret = -ENOMEM; | ||
2341 | goto release_vrfb_ctx; | ||
2342 | } | ||
2343 | vout->vrfb_static_allocation = 1; | ||
2344 | } | 1976 | } |
2345 | return 0; | ||
2346 | 1977 | ||
2347 | release_vrfb_ctx: | 1978 | return ret; |
2348 | for (j = 0; j < VRFB_NUM_BUFS; j++) | ||
2349 | omap_vrfb_release_ctx(&vout->vrfb_context[j]); | ||
2350 | 1979 | ||
2351 | free_buffers: | 1980 | free_buffers: |
2352 | for (i = 0; i < numbuffers; i++) { | 1981 | for (i = 0; i < numbuffers; i++) { |
@@ -2389,6 +2018,10 @@ static int __init omap_vout_create_video_devices(struct platform_device *pdev) | |||
2389 | vout->vid_info.num_overlays = 1; | 2018 | vout->vid_info.num_overlays = 1; |
2390 | vout->vid_info.id = k + 1; | 2019 | vout->vid_info.id = k + 1; |
2391 | 2020 | ||
2021 | /* Set VRFB as rotation_type for omap2 and omap3 */ | ||
2022 | if (cpu_is_omap24xx() || cpu_is_omap34xx()) | ||
2023 | vout->vid_info.rotation_type = VOUT_ROT_VRFB; | ||
2024 | |||
2392 | /* Setup the default configuration for the video devices | 2025 | /* Setup the default configuration for the video devices |
2393 | */ | 2026 | */ |
2394 | if (omap_vout_setup_video_data(vout) != 0) { | 2027 | if (omap_vout_setup_video_data(vout) != 0) { |
@@ -2422,7 +2055,8 @@ static int __init omap_vout_create_video_devices(struct platform_device *pdev) | |||
2422 | goto success; | 2055 | goto success; |
2423 | 2056 | ||
2424 | error2: | 2057 | error2: |
2425 | omap_vout_release_vrfb(vout); | 2058 | if (vout->vid_info.rotation_type == VOUT_ROT_VRFB) |
2059 | omap_vout_release_vrfb(vout); | ||
2426 | omap_vout_free_buffers(vout); | 2060 | omap_vout_free_buffers(vout); |
2427 | error1: | 2061 | error1: |
2428 | video_device_release(vfd); | 2062 | video_device_release(vfd); |
@@ -2443,11 +2077,13 @@ success: | |||
2443 | static void omap_vout_cleanup_device(struct omap_vout_device *vout) | 2077 | static void omap_vout_cleanup_device(struct omap_vout_device *vout) |
2444 | { | 2078 | { |
2445 | struct video_device *vfd; | 2079 | struct video_device *vfd; |
2080 | struct omapvideo_info *ovid; | ||
2446 | 2081 | ||
2447 | if (!vout) | 2082 | if (!vout) |
2448 | return; | 2083 | return; |
2449 | 2084 | ||
2450 | vfd = vout->vfd; | 2085 | vfd = vout->vfd; |
2086 | ovid = &vout->vid_info; | ||
2451 | if (vfd) { | 2087 | if (vfd) { |
2452 | if (!video_is_registered(vfd)) { | 2088 | if (!video_is_registered(vfd)) { |
2453 | /* | 2089 | /* |
@@ -2463,14 +2099,15 @@ static void omap_vout_cleanup_device(struct omap_vout_device *vout) | |||
2463 | video_unregister_device(vfd); | 2099 | video_unregister_device(vfd); |
2464 | } | 2100 | } |
2465 | } | 2101 | } |
2466 | 2102 | if (ovid->rotation_type == VOUT_ROT_VRFB) { | |
2467 | omap_vout_release_vrfb(vout); | 2103 | omap_vout_release_vrfb(vout); |
2104 | /* Free the VRFB buffer if allocated | ||
2105 | * init time | ||
2106 | */ | ||
2107 | if (vout->vrfb_static_allocation) | ||
2108 | omap_vout_free_vrfb_buffers(vout); | ||
2109 | } | ||
2468 | omap_vout_free_buffers(vout); | 2110 | omap_vout_free_buffers(vout); |
2469 | /* Free the VRFB buffer if allocated | ||
2470 | * init time | ||
2471 | */ | ||
2472 | if (vout->vrfb_static_allocation) | ||
2473 | omap_vout_free_vrfb_buffers(vout); | ||
2474 | 2111 | ||
2475 | kfree(vout); | 2112 | kfree(vout); |
2476 | } | 2113 | } |