aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video
diff options
context:
space:
mode:
authorKuninori Morimoto <morimoto.kuninori@renesas.com>2009-12-11 09:53:53 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2009-12-16 06:27:32 -0500
commit1edcc10d7f4fd4085fcdcdd68afec258c3427530 (patch)
tree91912304d333950b9d6e2bbfdd6fb187c5444dbc /drivers/media/video
parenta3a4ac14774786bef160ea380bd75307a144a5e9 (diff)
V4L/DVB (13663): sh_mobile_ceu: Add V4L2_FIELD_INTERLACED_BT/TB support
Signed-off-by: Kuninori Morimoto <morimoto.kuninori@renesas.com> Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video')
-rw-r--r--drivers/media/video/sh_mobile_ceu_camera.c75
1 files changed, 51 insertions, 24 deletions
diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c
index 273ad34f9d8..df8dc1dde19 100644
--- a/drivers/media/video/sh_mobile_ceu_camera.c
+++ b/drivers/media/video/sh_mobile_ceu_camera.c
@@ -107,7 +107,8 @@ struct sh_mobile_ceu_dev {
107 107
108 u32 cflcr; 108 u32 cflcr;
109 109
110 unsigned int is_interlaced:1; 110 enum v4l2_field field;
111
111 unsigned int image_mode:1; 112 unsigned int image_mode:1;
112 unsigned int is_16bit:1; 113 unsigned int is_16bit:1;
113}; 114};
@@ -254,6 +255,8 @@ static int sh_mobile_ceu_capture(struct sh_mobile_ceu_dev *pcdev)
254{ 255{
255 struct soc_camera_device *icd = pcdev->icd; 256 struct soc_camera_device *icd = pcdev->icd;
256 dma_addr_t phys_addr_top, phys_addr_bottom; 257 dma_addr_t phys_addr_top, phys_addr_bottom;
258 unsigned long top1, top2;
259 unsigned long bottom1, bottom2;
257 u32 status; 260 u32 status;
258 int ret = 0; 261 int ret = 0;
259 262
@@ -282,11 +285,23 @@ static int sh_mobile_ceu_capture(struct sh_mobile_ceu_dev *pcdev)
282 if (!pcdev->active) 285 if (!pcdev->active)
283 return ret; 286 return ret;
284 287
288 if (V4L2_FIELD_INTERLACED_BT == pcdev->field) {
289 top1 = CDBYR;
290 top2 = CDBCR;
291 bottom1 = CDAYR;
292 bottom2 = CDACR;
293 } else {
294 top1 = CDAYR;
295 top2 = CDACR;
296 bottom1 = CDBYR;
297 bottom2 = CDBCR;
298 }
299
285 phys_addr_top = videobuf_to_dma_contig(pcdev->active); 300 phys_addr_top = videobuf_to_dma_contig(pcdev->active);
286 ceu_write(pcdev, CDAYR, phys_addr_top); 301 ceu_write(pcdev, top1, phys_addr_top);
287 if (pcdev->is_interlaced) { 302 if (V4L2_FIELD_NONE != pcdev->field) {
288 phys_addr_bottom = phys_addr_top + icd->user_width; 303 phys_addr_bottom = phys_addr_top + icd->user_width;
289 ceu_write(pcdev, CDBYR, phys_addr_bottom); 304 ceu_write(pcdev, bottom1, phys_addr_bottom);
290 } 305 }
291 306
292 switch (icd->current_fmt->host_fmt->fourcc) { 307 switch (icd->current_fmt->host_fmt->fourcc) {
@@ -296,11 +311,10 @@ static int sh_mobile_ceu_capture(struct sh_mobile_ceu_dev *pcdev)
296 case V4L2_PIX_FMT_NV61: 311 case V4L2_PIX_FMT_NV61:
297 phys_addr_top += icd->user_width * 312 phys_addr_top += icd->user_width *
298 icd->user_height; 313 icd->user_height;
299 ceu_write(pcdev, CDACR, phys_addr_top); 314 ceu_write(pcdev, top2, phys_addr_top);
300 if (pcdev->is_interlaced) { 315 if (V4L2_FIELD_NONE != pcdev->field) {
301 phys_addr_bottom = phys_addr_top + 316 phys_addr_bottom = phys_addr_top + icd->user_width;
302 icd->user_width; 317 ceu_write(pcdev, bottom2, phys_addr_bottom);
303 ceu_write(pcdev, CDBCR, phys_addr_bottom);
304 } 318 }
305 } 319 }
306 320
@@ -602,7 +616,7 @@ static void sh_mobile_ceu_set_rect(struct soc_camera_device *icd,
602 616
603 height = out_height; 617 height = out_height;
604 in_height = rect->height; 618 in_height = rect->height;
605 if (pcdev->is_interlaced) { 619 if (V4L2_FIELD_NONE != pcdev->field) {
606 height /= 2; 620 height /= 2;
607 in_height /= 2; 621 in_height /= 2;
608 top_offset /= 2; 622 top_offset /= 2;
@@ -729,7 +743,19 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd,
729 ceu_write(pcdev, CAMCR, value); 743 ceu_write(pcdev, CAMCR, value);
730 744
731 ceu_write(pcdev, CAPCR, 0x00300000); 745 ceu_write(pcdev, CAPCR, 0x00300000);
732 ceu_write(pcdev, CAIFR, pcdev->is_interlaced ? 0x101 : 0); 746
747 switch (pcdev->field) {
748 case V4L2_FIELD_INTERLACED_TB:
749 value = 0x101;
750 break;
751 case V4L2_FIELD_INTERLACED_BT:
752 value = 0x102;
753 break;
754 default:
755 value = 0;
756 break;
757 }
758 ceu_write(pcdev, CAIFR, value);
733 759
734 sh_mobile_ceu_set_rect(icd, icd->user_width, icd->user_height); 760 sh_mobile_ceu_set_rect(icd, icd->user_width, icd->user_height);
735 mdelay(1); 761 mdelay(1);
@@ -1357,8 +1383,7 @@ static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd,
1357 1383
1358 /* 6. - 9. */ 1384 /* 6. - 9. */
1359 mf.code = cam->code; 1385 mf.code = cam->code;
1360 mf.field = pcdev->is_interlaced ? V4L2_FIELD_INTERLACED : 1386 mf.field = pcdev->field;
1361 V4L2_FIELD_NONE;
1362 1387
1363 capsr = capture_save_reset(pcdev); 1388 capsr = capture_save_reset(pcdev);
1364 dev_dbg(dev, "CAPSR 0x%x, CFLCR 0x%x\n", capsr, pcdev->cflcr); 1389 dev_dbg(dev, "CAPSR 0x%x, CFLCR 0x%x\n", capsr, pcdev->cflcr);
@@ -1368,7 +1393,8 @@ static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd,
1368 rect->top -= cam_rect->top; 1393 rect->top -= cam_rect->top;
1369 1394
1370 ret = client_scale(icd, cam_rect, rect, ceu_rect, &mf, 1395 ret = client_scale(icd, cam_rect, rect, ceu_rect, &mf,
1371 pcdev->image_mode && !pcdev->is_interlaced); 1396 pcdev->image_mode &&
1397 V4L2_FIELD_NONE == pcdev->field);
1372 1398
1373 dev_geo(dev, "6-9: %d\n", ret); 1399 dev_geo(dev, "6-9: %d\n", ret);
1374 1400
@@ -1425,18 +1451,20 @@ static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd,
1425 unsigned int scale_cam_h, scale_cam_v; 1451 unsigned int scale_cam_h, scale_cam_v;
1426 u16 scale_v, scale_h; 1452 u16 scale_v, scale_h;
1427 int ret; 1453 int ret;
1428 bool is_interlaced, image_mode; 1454 bool image_mode;
1455 enum v4l2_field field;
1429 1456
1430 switch (pix->field) { 1457 switch (pix->field) {
1431 case V4L2_FIELD_INTERLACED:
1432 is_interlaced = true;
1433 break;
1434 case V4L2_FIELD_ANY:
1435 default: 1458 default:
1436 pix->field = V4L2_FIELD_NONE; 1459 pix->field = V4L2_FIELD_NONE;
1437 /* fall-through */ 1460 /* fall-through */
1461 case V4L2_FIELD_INTERLACED_TB:
1462 case V4L2_FIELD_INTERLACED_BT:
1438 case V4L2_FIELD_NONE: 1463 case V4L2_FIELD_NONE:
1439 is_interlaced = false; 1464 field = pix->field;
1465 break;
1466 case V4L2_FIELD_INTERLACED:
1467 field = V4L2_FIELD_INTERLACED_TB;
1440 break; 1468 break;
1441 } 1469 }
1442 1470
@@ -1505,7 +1533,7 @@ static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd,
1505 1533
1506 /* 5. - 9. */ 1534 /* 5. - 9. */
1507 ret = client_scale(icd, cam_rect, &cam_subrect, &ceu_rect, &mf, 1535 ret = client_scale(icd, cam_rect, &cam_subrect, &ceu_rect, &mf,
1508 image_mode && !is_interlaced); 1536 image_mode && V4L2_FIELD_NONE == field);
1509 1537
1510 dev_geo(dev, "5-9: client scale %d\n", ret); 1538 dev_geo(dev, "5-9: client scale %d\n", ret);
1511 1539
@@ -1555,7 +1583,7 @@ static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd,
1555 cam->ceu_rect = ceu_rect; 1583 cam->ceu_rect = ceu_rect;
1556 icd->current_fmt = xlate; 1584 icd->current_fmt = xlate;
1557 1585
1558 pcdev->is_interlaced = is_interlaced; 1586 pcdev->field = field;
1559 pcdev->image_mode = image_mode; 1587 pcdev->image_mode = image_mode;
1560 1588
1561 return 0; 1589 return 0;
@@ -1698,8 +1726,7 @@ static void sh_mobile_ceu_init_videobuf(struct videobuf_queue *q,
1698 &sh_mobile_ceu_videobuf_ops, 1726 &sh_mobile_ceu_videobuf_ops,
1699 icd->dev.parent, &pcdev->lock, 1727 icd->dev.parent, &pcdev->lock,
1700 V4L2_BUF_TYPE_VIDEO_CAPTURE, 1728 V4L2_BUF_TYPE_VIDEO_CAPTURE,
1701 pcdev->is_interlaced ? 1729 pcdev->field,
1702 V4L2_FIELD_INTERLACED : V4L2_FIELD_NONE,
1703 sizeof(struct sh_mobile_ceu_buffer), 1730 sizeof(struct sh_mobile_ceu_buffer),
1704 icd); 1731 icd);
1705} 1732}