diff options
author | Kuninori Morimoto <morimoto.kuninori@renesas.com> | 2009-12-11 09:53:53 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-12-16 06:27:32 -0500 |
commit | 1edcc10d7f4fd4085fcdcdd68afec258c3427530 (patch) | |
tree | 91912304d333950b9d6e2bbfdd6fb187c5444dbc /drivers/media | |
parent | a3a4ac14774786bef160ea380bd75307a144a5e9 (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')
-rw-r--r-- | drivers/media/video/sh_mobile_ceu_camera.c | 75 |
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 273ad34f9d8d..df8dc1dde19f 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 | } |