diff options
author | Scott Jiang <scott.jiang.linux@gmail.com> | 2012-11-20 13:49:36 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-12-26 07:33:44 -0500 |
commit | 45b82596be0214f161c8176bd3e18f779e36eccd (patch) | |
tree | 15f8f8faec4191f6d4df58af8f4b52b131ef36e0 /drivers/media/platform/blackfin | |
parent | fab0e8fa432e42d7b5c91a3d4c8af053f291a65a (diff) |
[media] v4l2: blackfin: add EPPI3 support
Bf60x soc has a new PPI called Enhanced PPI version 3.
HD video is supported now. To achieve this, we redesign
ppi params and add dv timings feature.
Signed-off-by: Scott Jiang <scott.jiang.linux@gmail.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/platform/blackfin')
-rw-r--r-- | drivers/media/platform/blackfin/bfin_capture.c | 148 | ||||
-rw-r--r-- | drivers/media/platform/blackfin/ppi.c | 72 |
2 files changed, 192 insertions, 28 deletions
diff --git a/drivers/media/platform/blackfin/bfin_capture.c b/drivers/media/platform/blackfin/bfin_capture.c index d422d3c379e4..aa9f846a667e 100644 --- a/drivers/media/platform/blackfin/bfin_capture.c +++ b/drivers/media/platform/blackfin/bfin_capture.c | |||
@@ -52,6 +52,7 @@ struct bcap_format { | |||
52 | u32 pixelformat; | 52 | u32 pixelformat; |
53 | enum v4l2_mbus_pixelcode mbus_code; | 53 | enum v4l2_mbus_pixelcode mbus_code; |
54 | int bpp; /* bits per pixel */ | 54 | int bpp; /* bits per pixel */ |
55 | int dlen; /* data length for ppi in bits */ | ||
55 | }; | 56 | }; |
56 | 57 | ||
57 | struct bcap_buffer { | 58 | struct bcap_buffer { |
@@ -76,10 +77,14 @@ struct bcap_device { | |||
76 | unsigned int cur_input; | 77 | unsigned int cur_input; |
77 | /* current selected standard */ | 78 | /* current selected standard */ |
78 | v4l2_std_id std; | 79 | v4l2_std_id std; |
80 | /* current selected dv_timings */ | ||
81 | struct v4l2_dv_timings dv_timings; | ||
79 | /* used to store pixel format */ | 82 | /* used to store pixel format */ |
80 | struct v4l2_pix_format fmt; | 83 | struct v4l2_pix_format fmt; |
81 | /* bits per pixel*/ | 84 | /* bits per pixel*/ |
82 | int bpp; | 85 | int bpp; |
86 | /* data length for ppi in bits */ | ||
87 | int dlen; | ||
83 | /* used to store sensor supported format */ | 88 | /* used to store sensor supported format */ |
84 | struct bcap_format *sensor_formats; | 89 | struct bcap_format *sensor_formats; |
85 | /* number of sensor formats array */ | 90 | /* number of sensor formats array */ |
@@ -116,24 +121,35 @@ static const struct bcap_format bcap_formats[] = { | |||
116 | .pixelformat = V4L2_PIX_FMT_UYVY, | 121 | .pixelformat = V4L2_PIX_FMT_UYVY, |
117 | .mbus_code = V4L2_MBUS_FMT_UYVY8_2X8, | 122 | .mbus_code = V4L2_MBUS_FMT_UYVY8_2X8, |
118 | .bpp = 16, | 123 | .bpp = 16, |
124 | .dlen = 8, | ||
119 | }, | 125 | }, |
120 | { | 126 | { |
121 | .desc = "YCbCr 4:2:2 Interleaved YUYV", | 127 | .desc = "YCbCr 4:2:2 Interleaved YUYV", |
122 | .pixelformat = V4L2_PIX_FMT_YUYV, | 128 | .pixelformat = V4L2_PIX_FMT_YUYV, |
123 | .mbus_code = V4L2_MBUS_FMT_YUYV8_2X8, | 129 | .mbus_code = V4L2_MBUS_FMT_YUYV8_2X8, |
124 | .bpp = 16, | 130 | .bpp = 16, |
131 | .dlen = 8, | ||
132 | }, | ||
133 | { | ||
134 | .desc = "YCbCr 4:2:2 Interleaved UYVY", | ||
135 | .pixelformat = V4L2_PIX_FMT_UYVY, | ||
136 | .mbus_code = V4L2_MBUS_FMT_UYVY8_1X16, | ||
137 | .bpp = 16, | ||
138 | .dlen = 16, | ||
125 | }, | 139 | }, |
126 | { | 140 | { |
127 | .desc = "RGB 565", | 141 | .desc = "RGB 565", |
128 | .pixelformat = V4L2_PIX_FMT_RGB565, | 142 | .pixelformat = V4L2_PIX_FMT_RGB565, |
129 | .mbus_code = V4L2_MBUS_FMT_RGB565_2X8_LE, | 143 | .mbus_code = V4L2_MBUS_FMT_RGB565_2X8_LE, |
130 | .bpp = 16, | 144 | .bpp = 16, |
145 | .dlen = 8, | ||
131 | }, | 146 | }, |
132 | { | 147 | { |
133 | .desc = "RGB 444", | 148 | .desc = "RGB 444", |
134 | .pixelformat = V4L2_PIX_FMT_RGB444, | 149 | .pixelformat = V4L2_PIX_FMT_RGB444, |
135 | .mbus_code = V4L2_MBUS_FMT_RGB444_2X8_PADHI_LE, | 150 | .mbus_code = V4L2_MBUS_FMT_RGB444_2X8_PADHI_LE, |
136 | .bpp = 16, | 151 | .bpp = 16, |
152 | .dlen = 8, | ||
137 | }, | 153 | }, |
138 | 154 | ||
139 | }; | 155 | }; |
@@ -366,9 +382,39 @@ static int bcap_start_streaming(struct vb2_queue *vq, unsigned int count) | |||
366 | params.width = bcap_dev->fmt.width; | 382 | params.width = bcap_dev->fmt.width; |
367 | params.height = bcap_dev->fmt.height; | 383 | params.height = bcap_dev->fmt.height; |
368 | params.bpp = bcap_dev->bpp; | 384 | params.bpp = bcap_dev->bpp; |
385 | params.dlen = bcap_dev->dlen; | ||
369 | params.ppi_control = bcap_dev->cfg->ppi_control; | 386 | params.ppi_control = bcap_dev->cfg->ppi_control; |
370 | params.int_mask = bcap_dev->cfg->int_mask; | 387 | params.int_mask = bcap_dev->cfg->int_mask; |
371 | params.blank_clocks = bcap_dev->cfg->blank_clocks; | 388 | if (bcap_dev->cfg->inputs[bcap_dev->cur_input].capabilities |
389 | & V4L2_IN_CAP_CUSTOM_TIMINGS) { | ||
390 | struct v4l2_bt_timings *bt = &bcap_dev->dv_timings.bt; | ||
391 | |||
392 | params.hdelay = bt->hsync + bt->hbackporch; | ||
393 | params.vdelay = bt->vsync + bt->vbackporch; | ||
394 | params.line = bt->hfrontporch + bt->hsync | ||
395 | + bt->hbackporch + bt->width; | ||
396 | params.frame = bt->vfrontporch + bt->vsync | ||
397 | + bt->vbackporch + bt->height; | ||
398 | if (bt->interlaced) | ||
399 | params.frame += bt->il_vfrontporch + bt->il_vsync | ||
400 | + bt->il_vbackporch; | ||
401 | } else if (bcap_dev->cfg->inputs[bcap_dev->cur_input].capabilities | ||
402 | & V4L2_IN_CAP_STD) { | ||
403 | params.hdelay = 0; | ||
404 | params.vdelay = 0; | ||
405 | if (bcap_dev->std & V4L2_STD_525_60) { | ||
406 | params.line = 858; | ||
407 | params.frame = 525; | ||
408 | } else { | ||
409 | params.line = 864; | ||
410 | params.frame = 625; | ||
411 | } | ||
412 | } else { | ||
413 | params.hdelay = 0; | ||
414 | params.vdelay = 0; | ||
415 | params.line = params.width + bcap_dev->cfg->blank_pixels; | ||
416 | params.frame = params.height; | ||
417 | } | ||
372 | ret = ppi->ops->set_params(ppi, ¶ms); | 418 | ret = ppi->ops->set_params(ppi, ¶ms); |
373 | if (ret < 0) { | 419 | if (ret < 0) { |
374 | v4l2_err(&bcap_dev->v4l2_dev, | 420 | v4l2_err(&bcap_dev->v4l2_dev, |
@@ -600,6 +646,37 @@ static int bcap_s_std(struct file *file, void *priv, v4l2_std_id *std) | |||
600 | return 0; | 646 | return 0; |
601 | } | 647 | } |
602 | 648 | ||
649 | static int bcap_g_dv_timings(struct file *file, void *priv, | ||
650 | struct v4l2_dv_timings *timings) | ||
651 | { | ||
652 | struct bcap_device *bcap_dev = video_drvdata(file); | ||
653 | int ret; | ||
654 | |||
655 | ret = v4l2_subdev_call(bcap_dev->sd, video, | ||
656 | g_dv_timings, timings); | ||
657 | if (ret < 0) | ||
658 | return ret; | ||
659 | |||
660 | bcap_dev->dv_timings = *timings; | ||
661 | return 0; | ||
662 | } | ||
663 | |||
664 | static int bcap_s_dv_timings(struct file *file, void *priv, | ||
665 | struct v4l2_dv_timings *timings) | ||
666 | { | ||
667 | struct bcap_device *bcap_dev = video_drvdata(file); | ||
668 | int ret; | ||
669 | if (vb2_is_busy(&bcap_dev->buffer_queue)) | ||
670 | return -EBUSY; | ||
671 | |||
672 | ret = v4l2_subdev_call(bcap_dev->sd, video, s_dv_timings, timings); | ||
673 | if (ret < 0) | ||
674 | return ret; | ||
675 | |||
676 | bcap_dev->dv_timings = *timings; | ||
677 | return 0; | ||
678 | } | ||
679 | |||
603 | static int bcap_enum_input(struct file *file, void *priv, | 680 | static int bcap_enum_input(struct file *file, void *priv, |
604 | struct v4l2_input *input) | 681 | struct v4l2_input *input) |
605 | { | 682 | { |
@@ -648,13 +725,15 @@ static int bcap_s_input(struct file *file, void *priv, unsigned int index) | |||
648 | return ret; | 725 | return ret; |
649 | } | 726 | } |
650 | bcap_dev->cur_input = index; | 727 | bcap_dev->cur_input = index; |
728 | /* if this route has specific config, update ppi control */ | ||
729 | if (route->ppi_control) | ||
730 | config->ppi_control = route->ppi_control; | ||
651 | return 0; | 731 | return 0; |
652 | } | 732 | } |
653 | 733 | ||
654 | static int bcap_try_format(struct bcap_device *bcap, | 734 | static int bcap_try_format(struct bcap_device *bcap, |
655 | struct v4l2_pix_format *pixfmt, | 735 | struct v4l2_pix_format *pixfmt, |
656 | enum v4l2_mbus_pixelcode *mbus_code, | 736 | struct bcap_format *bcap_fmt) |
657 | int *bpp) | ||
658 | { | 737 | { |
659 | struct bcap_format *sf = bcap->sensor_formats; | 738 | struct bcap_format *sf = bcap->sensor_formats; |
660 | struct bcap_format *fmt = NULL; | 739 | struct bcap_format *fmt = NULL; |
@@ -669,16 +748,20 @@ static int bcap_try_format(struct bcap_device *bcap, | |||
669 | if (i == bcap->num_sensor_formats) | 748 | if (i == bcap->num_sensor_formats) |
670 | fmt = &sf[0]; | 749 | fmt = &sf[0]; |
671 | 750 | ||
672 | if (mbus_code) | ||
673 | *mbus_code = fmt->mbus_code; | ||
674 | if (bpp) | ||
675 | *bpp = fmt->bpp; | ||
676 | v4l2_fill_mbus_format(&mbus_fmt, pixfmt, fmt->mbus_code); | 751 | v4l2_fill_mbus_format(&mbus_fmt, pixfmt, fmt->mbus_code); |
677 | ret = v4l2_subdev_call(bcap->sd, video, | 752 | ret = v4l2_subdev_call(bcap->sd, video, |
678 | try_mbus_fmt, &mbus_fmt); | 753 | try_mbus_fmt, &mbus_fmt); |
679 | if (ret < 0) | 754 | if (ret < 0) |
680 | return ret; | 755 | return ret; |
681 | v4l2_fill_pix_format(pixfmt, &mbus_fmt); | 756 | v4l2_fill_pix_format(pixfmt, &mbus_fmt); |
757 | if (bcap_fmt) { | ||
758 | for (i = 0; i < bcap->num_sensor_formats; i++) { | ||
759 | fmt = &sf[i]; | ||
760 | if (mbus_fmt.code == fmt->mbus_code) | ||
761 | break; | ||
762 | } | ||
763 | *bcap_fmt = *fmt; | ||
764 | } | ||
682 | pixfmt->bytesperline = pixfmt->width * fmt->bpp / 8; | 765 | pixfmt->bytesperline = pixfmt->width * fmt->bpp / 8; |
683 | pixfmt->sizeimage = pixfmt->bytesperline * pixfmt->height; | 766 | pixfmt->sizeimage = pixfmt->bytesperline * pixfmt->height; |
684 | return 0; | 767 | return 0; |
@@ -707,7 +790,7 @@ static int bcap_try_fmt_vid_cap(struct file *file, void *priv, | |||
707 | struct bcap_device *bcap_dev = video_drvdata(file); | 790 | struct bcap_device *bcap_dev = video_drvdata(file); |
708 | struct v4l2_pix_format *pixfmt = &fmt->fmt.pix; | 791 | struct v4l2_pix_format *pixfmt = &fmt->fmt.pix; |
709 | 792 | ||
710 | return bcap_try_format(bcap_dev, pixfmt, NULL, NULL); | 793 | return bcap_try_format(bcap_dev, pixfmt, NULL); |
711 | } | 794 | } |
712 | 795 | ||
713 | static int bcap_g_fmt_vid_cap(struct file *file, void *priv, | 796 | static int bcap_g_fmt_vid_cap(struct file *file, void *priv, |
@@ -724,24 +807,25 @@ static int bcap_s_fmt_vid_cap(struct file *file, void *priv, | |||
724 | { | 807 | { |
725 | struct bcap_device *bcap_dev = video_drvdata(file); | 808 | struct bcap_device *bcap_dev = video_drvdata(file); |
726 | struct v4l2_mbus_framefmt mbus_fmt; | 809 | struct v4l2_mbus_framefmt mbus_fmt; |
727 | enum v4l2_mbus_pixelcode mbus_code; | 810 | struct bcap_format bcap_fmt; |
728 | struct v4l2_pix_format *pixfmt = &fmt->fmt.pix; | 811 | struct v4l2_pix_format *pixfmt = &fmt->fmt.pix; |
729 | int ret, bpp; | 812 | int ret; |
730 | 813 | ||
731 | if (vb2_is_busy(&bcap_dev->buffer_queue)) | 814 | if (vb2_is_busy(&bcap_dev->buffer_queue)) |
732 | return -EBUSY; | 815 | return -EBUSY; |
733 | 816 | ||
734 | /* see if format works */ | 817 | /* see if format works */ |
735 | ret = bcap_try_format(bcap_dev, pixfmt, &mbus_code, &bpp); | 818 | ret = bcap_try_format(bcap_dev, pixfmt, &bcap_fmt); |
736 | if (ret < 0) | 819 | if (ret < 0) |
737 | return ret; | 820 | return ret; |
738 | 821 | ||
739 | v4l2_fill_mbus_format(&mbus_fmt, pixfmt, mbus_code); | 822 | v4l2_fill_mbus_format(&mbus_fmt, pixfmt, bcap_fmt.mbus_code); |
740 | ret = v4l2_subdev_call(bcap_dev->sd, video, s_mbus_fmt, &mbus_fmt); | 823 | ret = v4l2_subdev_call(bcap_dev->sd, video, s_mbus_fmt, &mbus_fmt); |
741 | if (ret < 0) | 824 | if (ret < 0) |
742 | return ret; | 825 | return ret; |
743 | bcap_dev->fmt = *pixfmt; | 826 | bcap_dev->fmt = *pixfmt; |
744 | bcap_dev->bpp = bpp; | 827 | bcap_dev->bpp = bcap_fmt.bpp; |
828 | bcap_dev->dlen = bcap_fmt.dlen; | ||
745 | return 0; | 829 | return 0; |
746 | } | 830 | } |
747 | 831 | ||
@@ -832,6 +916,8 @@ static const struct v4l2_ioctl_ops bcap_ioctl_ops = { | |||
832 | .vidioc_querystd = bcap_querystd, | 916 | .vidioc_querystd = bcap_querystd, |
833 | .vidioc_s_std = bcap_s_std, | 917 | .vidioc_s_std = bcap_s_std, |
834 | .vidioc_g_std = bcap_g_std, | 918 | .vidioc_g_std = bcap_g_std, |
919 | .vidioc_s_dv_timings = bcap_s_dv_timings, | ||
920 | .vidioc_g_dv_timings = bcap_g_dv_timings, | ||
835 | .vidioc_reqbufs = bcap_reqbufs, | 921 | .vidioc_reqbufs = bcap_reqbufs, |
836 | .vidioc_querybuf = bcap_querybuf, | 922 | .vidioc_querybuf = bcap_querybuf, |
837 | .vidioc_qbuf = bcap_qbuf, | 923 | .vidioc_qbuf = bcap_qbuf, |
@@ -867,6 +953,7 @@ static int __devinit bcap_probe(struct platform_device *pdev) | |||
867 | struct i2c_adapter *i2c_adap; | 953 | struct i2c_adapter *i2c_adap; |
868 | struct bfin_capture_config *config; | 954 | struct bfin_capture_config *config; |
869 | struct vb2_queue *q; | 955 | struct vb2_queue *q; |
956 | struct bcap_route *route; | ||
870 | int ret; | 957 | int ret; |
871 | 958 | ||
872 | config = pdev->dev.platform_data; | 959 | config = pdev->dev.platform_data; |
@@ -976,6 +1063,12 @@ static int __devinit bcap_probe(struct platform_device *pdev) | |||
976 | NULL); | 1063 | NULL); |
977 | if (bcap_dev->sd) { | 1064 | if (bcap_dev->sd) { |
978 | int i; | 1065 | int i; |
1066 | if (!config->num_inputs) { | ||
1067 | v4l2_err(&bcap_dev->v4l2_dev, | ||
1068 | "Unable to work without input\n"); | ||
1069 | goto err_unreg_vdev; | ||
1070 | } | ||
1071 | |||
979 | /* update tvnorms from the sub devices */ | 1072 | /* update tvnorms from the sub devices */ |
980 | for (i = 0; i < config->num_inputs; i++) | 1073 | for (i = 0; i < config->num_inputs; i++) |
981 | vfd->tvnorms |= config->inputs[i].std; | 1074 | vfd->tvnorms |= config->inputs[i].std; |
@@ -987,8 +1080,24 @@ static int __devinit bcap_probe(struct platform_device *pdev) | |||
987 | 1080 | ||
988 | v4l2_info(&bcap_dev->v4l2_dev, "v4l2 sub device registered\n"); | 1081 | v4l2_info(&bcap_dev->v4l2_dev, "v4l2 sub device registered\n"); |
989 | 1082 | ||
1083 | /* | ||
1084 | * explicitly set input, otherwise some boards | ||
1085 | * may not work at the state as we expected | ||
1086 | */ | ||
1087 | route = &config->routes[0]; | ||
1088 | ret = v4l2_subdev_call(bcap_dev->sd, video, s_routing, | ||
1089 | route->input, route->output, 0); | ||
1090 | if ((ret < 0) && (ret != -ENOIOCTLCMD)) { | ||
1091 | v4l2_err(&bcap_dev->v4l2_dev, "Failed to set input\n"); | ||
1092 | goto err_unreg_vdev; | ||
1093 | } | ||
1094 | bcap_dev->cur_input = 0; | ||
1095 | /* if this route has specific config, update ppi control */ | ||
1096 | if (route->ppi_control) | ||
1097 | config->ppi_control = route->ppi_control; | ||
1098 | |||
990 | /* now we can probe the default state */ | 1099 | /* now we can probe the default state */ |
991 | if (vfd->tvnorms) { | 1100 | if (config->inputs[0].capabilities & V4L2_IN_CAP_STD) { |
992 | v4l2_std_id std; | 1101 | v4l2_std_id std; |
993 | ret = v4l2_subdev_call(bcap_dev->sd, core, g_std, &std); | 1102 | ret = v4l2_subdev_call(bcap_dev->sd, core, g_std, &std); |
994 | if (ret) { | 1103 | if (ret) { |
@@ -998,6 +1107,17 @@ static int __devinit bcap_probe(struct platform_device *pdev) | |||
998 | } | 1107 | } |
999 | bcap_dev->std = std; | 1108 | bcap_dev->std = std; |
1000 | } | 1109 | } |
1110 | if (config->inputs[0].capabilities & V4L2_IN_CAP_CUSTOM_TIMINGS) { | ||
1111 | struct v4l2_dv_timings dv_timings; | ||
1112 | ret = v4l2_subdev_call(bcap_dev->sd, video, | ||
1113 | g_dv_timings, &dv_timings); | ||
1114 | if (ret) { | ||
1115 | v4l2_err(&bcap_dev->v4l2_dev, | ||
1116 | "Unable to get dv timings\n"); | ||
1117 | goto err_unreg_vdev; | ||
1118 | } | ||
1119 | bcap_dev->dv_timings = dv_timings; | ||
1120 | } | ||
1001 | ret = bcap_init_sensor_formats(bcap_dev); | 1121 | ret = bcap_init_sensor_formats(bcap_dev); |
1002 | if (ret) { | 1122 | if (ret) { |
1003 | v4l2_err(&bcap_dev->v4l2_dev, | 1123 | v4l2_err(&bcap_dev->v4l2_dev, |
diff --git a/drivers/media/platform/blackfin/ppi.c b/drivers/media/platform/blackfin/ppi.c index 9374d676f63d..1e24584605f2 100644 --- a/drivers/media/platform/blackfin/ppi.c +++ b/drivers/media/platform/blackfin/ppi.c | |||
@@ -68,6 +68,13 @@ static irqreturn_t ppi_irq_err(int irq, void *dev_id) | |||
68 | bfin_write16(®->status, 0xffff); | 68 | bfin_write16(®->status, 0xffff); |
69 | break; | 69 | break; |
70 | } | 70 | } |
71 | case PPI_TYPE_EPPI3: | ||
72 | { | ||
73 | struct bfin_eppi3_regs *reg = info->base; | ||
74 | |||
75 | bfin_write32(®->stat, 0xc0ff); | ||
76 | break; | ||
77 | } | ||
71 | default: | 78 | default: |
72 | break; | 79 | break; |
73 | } | 80 | } |
@@ -129,6 +136,12 @@ static int ppi_start(struct ppi_if *ppi) | |||
129 | bfin_write32(®->control, ppi->ppi_control); | 136 | bfin_write32(®->control, ppi->ppi_control); |
130 | break; | 137 | break; |
131 | } | 138 | } |
139 | case PPI_TYPE_EPPI3: | ||
140 | { | ||
141 | struct bfin_eppi3_regs *reg = info->base; | ||
142 | bfin_write32(®->ctl, ppi->ppi_control); | ||
143 | break; | ||
144 | } | ||
132 | default: | 145 | default: |
133 | return -EINVAL; | 146 | return -EINVAL; |
134 | } | 147 | } |
@@ -156,6 +169,12 @@ static int ppi_stop(struct ppi_if *ppi) | |||
156 | bfin_write32(®->control, ppi->ppi_control); | 169 | bfin_write32(®->control, ppi->ppi_control); |
157 | break; | 170 | break; |
158 | } | 171 | } |
172 | case PPI_TYPE_EPPI3: | ||
173 | { | ||
174 | struct bfin_eppi3_regs *reg = info->base; | ||
175 | bfin_write32(®->ctl, ppi->ppi_control); | ||
176 | break; | ||
177 | } | ||
159 | default: | 178 | default: |
160 | return -EINVAL; | 179 | return -EINVAL; |
161 | } | 180 | } |
@@ -172,17 +191,23 @@ static int ppi_set_params(struct ppi_if *ppi, struct ppi_params *params) | |||
172 | { | 191 | { |
173 | const struct ppi_info *info = ppi->info; | 192 | const struct ppi_info *info = ppi->info; |
174 | int dma32 = 0; | 193 | int dma32 = 0; |
175 | int dma_config, bytes_per_line, lines_per_frame; | 194 | int dma_config, bytes_per_line; |
195 | int hcount, hdelay, samples_per_line; | ||
176 | 196 | ||
177 | bytes_per_line = params->width * params->bpp / 8; | 197 | bytes_per_line = params->width * params->bpp / 8; |
178 | lines_per_frame = params->height; | 198 | /* convert parameters unit from pixels to samples */ |
199 | hcount = params->width * params->bpp / params->dlen; | ||
200 | hdelay = params->hdelay * params->bpp / params->dlen; | ||
201 | samples_per_line = params->line * params->bpp / params->dlen; | ||
179 | if (params->int_mask == 0xFFFFFFFF) | 202 | if (params->int_mask == 0xFFFFFFFF) |
180 | ppi->err_int = false; | 203 | ppi->err_int = false; |
181 | else | 204 | else |
182 | ppi->err_int = true; | 205 | ppi->err_int = true; |
183 | 206 | ||
184 | dma_config = (DMA_FLOW_STOP | WNR | RESTART | DMA2D | DI_EN); | 207 | dma_config = (DMA_FLOW_STOP | RESTART | DMA2D | DI_EN_Y); |
185 | ppi->ppi_control = params->ppi_control & ~PORT_EN; | 208 | ppi->ppi_control = params->ppi_control & ~PORT_EN; |
209 | if (!(ppi->ppi_control & PORT_DIR)) | ||
210 | dma_config |= WNR; | ||
186 | switch (info->type) { | 211 | switch (info->type) { |
187 | case PPI_TYPE_PPI: | 212 | case PPI_TYPE_PPI: |
188 | { | 213 | { |
@@ -192,8 +217,8 @@ static int ppi_set_params(struct ppi_if *ppi, struct ppi_params *params) | |||
192 | dma32 = 1; | 217 | dma32 = 1; |
193 | 218 | ||
194 | bfin_write16(®->control, ppi->ppi_control); | 219 | bfin_write16(®->control, ppi->ppi_control); |
195 | bfin_write16(®->count, bytes_per_line - 1); | 220 | bfin_write16(®->count, samples_per_line - 1); |
196 | bfin_write16(®->frame, lines_per_frame); | 221 | bfin_write16(®->frame, params->frame); |
197 | break; | 222 | break; |
198 | } | 223 | } |
199 | case PPI_TYPE_EPPI: | 224 | case PPI_TYPE_EPPI: |
@@ -205,12 +230,31 @@ static int ppi_set_params(struct ppi_if *ppi, struct ppi_params *params) | |||
205 | dma32 = 1; | 230 | dma32 = 1; |
206 | 231 | ||
207 | bfin_write32(®->control, ppi->ppi_control); | 232 | bfin_write32(®->control, ppi->ppi_control); |
208 | bfin_write16(®->line, bytes_per_line + params->blank_clocks); | 233 | bfin_write16(®->line, samples_per_line); |
209 | bfin_write16(®->frame, lines_per_frame); | 234 | bfin_write16(®->frame, params->frame); |
210 | bfin_write16(®->hdelay, 0); | 235 | bfin_write16(®->hdelay, hdelay); |
211 | bfin_write16(®->vdelay, 0); | 236 | bfin_write16(®->vdelay, params->vdelay); |
212 | bfin_write16(®->hcount, bytes_per_line); | 237 | bfin_write16(®->hcount, hcount); |
213 | bfin_write16(®->vcount, lines_per_frame); | 238 | bfin_write16(®->vcount, params->height); |
239 | break; | ||
240 | } | ||
241 | case PPI_TYPE_EPPI3: | ||
242 | { | ||
243 | struct bfin_eppi3_regs *reg = info->base; | ||
244 | |||
245 | if ((params->ppi_control & PACK_EN) | ||
246 | || (params->ppi_control & 0x70000) > DLEN_16) | ||
247 | dma32 = 1; | ||
248 | |||
249 | bfin_write32(®->ctl, ppi->ppi_control); | ||
250 | bfin_write32(®->line, samples_per_line); | ||
251 | bfin_write32(®->frame, params->frame); | ||
252 | bfin_write32(®->hdly, hdelay); | ||
253 | bfin_write32(®->vdly, params->vdelay); | ||
254 | bfin_write32(®->hcnt, hcount); | ||
255 | bfin_write32(®->vcnt, params->height); | ||
256 | if (params->int_mask) | ||
257 | bfin_write32(®->imsk, params->int_mask & 0xFF); | ||
214 | break; | 258 | break; |
215 | } | 259 | } |
216 | default: | 260 | default: |
@@ -218,17 +262,17 @@ static int ppi_set_params(struct ppi_if *ppi, struct ppi_params *params) | |||
218 | } | 262 | } |
219 | 263 | ||
220 | if (dma32) { | 264 | if (dma32) { |
221 | dma_config |= WDSIZE_32; | 265 | dma_config |= WDSIZE_32 | PSIZE_32; |
222 | set_dma_x_count(info->dma_ch, bytes_per_line >> 2); | 266 | set_dma_x_count(info->dma_ch, bytes_per_line >> 2); |
223 | set_dma_x_modify(info->dma_ch, 4); | 267 | set_dma_x_modify(info->dma_ch, 4); |
224 | set_dma_y_modify(info->dma_ch, 4); | 268 | set_dma_y_modify(info->dma_ch, 4); |
225 | } else { | 269 | } else { |
226 | dma_config |= WDSIZE_16; | 270 | dma_config |= WDSIZE_16 | PSIZE_16; |
227 | set_dma_x_count(info->dma_ch, bytes_per_line >> 1); | 271 | set_dma_x_count(info->dma_ch, bytes_per_line >> 1); |
228 | set_dma_x_modify(info->dma_ch, 2); | 272 | set_dma_x_modify(info->dma_ch, 2); |
229 | set_dma_y_modify(info->dma_ch, 2); | 273 | set_dma_y_modify(info->dma_ch, 2); |
230 | } | 274 | } |
231 | set_dma_y_count(info->dma_ch, lines_per_frame); | 275 | set_dma_y_count(info->dma_ch, params->height); |
232 | set_dma_config(info->dma_ch, dma_config); | 276 | set_dma_config(info->dma_ch, dma_config); |
233 | 277 | ||
234 | SSYNC(); | 278 | SSYNC(); |