diff options
author | Krzysztof HaĆasa <khalasa@piap.pl> | 2013-09-12 07:28:07 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <m.chehab@samsung.com> | 2013-10-14 05:32:42 -0400 |
commit | 4a61ad3c4a2c8b50f6b5835d0d36bd8639b9f7ee (patch) | |
tree | accaafd8f3f25914b52d474b1e68c04b43b19264 | |
parent | a3d2d196e13721257cead2227a3ae89b5c6f4de1 (diff) |
[media] SOLO6x10: Fix video encoding on big-endian systems
Signed-off-by: Krzysztof Ha?asa <khalasa@piap.pl>
[hans.verkuil@cisco.com: fix merge problems due to the recent solo sg_table changes]
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
-rw-r--r-- | drivers/staging/media/solo6x10/solo6x10-v4l2-enc.c | 132 |
1 files changed, 80 insertions, 52 deletions
diff --git a/drivers/staging/media/solo6x10/solo6x10-v4l2-enc.c b/drivers/staging/media/solo6x10/solo6x10-v4l2-enc.c index 9a6d5c0b1339..9bf878d57af4 100644 --- a/drivers/staging/media/solo6x10/solo6x10-v4l2-enc.c +++ b/drivers/staging/media/solo6x10/solo6x10-v4l2-enc.c | |||
@@ -95,38 +95,11 @@ static unsigned char vop_6110_pal_cif[] = { | |||
95 | 0x01, 0x68, 0xce, 0x32, 0x28, 0x00, 0x00, 0x00, | 95 | 0x01, 0x68, 0xce, 0x32, 0x28, 0x00, 0x00, 0x00, |
96 | }; | 96 | }; |
97 | 97 | ||
98 | struct vop_header { | 98 | typedef __le32 vop_header[16]; |
99 | /* VE_STATUS0 */ | ||
100 | u32 mpeg_size:20, sad_motion_flag:1, video_motion_flag:1, vop_type:2, | ||
101 | channel:5, source_fl:1, interlace:1, progressive:1; | ||
102 | |||
103 | /* VE_STATUS1 */ | ||
104 | u32 vsize:8, hsize:8, last_queue:4, nop0:8, scale:4; | ||
105 | |||
106 | /* VE_STATUS2 */ | ||
107 | u32 mpeg_off; | ||
108 | |||
109 | /* VE_STATUS3 */ | ||
110 | u32 jpeg_off; | ||
111 | |||
112 | /* VE_STATUS4 */ | ||
113 | u32 jpeg_size:20, interval:10, nop1:2; | ||
114 | |||
115 | /* VE_STATUS5/6 */ | ||
116 | u32 sec, usec; | ||
117 | |||
118 | /* VE_STATUS7/8/9 */ | ||
119 | u32 nop2[3]; | ||
120 | |||
121 | /* VE_STATUS10 */ | ||
122 | u32 mpeg_size_alt:20, nop3:12; | ||
123 | |||
124 | u32 end_nops[5]; | ||
125 | } __packed; | ||
126 | 99 | ||
127 | struct solo_enc_buf { | 100 | struct solo_enc_buf { |
128 | enum solo_enc_types type; | 101 | enum solo_enc_types type; |
129 | struct vop_header *vh; | 102 | const vop_header *vh; |
130 | int motion; | 103 | int motion; |
131 | }; | 104 | }; |
132 | 105 | ||
@@ -430,8 +403,64 @@ static int solo_send_desc(struct solo_enc_dev *solo_enc, int skip, | |||
430 | solo_enc->desc_count - 1); | 403 | solo_enc->desc_count - 1); |
431 | } | 404 | } |
432 | 405 | ||
406 | /* Extract values from VOP header - VE_STATUSxx */ | ||
407 | static inline int vop_interlaced(const vop_header *vh) | ||
408 | { | ||
409 | return (__le32_to_cpu((*vh)[0]) >> 30) & 1; | ||
410 | } | ||
411 | |||
412 | static inline u8 vop_channel(const vop_header *vh) | ||
413 | { | ||
414 | return (__le32_to_cpu((*vh)[0]) >> 24) & 0x1F; | ||
415 | } | ||
416 | |||
417 | static inline u8 vop_type(const vop_header *vh) | ||
418 | { | ||
419 | return (__le32_to_cpu((*vh)[0]) >> 22) & 3; | ||
420 | } | ||
421 | |||
422 | static inline u32 vop_mpeg_size(const vop_header *vh) | ||
423 | { | ||
424 | return __le32_to_cpu((*vh)[0]) & 0xFFFFF; | ||
425 | } | ||
426 | |||
427 | static inline u8 vop_hsize(const vop_header *vh) | ||
428 | { | ||
429 | return (__le32_to_cpu((*vh)[1]) >> 8) & 0xFF; | ||
430 | } | ||
431 | |||
432 | static inline u8 vop_vsize(const vop_header *vh) | ||
433 | { | ||
434 | return __le32_to_cpu((*vh)[1]) & 0xFF; | ||
435 | } | ||
436 | |||
437 | static inline u32 vop_mpeg_offset(const vop_header *vh) | ||
438 | { | ||
439 | return __le32_to_cpu((*vh)[2]); | ||
440 | } | ||
441 | |||
442 | static inline u32 vop_jpeg_offset(const vop_header *vh) | ||
443 | { | ||
444 | return __le32_to_cpu((*vh)[3]); | ||
445 | } | ||
446 | |||
447 | static inline u32 vop_jpeg_size(const vop_header *vh) | ||
448 | { | ||
449 | return __le32_to_cpu((*vh)[4]) & 0xFFFFF; | ||
450 | } | ||
451 | |||
452 | static inline u32 vop_sec(const vop_header *vh) | ||
453 | { | ||
454 | return __le32_to_cpu((*vh)[5]); | ||
455 | } | ||
456 | |||
457 | static inline u32 vop_usec(const vop_header *vh) | ||
458 | { | ||
459 | return __le32_to_cpu((*vh)[6]); | ||
460 | } | ||
461 | |||
433 | static int solo_fill_jpeg(struct solo_enc_dev *solo_enc, | 462 | static int solo_fill_jpeg(struct solo_enc_dev *solo_enc, |
434 | struct vb2_buffer *vb, struct vop_header *vh) | 463 | struct vb2_buffer *vb, const vop_header *vh) |
435 | { | 464 | { |
436 | struct solo_dev *solo_dev = solo_enc->solo_dev; | 465 | struct solo_dev *solo_dev = solo_enc->solo_dev; |
437 | struct sg_table *vbuf = vb2_dma_sg_plane_desc(vb, 0); | 466 | struct sg_table *vbuf = vb2_dma_sg_plane_desc(vb, 0); |
@@ -440,29 +469,30 @@ static int solo_fill_jpeg(struct solo_enc_dev *solo_enc, | |||
440 | 469 | ||
441 | vb->v4l2_buf.flags |= V4L2_BUF_FLAG_KEYFRAME; | 470 | vb->v4l2_buf.flags |= V4L2_BUF_FLAG_KEYFRAME; |
442 | 471 | ||
443 | if (vb2_plane_size(vb, 0) < vh->jpeg_size + solo_enc->jpeg_len) | 472 | if (vb2_plane_size(vb, 0) < vop_jpeg_size(vh) + solo_enc->jpeg_len) |
444 | return -EIO; | 473 | return -EIO; |
445 | 474 | ||
446 | sg_copy_from_buffer(vbuf->sgl, vbuf->nents, | 475 | sg_copy_from_buffer(vbuf->sgl, vbuf->nents, |
447 | solo_enc->jpeg_header, | 476 | solo_enc->jpeg_header, |
448 | solo_enc->jpeg_len); | 477 | solo_enc->jpeg_len); |
449 | 478 | ||
450 | frame_size = (vh->jpeg_size + solo_enc->jpeg_len + (DMA_ALIGN - 1)) | 479 | frame_size = (vop_jpeg_size(vh) + solo_enc->jpeg_len + (DMA_ALIGN - 1)) |
451 | & ~(DMA_ALIGN - 1); | 480 | & ~(DMA_ALIGN - 1); |
452 | vb2_set_plane_payload(vb, 0, vh->jpeg_size + solo_enc->jpeg_len); | 481 | vb2_set_plane_payload(vb, 0, vop_jpeg_size(vh) + solo_enc->jpeg_len); |
453 | 482 | ||
454 | dma_map_sg(&solo_dev->pdev->dev, vbuf->sgl, vbuf->nents, | 483 | dma_map_sg(&solo_dev->pdev->dev, vbuf->sgl, vbuf->nents, |
455 | DMA_FROM_DEVICE); | 484 | DMA_FROM_DEVICE); |
456 | ret = solo_send_desc(solo_enc, solo_enc->jpeg_len, vbuf, vh->jpeg_off, | 485 | ret = solo_send_desc(solo_enc, solo_enc->jpeg_len, vbuf, |
457 | frame_size, SOLO_JPEG_EXT_ADDR(solo_dev), | 486 | vop_jpeg_offset(vh) - SOLO_JPEG_EXT_ADDR(solo_dev), |
458 | SOLO_JPEG_EXT_SIZE(solo_dev)); | 487 | frame_size, SOLO_JPEG_EXT_ADDR(solo_dev), |
488 | SOLO_JPEG_EXT_SIZE(solo_dev)); | ||
459 | dma_unmap_sg(&solo_dev->pdev->dev, vbuf->sgl, vbuf->nents, | 489 | dma_unmap_sg(&solo_dev->pdev->dev, vbuf->sgl, vbuf->nents, |
460 | DMA_FROM_DEVICE); | 490 | DMA_FROM_DEVICE); |
461 | return ret; | 491 | return ret; |
462 | } | 492 | } |
463 | 493 | ||
464 | static int solo_fill_mpeg(struct solo_enc_dev *solo_enc, | 494 | static int solo_fill_mpeg(struct solo_enc_dev *solo_enc, |
465 | struct vb2_buffer *vb, struct vop_header *vh) | 495 | struct vb2_buffer *vb, const vop_header *vh) |
466 | { | 496 | { |
467 | struct solo_dev *solo_dev = solo_enc->solo_dev; | 497 | struct solo_dev *solo_dev = solo_enc->solo_dev; |
468 | struct sg_table *vbuf = vb2_dma_sg_plane_desc(vb, 0); | 498 | struct sg_table *vbuf = vb2_dma_sg_plane_desc(vb, 0); |
@@ -470,11 +500,11 @@ static int solo_fill_mpeg(struct solo_enc_dev *solo_enc, | |||
470 | int skip = 0; | 500 | int skip = 0; |
471 | int ret; | 501 | int ret; |
472 | 502 | ||
473 | if (vb2_plane_size(vb, 0) < vh->mpeg_size) | 503 | if (vb2_plane_size(vb, 0) < vop_mpeg_size(vh)) |
474 | return -EIO; | 504 | return -EIO; |
475 | 505 | ||
476 | /* If this is a key frame, add extra header */ | 506 | /* If this is a key frame, add extra header */ |
477 | if (!vh->vop_type) { | 507 | if (!vop_type(vh)) { |
478 | sg_copy_from_buffer(vbuf->sgl, vbuf->nents, | 508 | sg_copy_from_buffer(vbuf->sgl, vbuf->nents, |
479 | solo_enc->vop, | 509 | solo_enc->vop, |
480 | solo_enc->vop_len); | 510 | solo_enc->vop_len); |
@@ -482,16 +512,16 @@ static int solo_fill_mpeg(struct solo_enc_dev *solo_enc, | |||
482 | skip = solo_enc->vop_len; | 512 | skip = solo_enc->vop_len; |
483 | 513 | ||
484 | vb->v4l2_buf.flags |= V4L2_BUF_FLAG_KEYFRAME; | 514 | vb->v4l2_buf.flags |= V4L2_BUF_FLAG_KEYFRAME; |
485 | vb2_set_plane_payload(vb, 0, vh->mpeg_size + solo_enc->vop_len); | 515 | vb2_set_plane_payload(vb, 0, vop_mpeg_size(vh) + solo_enc->vop_len); |
486 | } else { | 516 | } else { |
487 | vb->v4l2_buf.flags |= V4L2_BUF_FLAG_PFRAME; | 517 | vb->v4l2_buf.flags |= V4L2_BUF_FLAG_PFRAME; |
488 | vb2_set_plane_payload(vb, 0, vh->mpeg_size); | 518 | vb2_set_plane_payload(vb, 0, vop_mpeg_size(vh)); |
489 | } | 519 | } |
490 | 520 | ||
491 | /* Now get the actual mpeg payload */ | 521 | /* Now get the actual mpeg payload */ |
492 | frame_off = (vh->mpeg_off + sizeof(*vh)) | 522 | frame_off = (vop_mpeg_offset(vh) - SOLO_MP4E_EXT_ADDR(solo_dev) + sizeof(*vh)) |
493 | % SOLO_MP4E_EXT_SIZE(solo_dev); | 523 | % SOLO_MP4E_EXT_SIZE(solo_dev); |
494 | frame_size = (vh->mpeg_size + skip + (DMA_ALIGN - 1)) | 524 | frame_size = (vop_mpeg_size(vh) + skip + (DMA_ALIGN - 1)) |
495 | & ~(DMA_ALIGN - 1); | 525 | & ~(DMA_ALIGN - 1); |
496 | 526 | ||
497 | dma_map_sg(&solo_dev->pdev->dev, vbuf->sgl, vbuf->nents, | 527 | dma_map_sg(&solo_dev->pdev->dev, vbuf->sgl, vbuf->nents, |
@@ -507,7 +537,7 @@ static int solo_fill_mpeg(struct solo_enc_dev *solo_enc, | |||
507 | static int solo_enc_fillbuf(struct solo_enc_dev *solo_enc, | 537 | static int solo_enc_fillbuf(struct solo_enc_dev *solo_enc, |
508 | struct vb2_buffer *vb, struct solo_enc_buf *enc_buf) | 538 | struct vb2_buffer *vb, struct solo_enc_buf *enc_buf) |
509 | { | 539 | { |
510 | struct vop_header *vh = enc_buf->vh; | 540 | const vop_header *vh = enc_buf->vh; |
511 | int ret; | 541 | int ret; |
512 | 542 | ||
513 | /* Check for motion flags */ | 543 | /* Check for motion flags */ |
@@ -531,8 +561,8 @@ static int solo_enc_fillbuf(struct solo_enc_dev *solo_enc, | |||
531 | 561 | ||
532 | if (!ret) { | 562 | if (!ret) { |
533 | vb->v4l2_buf.sequence = solo_enc->sequence++; | 563 | vb->v4l2_buf.sequence = solo_enc->sequence++; |
534 | vb->v4l2_buf.timestamp.tv_sec = vh->sec; | 564 | vb->v4l2_buf.timestamp.tv_sec = vop_sec(vh); |
535 | vb->v4l2_buf.timestamp.tv_usec = vh->usec; | 565 | vb->v4l2_buf.timestamp.tv_usec = vop_usec(vh); |
536 | } | 566 | } |
537 | 567 | ||
538 | vb2_buffer_done(vb, ret ? VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE); | 568 | vb2_buffer_done(vb, ret ? VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE); |
@@ -605,15 +635,13 @@ static void solo_handle_ring(struct solo_dev *solo_dev) | |||
605 | 635 | ||
606 | /* FAIL... */ | 636 | /* FAIL... */ |
607 | if (enc_get_mpeg_dma(solo_dev, solo_dev->vh_dma, off, | 637 | if (enc_get_mpeg_dma(solo_dev, solo_dev->vh_dma, off, |
608 | sizeof(struct vop_header))) | 638 | sizeof(vop_header))) |
609 | continue; | 639 | continue; |
610 | 640 | ||
611 | enc_buf.vh = (struct vop_header *)solo_dev->vh_buf; | 641 | enc_buf.vh = solo_dev->vh_buf; |
612 | enc_buf.vh->mpeg_off -= SOLO_MP4E_EXT_ADDR(solo_dev); | ||
613 | enc_buf.vh->jpeg_off -= SOLO_JPEG_EXT_ADDR(solo_dev); | ||
614 | 642 | ||
615 | /* Sanity check */ | 643 | /* Sanity check */ |
616 | if (enc_buf.vh->mpeg_off != off) | 644 | if (vop_mpeg_offset(enc_buf.vh) != SOLO_MP4E_EXT_ADDR(solo_dev) + off) |
617 | continue; | 645 | continue; |
618 | 646 | ||
619 | if (solo_motion_detected(solo_enc)) | 647 | if (solo_motion_detected(solo_enc)) |
@@ -1329,7 +1357,7 @@ int solo_enc_v4l2_init(struct solo_dev *solo_dev, unsigned nr) | |||
1329 | 1357 | ||
1330 | init_waitqueue_head(&solo_dev->ring_thread_wait); | 1358 | init_waitqueue_head(&solo_dev->ring_thread_wait); |
1331 | 1359 | ||
1332 | solo_dev->vh_size = sizeof(struct vop_header); | 1360 | solo_dev->vh_size = sizeof(vop_header); |
1333 | solo_dev->vh_buf = pci_alloc_consistent(solo_dev->pdev, | 1361 | solo_dev->vh_buf = pci_alloc_consistent(solo_dev->pdev, |
1334 | solo_dev->vh_size, | 1362 | solo_dev->vh_size, |
1335 | &solo_dev->vh_dma); | 1363 | &solo_dev->vh_dma); |