aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/omap
diff options
context:
space:
mode:
authorarchit taneja <archit@ti.com>2011-06-14 02:54:47 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2011-07-27 16:56:06 -0400
commit445e258fa286cb83818b731ef4075a8cc183f2f3 (patch)
treecf76fc42c53bab44c76e012cc8635b01a1ab0017 /drivers/media/video/omap
parentb366888a9020f933bdab8f15f8d4a63e988ce6b3 (diff)
[media] OMAP_VOUT: Create separate file for VRFB related API's
Introduce omap_vout_vrfb.c and omap_vout_vrfb.h, for all VRFB related API's, making OMAP_VOUT driver independent from VRFB. This is required for OMAP4 DSS, since OMAP4 doesn't have VRFB block. Added new enum vout_rotation_type and "rotation_type" member to omapvideo_info, this is initialized based on the arch type in omap_vout_probe. The rotation_type var is now used to choose between vrfb and non-vrfb calls. Signed-off-by: Archit Taneja <archit@ti.com> Signed-off-by: Vaibhav Hiremath <hvaibhav@ti.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/omap')
-rw-r--r--drivers/media/video/omap/Kconfig7
-rw-r--r--drivers/media/video/omap/Makefile1
-rw-r--r--drivers/media/video/omap/omap_vout.c455
-rw-r--r--drivers/media/video/omap/omap_vout_vrfb.c390
-rw-r--r--drivers/media/video/omap/omap_vout_vrfb.h40
-rw-r--r--drivers/media/video/omap/omap_voutdef.h16
6 files changed, 537 insertions, 372 deletions
diff --git a/drivers/media/video/omap/Kconfig b/drivers/media/video/omap/Kconfig
index e63233fd2aaa..390ab094f9f2 100644
--- a/drivers/media/video/omap/Kconfig
+++ b/drivers/media/video/omap/Kconfig
@@ -1,11 +1,14 @@
1config VIDEO_OMAP2_VOUT_VRFB
2 bool
3
1config VIDEO_OMAP2_VOUT 4config VIDEO_OMAP2_VOUT
2 tristate "OMAP2/OMAP3 V4L2-Display driver" 5 tristate "OMAP2/OMAP3 V4L2-Display driver"
3 depends on ARCH_OMAP2 || ARCH_OMAP3 6 depends on ARCH_OMAP2 || ARCH_OMAP3
4 select VIDEOBUF_GEN 7 select VIDEOBUF_GEN
5 select VIDEOBUF_DMA_CONTIG 8 select VIDEOBUF_DMA_CONTIG
6 select OMAP2_DSS 9 select OMAP2_DSS
7 select OMAP2_VRAM 10 select OMAP2_VRFB if ARCH_OMAP2 || ARCH_OMAP3
8 select OMAP2_VRFB 11 select VIDEO_OMAP2_VOUT_VRFB if VIDEO_OMAP2_VOUT && OMAP2_VRFB
9 default n 12 default n
10 ---help--- 13 ---help---
11 V4L2 Display driver support for OMAP2/3 based boards. 14 V4L2 Display driver support for OMAP2/3 based boards.
diff --git a/drivers/media/video/omap/Makefile b/drivers/media/video/omap/Makefile
index b28788070ae1..fc410b438f7d 100644
--- a/drivers/media/video/omap/Makefile
+++ b/drivers/media/video/omap/Makefile
@@ -4,4 +4,5 @@
4 4
5# OMAP2/3 Display driver 5# OMAP2/3 Display driver
6omap-vout-y := omap_vout.o omap_voutlib.o 6omap-vout-y := omap_vout.o omap_voutlib.o
7omap-vout-$(CONFIG_VIDEO_OMAP2_VOUT_VRFB) += omap_vout_vrfb.o
7obj-$(CONFIG_VIDEO_OMAP2_VOUT) += omap-vout.o 8obj-$(CONFIG_VIDEO_OMAP2_VOUT) += omap-vout.o
diff --git a/drivers/media/video/omap/omap_vout.c b/drivers/media/video/omap/omap_vout.c
index 8d69f287ad08..56b22b9356a5 100644
--- a/drivers/media/video/omap/omap_vout.c
+++ b/drivers/media/video/omap/omap_vout.c
@@ -48,6 +48,7 @@
48 48
49#include "omap_voutlib.h" 49#include "omap_voutlib.h"
50#include "omap_voutdef.h" 50#include "omap_voutdef.h"
51#include "omap_vout_vrfb.h"
51 52
52MODULE_AUTHOR("Texas Instruments"); 53MODULE_AUTHOR("Texas Instruments");
53MODULE_DESCRIPTION("OMAP Video for Linux Video out driver"); 54MODULE_DESCRIPTION("OMAP Video for Linux Video out driver");
@@ -143,41 +144,6 @@ static const struct v4l2_fmtdesc omap_formats[] = {
143#define NUM_OUTPUT_FORMATS (ARRAY_SIZE(omap_formats)) 144#define NUM_OUTPUT_FORMATS (ARRAY_SIZE(omap_formats))
144 145
145/* 146/*
146 * Function for allocating video buffers
147 */
148static int omap_vout_allocate_vrfb_buffers(struct omap_vout_device *vout,
149 unsigned int *count, int startindex)
150{
151 int i, j;
152
153 for (i = 0; i < *count; i++) {
154 if (!vout->smsshado_virt_addr[i]) {
155 vout->smsshado_virt_addr[i] =
156 omap_vout_alloc_buffer(vout->smsshado_size,
157 &vout->smsshado_phy_addr[i]);
158 }
159 if (!vout->smsshado_virt_addr[i] && startindex != -1) {
160 if (V4L2_MEMORY_MMAP == vout->memory && i >= startindex)
161 break;
162 }
163 if (!vout->smsshado_virt_addr[i]) {
164 for (j = 0; j < i; j++) {
165 omap_vout_free_buffer(
166 vout->smsshado_virt_addr[j],
167 vout->smsshado_size);
168 vout->smsshado_virt_addr[j] = 0;
169 vout->smsshado_phy_addr[j] = 0;
170 }
171 *count = 0;
172 return -ENOMEM;
173 }
174 memset((void *) vout->smsshado_virt_addr[i], 0,
175 vout->smsshado_size);
176 }
177 return 0;
178}
179
180/*
181 * Try format 147 * Try format
182 */ 148 */
183static int omap_vout_try_format(struct v4l2_pix_format *pix) 149static int omap_vout_try_format(struct v4l2_pix_format *pix)
@@ -270,36 +236,9 @@ static u32 omap_vout_uservirt_to_phys(u32 virtp)
270} 236}
271 237
272/* 238/*
273 * Wakes up the application once the DMA transfer to VRFB space is completed.
274 */
275static void omap_vout_vrfb_dma_tx_callback(int lch, u16 ch_status, void *data)
276{
277 struct vid_vrfb_dma *t = (struct vid_vrfb_dma *) data;
278
279 t->tx_status = 1;
280 wake_up_interruptible(&t->wait);
281}
282
283/*
284 * Release the VRFB context once the module exits
285 */
286static void omap_vout_release_vrfb(struct omap_vout_device *vout)
287{
288 int i;
289
290 for (i = 0; i < VRFB_NUM_BUFS; i++)
291 omap_vrfb_release_ctx(&vout->vrfb_context[i]);
292
293 if (vout->vrfb_dma_tx.req_status == DMA_CHAN_ALLOTED) {
294 vout->vrfb_dma_tx.req_status = DMA_CHAN_NOT_ALLOTED;
295 omap_free_dma(vout->vrfb_dma_tx.dma_ch);
296 }
297}
298
299/*
300 * Free the V4L2 buffers 239 * Free the V4L2 buffers
301 */ 240 */
302static void omap_vout_free_buffers(struct omap_vout_device *vout) 241void omap_vout_free_buffers(struct omap_vout_device *vout)
303{ 242{
304 int i, numbuffers; 243 int i, numbuffers;
305 244
@@ -316,52 +255,6 @@ static void omap_vout_free_buffers(struct omap_vout_device *vout)
316} 255}
317 256
318/* 257/*
319 * Free VRFB buffers
320 */
321static void omap_vout_free_vrfb_buffers(struct omap_vout_device *vout)
322{
323 int j;
324
325 for (j = 0; j < VRFB_NUM_BUFS; j++) {
326 omap_vout_free_buffer(vout->smsshado_virt_addr[j],
327 vout->smsshado_size);
328 vout->smsshado_virt_addr[j] = 0;
329 vout->smsshado_phy_addr[j] = 0;
330 }
331}
332
333/*
334 * Allocate the buffers for the VRFB space. Data is copied from V4L2
335 * buffers to the VRFB buffers using the DMA engine.
336 */
337static int omap_vout_vrfb_buffer_setup(struct omap_vout_device *vout,
338 unsigned int *count, unsigned int startindex)
339{
340 int i;
341 bool yuv_mode;
342
343 /* Allocate the VRFB buffers only if the buffers are not
344 * allocated during init time.
345 */
346 if ((is_rotation_enabled(vout)) && !vout->vrfb_static_allocation)
347 if (omap_vout_allocate_vrfb_buffers(vout, count, startindex))
348 return -ENOMEM;
349
350 if (vout->dss_mode == OMAP_DSS_COLOR_YUV2 ||
351 vout->dss_mode == OMAP_DSS_COLOR_UYVY)
352 yuv_mode = true;
353 else
354 yuv_mode = false;
355
356 for (i = 0; i < *count; i++)
357 omap_vrfb_setup(&vout->vrfb_context[i],
358 vout->smsshado_phy_addr[i], vout->pix.width,
359 vout->pix.height, vout->bpp, yuv_mode);
360
361 return 0;
362}
363
364/*
365 * Convert V4L2 rotation to DSS rotation 258 * Convert V4L2 rotation to DSS rotation
366 * V4L2 understand 0, 90, 180, 270. 259 * V4L2 understand 0, 90, 180, 270.
367 * Convert to 0, 1, 2 and 3 respectively for DSS 260 * Convert to 0, 1, 2 and 3 respectively for DSS
@@ -390,124 +283,38 @@ static int v4l2_rot_to_dss_rot(int v4l2_rotation,
390 return ret; 283 return ret;
391} 284}
392 285
393/*
394 * Calculate the buffer offsets from which the streaming should
395 * start. This offset calculation is mainly required because of
396 * the VRFB 32 pixels alignment with rotation.
397 */
398static int omap_vout_calculate_offset(struct omap_vout_device *vout) 286static int omap_vout_calculate_offset(struct omap_vout_device *vout)
399{ 287{
400 struct omap_overlay *ovl;
401 enum dss_rotation rotation;
402 struct omapvideo_info *ovid; 288 struct omapvideo_info *ovid;
403 bool mirroring = vout->mirror;
404 struct omap_dss_device *cur_display;
405 struct v4l2_rect *crop = &vout->crop; 289 struct v4l2_rect *crop = &vout->crop;
406 struct v4l2_pix_format *pix = &vout->pix; 290 struct v4l2_pix_format *pix = &vout->pix;
407 int *cropped_offset = &vout->cropped_offset; 291 int *cropped_offset = &vout->cropped_offset;
408 int vr_ps = 1, ps = 2, temp_ps = 2; 292 int ps = 2, line_length = 0;
409 int offset = 0, ctop = 0, cleft = 0, line_length = 0;
410 293
411 ovid = &vout->vid_info; 294 ovid = &vout->vid_info;
412 ovl = ovid->overlays[0];
413 /* get the display device attached to the overlay */
414 if (!ovl->manager || !ovl->manager->device)
415 return -1;
416 295
417 cur_display = ovl->manager->device; 296 if (ovid->rotation_type == VOUT_ROT_VRFB) {
418 rotation = calc_rotation(vout); 297 omap_vout_calculate_vrfb_offset(vout);
298 } else {
299 vout->line_length = line_length = pix->width;
419 300
420 if (V4L2_PIX_FMT_YUYV == pix->pixelformat || 301 if (V4L2_PIX_FMT_YUYV == pix->pixelformat ||
421 V4L2_PIX_FMT_UYVY == pix->pixelformat) { 302 V4L2_PIX_FMT_UYVY == pix->pixelformat)
422 if (is_rotation_enabled(vout)) { 303 ps = 2;
423 /* 304 else if (V4L2_PIX_FMT_RGB32 == pix->pixelformat)
424 * ps - Actual pixel size for YUYV/UYVY for
425 * VRFB/Mirroring is 4 bytes
426 * vr_ps - Virtually pixel size for YUYV/UYVY is
427 * 2 bytes
428 */
429 ps = 4; 305 ps = 4;
430 vr_ps = 2; 306 else if (V4L2_PIX_FMT_RGB24 == pix->pixelformat)
431 } else { 307 ps = 3;
432 ps = 2; /* otherwise the pixel size is 2 byte */
433 }
434 } else if (V4L2_PIX_FMT_RGB32 == pix->pixelformat) {
435 ps = 4;
436 } else if (V4L2_PIX_FMT_RGB24 == pix->pixelformat) {
437 ps = 3;
438 }
439 vout->ps = ps;
440 vout->vr_ps = vr_ps;
441
442 if (is_rotation_enabled(vout)) {
443 line_length = MAX_PIXELS_PER_LINE;
444 ctop = (pix->height - crop->height) - crop->top;
445 cleft = (pix->width - crop->width) - crop->left;
446 } else {
447 line_length = pix->width;
448 }
449 vout->line_length = line_length;
450 switch (rotation) {
451 case dss_rotation_90_degree:
452 offset = vout->vrfb_context[0].yoffset *
453 vout->vrfb_context[0].bytespp;
454 temp_ps = ps / vr_ps;
455 if (mirroring == 0) {
456 *cropped_offset = offset + line_length *
457 temp_ps * cleft + crop->top * temp_ps;
458 } else {
459 *cropped_offset = offset + line_length * temp_ps *
460 cleft + crop->top * temp_ps + (line_length *
461 ((crop->width / (vr_ps)) - 1) * ps);
462 }
463 break;
464 case dss_rotation_180_degree:
465 offset = ((MAX_PIXELS_PER_LINE * vout->vrfb_context[0].yoffset *
466 vout->vrfb_context[0].bytespp) +
467 (vout->vrfb_context[0].xoffset *
468 vout->vrfb_context[0].bytespp));
469 if (mirroring == 0) {
470 *cropped_offset = offset + (line_length * ps * ctop) +
471 (cleft / vr_ps) * ps;
472 308
473 } else { 309 vout->ps = ps;
474 *cropped_offset = offset + (line_length * ps * ctop) + 310
475 (cleft / vr_ps) * ps + (line_length * 311 *cropped_offset = (line_length * ps) *
476 (crop->height - 1) * ps); 312 crop->top + crop->left * ps;
477 }
478 break;
479 case dss_rotation_270_degree:
480 offset = MAX_PIXELS_PER_LINE * vout->vrfb_context[0].xoffset *
481 vout->vrfb_context[0].bytespp;
482 temp_ps = ps / vr_ps;
483 if (mirroring == 0) {
484 *cropped_offset = offset + line_length *
485 temp_ps * crop->left + ctop * ps;
486 } else {
487 *cropped_offset = offset + line_length *
488 temp_ps * crop->left + ctop * ps +
489 (line_length * ((crop->width / vr_ps) - 1) *
490 ps);
491 }
492 break;
493 case dss_rotation_0_degree:
494 if (mirroring == 0) {
495 *cropped_offset = (line_length * ps) *
496 crop->top + (crop->left / vr_ps) * ps;
497 } else {
498 *cropped_offset = (line_length * ps) *
499 crop->top + (crop->left / vr_ps) * ps +
500 (line_length * (crop->height - 1) * ps);
501 }
502 break;
503 default:
504 *cropped_offset = (line_length * ps * crop->top) /
505 vr_ps + (crop->left * ps) / vr_ps +
506 ((crop->width / vr_ps) - 1) * ps;
507 break;
508 } 313 }
314
509 v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev, "%s Offset:%x\n", 315 v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev, "%s Offset:%x\n",
510 __func__, *cropped_offset); 316 __func__, vout->cropped_offset);
317
511 return 0; 318 return 0;
512} 319}
513 320
@@ -845,6 +652,7 @@ static int omap_vout_buffer_setup(struct videobuf_queue *q, unsigned int *count,
845 int startindex = 0, i, j; 652 int startindex = 0, i, j;
846 u32 phy_addr = 0, virt_addr = 0; 653 u32 phy_addr = 0, virt_addr = 0;
847 struct omap_vout_device *vout = q->priv_data; 654 struct omap_vout_device *vout = q->priv_data;
655 struct omapvideo_info *ovid = &vout->vid_info;
848 656
849 if (!vout) 657 if (!vout)
850 return -EINVAL; 658 return -EINVAL;
@@ -857,13 +665,10 @@ static int omap_vout_buffer_setup(struct videobuf_queue *q, unsigned int *count,
857 if (V4L2_MEMORY_MMAP == vout->memory && *count < startindex) 665 if (V4L2_MEMORY_MMAP == vout->memory && *count < startindex)
858 *count = startindex; 666 *count = startindex;
859 667
860 if ((is_rotation_enabled(vout)) && *count > VRFB_NUM_BUFS) 668 if (ovid->rotation_type == VOUT_ROT_VRFB) {
861 *count = VRFB_NUM_BUFS;
862
863 /* If rotation is enabled, allocate memory for VRFB space also */
864 if (is_rotation_enabled(vout))
865 if (omap_vout_vrfb_buffer_setup(vout, count, startindex)) 669 if (omap_vout_vrfb_buffer_setup(vout, count, startindex))
866 return -ENOMEM; 670 return -ENOMEM;
671 }
867 672
868 if (V4L2_MEMORY_MMAP != vout->memory) 673 if (V4L2_MEMORY_MMAP != vout->memory)
869 return 0; 674 return 0;
@@ -887,8 +692,11 @@ static int omap_vout_buffer_setup(struct videobuf_queue *q, unsigned int *count,
887 virt_addr = omap_vout_alloc_buffer(vout->buffer_size, 692 virt_addr = omap_vout_alloc_buffer(vout->buffer_size,
888 &phy_addr); 693 &phy_addr);
889 if (!virt_addr) { 694 if (!virt_addr) {
890 if (!is_rotation_enabled(vout)) 695 if (ovid->rotation_type == VOUT_ROT_NONE) {
891 break; 696 break;
697 } else {
698 if (!is_rotation_enabled(vout))
699 break;
892 /* Free the VRFB buffers if no space for V4L2 buffers */ 700 /* Free the VRFB buffers if no space for V4L2 buffers */
893 for (j = i; j < *count; j++) { 701 for (j = i; j < *count; j++) {
894 omap_vout_free_buffer( 702 omap_vout_free_buffer(
@@ -896,6 +704,7 @@ static int omap_vout_buffer_setup(struct videobuf_queue *q, unsigned int *count,
896 vout->smsshado_size); 704 vout->smsshado_size);
897 vout->smsshado_virt_addr[j] = 0; 705 vout->smsshado_virt_addr[j] = 0;
898 vout->smsshado_phy_addr[j] = 0; 706 vout->smsshado_phy_addr[j] = 0;
707 }
899 } 708 }
900 } 709 }
901 vout->buf_virt_addr[i] = virt_addr; 710 vout->buf_virt_addr[i] = virt_addr;
@@ -908,9 +717,9 @@ static int omap_vout_buffer_setup(struct videobuf_queue *q, unsigned int *count,
908 717
909/* 718/*
910 * Free the V4L2 buffers additionally allocated than default 719 * Free the V4L2 buffers additionally allocated than default
911 * number of buffers and free all the VRFB buffers 720 * number of buffers
912 */ 721 */
913static void omap_vout_free_allbuffers(struct omap_vout_device *vout) 722static void omap_vout_free_extra_buffers(struct omap_vout_device *vout)
914{ 723{
915 int num_buffers = 0, i; 724 int num_buffers = 0, i;
916 725
@@ -925,20 +734,6 @@ static void omap_vout_free_allbuffers(struct omap_vout_device *vout)
925 vout->buf_virt_addr[i] = 0; 734 vout->buf_virt_addr[i] = 0;
926 vout->buf_phy_addr[i] = 0; 735 vout->buf_phy_addr[i] = 0;
927 } 736 }
928 /* Free the VRFB buffers only if they are allocated
929 * during reqbufs. Don't free if init time allocated
930 */
931 if (!vout->vrfb_static_allocation) {
932 for (i = 0; i < VRFB_NUM_BUFS; i++) {
933 if (vout->smsshado_virt_addr[i]) {
934 omap_vout_free_buffer(
935 vout->smsshado_virt_addr[i],
936 vout->smsshado_size);
937 vout->smsshado_virt_addr[i] = 0;
938 vout->smsshado_phy_addr[i] = 0;
939 }
940 }
941 }
942 vout->buffer_allocated = num_buffers; 737 vout->buffer_allocated = num_buffers;
943} 738}
944 739
@@ -950,16 +745,11 @@ static void omap_vout_free_allbuffers(struct omap_vout_device *vout)
950 * buffer into VRFB memory space before giving it to the DSS. 745 * buffer into VRFB memory space before giving it to the DSS.
951 */ 746 */
952static int omap_vout_buffer_prepare(struct videobuf_queue *q, 747static int omap_vout_buffer_prepare(struct videobuf_queue *q,
953 struct videobuf_buffer *vb, 748 struct videobuf_buffer *vb,
954 enum v4l2_field field) 749 enum v4l2_field field)
955{ 750{
956 dma_addr_t dmabuf;
957 struct vid_vrfb_dma *tx;
958 enum dss_rotation rotation;
959 struct omap_vout_device *vout = q->priv_data; 751 struct omap_vout_device *vout = q->priv_data;
960 u32 dest_frame_index = 0, src_element_index = 0; 752 struct omapvideo_info *ovid = &vout->vid_info;
961 u32 dest_element_index = 0, src_frame_index = 0;
962 u32 elem_count = 0, frame_count = 0, pixsize = 2;
963 753
964 if (VIDEOBUF_NEEDS_INIT == vb->state) { 754 if (VIDEOBUF_NEEDS_INIT == vb->state) {
965 vb->width = vout->pix.width; 755 vb->width = vout->pix.width;
@@ -981,63 +771,10 @@ static int omap_vout_buffer_prepare(struct videobuf_queue *q,
981 vout->queued_buf_addr[vb->i] = (u8 *)vout->buf_phy_addr[vb->i]; 771 vout->queued_buf_addr[vb->i] = (u8 *)vout->buf_phy_addr[vb->i];
982 } 772 }
983 773
984 if (!is_rotation_enabled(vout)) 774 if (ovid->rotation_type == VOUT_ROT_VRFB)
775 return omap_vout_prepare_vrfb(vout, vb);
776 else
985 return 0; 777 return 0;
986
987 dmabuf = vout->buf_phy_addr[vb->i];
988 /* If rotation is enabled, copy input buffer into VRFB
989 * memory space using DMA. We are copying input buffer
990 * into VRFB memory space of desired angle and DSS will
991 * read image VRFB memory for 0 degree angle
992 */
993 pixsize = vout->bpp * vout->vrfb_bpp;
994 /*
995 * DMA transfer in double index mode
996 */
997
998 /* Frame index */
999 dest_frame_index = ((MAX_PIXELS_PER_LINE * pixsize) -
1000 (vout->pix.width * vout->bpp)) + 1;
1001
1002 /* Source and destination parameters */
1003 src_element_index = 0;
1004 src_frame_index = 0;
1005 dest_element_index = 1;
1006 /* Number of elements per frame */
1007 elem_count = vout->pix.width * vout->bpp;
1008 frame_count = vout->pix.height;
1009 tx = &vout->vrfb_dma_tx;
1010 tx->tx_status = 0;
1011 omap_set_dma_transfer_params(tx->dma_ch, OMAP_DMA_DATA_TYPE_S32,
1012 (elem_count / 4), frame_count, OMAP_DMA_SYNC_ELEMENT,
1013 tx->dev_id, 0x0);
1014 /* src_port required only for OMAP1 */
1015 omap_set_dma_src_params(tx->dma_ch, 0, OMAP_DMA_AMODE_POST_INC,
1016 dmabuf, src_element_index, src_frame_index);
1017 /*set dma source burst mode for VRFB */
1018 omap_set_dma_src_burst_mode(tx->dma_ch, OMAP_DMA_DATA_BURST_16);
1019 rotation = calc_rotation(vout);
1020
1021 /* dest_port required only for OMAP1 */
1022 omap_set_dma_dest_params(tx->dma_ch, 0, OMAP_DMA_AMODE_DOUBLE_IDX,
1023 vout->vrfb_context[vb->i].paddr[0], dest_element_index,
1024 dest_frame_index);
1025 /*set dma dest burst mode for VRFB */
1026 omap_set_dma_dest_burst_mode(tx->dma_ch, OMAP_DMA_DATA_BURST_16);
1027 omap_dma_set_global_params(DMA_DEFAULT_ARB_RATE, 0x20, 0);
1028
1029 omap_start_dma(tx->dma_ch);
1030 interruptible_sleep_on_timeout(&tx->wait, VRFB_TX_TIMEOUT);
1031
1032 if (tx->tx_status == 0) {
1033 omap_stop_dma(tx->dma_ch);
1034 return -EINVAL;
1035 }
1036 /* Store buffers physical address into an array. Addresses
1037 * from this array will be used to configure DSS */
1038 vout->queued_buf_addr[vb->i] = (u8 *)
1039 vout->vrfb_context[vb->i].paddr[rotation];
1040 return 0;
1041} 778}
1042 779
1043/* 780/*
@@ -1189,7 +926,15 @@ static int omap_vout_release(struct file *file)
1189 "Unable to apply changes\n"); 926 "Unable to apply changes\n");
1190 927
1191 /* Free all buffers */ 928 /* Free all buffers */
1192 omap_vout_free_allbuffers(vout); 929 omap_vout_free_extra_buffers(vout);
930
931 /* Free the VRFB buffers only if they are allocated
932 * during reqbufs. Don't free if init time allocated
933 */
934 if (ovid->rotation_type == VOUT_ROT_VRFB) {
935 if (!vout->vrfb_static_allocation)
936 omap_vout_free_vrfb_buffers(vout);
937 }
1193 videobuf_mmap_free(q); 938 videobuf_mmap_free(q);
1194 939
1195 /* Even if apply changes fails we should continue 940 /* Even if apply changes fails we should continue
@@ -1616,9 +1361,17 @@ static int vidioc_s_ctrl(struct file *file, void *fh, struct v4l2_control *a)
1616 switch (a->id) { 1361 switch (a->id) {
1617 case V4L2_CID_ROTATE: 1362 case V4L2_CID_ROTATE:
1618 { 1363 {
1364 struct omapvideo_info *ovid;
1619 int rotation = a->value; 1365 int rotation = a->value;
1620 1366
1367 ovid = &vout->vid_info;
1368
1621 mutex_lock(&vout->lock); 1369 mutex_lock(&vout->lock);
1370 if (rotation && ovid->rotation_type == VOUT_ROT_NONE) {
1371 mutex_unlock(&vout->lock);
1372 ret = -ERANGE;
1373 break;
1374 }
1622 1375
1623 if (rotation && vout->pix.pixelformat == V4L2_PIX_FMT_RGB24) { 1376 if (rotation && vout->pix.pixelformat == V4L2_PIX_FMT_RGB24) {
1624 mutex_unlock(&vout->lock); 1377 mutex_unlock(&vout->lock);
@@ -1674,6 +1427,11 @@ static int vidioc_s_ctrl(struct file *file, void *fh, struct v4l2_control *a)
1674 ovl = ovid->overlays[0]; 1427 ovl = ovid->overlays[0];
1675 1428
1676 mutex_lock(&vout->lock); 1429 mutex_lock(&vout->lock);
1430 if (mirror && ovid->rotation_type == VOUT_ROT_NONE) {
1431 mutex_unlock(&vout->lock);
1432 ret = -ERANGE;
1433 break;
1434 }
1677 1435
1678 if (mirror && vout->pix.pixelformat == V4L2_PIX_FMT_RGB24) { 1436 if (mirror && vout->pix.pixelformat == V4L2_PIX_FMT_RGB24) {
1679 mutex_unlock(&vout->lock); 1437 mutex_unlock(&vout->lock);
@@ -2119,7 +1877,8 @@ static int __init omap_vout_setup_video_data(struct omap_vout_device *vout)
2119 vout->mirror = 0; 1877 vout->mirror = 0;
2120 vout->control[2].id = V4L2_CID_HFLIP; 1878 vout->control[2].id = V4L2_CID_HFLIP;
2121 vout->control[2].value = 0; 1879 vout->control[2].value = 0;
2122 vout->vrfb_bpp = 2; 1880 if (vout->vid_info.rotation_type == VOUT_ROT_VRFB)
1881 vout->vrfb_bpp = 2;
2123 1882
2124 control[1].id = V4L2_CID_BG_COLOR; 1883 control[1].id = V4L2_CID_BG_COLOR;
2125 control[1].value = 0; 1884 control[1].value = 0;
@@ -2151,17 +1910,15 @@ static int __init omap_vout_setup_video_bufs(struct platform_device *pdev,
2151 int vid_num) 1910 int vid_num)
2152{ 1911{
2153 u32 numbuffers; 1912 u32 numbuffers;
2154 int ret = 0, i, j; 1913 int ret = 0, i;
2155 int image_width, image_height; 1914 struct omapvideo_info *ovid;
2156 struct video_device *vfd;
2157 struct omap_vout_device *vout; 1915 struct omap_vout_device *vout;
2158 int static_vrfb_allocation = 0, vrfb_num_bufs = VRFB_NUM_BUFS;
2159 struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev); 1916 struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev);
2160 struct omap2video_device *vid_dev = 1917 struct omap2video_device *vid_dev =
2161 container_of(v4l2_dev, struct omap2video_device, v4l2_dev); 1918 container_of(v4l2_dev, struct omap2video_device, v4l2_dev);
2162 1919
2163 vout = vid_dev->vouts[vid_num]; 1920 vout = vid_dev->vouts[vid_num];
2164 vfd = vout->vfd; 1921 ovid = &vout->vid_info;
2165 1922
2166 numbuffers = (vid_num == 0) ? video1_numbuffers : video2_numbuffers; 1923 numbuffers = (vid_num == 0) ? video1_numbuffers : video2_numbuffers;
2167 vout->buffer_size = (vid_num == 0) ? video1_bufsize : video2_bufsize; 1924 vout->buffer_size = (vid_num == 0) ? video1_bufsize : video2_bufsize;
@@ -2178,66 +1935,16 @@ static int __init omap_vout_setup_video_bufs(struct platform_device *pdev,
2178 } 1935 }
2179 } 1936 }
2180 1937
2181 for (i = 0; i < VRFB_NUM_BUFS; i++) {
2182 if (omap_vrfb_request_ctx(&vout->vrfb_context[i])) {
2183 dev_info(&pdev->dev, ": VRFB allocation failed\n");
2184 for (j = 0; j < i; j++)
2185 omap_vrfb_release_ctx(&vout->vrfb_context[j]);
2186 ret = -ENOMEM;
2187 goto free_buffers;
2188 }
2189 }
2190 vout->cropped_offset = 0; 1938 vout->cropped_offset = 0;
2191 1939
2192 /* Calculate VRFB memory size */ 1940 if (ovid->rotation_type == VOUT_ROT_VRFB) {
2193 /* allocate for worst case size */ 1941 int static_vrfb_allocation = (vid_num == 0) ?
2194 image_width = VID_MAX_WIDTH / TILE_SIZE; 1942 vid1_static_vrfb_alloc : vid2_static_vrfb_alloc;
2195 if (VID_MAX_WIDTH % TILE_SIZE) 1943 ret = omap_vout_setup_vrfb_bufs(pdev, vid_num,
2196 image_width++; 1944 static_vrfb_allocation);
2197
2198 image_width = image_width * TILE_SIZE;
2199 image_height = VID_MAX_HEIGHT / TILE_SIZE;
2200
2201 if (VID_MAX_HEIGHT % TILE_SIZE)
2202 image_height++;
2203
2204 image_height = image_height * TILE_SIZE;
2205 vout->smsshado_size = PAGE_ALIGN(image_width * image_height * 2 * 2);
2206
2207 /*
2208 * Request and Initialize DMA, for DMA based VRFB transfer
2209 */
2210 vout->vrfb_dma_tx.dev_id = OMAP_DMA_NO_DEVICE;
2211 vout->vrfb_dma_tx.dma_ch = -1;
2212 vout->vrfb_dma_tx.req_status = DMA_CHAN_ALLOTED;
2213 ret = omap_request_dma(vout->vrfb_dma_tx.dev_id, "VRFB DMA TX",
2214 omap_vout_vrfb_dma_tx_callback,
2215 (void *) &vout->vrfb_dma_tx, &vout->vrfb_dma_tx.dma_ch);
2216 if (ret < 0) {
2217 vout->vrfb_dma_tx.req_status = DMA_CHAN_NOT_ALLOTED;
2218 dev_info(&pdev->dev, ": failed to allocate DMA Channel for"
2219 " video%d\n", vfd->minor);
2220 }
2221 init_waitqueue_head(&vout->vrfb_dma_tx.wait);
2222
2223 /* Allocate VRFB buffers if selected through bootargs */
2224 static_vrfb_allocation = (vid_num == 0) ?
2225 vid1_static_vrfb_alloc : vid2_static_vrfb_alloc;
2226
2227 /* statically allocated the VRFB buffer is done through
2228 commands line aruments */
2229 if (static_vrfb_allocation) {
2230 if (omap_vout_allocate_vrfb_buffers(vout, &vrfb_num_bufs, -1)) {
2231 ret = -ENOMEM;
2232 goto release_vrfb_ctx;
2233 }
2234 vout->vrfb_static_allocation = 1;
2235 } 1945 }
2236 return 0;
2237 1946
2238release_vrfb_ctx: 1947 return ret;
2239 for (j = 0; j < VRFB_NUM_BUFS; j++)
2240 omap_vrfb_release_ctx(&vout->vrfb_context[j]);
2241 1948
2242free_buffers: 1949free_buffers:
2243 for (i = 0; i < numbuffers; i++) { 1950 for (i = 0; i < numbuffers; i++) {
@@ -2280,6 +1987,10 @@ static int __init omap_vout_create_video_devices(struct platform_device *pdev)
2280 vout->vid_info.num_overlays = 1; 1987 vout->vid_info.num_overlays = 1;
2281 vout->vid_info.id = k + 1; 1988 vout->vid_info.id = k + 1;
2282 1989
1990 /* Set VRFB as rotation_type for omap2 and omap3 */
1991 if (cpu_is_omap24xx() || cpu_is_omap34xx())
1992 vout->vid_info.rotation_type = VOUT_ROT_VRFB;
1993
2283 /* Setup the default configuration for the video devices 1994 /* Setup the default configuration for the video devices
2284 */ 1995 */
2285 if (omap_vout_setup_video_data(vout) != 0) { 1996 if (omap_vout_setup_video_data(vout) != 0) {
@@ -2313,7 +2024,8 @@ static int __init omap_vout_create_video_devices(struct platform_device *pdev)
2313 goto success; 2024 goto success;
2314 2025
2315error2: 2026error2:
2316 omap_vout_release_vrfb(vout); 2027 if (vout->vid_info.rotation_type == VOUT_ROT_VRFB)
2028 omap_vout_release_vrfb(vout);
2317 omap_vout_free_buffers(vout); 2029 omap_vout_free_buffers(vout);
2318error1: 2030error1:
2319 video_device_release(vfd); 2031 video_device_release(vfd);
@@ -2334,11 +2046,13 @@ success:
2334static void omap_vout_cleanup_device(struct omap_vout_device *vout) 2046static void omap_vout_cleanup_device(struct omap_vout_device *vout)
2335{ 2047{
2336 struct video_device *vfd; 2048 struct video_device *vfd;
2049 struct omapvideo_info *ovid;
2337 2050
2338 if (!vout) 2051 if (!vout)
2339 return; 2052 return;
2340 2053
2341 vfd = vout->vfd; 2054 vfd = vout->vfd;
2055 ovid = &vout->vid_info;
2342 if (vfd) { 2056 if (vfd) {
2343 if (!video_is_registered(vfd)) { 2057 if (!video_is_registered(vfd)) {
2344 /* 2058 /*
@@ -2354,14 +2068,15 @@ static void omap_vout_cleanup_device(struct omap_vout_device *vout)
2354 video_unregister_device(vfd); 2068 video_unregister_device(vfd);
2355 } 2069 }
2356 } 2070 }
2357 2071 if (ovid->rotation_type == VOUT_ROT_VRFB) {
2358 omap_vout_release_vrfb(vout); 2072 omap_vout_release_vrfb(vout);
2073 /* Free the VRFB buffer if allocated
2074 * init time
2075 */
2076 if (vout->vrfb_static_allocation)
2077 omap_vout_free_vrfb_buffers(vout);
2078 }
2359 omap_vout_free_buffers(vout); 2079 omap_vout_free_buffers(vout);
2360 /* Free the VRFB buffer if allocated
2361 * init time
2362 */
2363 if (vout->vrfb_static_allocation)
2364 omap_vout_free_vrfb_buffers(vout);
2365 2080
2366 kfree(vout); 2081 kfree(vout);
2367} 2082}
diff --git a/drivers/media/video/omap/omap_vout_vrfb.c b/drivers/media/video/omap/omap_vout_vrfb.c
new file mode 100644
index 000000000000..ebebcac49225
--- /dev/null
+++ b/drivers/media/video/omap/omap_vout_vrfb.c
@@ -0,0 +1,390 @@
1/*
2 * omap_vout_vrfb.c
3 *
4 * Copyright (C) 2010 Texas Instruments.
5 *
6 * This file is licensed under the terms of the GNU General Public License
7 * version 2. This program is licensed "as is" without any warranty of any
8 * kind, whether express or implied.
9 *
10 */
11
12#include <linux/sched.h>
13#include <linux/platform_device.h>
14#include <linux/videodev2.h>
15
16#include <media/videobuf-dma-contig.h>
17#include <media/v4l2-device.h>
18
19#include <plat/dma.h>
20#include <plat/vrfb.h>
21
22#include "omap_voutdef.h"
23#include "omap_voutlib.h"
24
25/*
26 * Function for allocating video buffers
27 */
28static int omap_vout_allocate_vrfb_buffers(struct omap_vout_device *vout,
29 unsigned int *count, int startindex)
30{
31 int i, j;
32
33 for (i = 0; i < *count; i++) {
34 if (!vout->smsshado_virt_addr[i]) {
35 vout->smsshado_virt_addr[i] =
36 omap_vout_alloc_buffer(vout->smsshado_size,
37 &vout->smsshado_phy_addr[i]);
38 }
39 if (!vout->smsshado_virt_addr[i] && startindex != -1) {
40 if (V4L2_MEMORY_MMAP == vout->memory && i >= startindex)
41 break;
42 }
43 if (!vout->smsshado_virt_addr[i]) {
44 for (j = 0; j < i; j++) {
45 omap_vout_free_buffer(
46 vout->smsshado_virt_addr[j],
47 vout->smsshado_size);
48 vout->smsshado_virt_addr[j] = 0;
49 vout->smsshado_phy_addr[j] = 0;
50 }
51 *count = 0;
52 return -ENOMEM;
53 }
54 memset((void *) vout->smsshado_virt_addr[i], 0,
55 vout->smsshado_size);
56 }
57 return 0;
58}
59
60/*
61 * Wakes up the application once the DMA transfer to VRFB space is completed.
62 */
63static void omap_vout_vrfb_dma_tx_callback(int lch, u16 ch_status, void *data)
64{
65 struct vid_vrfb_dma *t = (struct vid_vrfb_dma *) data;
66
67 t->tx_status = 1;
68 wake_up_interruptible(&t->wait);
69}
70
71/*
72 * Free VRFB buffers
73 */
74void omap_vout_free_vrfb_buffers(struct omap_vout_device *vout)
75{
76 int j;
77
78 for (j = 0; j < VRFB_NUM_BUFS; j++) {
79 omap_vout_free_buffer(vout->smsshado_virt_addr[j],
80 vout->smsshado_size);
81 vout->smsshado_virt_addr[j] = 0;
82 vout->smsshado_phy_addr[j] = 0;
83 }
84}
85
86int omap_vout_setup_vrfb_bufs(struct platform_device *pdev, int vid_num,
87 u32 static_vrfb_allocation)
88{
89 int ret = 0, i, j;
90 struct omap_vout_device *vout;
91 struct video_device *vfd;
92 int image_width, image_height;
93 int vrfb_num_bufs = VRFB_NUM_BUFS;
94 struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev);
95 struct omap2video_device *vid_dev =
96 container_of(v4l2_dev, struct omap2video_device, v4l2_dev);
97
98 vout = vid_dev->vouts[vid_num];
99 vfd = vout->vfd;
100
101 for (i = 0; i < VRFB_NUM_BUFS; i++) {
102 if (omap_vrfb_request_ctx(&vout->vrfb_context[i])) {
103 dev_info(&pdev->dev, ": VRFB allocation failed\n");
104 for (j = 0; j < i; j++)
105 omap_vrfb_release_ctx(&vout->vrfb_context[j]);
106 ret = -ENOMEM;
107 goto free_buffers;
108 }
109 }
110
111 /* Calculate VRFB memory size */
112 /* allocate for worst case size */
113 image_width = VID_MAX_WIDTH / TILE_SIZE;
114 if (VID_MAX_WIDTH % TILE_SIZE)
115 image_width++;
116
117 image_width = image_width * TILE_SIZE;
118 image_height = VID_MAX_HEIGHT / TILE_SIZE;
119
120 if (VID_MAX_HEIGHT % TILE_SIZE)
121 image_height++;
122
123 image_height = image_height * TILE_SIZE;
124 vout->smsshado_size = PAGE_ALIGN(image_width * image_height * 2 * 2);
125
126 /*
127 * Request and Initialize DMA, for DMA based VRFB transfer
128 */
129 vout->vrfb_dma_tx.dev_id = OMAP_DMA_NO_DEVICE;
130 vout->vrfb_dma_tx.dma_ch = -1;
131 vout->vrfb_dma_tx.req_status = DMA_CHAN_ALLOTED;
132 ret = omap_request_dma(vout->vrfb_dma_tx.dev_id, "VRFB DMA TX",
133 omap_vout_vrfb_dma_tx_callback,
134 (void *) &vout->vrfb_dma_tx, &vout->vrfb_dma_tx.dma_ch);
135 if (ret < 0) {
136 vout->vrfb_dma_tx.req_status = DMA_CHAN_NOT_ALLOTED;
137 dev_info(&pdev->dev, ": failed to allocate DMA Channel for"
138 " video%d\n", vfd->minor);
139 }
140 init_waitqueue_head(&vout->vrfb_dma_tx.wait);
141
142 /* statically allocated the VRFB buffer is done through
143 commands line aruments */
144 if (static_vrfb_allocation) {
145 if (omap_vout_allocate_vrfb_buffers(vout, &vrfb_num_bufs, -1)) {
146 ret = -ENOMEM;
147 goto release_vrfb_ctx;
148 }
149 vout->vrfb_static_allocation = 1;
150 }
151 return 0;
152
153release_vrfb_ctx:
154 for (j = 0; j < VRFB_NUM_BUFS; j++)
155 omap_vrfb_release_ctx(&vout->vrfb_context[j]);
156free_buffers:
157 omap_vout_free_buffers(vout);
158
159 return ret;
160}
161
162/*
163 * Release the VRFB context once the module exits
164 */
165void omap_vout_release_vrfb(struct omap_vout_device *vout)
166{
167 int i;
168
169 for (i = 0; i < VRFB_NUM_BUFS; i++)
170 omap_vrfb_release_ctx(&vout->vrfb_context[i]);
171
172 if (vout->vrfb_dma_tx.req_status == DMA_CHAN_ALLOTED) {
173 vout->vrfb_dma_tx.req_status = DMA_CHAN_NOT_ALLOTED;
174 omap_free_dma(vout->vrfb_dma_tx.dma_ch);
175 }
176}
177
178/*
179 * Allocate the buffers for the VRFB space. Data is copied from V4L2
180 * buffers to the VRFB buffers using the DMA engine.
181 */
182int omap_vout_vrfb_buffer_setup(struct omap_vout_device *vout,
183 unsigned int *count, unsigned int startindex)
184{
185 int i;
186 bool yuv_mode;
187
188 if (!is_rotation_enabled(vout))
189 return 0;
190
191 /* If rotation is enabled, allocate memory for VRFB space also */
192 *count = *count > VRFB_NUM_BUFS ? VRFB_NUM_BUFS : *count;
193
194 /* Allocate the VRFB buffers only if the buffers are not
195 * allocated during init time.
196 */
197 if (!vout->vrfb_static_allocation)
198 if (omap_vout_allocate_vrfb_buffers(vout, count, startindex))
199 return -ENOMEM;
200
201 if (vout->dss_mode == OMAP_DSS_COLOR_YUV2 ||
202 vout->dss_mode == OMAP_DSS_COLOR_UYVY)
203 yuv_mode = true;
204 else
205 yuv_mode = false;
206
207 for (i = 0; i < *count; i++)
208 omap_vrfb_setup(&vout->vrfb_context[i],
209 vout->smsshado_phy_addr[i], vout->pix.width,
210 vout->pix.height, vout->bpp, yuv_mode);
211
212 return 0;
213}
214
215int omap_vout_prepare_vrfb(struct omap_vout_device *vout,
216 struct videobuf_buffer *vb)
217{
218 dma_addr_t dmabuf;
219 struct vid_vrfb_dma *tx;
220 enum dss_rotation rotation;
221 u32 dest_frame_index = 0, src_element_index = 0;
222 u32 dest_element_index = 0, src_frame_index = 0;
223 u32 elem_count = 0, frame_count = 0, pixsize = 2;
224
225 if (!is_rotation_enabled(vout))
226 return 0;
227
228 dmabuf = vout->buf_phy_addr[vb->i];
229 /* If rotation is enabled, copy input buffer into VRFB
230 * memory space using DMA. We are copying input buffer
231 * into VRFB memory space of desired angle and DSS will
232 * read image VRFB memory for 0 degree angle
233 */
234 pixsize = vout->bpp * vout->vrfb_bpp;
235 /*
236 * DMA transfer in double index mode
237 */
238
239 /* Frame index */
240 dest_frame_index = ((MAX_PIXELS_PER_LINE * pixsize) -
241 (vout->pix.width * vout->bpp)) + 1;
242
243 /* Source and destination parameters */
244 src_element_index = 0;
245 src_frame_index = 0;
246 dest_element_index = 1;
247 /* Number of elements per frame */
248 elem_count = vout->pix.width * vout->bpp;
249 frame_count = vout->pix.height;
250 tx = &vout->vrfb_dma_tx;
251 tx->tx_status = 0;
252 omap_set_dma_transfer_params(tx->dma_ch, OMAP_DMA_DATA_TYPE_S32,
253 (elem_count / 4), frame_count, OMAP_DMA_SYNC_ELEMENT,
254 tx->dev_id, 0x0);
255 /* src_port required only for OMAP1 */
256 omap_set_dma_src_params(tx->dma_ch, 0, OMAP_DMA_AMODE_POST_INC,
257 dmabuf, src_element_index, src_frame_index);
258 /*set dma source burst mode for VRFB */
259 omap_set_dma_src_burst_mode(tx->dma_ch, OMAP_DMA_DATA_BURST_16);
260 rotation = calc_rotation(vout);
261
262 /* dest_port required only for OMAP1 */
263 omap_set_dma_dest_params(tx->dma_ch, 0, OMAP_DMA_AMODE_DOUBLE_IDX,
264 vout->vrfb_context[vb->i].paddr[0], dest_element_index,
265 dest_frame_index);
266 /*set dma dest burst mode for VRFB */
267 omap_set_dma_dest_burst_mode(tx->dma_ch, OMAP_DMA_DATA_BURST_16);
268 omap_dma_set_global_params(DMA_DEFAULT_ARB_RATE, 0x20, 0);
269
270 omap_start_dma(tx->dma_ch);
271 interruptible_sleep_on_timeout(&tx->wait, VRFB_TX_TIMEOUT);
272
273 if (tx->tx_status == 0) {
274 omap_stop_dma(tx->dma_ch);
275 return -EINVAL;
276 }
277 /* Store buffers physical address into an array. Addresses
278 * from this array will be used to configure DSS */
279 vout->queued_buf_addr[vb->i] = (u8 *)
280 vout->vrfb_context[vb->i].paddr[rotation];
281 return 0;
282}
283
284/*
285 * Calculate the buffer offsets from which the streaming should
286 * start. This offset calculation is mainly required because of
287 * the VRFB 32 pixels alignment with rotation.
288 */
289void omap_vout_calculate_vrfb_offset(struct omap_vout_device *vout)
290{
291 enum dss_rotation rotation;
292 bool mirroring = vout->mirror;
293 struct v4l2_rect *crop = &vout->crop;
294 struct v4l2_pix_format *pix = &vout->pix;
295 int *cropped_offset = &vout->cropped_offset;
296 int vr_ps = 1, ps = 2, temp_ps = 2;
297 int offset = 0, ctop = 0, cleft = 0, line_length = 0;
298
299 rotation = calc_rotation(vout);
300
301 if (V4L2_PIX_FMT_YUYV == pix->pixelformat ||
302 V4L2_PIX_FMT_UYVY == pix->pixelformat) {
303 if (is_rotation_enabled(vout)) {
304 /*
305 * ps - Actual pixel size for YUYV/UYVY for
306 * VRFB/Mirroring is 4 bytes
307 * vr_ps - Virtually pixel size for YUYV/UYVY is
308 * 2 bytes
309 */
310 ps = 4;
311 vr_ps = 2;
312 } else {
313 ps = 2; /* otherwise the pixel size is 2 byte */
314 }
315 } else if (V4L2_PIX_FMT_RGB32 == pix->pixelformat) {
316 ps = 4;
317 } else if (V4L2_PIX_FMT_RGB24 == pix->pixelformat) {
318 ps = 3;
319 }
320 vout->ps = ps;
321 vout->vr_ps = vr_ps;
322
323 if (is_rotation_enabled(vout)) {
324 line_length = MAX_PIXELS_PER_LINE;
325 ctop = (pix->height - crop->height) - crop->top;
326 cleft = (pix->width - crop->width) - crop->left;
327 } else {
328 line_length = pix->width;
329 }
330 vout->line_length = line_length;
331 switch (rotation) {
332 case dss_rotation_90_degree:
333 offset = vout->vrfb_context[0].yoffset *
334 vout->vrfb_context[0].bytespp;
335 temp_ps = ps / vr_ps;
336 if (mirroring == 0) {
337 *cropped_offset = offset + line_length *
338 temp_ps * cleft + crop->top * temp_ps;
339 } else {
340 *cropped_offset = offset + line_length * temp_ps *
341 cleft + crop->top * temp_ps + (line_length *
342 ((crop->width / (vr_ps)) - 1) * ps);
343 }
344 break;
345 case dss_rotation_180_degree:
346 offset = ((MAX_PIXELS_PER_LINE * vout->vrfb_context[0].yoffset *
347 vout->vrfb_context[0].bytespp) +
348 (vout->vrfb_context[0].xoffset *
349 vout->vrfb_context[0].bytespp));
350 if (mirroring == 0) {
351 *cropped_offset = offset + (line_length * ps * ctop) +
352 (cleft / vr_ps) * ps;
353
354 } else {
355 *cropped_offset = offset + (line_length * ps * ctop) +
356 (cleft / vr_ps) * ps + (line_length *
357 (crop->height - 1) * ps);
358 }
359 break;
360 case dss_rotation_270_degree:
361 offset = MAX_PIXELS_PER_LINE * vout->vrfb_context[0].xoffset *
362 vout->vrfb_context[0].bytespp;
363 temp_ps = ps / vr_ps;
364 if (mirroring == 0) {
365 *cropped_offset = offset + line_length *
366 temp_ps * crop->left + ctop * ps;
367 } else {
368 *cropped_offset = offset + line_length *
369 temp_ps * crop->left + ctop * ps +
370 (line_length * ((crop->width / vr_ps) - 1) *
371 ps);
372 }
373 break;
374 case dss_rotation_0_degree:
375 if (mirroring == 0) {
376 *cropped_offset = (line_length * ps) *
377 crop->top + (crop->left / vr_ps) * ps;
378 } else {
379 *cropped_offset = (line_length * ps) *
380 crop->top + (crop->left / vr_ps) * ps +
381 (line_length * (crop->height - 1) * ps);
382 }
383 break;
384 default:
385 *cropped_offset = (line_length * ps * crop->top) /
386 vr_ps + (crop->left * ps) / vr_ps +
387 ((crop->width / vr_ps) - 1) * ps;
388 break;
389 }
390}
diff --git a/drivers/media/video/omap/omap_vout_vrfb.h b/drivers/media/video/omap/omap_vout_vrfb.h
new file mode 100644
index 000000000000..ffde741e0590
--- /dev/null
+++ b/drivers/media/video/omap/omap_vout_vrfb.h
@@ -0,0 +1,40 @@
1/*
2 * omap_vout_vrfb.h
3 *
4 * Copyright (C) 2010 Texas Instruments.
5 *
6 * This file is licensed under the terms of the GNU General Public License
7 * version 2. This program is licensed "as is" without any warranty of any
8 * kind, whether express or implied.
9 *
10 */
11
12#ifndef OMAP_VOUT_VRFB_H
13#define OMAP_VOUT_VRFB_H
14
15#ifdef CONFIG_VIDEO_OMAP2_VOUT_VRFB
16void omap_vout_free_vrfb_buffers(struct omap_vout_device *vout);
17int omap_vout_setup_vrfb_bufs(struct platform_device *pdev, int vid_num,
18 u32 static_vrfb_allocation);
19void omap_vout_release_vrfb(struct omap_vout_device *vout);
20int omap_vout_vrfb_buffer_setup(struct omap_vout_device *vout,
21 unsigned int *count, unsigned int startindex);
22int omap_vout_prepare_vrfb(struct omap_vout_device *vout,
23 struct videobuf_buffer *vb);
24void omap_vout_calculate_vrfb_offset(struct omap_vout_device *vout);
25#else
26void omap_vout_free_vrfb_buffers(struct omap_vout_device *vout) { }
27int omap_vout_setup_vrfb_bufs(struct platform_device *pdev, int vid_num,
28 u32 static_vrfb_allocation)
29 { return 0; }
30void omap_vout_release_vrfb(struct omap_vout_device *vout) { }
31int omap_vout_vrfb_buffer_setup(struct omap_vout_device *vout,
32 unsigned int *count, unsigned int startindex)
33 { return 0; }
34int omap_vout_prepare_vrfb(struct omap_vout_device *vout,
35 struct videobuf_buffer *vb)
36 { return 0; }
37void omap_vout_calculate_vrfb_offset(struct omap_vout_device *vout) { }
38#endif
39
40#endif
diff --git a/drivers/media/video/omap/omap_voutdef.h b/drivers/media/video/omap/omap_voutdef.h
index 1ef3ed22660c..d793501cafcc 100644
--- a/drivers/media/video/omap/omap_voutdef.h
+++ b/drivers/media/video/omap/omap_voutdef.h
@@ -12,6 +12,7 @@
12#define OMAP_VOUTDEF_H 12#define OMAP_VOUTDEF_H
13 13
14#include <video/omapdss.h> 14#include <video/omapdss.h>
15#include <plat/vrfb.h>
15 16
16#define YUYV_BPP 2 17#define YUYV_BPP 2
17#define RGB565_BPP 2 18#define RGB565_BPP 2
@@ -62,6 +63,18 @@ enum dss_rotation {
62 dss_rotation_180_degree = 2, 63 dss_rotation_180_degree = 2,
63 dss_rotation_270_degree = 3, 64 dss_rotation_270_degree = 3,
64}; 65};
66
67/* Enum for choosing rotation type for vout
68 * DSS2 doesn't understand no rotation as an
69 * option while V4L2 driver doesn't support
70 * rotation in the case where VRFB is not built in
71 * the kernel
72 */
73enum vout_rotaion_type {
74 VOUT_ROT_NONE = 0,
75 VOUT_ROT_VRFB = 1,
76};
77
65/* 78/*
66 * This structure is used to store the DMA transfer parameters 79 * This structure is used to store the DMA transfer parameters
67 * for VRFB hidden buffer 80 * for VRFB hidden buffer
@@ -78,6 +91,7 @@ struct omapvideo_info {
78 int id; 91 int id;
79 int num_overlays; 92 int num_overlays;
80 struct omap_overlay *overlays[MAX_OVLS]; 93 struct omap_overlay *overlays[MAX_OVLS];
94 enum vout_rotaion_type rotation_type;
81}; 95};
82 96
83struct omap2video_device { 97struct omap2video_device {
@@ -206,4 +220,6 @@ static inline int calc_rotation(const struct omap_vout_device *vout)
206 return dss_rotation_180_degree; 220 return dss_rotation_180_degree;
207 } 221 }
208} 222}
223
224void omap_vout_free_buffers(struct omap_vout_device *vout);
209#endif /* ifndef OMAP_VOUTDEF_H */ 225#endif /* ifndef OMAP_VOUTDEF_H */