aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRakesh Movva2014-05-01 14:36:43 -0500
committerRakesh Movva2014-05-01 14:36:43 -0500
commiteb5cb3a183ce2d1d4ab4c83602b67d9e974a0c63 (patch)
tree68b69a70236eee6845c1256e428d6ee1814ddc35
parentdffc0c9166ccae9d6a66af99ba47cfae2684c10b (diff)
parentad429e8ade4bd66323f02e16ac6db79aa45a06ba (diff)
downloadkernel-video-p-ti-linux-3.8.y-video.tar.gz
kernel-video-p-ti-linux-3.8.y-video.tar.xz
kernel-video-p-ti-linux-3.8.y-video.zip
Merge branch 'vip' into p-ti-linux-3.8.y-videop-ti-linux-3.8.y-video
* vip: v4l: ti-vps: vip: Different list_head for dequeue list v4l: ti-vps: vip: Populate sequence number for frame v4l: ti-vps: vip: Handle short frames irqs arm: dts: dra7xx: Add gpio properties for fpdlink camera i2c: fpdlink: Parse and set gpios in probe v4l: ti-vps: vip: Populate field ID for interlaced capture v4l: ti-vps: vpdma: Use write desciptor bit in dtd v4l: ti-vps: vpdma: Add enum for max width height v4l: ti-vps: vip: Dequeue only once while dropping v4l: ti-vps: vip: Improve buffer dropping logic Conflicts: drivers/media/platform/ti-vps/vpdma.c drivers/media/platform/ti-vps/vpe.c
-rw-r--r--arch/arm/boot/dts/dra7-evm.dts2
-rw-r--r--drivers/media/i2c/fpdlink.c68
-rw-r--r--drivers/media/platform/ti-vps/vip.c175
-rw-r--r--drivers/media/platform/ti-vps/vip.h7
-rw-r--r--drivers/media/platform/ti-vps/vpdma.c33
-rw-r--r--drivers/media/platform/ti-vps/vpdma.h30
-rw-r--r--drivers/media/platform/ti-vps/vpdma_priv.h39
-rw-r--r--drivers/media/platform/ti-vps/vpe.c1
8 files changed, 219 insertions, 136 deletions
diff --git a/arch/arm/boot/dts/dra7-evm.dts b/arch/arm/boot/dts/dra7-evm.dts
index 763493311e1..81ddc3dac60 100644
--- a/arch/arm/boot/dts/dra7-evm.dts
+++ b/arch/arm/boot/dts/dra7-evm.dts
@@ -699,6 +699,8 @@
699 fpdlink_camera { 699 fpdlink_camera {
700 compatible = "ti,fpdlink"; 700 compatible = "ti,fpdlink";
701 reg = <0x20>; 701 reg = <0x20>;
702 gpios = <&pcf_hdmi 3 0>,
703 <&pcf_lcd3 8 0>;
702 port { 704 port {
703 cam_fpdlink: endpoint { 705 cam_fpdlink: endpoint {
704 hsync-active = <1>; 706 hsync-active = <1>;
diff --git a/drivers/media/i2c/fpdlink.c b/drivers/media/i2c/fpdlink.c
index 42e8bca6f51..7b927bd864c 100644
--- a/drivers/media/i2c/fpdlink.c
+++ b/drivers/media/i2c/fpdlink.c
@@ -1,5 +1,6 @@
1#include <linux/i2c.h> 1#include <linux/i2c.h>
2#include <linux/init.h> 2#include <linux/init.h>
3#include <linux/gpio.h>
3#include <linux/module.h> 4#include <linux/module.h>
4#include <linux/regmap.h> 5#include <linux/regmap.h>
5#include <linux/slab.h> 6#include <linux/slab.h>
@@ -12,6 +13,8 @@
12#include <media/v4l2-ctrls.h> 13#include <media/v4l2-ctrls.h>
13 14
14#include <linux/pm_runtime.h> 15#include <linux/pm_runtime.h>
16#include <linux/of_gpio.h>
17
15 18
16struct fpdlink_color_format { 19struct fpdlink_color_format {
17 enum v4l2_mbus_pixelcode code; 20 enum v4l2_mbus_pixelcode code;
@@ -25,6 +28,57 @@ static const struct fpdlink_color_format fpdlink_cfmts[] = {
25 }, 28 },
26}; 29};
27 30
31struct fpdlink_priv {
32 struct v4l2_subdev subdev;
33 int cam_fpd_mux_s0_gpio;
34 int sel_tvp_fpd_s0;
35};
36
37static int fpdlink_set_gpios(struct i2c_client *client)
38{
39 struct fpdlink_priv *priv = i2c_get_clientdata(client);
40 struct gpio gpios[] = {
41 { priv->sel_tvp_fpd_s0, GPIOF_OUT_INIT_HIGH,
42 "tvp_fpd_mux_s0" },
43 { priv->cam_fpd_mux_s0_gpio, GPIOF_OUT_INIT_HIGH,
44 "cam_fpd_mux_s0" },
45 };
46 int ret = -1;
47
48 ret = gpio_request_array(gpios, ARRAY_SIZE(gpios));
49 if (ret)
50 return ret;
51
52 gpio_free_array(gpios, ARRAY_SIZE(gpios));
53
54 return 0;
55}
56
57static int fpdlink_parse_gpios(struct i2c_client *client,
58 struct device_node *node)
59{
60
61 struct fpdlink_priv *priv = i2c_get_clientdata(client);
62 int gpio;
63
64 gpio = of_get_gpio(node, 0);
65 if (gpio_is_valid(gpio)) {
66 priv->cam_fpd_mux_s0_gpio = gpio;
67 } else {
68 dev_err(&client->dev, "failed to parse CAM_FPD_MUX_S0 gpio\n");
69 return -EINVAL;
70 }
71 gpio = of_get_gpio(node, 1);
72 if (gpio_is_valid(gpio)) {
73 priv->sel_tvp_fpd_s0 = gpio;
74 } else {
75 dev_err(&client->dev, "failed to parse TVP_FPD_MUX_S0 gpio\n");
76 return -EINVAL;
77 }
78
79 return 0;
80}
81
28static int fpdlink_enum_fmt(struct v4l2_subdev *sd, unsigned int index, 82static int fpdlink_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
29 enum v4l2_mbus_pixelcode *code) 83 enum v4l2_mbus_pixelcode *code)
30{ 84{
@@ -51,6 +105,9 @@ static int fpdlink_try_fmt(struct v4l2_subdev *sd,
51static int fpdlink_s_fmt(struct v4l2_subdev *sd, 105static int fpdlink_s_fmt(struct v4l2_subdev *sd,
52 struct v4l2_mbus_framefmt *mf) 106 struct v4l2_mbus_framefmt *mf)
53{ 107{
108 struct i2c_client *client = v4l2_get_subdevdata(sd);
109
110 fpdlink_set_gpios(client);
54 return 0; 111 return 0;
55} 112}
56 113
@@ -88,20 +145,25 @@ static const struct of_device_id fpdlink_dt_id[] = {
88static int fpdlink_probe(struct i2c_client *client, 145static int fpdlink_probe(struct i2c_client *client,
89 const struct i2c_device_id *did) 146 const struct i2c_device_id *did)
90{ 147{
148 struct fpdlink_priv *priv;
91 struct v4l2_subdev *sd; 149 struct v4l2_subdev *sd;
92 int ret = -1; 150 int ret = -1;
93 151
94 sd = devm_kzalloc(&client->dev, sizeof(*sd), GFP_KERNEL); 152 priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL);
95 if (!sd) 153 if (!priv)
96 return -ENOMEM; 154 return -ENOMEM;
155 i2c_set_clientdata(client, priv);
156
157 fpdlink_parse_gpios(client, client->dev.of_node);
158 fpdlink_set_gpios(client);
97 159
160 sd = &priv->subdev;
98 v4l2_i2c_subdev_init(sd, client, &fpdlink_subdev_ops); 161 v4l2_i2c_subdev_init(sd, client, &fpdlink_subdev_ops);
99 162
100 /* V4l2 asyn subdev register */ 163 /* V4l2 asyn subdev register */
101 sd->dev = &client->dev; 164 sd->dev = &client->dev;
102 ret = v4l2_async_register_subdev(sd); 165 ret = v4l2_async_register_subdev(sd);
103 if (!ret) { 166 if (!ret) {
104 i2c_set_clientdata(client, sd);
105 v4l2_info(sd, "Camera sensor driver registered\n"); 167 v4l2_info(sd, "Camera sensor driver registered\n");
106 pm_runtime_enable(&client->dev); 168 pm_runtime_enable(&client->dev);
107 } 169 }
diff --git a/drivers/media/platform/ti-vps/vip.c b/drivers/media/platform/ti-vps/vip.c
index 648baceb3cf..38982275f05 100644
--- a/drivers/media/platform/ti-vps/vip.c
+++ b/drivers/media/platform/ti-vps/vip.c
@@ -52,7 +52,7 @@ MODULE_VERSION("0.1");
52 52
53/* 53/*
54 * Need a descriptor entry for each of up to 15 outputs, 54 * Need a descriptor entry for each of up to 15 outputs,
55 * and up to 2 control transfers. 55 * and up to 2 write descriptor.
56 */ 56 */
57#define VIP_DESC_LIST_SIZE (17 * sizeof(struct vpdma_dtd)) 57#define VIP_DESC_LIST_SIZE (17 * sizeof(struct vpdma_dtd))
58 58
@@ -757,6 +757,7 @@ static int add_out_dtd(struct vip_stream *stream, int srce_type)
757 struct vip_fmt *fmt = port->fmt; 757 struct vip_fmt *fmt = port->fmt;
758 struct vpdma_dtd *dtd; 758 struct vpdma_dtd *dtd;
759 int channel, plane = 0; 759 int channel, plane = 0;
760 int vpdma_max_width, vpdma_max_height;
760 dma_addr_t dma_addr; 761 dma_addr_t dma_addr;
761 u32 flags; 762 u32 flags;
762 763
@@ -795,14 +796,8 @@ static int add_out_dtd(struct vip_stream *stream, int srce_type)
795 return -1; 796 return -1;
796 } 797 }
797 798
798 vpdma_add_out_dtd(&dev->desc_list, c_rect->width,
799 fmt->vpdma_fmt[plane], dma_addr, channel, flags);
800
801 /* 799 /*
802 * add_out_dtd sets the max WIDTH and HEIGHT to be 1920x1080 800 * Use VPDMA_MAX_SIZE1 or VPDMA_MAX_SIZE2 register for slice0/1
803 * Change this later so that max WIDTH and HEIGHT are taken from
804 * VPDMA_MAX_SIZE1 or VPDMA_MAX_SIZE2 register
805 * This allows to use different sets for different slices
806 */ 801 */
807 802
808 dtd = dev->desc_list.buf.addr; 803 dtd = dev->desc_list.buf.addr;
@@ -810,16 +805,20 @@ static int add_out_dtd(struct vip_stream *stream, int srce_type)
810 vpdma_set_max_size(dev->shared->vpdma, VPDMA_MAX_SIZE1, 805 vpdma_set_max_size(dev->shared->vpdma, VPDMA_MAX_SIZE1,
811 stream->width, stream->height); 806 stream->width, stream->height);
812 807
813 dtd_set_max_width_height(dtd, 808 vpdma_max_width = MAX_OUT_WIDTH_REG1;
814 MAX_OUT_WIDTH_REG1, MAX_OUT_HEIGHT_REG1); 809 vpdma_max_height = MAX_OUT_HEIGHT_REG1;
815 } else { 810 } else {
816 vpdma_set_max_size(dev->shared->vpdma, VPDMA_MAX_SIZE2, 811 vpdma_set_max_size(dev->shared->vpdma, VPDMA_MAX_SIZE2,
817 stream->width, stream->height); 812 stream->width, stream->height);
818 813
819 dtd_set_max_width_height(dtd, 814 vpdma_max_width = MAX_OUT_WIDTH_REG2;
820 MAX_OUT_WIDTH_REG2, MAX_OUT_HEIGHT_REG2); 815 vpdma_max_height = MAX_OUT_HEIGHT_REG2;
821 } 816 }
822 817
818 vpdma_add_out_dtd(&dev->desc_list, c_rect->width,
819 fmt->vpdma_fmt[plane], dma_addr,
820 vpdma_max_width, vpdma_max_height, channel, flags);
821
823 return 0; 822 return 0;
824} 823}
825 824
@@ -892,6 +891,7 @@ static void populate_desc_list(struct vip_stream *stream)
892static void start_dma(struct vip_dev *dev, struct vip_buffer *buf) 891static void start_dma(struct vip_dev *dev, struct vip_buffer *buf)
893{ 892{
894 struct vpdma_data *vpdma = dev->shared->vpdma; 893 struct vpdma_data *vpdma = dev->shared->vpdma;
894 struct vpdma_dtd *write_dtd;
895 dma_addr_t dma_addr; 895 dma_addr_t dma_addr;
896 int drop_data; 896 int drop_data;
897 897
@@ -913,8 +913,12 @@ static void start_dma(struct vip_dev *dev, struct vip_buffer *buf)
913 913
914 enable_irqs(dev, dev->slice_id); 914 enable_irqs(dev, dev->slice_id);
915 915
916 vpdma_buf_unmap(dev->shared->vpdma, &dev->desc_list.buf);
917
916 vpdma_update_dma_addr(dev->shared->vpdma, &dev->desc_list, 918 vpdma_update_dma_addr(dev->shared->vpdma, &dev->desc_list,
917 dma_addr, drop_data); 919 dma_addr, dev->write_desc, drop_data);
920 vpdma_buf_map(dev->shared->vpdma, &dev->desc_list.buf);
921
918 vpdma_submit_descs(dev->shared->vpdma, &dev->desc_list, dev->slice_id); 922 vpdma_submit_descs(dev->shared->vpdma, &dev->desc_list, dev->slice_id);
919} 923}
920 924
@@ -926,59 +930,74 @@ static void vip_active_buf_next(struct vip_stream *stream)
926 930
927 spin_lock_irqsave(&dev->slock, flags); 931 spin_lock_irqsave(&dev->slock, flags);
928 if (list_empty(&stream->vidq)) { 932 if (list_empty(&stream->vidq)) {
929 v4l2_dbg(1, debug, &dev->v4l2_dev, "%s No buffers to queue, dropping frame, Queue faster or increase no of buffers"); 933 vip_dprintk(dev, "Dropping frame");
930 buf = kzalloc(sizeof(*buf), GFP_KERNEL); 934 /* Increment drop_count for last buffer in the list */
931 if (!buf) { 935 buf = list_entry(dev->vip_bufs.prev,
932 v4l2_err(&dev->v4l2_dev, "No memory!!"); 936 struct vip_buffer, dq_list);
933 spin_unlock_irqrestore(&dev->slock, flags); 937 buf->drop_count++;
934 return; 938 buf = NULL;
935 } 939
936 buf->drop = true; 940 } else if (vb2_is_streaming(&stream->vb_vidq)) {
937 list_add_tail(&buf->list, &dev->vip_bufs); 941 buf = list_entry(stream->vidq.next, struct vip_buffer, list);
938 spin_unlock_irqrestore(&dev->slock, flags); 942 buf->drop_count = 0;
939 start_dma(dev, NULL); 943 buf->allow_dq = true;
940 } else if (vb2_is_streaming(&stream->vb_vidq)) { 944 list_del(&buf->list);
941 buf = list_entry(stream->vidq.next, 945 list_add_tail(&buf->dq_list, &dev->vip_bufs);
942 struct vip_buffer, list); 946 } else {
943 list_move_tail(&buf->list, &dev->vip_bufs); 947 v4l2_err(&dev->v4l2_dev, "IRQ occurred when not streaming");
944 spin_unlock_irqrestore(&dev->slock, flags); 948 spin_unlock_irqrestore(&dev->slock, flags);
945 start_dma(dev, buf); 949 return;
946 } else 950 }
947 spin_unlock_irqrestore(&dev->slock, flags);
948 951
949 if (list_empty(&dev->vip_bufs)) 952 spin_unlock_irqrestore(&dev->slock, flags);
950 stream->cur_buf = NULL; 953 start_dma(dev, buf);
951 else
952 stream->cur_buf = list_first_entry(&dev->vip_bufs,
953 struct vip_buffer, list);
954} 954}
955 955
956static void vip_process_buffer_complete(struct vip_stream *stream) 956static void vip_process_buffer_complete(struct vip_stream *stream)
957{ 957{
958 struct vip_dev *dev = stream->port->dev; 958 struct vip_dev *dev = stream->port->dev;
959 struct vb2_buffer *vb = NULL; 959 struct vb2_buffer *vb = NULL;
960 unsigned long flags; 960 struct vip_buffer *buf;
961 unsigned long flags, fld;
962
963 buf = list_first_entry(&dev->vip_bufs, struct vip_buffer, dq_list);
964
965 if (stream->port->flags & FLAG_INTERLACED) {
966 vpdma_buf_unmap(dev->shared->vpdma, &dev->desc_list.buf);
967
968 fld = dtd_get_field(dev->write_desc);
969 stream->field = fld ? V4L2_FIELD_TOP : V4L2_FIELD_BOTTOM;
961 970
962 if (stream->cur_buf) { 971 vpdma_buf_map(dev->shared->vpdma, &dev->desc_list.buf);
963 vb = &stream->cur_buf->vb; 972 }
973
974 if (buf) {
975 vb = &buf->vb;
976 vb->v4l2_buf.field = stream->field;
977 vb->v4l2_buf.sequence = stream->sequence;
964 do_gettimeofday(&vb->v4l2_buf.timestamp); 978 do_gettimeofday(&vb->v4l2_buf.timestamp);
965 979
966 spin_lock_irqsave(&dev->slock, flags); 980 if (buf->drop_count-- == 0) {
967 list_del(&stream->cur_buf->list); 981 spin_lock_irqsave(&dev->slock, flags);
968 spin_unlock_irqrestore(&dev->slock, flags); 982 list_del(&buf->dq_list);
983 spin_unlock_irqrestore(&dev->slock, flags);
984 }
969 985
970 if (stream->cur_buf->drop) 986 if (buf->allow_dq) {
971 kfree(stream->cur_buf); 987 vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
972 else 988 buf->allow_dq = false;
973 vb2_buffer_done(vb, VB2_BUF_STATE_DONE); 989 }
974 } 990 } else {
991 BUG();
992 }
975 993
976 vip_active_buf_next(stream); 994 stream->sequence++;
977} 995}
978 996
979static irqreturn_t vip_irq(int irq_vip, void *data) 997static irqreturn_t vip_irq(int irq_vip, void *data)
980{ 998{
981 struct vip_dev *dev = (struct vip_dev *)data; 999 struct vip_dev *dev = (struct vip_dev *)data;
1000 struct vip_stream *stream;
982 int list_num = dev->slice_id; 1001 int list_num = dev->slice_id;
983 int irq_num = dev->slice_id; 1002 int irq_num = dev->slice_id;
984 u32 irqst, reg_addr; 1003 u32 irqst, reg_addr;
@@ -1003,14 +1022,17 @@ static irqreturn_t vip_irq(int irq_vip, void *data)
1003 irqst &= ~((1 << list_num * 2)); 1022 irqst &= ~((1 << list_num * 2));
1004 } 1023 }
1005 1024
1025 disable_irqs(dev, dev->slice_id);
1026
1027 stream = dev->ports[0]->cap_streams[0];
1028
1006 if (dev->num_skip_irq) { 1029 if (dev->num_skip_irq) {
1007 dev->num_skip_irq--; 1030 dev->num_skip_irq--;
1008 return IRQ_HANDLED; 1031 } else {
1032 vip_process_buffer_complete(stream);
1009 } 1033 }
1010 1034
1011 /* disable_irqs(dev); */ 1035 vip_active_buf_next(stream);
1012
1013 vip_process_buffer_complete(dev->ports[0]->cap_streams[0]);
1014 1036
1015 return IRQ_HANDLED; 1037 return IRQ_HANDLED;
1016} 1038}
@@ -1215,7 +1237,7 @@ static int vip_try_fmt_vid_cap(struct file *file, void *priv,
1215 1237
1216 if (field == V4L2_FIELD_ANY) 1238 if (field == V4L2_FIELD_ANY)
1217 field = V4L2_FIELD_NONE; 1239 field = V4L2_FIELD_NONE;
1218 else if (V4L2_FIELD_NONE != field) 1240 else if (V4L2_FIELD_NONE != field && V4L2_FIELD_ALTERNATE != field)
1219 return -EINVAL; 1241 return -EINVAL;
1220 1242
1221 f->fmt.pix.field = field; 1243 f->fmt.pix.field = field;
@@ -1498,36 +1520,30 @@ static int vip_start_streaming(struct vb2_queue *vq, unsigned int count)
1498 return -EIO; 1520 return -EIO;
1499 } 1521 }
1500 1522
1501 stream->cur_buf = list_entry(stream->vidq.next, 1523 buf = list_entry(stream->vidq.next, struct vip_buffer, list);
1502 struct vip_buffer, list); 1524 buf->drop_count = 0;
1503 stream->cur_buf->vb.state = VB2_BUF_STATE_ACTIVE; 1525 buf->allow_dq = true;
1526
1527 stream->cur_buf = buf;
1528 stream->sequence = 0;
1504 stream->field = V4L2_FIELD_TOP; 1529 stream->field = V4L2_FIELD_TOP;
1505 1530
1506 populate_desc_list(stream); 1531 populate_desc_list(stream);
1507 dev->num_skip_irq = VIP_VPDMA_FIFO_SIZE; 1532 dev->num_skip_irq = VIP_VPDMA_FIFO_SIZE;
1508 1533
1509 for (i = 0; i < count; i++) { 1534 spin_lock_irqsave(&dev->slock, flags);
1510 1535 if (vpdma_list_busy(dev->shared->vpdma, dev->slice_id)) {
1511 spin_lock_irqsave(&dev->slock, flags); 1536 spin_unlock_irqrestore(&dev->slock, flags);
1512 if (!vpdma_list_busy(dev->shared->vpdma, dev->slice_id)) { 1537 vpdma_buf_unmap(dev->shared->vpdma, &dev->desc_list.buf);
1513 1538 vpdma_reset_desc_list(&dev->desc_list);
1514 buf = list_entry(stream->vidq.next, 1539 return -EBUSY;
1515 struct vip_buffer, list); 1540 }
1516 list_move_tail(&buf->list, &dev->vip_bufs);
1517 spin_unlock_irqrestore(&dev->slock, flags);
1518 1541
1519 if (!stream->cur_buf) 1542 list_del(&buf->list);
1520 stream->cur_buf = buf; 1543 list_add_tail(&buf->dq_list, &dev->vip_bufs);
1521 start_dma(dev, buf); 1544 spin_unlock_irqrestore(&dev->slock, flags);
1522 1545
1523 if (i == VIP_VPDMA_FIFO_SIZE) 1546 start_dma(dev, buf);
1524 break;
1525 while (vpdma_list_busy(dev->shared->vpdma,
1526 dev->slice_id))
1527 ;
1528 } else
1529 spin_unlock_irqrestore(&dev->slock, flags);
1530 }
1531 1547
1532 return 0; 1548 return 0;
1533} 1549}
@@ -1551,8 +1567,9 @@ static int vip_stop_streaming(struct vb2_queue *vq)
1551 disable_irqs(dev, dev->slice_id); 1567 disable_irqs(dev, dev->slice_id);
1552 /* release all active buffers */ 1568 /* release all active buffers */
1553 while (!list_empty(&dev->vip_bufs)) { 1569 while (!list_empty(&dev->vip_bufs)) {
1554 buf = list_entry(dev->vip_bufs.next, struct vip_buffer, list); 1570 buf = list_entry(dev->vip_bufs.next,
1555 list_del(&buf->list); 1571 struct vip_buffer, dq_list);
1572 list_del(&buf->dq_list);
1556 vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); 1573 vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
1557 } 1574 }
1558 while (!list_empty(&stream->vidq)) { 1575 while (!list_empty(&stream->vidq)) {
@@ -1606,6 +1623,8 @@ static int vip_init_dev(struct vip_dev *dev)
1606 if (ret != 0) 1623 if (ret != 0)
1607 return ret; 1624 return ret;
1608 1625
1626 dev->write_desc = (struct vpdma_dtd *)dev->desc_list.buf.addr
1627 + 15;
1609 vip_set_clock_enable(dev, 1); 1628 vip_set_clock_enable(dev, 1);
1610done: 1629done:
1611 dev->num_ports++; 1630 dev->num_ports++;
diff --git a/drivers/media/platform/ti-vps/vip.h b/drivers/media/platform/ti-vps/vip.h
index 8ff8d337e99..1b41164f788 100644
--- a/drivers/media/platform/ti-vps/vip.h
+++ b/drivers/media/platform/ti-vps/vip.h
@@ -38,7 +38,11 @@ struct vip_buffer {
38 /* common v4l buffer stuff */ 38 /* common v4l buffer stuff */
39 struct vb2_buffer vb; 39 struct vb2_buffer vb;
40 struct list_head list; 40 struct list_head list;
41 bool drop; 41 struct list_head dq_list;
42 /* Number of buffers to drop after this */
43 int drop_count;
44 /* To make sure same buffer isn't dequeued again */
45 bool allow_dq;
42}; 46};
43 47
44/* 48/*
@@ -89,6 +93,7 @@ struct vip_dev {
89 void __iomem *base; 93 void __iomem *base;
90 94
91 struct vpdma_desc_list desc_list; /* DMA descriptor list */ 95 struct vpdma_desc_list desc_list; /* DMA descriptor list */
96 struct vpdma_dtd *write_desc;
92 void *desc_next; /* next unused desc_list addr */ 97 void *desc_next; /* next unused desc_list addr */
93 struct list_head vip_bufs; /* vip_bufs to be DMAed */ 98 struct list_head vip_bufs; /* vip_bufs to be DMAed */
94 struct vb2_alloc_ctx *alloc_ctx; 99 struct vb2_alloc_ctx *alloc_ctx;
diff --git a/drivers/media/platform/ti-vps/vpdma.c b/drivers/media/platform/ti-vps/vpdma.c
index d8252d26856..370a8cc1846 100644
--- a/drivers/media/platform/ti-vps/vpdma.c
+++ b/drivers/media/platform/ti-vps/vpdma.c
@@ -343,7 +343,7 @@ void vpdma_buf_map(struct vpdma_data *vpdma, struct vpdma_buf *buf)
343 343
344 WARN_ON(buf->mapped != 0); 344 WARN_ON(buf->mapped != 0);
345 buf->dma_addr = dma_map_single(dev, buf->addr, buf->size, 345 buf->dma_addr = dma_map_single(dev, buf->addr, buf->size,
346 DMA_TO_DEVICE); 346 DMA_BIDIRECTIONAL);
347 buf->mapped = 1; 347 buf->mapped = 1;
348 WARN_ON(dma_mapping_error(dev, buf->dma_addr)); 348 WARN_ON(dma_mapping_error(dev, buf->dma_addr));
349} 349}
@@ -363,7 +363,8 @@ void vpdma_buf_unmap(struct vpdma_data *vpdma, struct vpdma_buf *buf)
363 } 363 }
364 364
365 if (buf->mapped) 365 if (buf->mapped)
366 dma_unmap_single(dev, buf->dma_addr, buf->size, DMA_TO_DEVICE); 366 dma_unmap_single(dev, buf->dma_addr, buf->size,
367 DMA_BIDIRECTIONAL);
367 368
368 buf->mapped = 0; 369 buf->mapped = 0;
369} 370}
@@ -450,24 +451,25 @@ int vpdma_submit_descs(struct vpdma_data *vpdma,
450EXPORT_SYMBOL(vpdma_submit_descs); 451EXPORT_SYMBOL(vpdma_submit_descs);
451 452
452void vpdma_update_dma_addr(struct vpdma_data *vpdma, 453void vpdma_update_dma_addr(struct vpdma_data *vpdma,
453 struct vpdma_desc_list *list, dma_addr_t dma_addr, int drop) 454 struct vpdma_desc_list *list, dma_addr_t dma_addr,
455 struct vpdma_dtd *write_dtd, int drop)
454{ 456{
455 struct vpdma_dtd *dtd = list->buf.addr; 457 struct vpdma_dtd *dtd = list->buf.addr;
456 unsigned int write_desc_addr; 458 dma_addr_t write_desc_addr;
457 459 int offset;
458 vpdma_buf_unmap(vpdma, &list->buf);
459 460
460 dtd_set_start_addr(dtd, dma_addr); 461 dtd_set_start_addr(dtd, dma_addr);
461 462
462 if (drop) { 463 /* Calculate write address from the offset of write_dtd from start
463 write_desc_addr = virt_to_phys( 464 * of the list->buf
464 (struct vpdma_dtd *)list->buf.dma_addr + 2); 465 */
466 offset = (void *)write_dtd - list->buf.addr;
467 write_desc_addr = list->buf.dma_addr + offset;
465 468
469 if (drop)
466 dtd_set_desc_write_addr(dtd, write_desc_addr, 1, 1, 0); 470 dtd_set_desc_write_addr(dtd, write_desc_addr, 1, 1, 0);
467 } else 471 else
468 dtd_set_desc_write_addr(dtd, 0, 0, 0, 0); 472 dtd_set_desc_write_addr(dtd, write_desc_addr, 1, 0, 0);
469
470 vpdma_buf_map(vpdma, &list->buf);
471} 473}
472EXPORT_SYMBOL(vpdma_update_dma_addr); 474EXPORT_SYMBOL(vpdma_update_dma_addr);
473 475
@@ -676,11 +678,14 @@ static void dump_dtd(struct vpdma_dtd *dtd)
676 * @width: width of the image in pixels in memory 678 * @width: width of the image in pixels in memory
677 * @fmt: vpdma data format of the buffer 679 * @fmt: vpdma data format of the buffer
678 * dma_addr: dma address as seen by VPDMA 680 * dma_addr: dma address as seen by VPDMA
681 * max_width: enum for maximum width of data transfer
682 * max_height: enum for maximum height of data transfer
679 * chan: VPDMA channel 683 * chan: VPDMA channel
680 * flags: VPDMA flags to configure some descriptor fileds 684 * flags: VPDMA flags to configure some descriptor fileds
681 */ 685 */
682int vpdma_add_out_dtd(struct vpdma_desc_list *list, int width, 686int vpdma_add_out_dtd(struct vpdma_desc_list *list, int width,
683 const struct vpdma_data_format *fmt, dma_addr_t dma_addr, 687 const struct vpdma_data_format *fmt, dma_addr_t dma_addr,
688 enum vpdma_max_width max_w, enum vpdma_max_height max_h,
684 int channel, u32 flags) 689 int channel, u32 flags)
685{ 690{
686 int priority = 0; 691 int priority = 0;
@@ -714,7 +719,7 @@ int vpdma_add_out_dtd(struct vpdma_desc_list *list, int width,
714 channel, priority, next_chan); 719 channel, priority, next_chan);
715 720
716 dtd_set_desc_write_addr(dtd, 0, 0, 0, 0); 721 dtd_set_desc_write_addr(dtd, 0, 0, 0, 0);
717 dtd_set_max_width_height(dtd, MAX_OUT_WIDTH_1920, MAX_OUT_HEIGHT_1080); 722 dtd_set_max_width_height(dtd, max_w, max_h);
718 dtd_set_client_attr0(dtd, 0); 723 dtd_set_client_attr0(dtd, 0);
719 dtd_set_client_attr1(dtd, 0); 724 dtd_set_client_attr1(dtd, 0);
720 725
diff --git a/drivers/media/platform/ti-vps/vpdma.h b/drivers/media/platform/ti-vps/vpdma.h
index 657d8a842a5..55563a1d84f 100644
--- a/drivers/media/platform/ti-vps/vpdma.h
+++ b/drivers/media/platform/ti-vps/vpdma.h
@@ -28,7 +28,7 @@ struct vpdma_buf {
28 28
29struct vpdma_desc_list { 29struct vpdma_desc_list {
30 struct vpdma_buf buf; 30 struct vpdma_buf buf;
31 void *next; 31 void *next, *current_desc;
32 int type; 32 int type;
33}; 33};
34 34
@@ -119,6 +119,30 @@ enum vpdma_frame_start_event {
119 VPDMA_FSEVENT_CHANNEL_ACTIVE, 119 VPDMA_FSEVENT_CHANNEL_ACTIVE,
120}; 120};
121 121
122/* max width configurations */
123enum vpdma_max_width {
124 MAX_OUT_WIDTH_UNLIMITED = 0,
125 MAX_OUT_WIDTH_REG1,
126 MAX_OUT_WIDTH_REG2,
127 MAX_OUT_WIDTH_REG3,
128 MAX_OUT_WIDTH_352,
129 MAX_OUT_WIDTH_768,
130 MAX_OUT_WIDTH_1280,
131 MAX_OUT_WIDTH_1920,
132};
133
134/* max height configurations */
135enum vpdma_max_height {
136 MAX_OUT_HEIGHT_UNLIMITED = 0,
137 MAX_OUT_HEIGHT_REG1,
138 MAX_OUT_HEIGHT_REG2,
139 MAX_OUT_HEIGHT_REG3,
140 MAX_OUT_HEIGHT_288,
141 MAX_OUT_HEIGHT_576,
142 MAX_OUT_HEIGHT_720,
143 MAX_OUT_HEIGHT_1080,
144};
145
122#define VIP_CHAN_VIP2_OFFSET 70 146#define VIP_CHAN_VIP2_OFFSET 70
123#define VIP_CHAN_MULT_PORTB_OFFSET 16 147#define VIP_CHAN_MULT_PORTB_OFFSET 16
124#define VIP_CHAN_YUV_PORTB_OFFSET 2 148#define VIP_CHAN_YUV_PORTB_OFFSET 2
@@ -177,6 +201,7 @@ void vpdma_add_cfd_adb(struct vpdma_desc_list *list, int client,
177void vpdma_add_sync_on_channel_ctd(struct vpdma_desc_list *list, int channel); 201void vpdma_add_sync_on_channel_ctd(struct vpdma_desc_list *list, int channel);
178int vpdma_add_out_dtd(struct vpdma_desc_list *list, int width, 202int vpdma_add_out_dtd(struct vpdma_desc_list *list, int width,
179 const struct vpdma_data_format *fmt, dma_addr_t dma_addr, 203 const struct vpdma_data_format *fmt, dma_addr_t dma_addr,
204 enum vpdma_max_width max_w, enum vpdma_max_height max_h,
180 int channel, u32 flags); 205 int channel, u32 flags);
181void vpdma_add_in_dtd(struct vpdma_desc_list *list, int width, 206void vpdma_add_in_dtd(struct vpdma_desc_list *list, int width,
182 const struct v4l2_rect *c_rect, 207 const struct v4l2_rect *c_rect,
@@ -190,7 +215,8 @@ void vpdma_free_desc_list(struct vpdma_desc_list *list);
190int vpdma_submit_descs(struct vpdma_data *vpdma, 215int vpdma_submit_descs(struct vpdma_data *vpdma,
191 struct vpdma_desc_list *list, int list_num); 216 struct vpdma_desc_list *list, int list_num);
192void vpdma_update_dma_addr(struct vpdma_data *vpdma, 217void vpdma_update_dma_addr(struct vpdma_data *vpdma,
193 struct vpdma_desc_list *list, dma_addr_t dma_addr, int drop); 218 struct vpdma_desc_list *list, dma_addr_t dma_addr,
219 struct vpdma_dtd *write_dtd, int drop);
194 220
195void vpdma_enable_channel_3_irq(struct vpdma_data *vpdma, bool enable); 221void vpdma_enable_channel_3_irq(struct vpdma_data *vpdma, bool enable);
196void vpdma_set_max_size(struct vpdma_data *vpdma, int reg_addr, 222void vpdma_set_max_size(struct vpdma_data *vpdma, int reg_addr,
diff --git a/drivers/media/platform/ti-vps/vpdma_priv.h b/drivers/media/platform/ti-vps/vpdma_priv.h
index 74881c5422f..78425eb75a7 100644
--- a/drivers/media/platform/ti-vps/vpdma_priv.h
+++ b/drivers/media/platform/ti-vps/vpdma_priv.h
@@ -219,7 +219,7 @@ struct vpdma_dtd {
219#define DTD_V_START_MASK 0xffff 219#define DTD_V_START_MASK 0xffff
220#define DTD_V_START_SHFT 0 220#define DTD_V_START_SHFT 0
221 221
222#define DTD_DESC_START_MASK 0xffe0 222#define DTD_DESC_START_MASK 0xffffffe0
223#define DTD_DESC_START_SHIFT 5 223#define DTD_DESC_START_SHIFT 5
224#define DTD_WRITE_DESC_MASK 0x01 224#define DTD_WRITE_DESC_MASK 0x01
225#define DTD_WRITE_DESC_SHIFT 2 225#define DTD_WRITE_DESC_SHIFT 2
@@ -234,43 +234,6 @@ struct vpdma_dtd {
234#define DTD_MAX_HEIGHT_MASK 0x07 234#define DTD_MAX_HEIGHT_MASK 0x07
235#define DTD_MAX_HEIGHT_SHFT 0 235#define DTD_MAX_HEIGHT_SHFT 0
236 236
237/* max width configurations */
238 /* unlimited width */
239#define MAX_OUT_WIDTH_UNLIMITED 0
240/* as specified in max_size1 reg */
241#define MAX_OUT_WIDTH_REG1 1
242/* as specified in max_size2 reg */
243#define MAX_OUT_WIDTH_REG2 2
244/* as specified in max_size3 reg */
245#define MAX_OUT_WIDTH_REG3 3
246/* maximum of 352 pixels as width */
247#define MAX_OUT_WIDTH_352 4
248/* maximum of 768 pixels as width */
249#define MAX_OUT_WIDTH_768 5
250/* maximum of 1280 pixels width */
251#define MAX_OUT_WIDTH_1280 6
252/* maximum of 1920 pixels as width */
253#define MAX_OUT_WIDTH_1920 7
254
255/* max height configurations */
256 /* unlimited height */
257#define MAX_OUT_HEIGHT_UNLIMITED 0
258/* as specified in max_size1 reg */
259#define MAX_OUT_HEIGHT_REG1 1
260/* as specified in max_size2 reg */
261#define MAX_OUT_HEIGHT_REG2 2
262/* as specified in max_size3 reg */
263#define MAX_OUT_HEIGHT_REG3 3
264/* maximum of 288 lines as height */
265#define MAX_OUT_HEIGHT_288 4
266/* maximum of 576 lines as height */
267#define MAX_OUT_HEIGHT_576 5
268/* maximum of 720 lines as height */
269#define MAX_OUT_HEIGHT_720 6
270/* maximum of 1080 lines as height */
271#define MAX_OUT_HEIGHT_1080 7
272
273
274/* 237/*
275 * The following macros may be useful for structure initialization 238 * The following macros may be useful for structure initialization
276 */ 239 */
diff --git a/drivers/media/platform/ti-vps/vpe.c b/drivers/media/platform/ti-vps/vpe.c
index 2833f82f6b4..2256a8bbbd6 100644
--- a/drivers/media/platform/ti-vps/vpe.c
+++ b/drivers/media/platform/ti-vps/vpe.c
@@ -1039,6 +1039,7 @@ static void add_out_dtd(struct vpe_ctx *ctx, int port)
1039 flags |= VPDMA_DATA_MODE_TILED; 1039 flags |= VPDMA_DATA_MODE_TILED;
1040 1040
1041 vpdma_add_out_dtd(&ctx->desc_list, q_data->width, vpdma_fmt, dma_addr, 1041 vpdma_add_out_dtd(&ctx->desc_list, q_data->width, vpdma_fmt, dma_addr,
1042 MAX_OUT_WIDTH_1920, MAX_OUT_HEIGHT_1080,
1042 p_data->channel, flags); 1043 p_data->channel, flags);
1043} 1044}
1044 1045