aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEzequiel Garcia <ezequiel@vanguardiasur.com.ar>2016-08-04 18:00:22 -0400
committerMauro Carvalho Chehab <mchehab@s-opensource.com>2016-08-24 07:45:38 -0400
commit95ad747e925299690c63bcc96c3f9bca640865bd (patch)
tree816aff2faee5becbb2f9b99c196a6944e64163f7
parent926605d05c9d5f9d43e17f0fc3dc906473325755 (diff)
[media] media: tw686x: Rework initial hardware configuration
Currently, the hardware is not given a complete initial configuration. In order to fix this, this rather large commit reworks standard, frame format and input configuration. While at it, we introduce proper functions to configure each parameter, and as a result the code is a bit cleaner. Reported-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Ezequiel Garcia <ezequiel@vanguardiasur.com.ar> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
-rw-r--r--drivers/media/pci/tw686x/tw686x-video.c139
1 files changed, 81 insertions, 58 deletions
diff --git a/drivers/media/pci/tw686x/tw686x-video.c b/drivers/media/pci/tw686x/tw686x-video.c
index cdb16de770fe..be257d0257a6 100644
--- a/drivers/media/pci/tw686x/tw686x-video.c
+++ b/drivers/media/pci/tw686x/tw686x-video.c
@@ -672,30 +672,20 @@ static int tw686x_try_fmt_vid_cap(struct file *file, void *priv,
672 return 0; 672 return 0;
673} 673}
674 674
675static int tw686x_s_fmt_vid_cap(struct file *file, void *priv, 675static int tw686x_set_format(struct tw686x_video_channel *vc,
676 struct v4l2_format *f) 676 unsigned int pixelformat, unsigned int width,
677 unsigned int height, bool realloc)
677{ 678{
678 struct tw686x_video_channel *vc = video_drvdata(file);
679 struct tw686x_dev *dev = vc->dev; 679 struct tw686x_dev *dev = vc->dev;
680 u32 val, width, line_width, height; 680 u32 val, dma_width, dma_height, dma_line_width;
681 unsigned long bitsperframe;
682 int err, pb; 681 int err, pb;
683 682
684 if (vb2_is_busy(&vc->vidq)) 683 vc->format = format_by_fourcc(pixelformat);
685 return -EBUSY; 684 vc->width = width;
686 685 vc->height = height;
687 bitsperframe = vc->width * vc->height * vc->format->depth;
688 err = tw686x_try_fmt_vid_cap(file, priv, f);
689 if (err)
690 return err;
691
692 vc->format = format_by_fourcc(f->fmt.pix.pixelformat);
693 vc->width = f->fmt.pix.width;
694 vc->height = f->fmt.pix.height;
695 686
696 /* We need new DMA buffers if the framesize has changed */ 687 /* We need new DMA buffers if the framesize has changed */
697 if (dev->dma_ops->alloc && 688 if (dev->dma_ops->alloc && realloc) {
698 bitsperframe != vc->width * vc->height * vc->format->depth) {
699 for (pb = 0; pb < 2; pb++) 689 for (pb = 0; pb < 2; pb++)
700 dev->dma_ops->free(vc, pb); 690 dev->dma_ops->free(vc, pb);
701 691
@@ -739,14 +729,36 @@ static int tw686x_s_fmt_vid_cap(struct file *file, void *priv,
739 reg_write(vc->dev, VDMA_CHANNEL_CONFIG[vc->ch], val); 729 reg_write(vc->dev, VDMA_CHANNEL_CONFIG[vc->ch], val);
740 730
741 /* Program the DMA frame size */ 731 /* Program the DMA frame size */
742 width = (vc->width * 2) & 0x7ff; 732 dma_width = (vc->width * 2) & 0x7ff;
743 height = vc->height / 2; 733 dma_height = vc->height / 2;
744 line_width = (vc->width * 2) & 0x7ff; 734 dma_line_width = (vc->width * 2) & 0x7ff;
745 val = (height << 22) | (line_width << 11) | width; 735 val = (dma_height << 22) | (dma_line_width << 11) | dma_width;
746 reg_write(vc->dev, VDMA_WHP[vc->ch], val); 736 reg_write(vc->dev, VDMA_WHP[vc->ch], val);
747 return 0; 737 return 0;
748} 738}
749 739
740static int tw686x_s_fmt_vid_cap(struct file *file, void *priv,
741 struct v4l2_format *f)
742{
743 struct tw686x_video_channel *vc = video_drvdata(file);
744 unsigned long area;
745 bool realloc;
746 int err;
747
748 if (vb2_is_busy(&vc->vidq))
749 return -EBUSY;
750
751 area = vc->width * vc->height;
752 err = tw686x_try_fmt_vid_cap(file, priv, f);
753 if (err)
754 return err;
755
756 realloc = area != (f->fmt.pix.width * f->fmt.pix.height);
757 return tw686x_set_format(vc, f->fmt.pix.pixelformat,
758 f->fmt.pix.width, f->fmt.pix.height,
759 realloc);
760}
761
750static int tw686x_querycap(struct file *file, void *priv, 762static int tw686x_querycap(struct file *file, void *priv,
751 struct v4l2_capability *cap) 763 struct v4l2_capability *cap)
752{ 764{
@@ -763,17 +775,9 @@ static int tw686x_querycap(struct file *file, void *priv,
763 return 0; 775 return 0;
764} 776}
765 777
766static int tw686x_s_std(struct file *file, void *priv, v4l2_std_id id) 778static int tw686x_set_standard(struct tw686x_video_channel *vc, v4l2_std_id id)
767{ 779{
768 struct tw686x_video_channel *vc = video_drvdata(file); 780 u32 val;
769 struct v4l2_format f;
770 u32 val, ret;
771
772 if (vc->video_standard == id)
773 return 0;
774
775 if (vb2_is_busy(&vc->vidq))
776 return -EBUSY;
777 781
778 if (id & V4L2_STD_NTSC) 782 if (id & V4L2_STD_NTSC)
779 val = 0; 783 val = 0;
@@ -802,14 +806,31 @@ static int tw686x_s_std(struct file *file, void *priv, v4l2_std_id id)
802 val |= (1 << (SYS_MODE_DMA_SHIFT + vc->ch)); 806 val |= (1 << (SYS_MODE_DMA_SHIFT + vc->ch));
803 reg_write(vc->dev, VIDEO_CONTROL1, val); 807 reg_write(vc->dev, VIDEO_CONTROL1, val);
804 808
809 return 0;
810}
811
812static int tw686x_s_std(struct file *file, void *priv, v4l2_std_id id)
813{
814 struct tw686x_video_channel *vc = video_drvdata(file);
815 struct v4l2_format f;
816 int ret;
817
818 if (vc->video_standard == id)
819 return 0;
820
821 if (vb2_is_busy(&vc->vidq))
822 return -EBUSY;
823
824 ret = tw686x_set_standard(vc, id);
825 if (ret)
826 return ret;
805 /* 827 /*
806 * Adjust format after V4L2_STD_525_60/V4L2_STD_625_50 change, 828 * Adjust format after V4L2_STD_525_60/V4L2_STD_625_50 change,
807 * calling g_fmt and s_fmt will sanitize the height 829 * calling g_fmt and s_fmt will sanitize the height
808 * according to the standard. 830 * according to the standard.
809 */ 831 */
810 ret = tw686x_g_fmt_vid_cap(file, priv, &f); 832 tw686x_g_fmt_vid_cap(file, priv, &f);
811 if (!ret) 833 tw686x_s_fmt_vid_cap(file, priv, &f);
812 tw686x_s_fmt_vid_cap(file, priv, &f);
813 834
814 /* 835 /*
815 * Frame decimation depends on the chosen standard, 836 * Frame decimation depends on the chosen standard,
@@ -928,10 +949,21 @@ static int tw686x_enum_fmt_vid_cap(struct file *file, void *priv,
928 return 0; 949 return 0;
929} 950}
930 951
952static void tw686x_set_input(struct tw686x_video_channel *vc, unsigned int i)
953{
954 u32 val;
955
956 vc->input = i;
957
958 val = reg_read(vc->dev, VDMA_CHANNEL_CONFIG[vc->ch]);
959 val &= ~(0x3 << 30);
960 val |= i << 30;
961 reg_write(vc->dev, VDMA_CHANNEL_CONFIG[vc->ch], val);
962}
963
931static int tw686x_s_input(struct file *file, void *priv, unsigned int i) 964static int tw686x_s_input(struct file *file, void *priv, unsigned int i)
932{ 965{
933 struct tw686x_video_channel *vc = video_drvdata(file); 966 struct tw686x_video_channel *vc = video_drvdata(file);
934 u32 val;
935 967
936 if (i >= TW686X_INPUTS_PER_CH) 968 if (i >= TW686X_INPUTS_PER_CH)
937 return -EINVAL; 969 return -EINVAL;
@@ -943,12 +975,7 @@ static int tw686x_s_input(struct file *file, void *priv, unsigned int i)
943 if (vb2_is_busy(&vc->vidq)) 975 if (vb2_is_busy(&vc->vidq))
944 return -EBUSY; 976 return -EBUSY;
945 977
946 vc->input = i; 978 tw686x_set_input(vc, i);
947
948 val = reg_read(vc->dev, VDMA_CHANNEL_CONFIG[vc->ch]);
949 val &= ~(0x3 << 30);
950 val |= i << 30;
951 reg_write(vc->dev, VDMA_CHANNEL_CONFIG[vc->ch], val);
952 return 0; 979 return 0;
953} 980}
954 981
@@ -1104,7 +1131,7 @@ void tw686x_video_free(struct tw686x_dev *dev)
1104 1131
1105int tw686x_video_init(struct tw686x_dev *dev) 1132int tw686x_video_init(struct tw686x_dev *dev)
1106{ 1133{
1107 unsigned int ch, val, pb; 1134 unsigned int ch, val;
1108 int err; 1135 int err;
1109 1136
1110 if (dev->dma_mode == TW686X_DMA_MODE_MEMCPY) 1137 if (dev->dma_mode == TW686X_DMA_MODE_MEMCPY)
@@ -1138,27 +1165,23 @@ int tw686x_video_init(struct tw686x_dev *dev)
1138 vc->ch = ch; 1165 vc->ch = ch;
1139 1166
1140 /* default settings */ 1167 /* default settings */
1141 vc->format = &formats[0]; 1168 err = tw686x_set_standard(vc, V4L2_STD_NTSC);
1142 vc->video_standard = V4L2_STD_NTSC; 1169 if (err)
1143 vc->width = TW686X_VIDEO_WIDTH; 1170 goto error;
1144 vc->height = TW686X_VIDEO_HEIGHT(vc->video_standard);
1145 vc->input = 0;
1146 1171
1147 reg_write(vc->dev, SDT[ch], 0); 1172 err = tw686x_set_format(vc, formats[0].fourcc,
1148 tw686x_set_framerate(vc, 30); 1173 TW686X_VIDEO_WIDTH,
1174 TW686X_VIDEO_HEIGHT(vc->video_standard),
1175 true);
1176 if (err)
1177 goto error;
1149 1178
1179 tw686x_set_input(vc, 0);
1180 tw686x_set_framerate(vc, 30);
1150 reg_write(dev, VDELAY_LO[ch], 0x14); 1181 reg_write(dev, VDELAY_LO[ch], 0x14);
1151 reg_write(dev, HACTIVE_LO[ch], 0xd0); 1182 reg_write(dev, HACTIVE_LO[ch], 0xd0);
1152 reg_write(dev, VIDEO_SIZE[ch], 0); 1183 reg_write(dev, VIDEO_SIZE[ch], 0);
1153 1184
1154 if (dev->dma_ops->alloc) {
1155 for (pb = 0; pb < 2; pb++) {
1156 err = dev->dma_ops->alloc(vc, pb);
1157 if (err)
1158 goto error;
1159 }
1160 }
1161
1162 vc->vidq.io_modes = VB2_READ | VB2_MMAP | VB2_DMABUF; 1185 vc->vidq.io_modes = VB2_READ | VB2_MMAP | VB2_DMABUF;
1163 vc->vidq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 1186 vc->vidq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1164 vc->vidq.drv_priv = vc; 1187 vc->vidq.drv_priv = vc;