aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/platform/ti-vpe
diff options
context:
space:
mode:
authorArchit Taneja <archit@ti.com>2013-10-16 01:36:48 -0400
committerMauro Carvalho Chehab <m.chehab@samsung.com>2013-10-28 13:19:38 -0400
commit585e6f010b1fcfd2b0f639933d2d97f7087503b2 (patch)
tree86c89b15d3155a184e01224e1b0cb0cee7e7668b /drivers/media/platform/ti-vpe
parent4571912743ac6a04a6644e5a292bb9876bb5329b (diff)
[media] v4l: ti-vpe: Add de-interlacer support in VPE
Add support for the de-interlacer block in VPE. For de-interlacer to work, we need to enable 2 more sets of VPE input ports which fetch data from the 'last' and 'last to last' fields of the interlaced video. Apart from that, we need to enable the Motion vector output and input ports, and also allocate DMA buffers for them. We need to make sure that two most recent fields in the source queue are available and in the 'READY' state. Once a mem2mem context gets access to the VPE HW(in device_run), it extracts the addresses of the 3 buffers, and provides it to the data descriptors for the 3 sets of input ports((LUMA1, CHROMA1), (LUMA2, CHROMA2), and (LUMA3, CHROMA3)) respectively for the 3 consecutive fields. The motion vector and output port descriptors are configured and the list is submitted to VPDMA. Once the transaction is done, the v4l2 buffer corresponding to the oldest field(the 3rd one) is changed to the state 'DONE', and the buffers corresponding to 1st and 2nd fields become the 2nd and 3rd field for the next de-interlace operation. This way, for each deinterlace operation, we have the 3 most recent fields. After each transaction, we also swap the motion vector buffers, the new input motion vector buffer contains the resultant motion information of all the previous frames, and the new output motion vector buffer will be used to hold the updated motion vector to capture the motion changes in the next field. The motion vector buffers are allocated using the DMA allocation API. The de-interlacer is removed from bypass mode, it requires some extra default configurations which are now added. The chrominance upsampler coefficients are added for interlaced frames. Some VPDMA parameters like frame start event and line mode are configured for the 2 extra sets of input ports. Signed-off-by: Archit Taneja <archit@ti.com> Acked-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Kamil Debski <k.debski@samsung.com> Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
Diffstat (limited to 'drivers/media/platform/ti-vpe')
-rw-r--r--drivers/media/platform/ti-vpe/vpe.c392
1 files changed, 358 insertions, 34 deletions
diff --git a/drivers/media/platform/ti-vpe/vpe.c b/drivers/media/platform/ti-vpe/vpe.c
index 3bd9ca658b54..4e58069e24ff 100644
--- a/drivers/media/platform/ti-vpe/vpe.c
+++ b/drivers/media/platform/ti-vpe/vpe.c
@@ -69,6 +69,8 @@
69#define VPE_CHROMA 1 69#define VPE_CHROMA 1
70 70
71/* per m2m context info */ 71/* per m2m context info */
72#define VPE_MAX_SRC_BUFS 3 /* need 3 src fields to de-interlace */
73
72#define VPE_DEF_BUFS_PER_JOB 1 /* default one buffer per batch job */ 74#define VPE_DEF_BUFS_PER_JOB 1 /* default one buffer per batch job */
73 75
74/* 76/*
@@ -111,6 +113,38 @@ static const struct vpe_us_coeffs us_coeffs[] = {
111 0x00C8, 0x0348, 0x0018, 0x3FD8, 0x3FB8, 0x0378, 0x00E8, 0x3FE8, 113 0x00C8, 0x0348, 0x0018, 0x3FD8, 0x3FB8, 0x0378, 0x00E8, 0x3FE8,
112 0x00C8, 0x0348, 0x0018, 0x3FD8, 0x3FB8, 0x0378, 0x00E8, 0x3FE8, 114 0x00C8, 0x0348, 0x0018, 0x3FD8, 0x3FB8, 0x0378, 0x00E8, 0x3FE8,
113 }, 115 },
116 {
117 /* Coefficients for Top Field Interlaced input */
118 0x0051, 0x03D5, 0x3FE3, 0x3FF7, 0x3FB5, 0x02E9, 0x018F, 0x3FD3,
119 /* Coefficients for Bottom Field Interlaced input */
120 0x016B, 0x0247, 0x00B1, 0x3F9D, 0x3FCF, 0x03DB, 0x005D, 0x3FF9,
121 },
122};
123
124/*
125 * the following registers are for configuring some of the parameters of the
126 * motion and edge detection blocks inside DEI, these generally remain the same,
127 * these could be passed later via userspace if some one needs to tweak these.
128 */
129struct vpe_dei_regs {
130 unsigned long mdt_spacial_freq_thr_reg; /* VPE_DEI_REG2 */
131 unsigned long edi_config_reg; /* VPE_DEI_REG3 */
132 unsigned long edi_lut_reg0; /* VPE_DEI_REG4 */
133 unsigned long edi_lut_reg1; /* VPE_DEI_REG5 */
134 unsigned long edi_lut_reg2; /* VPE_DEI_REG6 */
135 unsigned long edi_lut_reg3; /* VPE_DEI_REG7 */
136};
137
138/*
139 * default expert DEI register values, unlikely to be modified.
140 */
141static const struct vpe_dei_regs dei_regs = {
142 0x020C0804u,
143 0x0118100Fu,
144 0x08040200u,
145 0x1010100Cu,
146 0x10101010u,
147 0x10101010u,
114}; 148};
115 149
116/* 150/*
@@ -118,6 +152,7 @@ static const struct vpe_us_coeffs us_coeffs[] = {
118 */ 152 */
119struct vpe_port_data { 153struct vpe_port_data {
120 enum vpdma_channel channel; /* VPDMA channel */ 154 enum vpdma_channel channel; /* VPDMA channel */
155 u8 vb_index; /* input frame f, f-1, f-2 index */
121 u8 vb_part; /* plane index for co-panar formats */ 156 u8 vb_part; /* plane index for co-panar formats */
122}; 157};
123 158
@@ -126,6 +161,12 @@ struct vpe_port_data {
126 */ 161 */
127#define VPE_PORT_LUMA1_IN 0 162#define VPE_PORT_LUMA1_IN 0
128#define VPE_PORT_CHROMA1_IN 1 163#define VPE_PORT_CHROMA1_IN 1
164#define VPE_PORT_LUMA2_IN 2
165#define VPE_PORT_CHROMA2_IN 3
166#define VPE_PORT_LUMA3_IN 4
167#define VPE_PORT_CHROMA3_IN 5
168#define VPE_PORT_MV_IN 6
169#define VPE_PORT_MV_OUT 7
129#define VPE_PORT_LUMA_OUT 8 170#define VPE_PORT_LUMA_OUT 8
130#define VPE_PORT_CHROMA_OUT 9 171#define VPE_PORT_CHROMA_OUT 9
131#define VPE_PORT_RGB_OUT 10 172#define VPE_PORT_RGB_OUT 10
@@ -133,12 +174,40 @@ struct vpe_port_data {
133static const struct vpe_port_data port_data[11] = { 174static const struct vpe_port_data port_data[11] = {
134 [VPE_PORT_LUMA1_IN] = { 175 [VPE_PORT_LUMA1_IN] = {
135 .channel = VPE_CHAN_LUMA1_IN, 176 .channel = VPE_CHAN_LUMA1_IN,
177 .vb_index = 0,
136 .vb_part = VPE_LUMA, 178 .vb_part = VPE_LUMA,
137 }, 179 },
138 [VPE_PORT_CHROMA1_IN] = { 180 [VPE_PORT_CHROMA1_IN] = {
139 .channel = VPE_CHAN_CHROMA1_IN, 181 .channel = VPE_CHAN_CHROMA1_IN,
182 .vb_index = 0,
183 .vb_part = VPE_CHROMA,
184 },
185 [VPE_PORT_LUMA2_IN] = {
186 .channel = VPE_CHAN_LUMA2_IN,
187 .vb_index = 1,
188 .vb_part = VPE_LUMA,
189 },
190 [VPE_PORT_CHROMA2_IN] = {
191 .channel = VPE_CHAN_CHROMA2_IN,
192 .vb_index = 1,
193 .vb_part = VPE_CHROMA,
194 },
195 [VPE_PORT_LUMA3_IN] = {
196 .channel = VPE_CHAN_LUMA3_IN,
197 .vb_index = 2,
198 .vb_part = VPE_LUMA,
199 },
200 [VPE_PORT_CHROMA3_IN] = {
201 .channel = VPE_CHAN_CHROMA3_IN,
202 .vb_index = 2,
140 .vb_part = VPE_CHROMA, 203 .vb_part = VPE_CHROMA,
141 }, 204 },
205 [VPE_PORT_MV_IN] = {
206 .channel = VPE_CHAN_MV_IN,
207 },
208 [VPE_PORT_MV_OUT] = {
209 .channel = VPE_CHAN_MV_OUT,
210 },
142 [VPE_PORT_LUMA_OUT] = { 211 [VPE_PORT_LUMA_OUT] = {
143 .channel = VPE_CHAN_LUMA_OUT, 212 .channel = VPE_CHAN_LUMA_OUT,
144 .vb_part = VPE_LUMA, 213 .vb_part = VPE_LUMA,
@@ -210,6 +279,7 @@ struct vpe_q_data {
210 unsigned int height; /* frame height */ 279 unsigned int height; /* frame height */
211 unsigned int bytesperline[VPE_MAX_PLANES]; /* bytes per line in memory */ 280 unsigned int bytesperline[VPE_MAX_PLANES]; /* bytes per line in memory */
212 enum v4l2_colorspace colorspace; 281 enum v4l2_colorspace colorspace;
282 enum v4l2_field field; /* supported field value */
213 unsigned int flags; 283 unsigned int flags;
214 unsigned int sizeimage[VPE_MAX_PLANES]; /* image size in memory */ 284 unsigned int sizeimage[VPE_MAX_PLANES]; /* image size in memory */
215 struct v4l2_rect c_rect; /* crop/compose rectangle */ 285 struct v4l2_rect c_rect; /* crop/compose rectangle */
@@ -219,6 +289,7 @@ struct vpe_q_data {
219/* vpe_q_data flag bits */ 289/* vpe_q_data flag bits */
220#define Q_DATA_FRAME_1D (1 << 0) 290#define Q_DATA_FRAME_1D (1 << 0)
221#define Q_DATA_MODE_TILED (1 << 1) 291#define Q_DATA_MODE_TILED (1 << 1)
292#define Q_DATA_INTERLACED (1 << 2)
222 293
223enum { 294enum {
224 Q_DATA_SRC = 0, 295 Q_DATA_SRC = 0,
@@ -270,6 +341,7 @@ struct vpe_ctx {
270 struct v4l2_m2m_ctx *m2m_ctx; 341 struct v4l2_m2m_ctx *m2m_ctx;
271 struct v4l2_ctrl_handler hdl; 342 struct v4l2_ctrl_handler hdl;
272 343
344 unsigned int field; /* current field */
273 unsigned int sequence; /* current frame/field seq */ 345 unsigned int sequence; /* current frame/field seq */
274 unsigned int aborting; /* abort after next irq */ 346 unsigned int aborting; /* abort after next irq */
275 347
@@ -277,13 +349,19 @@ struct vpe_ctx {
277 unsigned int bufs_completed; /* bufs done in this batch */ 349 unsigned int bufs_completed; /* bufs done in this batch */
278 350
279 struct vpe_q_data q_data[2]; /* src & dst queue data */ 351 struct vpe_q_data q_data[2]; /* src & dst queue data */
280 struct vb2_buffer *src_vb; 352 struct vb2_buffer *src_vbs[VPE_MAX_SRC_BUFS];
281 struct vb2_buffer *dst_vb; 353 struct vb2_buffer *dst_vb;
282 354
355 dma_addr_t mv_buf_dma[2]; /* dma addrs of motion vector in/out bufs */
356 void *mv_buf[2]; /* virtual addrs of motion vector bufs */
357 size_t mv_buf_size; /* current motion vector buffer size */
283 struct vpdma_buf mmr_adb; /* shadow reg addr/data block */ 358 struct vpdma_buf mmr_adb; /* shadow reg addr/data block */
284 struct vpdma_desc_list desc_list; /* DMA descriptor list */ 359 struct vpdma_desc_list desc_list; /* DMA descriptor list */
285 360
361 bool deinterlacing; /* using de-interlacer */
286 bool load_mmrs; /* have new shadow reg values */ 362 bool load_mmrs; /* have new shadow reg values */
363
364 unsigned int src_mv_buf_selector;
287}; 365};
288 366
289 367
@@ -359,8 +437,7 @@ struct vpe_mmr_adb {
359 struct vpdma_adb_hdr us3_hdr; 437 struct vpdma_adb_hdr us3_hdr;
360 u32 us3_regs[8]; 438 u32 us3_regs[8];
361 struct vpdma_adb_hdr dei_hdr; 439 struct vpdma_adb_hdr dei_hdr;
362 u32 dei_regs[1]; 440 u32 dei_regs[8];
363 u32 dei_pad[3];
364 struct vpdma_adb_hdr sc_hdr; 441 struct vpdma_adb_hdr sc_hdr;
365 u32 sc_regs[1]; 442 u32 sc_regs[1];
366 u32 sc_pad[3]; 443 u32 sc_pad[3];
@@ -386,6 +463,80 @@ static void init_adb_hdrs(struct vpe_ctx *ctx)
386}; 463};
387 464
388/* 465/*
466 * Allocate or re-allocate the motion vector DMA buffers
467 * There are two buffers, one for input and one for output.
468 * However, the roles are reversed after each field is processed.
469 * In other words, after each field is processed, the previous
470 * output (dst) MV buffer becomes the new input (src) MV buffer.
471 */
472static int realloc_mv_buffers(struct vpe_ctx *ctx, size_t size)
473{
474 struct device *dev = ctx->dev->v4l2_dev.dev;
475
476 if (ctx->mv_buf_size == size)
477 return 0;
478
479 if (ctx->mv_buf[0])
480 dma_free_coherent(dev, ctx->mv_buf_size, ctx->mv_buf[0],
481 ctx->mv_buf_dma[0]);
482
483 if (ctx->mv_buf[1])
484 dma_free_coherent(dev, ctx->mv_buf_size, ctx->mv_buf[1],
485 ctx->mv_buf_dma[1]);
486
487 if (size == 0)
488 return 0;
489
490 ctx->mv_buf[0] = dma_alloc_coherent(dev, size, &ctx->mv_buf_dma[0],
491 GFP_KERNEL);
492 if (!ctx->mv_buf[0]) {
493 vpe_err(ctx->dev, "failed to allocate motion vector buffer\n");
494 return -ENOMEM;
495 }
496
497 ctx->mv_buf[1] = dma_alloc_coherent(dev, size, &ctx->mv_buf_dma[1],
498 GFP_KERNEL);
499 if (!ctx->mv_buf[1]) {
500 vpe_err(ctx->dev, "failed to allocate motion vector buffer\n");
501 dma_free_coherent(dev, size, ctx->mv_buf[0],
502 ctx->mv_buf_dma[0]);
503
504 return -ENOMEM;
505 }
506
507 ctx->mv_buf_size = size;
508 ctx->src_mv_buf_selector = 0;
509
510 return 0;
511}
512
513static void free_mv_buffers(struct vpe_ctx *ctx)
514{
515 realloc_mv_buffers(ctx, 0);
516}
517
518/*
519 * While de-interlacing, we keep the two most recent input buffers
520 * around. This function frees those two buffers when we have
521 * finished processing the current stream.
522 */
523static void free_vbs(struct vpe_ctx *ctx)
524{
525 struct vpe_dev *dev = ctx->dev;
526 unsigned long flags;
527
528 if (ctx->src_vbs[2] == NULL)
529 return;
530
531 spin_lock_irqsave(&dev->lock, flags);
532 if (ctx->src_vbs[2]) {
533 v4l2_m2m_buf_done(ctx->src_vbs[2], VB2_BUF_STATE_DONE);
534 v4l2_m2m_buf_done(ctx->src_vbs[1], VB2_BUF_STATE_DONE);
535 }
536 spin_unlock_irqrestore(&dev->lock, flags);
537}
538
539/*
389 * Enable or disable the VPE clocks 540 * Enable or disable the VPE clocks
390 */ 541 */
391static void vpe_set_clock_enable(struct vpe_dev *dev, bool on) 542static void vpe_set_clock_enable(struct vpe_dev *dev, bool on)
@@ -426,6 +577,7 @@ static void vpe_top_vpdma_reset(struct vpe_dev *dev)
426static void set_us_coefficients(struct vpe_ctx *ctx) 577static void set_us_coefficients(struct vpe_ctx *ctx)
427{ 578{
428 struct vpe_mmr_adb *mmr_adb = ctx->mmr_adb.addr; 579 struct vpe_mmr_adb *mmr_adb = ctx->mmr_adb.addr;
580 struct vpe_q_data *s_q_data = &ctx->q_data[Q_DATA_SRC];
429 u32 *us1_reg = &mmr_adb->us1_regs[0]; 581 u32 *us1_reg = &mmr_adb->us1_regs[0];
430 u32 *us2_reg = &mmr_adb->us2_regs[0]; 582 u32 *us2_reg = &mmr_adb->us2_regs[0];
431 u32 *us3_reg = &mmr_adb->us3_regs[0]; 583 u32 *us3_reg = &mmr_adb->us3_regs[0];
@@ -433,6 +585,9 @@ static void set_us_coefficients(struct vpe_ctx *ctx)
433 585
434 cp = &us_coeffs[0].anchor_fid0_c0; 586 cp = &us_coeffs[0].anchor_fid0_c0;
435 587
588 if (s_q_data->flags & Q_DATA_INTERLACED) /* interlaced */
589 cp += sizeof(us_coeffs[0]) / sizeof(*cp);
590
436 end_cp = cp + sizeof(us_coeffs[0]) / sizeof(*cp); 591 end_cp = cp + sizeof(us_coeffs[0]) / sizeof(*cp);
437 592
438 while (cp < end_cp) { 593 while (cp < end_cp) {
@@ -473,14 +628,28 @@ static void set_cfg_and_line_modes(struct vpe_ctx *ctx)
473 628
474 /* regs for now */ 629 /* regs for now */
475 vpdma_set_line_mode(ctx->dev->vpdma, line_mode, VPE_CHAN_CHROMA1_IN); 630 vpdma_set_line_mode(ctx->dev->vpdma, line_mode, VPE_CHAN_CHROMA1_IN);
631 vpdma_set_line_mode(ctx->dev->vpdma, line_mode, VPE_CHAN_CHROMA2_IN);
632 vpdma_set_line_mode(ctx->dev->vpdma, line_mode, VPE_CHAN_CHROMA3_IN);
476 633
477 /* frame start for input luma */ 634 /* frame start for input luma */
478 vpdma_set_frame_start_event(ctx->dev->vpdma, VPDMA_FSEVENT_CHANNEL_ACTIVE, 635 vpdma_set_frame_start_event(ctx->dev->vpdma, VPDMA_FSEVENT_CHANNEL_ACTIVE,
479 VPE_CHAN_LUMA1_IN); 636 VPE_CHAN_LUMA1_IN);
637 vpdma_set_frame_start_event(ctx->dev->vpdma, VPDMA_FSEVENT_CHANNEL_ACTIVE,
638 VPE_CHAN_LUMA2_IN);
639 vpdma_set_frame_start_event(ctx->dev->vpdma, VPDMA_FSEVENT_CHANNEL_ACTIVE,
640 VPE_CHAN_LUMA3_IN);
480 641
481 /* frame start for input chroma */ 642 /* frame start for input chroma */
482 vpdma_set_frame_start_event(ctx->dev->vpdma, VPDMA_FSEVENT_CHANNEL_ACTIVE, 643 vpdma_set_frame_start_event(ctx->dev->vpdma, VPDMA_FSEVENT_CHANNEL_ACTIVE,
483 VPE_CHAN_CHROMA1_IN); 644 VPE_CHAN_CHROMA1_IN);
645 vpdma_set_frame_start_event(ctx->dev->vpdma, VPDMA_FSEVENT_CHANNEL_ACTIVE,
646 VPE_CHAN_CHROMA2_IN);
647 vpdma_set_frame_start_event(ctx->dev->vpdma, VPDMA_FSEVENT_CHANNEL_ACTIVE,
648 VPE_CHAN_CHROMA3_IN);
649
650 /* frame start for MV in client */
651 vpdma_set_frame_start_event(ctx->dev->vpdma, VPDMA_FSEVENT_CHANNEL_ACTIVE,
652 VPE_CHAN_MV_IN);
484 653
485 ctx->load_mmrs = true; 654 ctx->load_mmrs = true;
486} 655}
@@ -524,13 +693,14 @@ static void set_dst_registers(struct vpe_ctx *ctx)
524/* 693/*
525 * Set the de-interlacer shadow register values 694 * Set the de-interlacer shadow register values
526 */ 695 */
527static void set_dei_regs_bypass(struct vpe_ctx *ctx) 696static void set_dei_regs(struct vpe_ctx *ctx)
528{ 697{
529 struct vpe_mmr_adb *mmr_adb = ctx->mmr_adb.addr; 698 struct vpe_mmr_adb *mmr_adb = ctx->mmr_adb.addr;
530 struct vpe_q_data *s_q_data = &ctx->q_data[Q_DATA_SRC]; 699 struct vpe_q_data *s_q_data = &ctx->q_data[Q_DATA_SRC];
531 unsigned int src_h = s_q_data->c_rect.height; 700 unsigned int src_h = s_q_data->c_rect.height;
532 unsigned int src_w = s_q_data->c_rect.width; 701 unsigned int src_w = s_q_data->c_rect.width;
533 u32 *dei_mmr0 = &mmr_adb->dei_regs[0]; 702 u32 *dei_mmr0 = &mmr_adb->dei_regs[0];
703 bool deinterlace = true;
534 u32 val = 0; 704 u32 val = 0;
535 705
536 /* 706 /*
@@ -539,7 +709,13 @@ static void set_dei_regs_bypass(struct vpe_ctx *ctx)
539 * for both progressive and interlace content in interlace bypass mode. 709 * for both progressive and interlace content in interlace bypass mode.
540 * It has been recommended not to use progressive bypass mode. 710 * It has been recommended not to use progressive bypass mode.
541 */ 711 */
542 val = VPE_DEI_INTERLACE_BYPASS; 712 if ((!ctx->deinterlacing && (s_q_data->flags & Q_DATA_INTERLACED)) ||
713 !(s_q_data->flags & Q_DATA_INTERLACED)) {
714 deinterlace = false;
715 val = VPE_DEI_INTERLACE_BYPASS;
716 }
717
718 src_h = deinterlace ? src_h * 2 : src_h;
543 719
544 val |= (src_h << VPE_DEI_HEIGHT_SHIFT) | 720 val |= (src_h << VPE_DEI_HEIGHT_SHIFT) |
545 (src_w << VPE_DEI_WIDTH_SHIFT) | 721 (src_w << VPE_DEI_WIDTH_SHIFT) |
@@ -550,6 +726,22 @@ static void set_dei_regs_bypass(struct vpe_ctx *ctx)
550 ctx->load_mmrs = true; 726 ctx->load_mmrs = true;
551} 727}
552 728
729static void set_dei_shadow_registers(struct vpe_ctx *ctx)
730{
731 struct vpe_mmr_adb *mmr_adb = ctx->mmr_adb.addr;
732 u32 *dei_mmr = &mmr_adb->dei_regs[0];
733 const struct vpe_dei_regs *cur = &dei_regs;
734
735 dei_mmr[2] = cur->mdt_spacial_freq_thr_reg;
736 dei_mmr[3] = cur->edi_config_reg;
737 dei_mmr[4] = cur->edi_lut_reg0;
738 dei_mmr[5] = cur->edi_lut_reg1;
739 dei_mmr[6] = cur->edi_lut_reg2;
740 dei_mmr[7] = cur->edi_lut_reg3;
741
742 ctx->load_mmrs = true;
743}
744
553static void set_csc_coeff_bypass(struct vpe_ctx *ctx) 745static void set_csc_coeff_bypass(struct vpe_ctx *ctx)
554{ 746{
555 struct vpe_mmr_adb *mmr_adb = ctx->mmr_adb.addr; 747 struct vpe_mmr_adb *mmr_adb = ctx->mmr_adb.addr;
@@ -578,10 +770,35 @@ static void set_sc_regs_bypass(struct vpe_ctx *ctx)
578 */ 770 */
579static int set_srcdst_params(struct vpe_ctx *ctx) 771static int set_srcdst_params(struct vpe_ctx *ctx)
580{ 772{
773 struct vpe_q_data *s_q_data = &ctx->q_data[Q_DATA_SRC];
774 struct vpe_q_data *d_q_data = &ctx->q_data[Q_DATA_DST];
775 size_t mv_buf_size;
776 int ret;
777
581 ctx->sequence = 0; 778 ctx->sequence = 0;
779 ctx->field = V4L2_FIELD_TOP;
780
781 if ((s_q_data->flags & Q_DATA_INTERLACED) &&
782 !(d_q_data->flags & Q_DATA_INTERLACED)) {
783 const struct vpdma_data_format *mv =
784 &vpdma_misc_fmts[VPDMA_DATA_FMT_MV];
785
786 ctx->deinterlacing = 1;
787 mv_buf_size =
788 (s_q_data->width * s_q_data->height * mv->depth) >> 3;
789 } else {
790 ctx->deinterlacing = 0;
791 mv_buf_size = 0;
792 }
793
794 free_vbs(ctx);
795
796 ret = realloc_mv_buffers(ctx, mv_buf_size);
797 if (ret)
798 return ret;
582 799
583 set_cfg_and_line_modes(ctx); 800 set_cfg_and_line_modes(ctx);
584 set_dei_regs_bypass(ctx); 801 set_dei_regs(ctx);
585 set_csc_coeff_bypass(ctx); 802 set_csc_coeff_bypass(ctx);
586 set_sc_regs_bypass(ctx); 803 set_sc_regs_bypass(ctx);
587 804
@@ -608,6 +825,9 @@ static int job_ready(void *priv)
608 struct vpe_ctx *ctx = priv; 825 struct vpe_ctx *ctx = priv;
609 int needed = ctx->bufs_per_job; 826 int needed = ctx->bufs_per_job;
610 827
828 if (ctx->deinterlacing && ctx->src_vbs[2] == NULL)
829 needed += 2; /* need additional two most recent fields */
830
611 if (v4l2_m2m_num_src_bufs_ready(ctx->m2m_ctx) < needed) 831 if (v4l2_m2m_num_src_bufs_ready(ctx->m2m_ctx) < needed)
612 return 0; 832 return 0;
613 833
@@ -735,17 +955,25 @@ static void add_out_dtd(struct vpe_ctx *ctx, int port)
735 struct v4l2_rect *c_rect = &q_data->c_rect; 955 struct v4l2_rect *c_rect = &q_data->c_rect;
736 struct vpe_fmt *fmt = q_data->fmt; 956 struct vpe_fmt *fmt = q_data->fmt;
737 const struct vpdma_data_format *vpdma_fmt; 957 const struct vpdma_data_format *vpdma_fmt;
738 int plane = fmt->coplanar ? p_data->vb_part : 0; 958 int mv_buf_selector = !ctx->src_mv_buf_selector;
739 dma_addr_t dma_addr; 959 dma_addr_t dma_addr;
740 u32 flags = 0; 960 u32 flags = 0;
741 961
742 vpdma_fmt = fmt->vpdma_fmt[plane]; 962 if (port == VPE_PORT_MV_OUT) {
743 dma_addr = vb2_dma_contig_plane_dma_addr(vb, plane); 963 vpdma_fmt = &vpdma_misc_fmts[VPDMA_DATA_FMT_MV];
744 if (!dma_addr) { 964 dma_addr = ctx->mv_buf_dma[mv_buf_selector];
745 vpe_err(ctx->dev, 965 } else {
746 "acquiring output buffer(%d) dma_addr failed\n", 966 /* to incorporate interleaved formats */
747 port); 967 int plane = fmt->coplanar ? p_data->vb_part : 0;
748 return; 968
969 vpdma_fmt = fmt->vpdma_fmt[plane];
970 dma_addr = vb2_dma_contig_plane_dma_addr(vb, plane);
971 if (!dma_addr) {
972 vpe_err(ctx->dev,
973 "acquiring output buffer(%d) dma_addr failed\n",
974 port);
975 return;
976 }
749 } 977 }
750 978
751 if (q_data->flags & Q_DATA_FRAME_1D) 979 if (q_data->flags & Q_DATA_FRAME_1D)
@@ -761,23 +989,31 @@ static void add_in_dtd(struct vpe_ctx *ctx, int port)
761{ 989{
762 struct vpe_q_data *q_data = &ctx->q_data[Q_DATA_SRC]; 990 struct vpe_q_data *q_data = &ctx->q_data[Q_DATA_SRC];
763 const struct vpe_port_data *p_data = &port_data[port]; 991 const struct vpe_port_data *p_data = &port_data[port];
764 struct vb2_buffer *vb = ctx->src_vb; 992 struct vb2_buffer *vb = ctx->src_vbs[p_data->vb_index];
765 struct v4l2_rect *c_rect = &q_data->c_rect; 993 struct v4l2_rect *c_rect = &q_data->c_rect;
766 struct vpe_fmt *fmt = q_data->fmt; 994 struct vpe_fmt *fmt = q_data->fmt;
767 const struct vpdma_data_format *vpdma_fmt; 995 const struct vpdma_data_format *vpdma_fmt;
768 int plane = fmt->coplanar ? p_data->vb_part : 0; 996 int mv_buf_selector = ctx->src_mv_buf_selector;
769 int field = 0; 997 int field = vb->v4l2_buf.field == V4L2_FIELD_BOTTOM;
770 dma_addr_t dma_addr; 998 dma_addr_t dma_addr;
771 u32 flags = 0; 999 u32 flags = 0;
772 1000
773 vpdma_fmt = fmt->vpdma_fmt[plane]; 1001 if (port == VPE_PORT_MV_IN) {
1002 vpdma_fmt = &vpdma_misc_fmts[VPDMA_DATA_FMT_MV];
1003 dma_addr = ctx->mv_buf_dma[mv_buf_selector];
1004 } else {
1005 /* to incorporate interleaved formats */
1006 int plane = fmt->coplanar ? p_data->vb_part : 0;
774 1007
775 dma_addr = vb2_dma_contig_plane_dma_addr(vb, plane); 1008 vpdma_fmt = fmt->vpdma_fmt[plane];
776 if (!dma_addr) { 1009
777 vpe_err(ctx->dev, 1010 dma_addr = vb2_dma_contig_plane_dma_addr(vb, plane);
778 "acquiring input buffer(%d) dma_addr failed\n", 1011 if (!dma_addr) {
779 port); 1012 vpe_err(ctx->dev,
780 return; 1013 "acquiring input buffer(%d) dma_addr failed\n",
1014 port);
1015 return;
1016 }
781 } 1017 }
782 1018
783 if (q_data->flags & Q_DATA_FRAME_1D) 1019 if (q_data->flags & Q_DATA_FRAME_1D)
@@ -795,7 +1031,8 @@ static void add_in_dtd(struct vpe_ctx *ctx, int port)
795static void enable_irqs(struct vpe_ctx *ctx) 1031static void enable_irqs(struct vpe_ctx *ctx)
796{ 1032{
797 write_reg(ctx->dev, VPE_INT0_ENABLE0_SET, VPE_INT0_LIST0_COMPLETE); 1033 write_reg(ctx->dev, VPE_INT0_ENABLE0_SET, VPE_INT0_LIST0_COMPLETE);
798 write_reg(ctx->dev, VPE_INT0_ENABLE1_SET, VPE_DS1_UV_ERROR_INT); 1034 write_reg(ctx->dev, VPE_INT0_ENABLE1_SET, VPE_DEI_ERROR_INT |
1035 VPE_DS1_UV_ERROR_INT);
799 1036
800 vpdma_enable_list_complete_irq(ctx->dev->vpdma, 0, true); 1037 vpdma_enable_list_complete_irq(ctx->dev->vpdma, 0, true);
801} 1038}
@@ -818,8 +1055,15 @@ static void device_run(void *priv)
818 struct vpe_ctx *ctx = priv; 1055 struct vpe_ctx *ctx = priv;
819 struct vpe_q_data *d_q_data = &ctx->q_data[Q_DATA_DST]; 1056 struct vpe_q_data *d_q_data = &ctx->q_data[Q_DATA_DST];
820 1057
821 ctx->src_vb = v4l2_m2m_src_buf_remove(ctx->m2m_ctx); 1058 if (ctx->deinterlacing && ctx->src_vbs[2] == NULL) {
822 WARN_ON(ctx->src_vb == NULL); 1059 ctx->src_vbs[2] = v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
1060 WARN_ON(ctx->src_vbs[2] == NULL);
1061 ctx->src_vbs[1] = v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
1062 WARN_ON(ctx->src_vbs[1] == NULL);
1063 }
1064
1065 ctx->src_vbs[0] = v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
1066 WARN_ON(ctx->src_vbs[0] == NULL);
823 ctx->dst_vb = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx); 1067 ctx->dst_vb = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx);
824 WARN_ON(ctx->dst_vb == NULL); 1068 WARN_ON(ctx->dst_vb == NULL);
825 1069
@@ -831,28 +1075,67 @@ static void device_run(void *priv)
831 ctx->load_mmrs = false; 1075 ctx->load_mmrs = false;
832 } 1076 }
833 1077
1078 /* output data descriptors */
1079 if (ctx->deinterlacing)
1080 add_out_dtd(ctx, VPE_PORT_MV_OUT);
1081
834 add_out_dtd(ctx, VPE_PORT_LUMA_OUT); 1082 add_out_dtd(ctx, VPE_PORT_LUMA_OUT);
835 if (d_q_data->fmt->coplanar) 1083 if (d_q_data->fmt->coplanar)
836 add_out_dtd(ctx, VPE_PORT_CHROMA_OUT); 1084 add_out_dtd(ctx, VPE_PORT_CHROMA_OUT);
837 1085
1086 /* input data descriptors */
1087 if (ctx->deinterlacing) {
1088 add_in_dtd(ctx, VPE_PORT_LUMA3_IN);
1089 add_in_dtd(ctx, VPE_PORT_CHROMA3_IN);
1090
1091 add_in_dtd(ctx, VPE_PORT_LUMA2_IN);
1092 add_in_dtd(ctx, VPE_PORT_CHROMA2_IN);
1093 }
1094
838 add_in_dtd(ctx, VPE_PORT_LUMA1_IN); 1095 add_in_dtd(ctx, VPE_PORT_LUMA1_IN);
839 add_in_dtd(ctx, VPE_PORT_CHROMA1_IN); 1096 add_in_dtd(ctx, VPE_PORT_CHROMA1_IN);
840 1097
1098 if (ctx->deinterlacing)
1099 add_in_dtd(ctx, VPE_PORT_MV_IN);
1100
841 /* sync on channel control descriptors for input ports */ 1101 /* sync on channel control descriptors for input ports */
842 vpdma_add_sync_on_channel_ctd(&ctx->desc_list, VPE_CHAN_LUMA1_IN); 1102 vpdma_add_sync_on_channel_ctd(&ctx->desc_list, VPE_CHAN_LUMA1_IN);
843 vpdma_add_sync_on_channel_ctd(&ctx->desc_list, VPE_CHAN_CHROMA1_IN); 1103 vpdma_add_sync_on_channel_ctd(&ctx->desc_list, VPE_CHAN_CHROMA1_IN);
844 1104
1105 if (ctx->deinterlacing) {
1106 vpdma_add_sync_on_channel_ctd(&ctx->desc_list,
1107 VPE_CHAN_LUMA2_IN);
1108 vpdma_add_sync_on_channel_ctd(&ctx->desc_list,
1109 VPE_CHAN_CHROMA2_IN);
1110
1111 vpdma_add_sync_on_channel_ctd(&ctx->desc_list,
1112 VPE_CHAN_LUMA3_IN);
1113 vpdma_add_sync_on_channel_ctd(&ctx->desc_list,
1114 VPE_CHAN_CHROMA3_IN);
1115
1116 vpdma_add_sync_on_channel_ctd(&ctx->desc_list, VPE_CHAN_MV_IN);
1117 }
1118
845 /* sync on channel control descriptors for output ports */ 1119 /* sync on channel control descriptors for output ports */
846 vpdma_add_sync_on_channel_ctd(&ctx->desc_list, VPE_CHAN_LUMA_OUT); 1120 vpdma_add_sync_on_channel_ctd(&ctx->desc_list, VPE_CHAN_LUMA_OUT);
847 if (d_q_data->fmt->coplanar) 1121 if (d_q_data->fmt->coplanar)
848 vpdma_add_sync_on_channel_ctd(&ctx->desc_list, VPE_CHAN_CHROMA_OUT); 1122 vpdma_add_sync_on_channel_ctd(&ctx->desc_list, VPE_CHAN_CHROMA_OUT);
849 1123
1124 if (ctx->deinterlacing)
1125 vpdma_add_sync_on_channel_ctd(&ctx->desc_list, VPE_CHAN_MV_OUT);
1126
850 enable_irqs(ctx); 1127 enable_irqs(ctx);
851 1128
852 vpdma_map_desc_buf(ctx->dev->vpdma, &ctx->desc_list.buf); 1129 vpdma_map_desc_buf(ctx->dev->vpdma, &ctx->desc_list.buf);
853 vpdma_submit_descs(ctx->dev->vpdma, &ctx->desc_list); 1130 vpdma_submit_descs(ctx->dev->vpdma, &ctx->desc_list);
854} 1131}
855 1132
1133static void dei_error(struct vpe_ctx *ctx)
1134{
1135 dev_warn(ctx->dev->v4l2_dev.dev,
1136 "received DEI error interrupt\n");
1137}
1138
856static void ds1_uv_error(struct vpe_ctx *ctx) 1139static void ds1_uv_error(struct vpe_ctx *ctx)
857{ 1140{
858 dev_warn(ctx->dev->v4l2_dev.dev, 1141 dev_warn(ctx->dev->v4l2_dev.dev,
@@ -863,6 +1146,7 @@ static irqreturn_t vpe_irq(int irq_vpe, void *data)
863{ 1146{
864 struct vpe_dev *dev = (struct vpe_dev *)data; 1147 struct vpe_dev *dev = (struct vpe_dev *)data;
865 struct vpe_ctx *ctx; 1148 struct vpe_ctx *ctx;
1149 struct vpe_q_data *d_q_data;
866 struct vb2_buffer *s_vb, *d_vb; 1150 struct vb2_buffer *s_vb, *d_vb;
867 struct v4l2_buffer *s_buf, *d_buf; 1151 struct v4l2_buffer *s_buf, *d_buf;
868 unsigned long flags; 1152 unsigned long flags;
@@ -886,9 +1170,15 @@ static irqreturn_t vpe_irq(int irq_vpe, void *data)
886 goto handled; 1170 goto handled;
887 } 1171 }
888 1172
889 if (irqst1 & VPE_DS1_UV_ERROR_INT) { 1173 if (irqst1) {
890 irqst1 &= ~VPE_DS1_UV_ERROR_INT; 1174 if (irqst1 & VPE_DEI_ERROR_INT) {
891 ds1_uv_error(ctx); 1175 irqst1 &= ~VPE_DEI_ERROR_INT;
1176 dei_error(ctx);
1177 }
1178 if (irqst1 & VPE_DS1_UV_ERROR_INT) {
1179 irqst1 &= ~VPE_DS1_UV_ERROR_INT;
1180 ds1_uv_error(ctx);
1181 }
892 } 1182 }
893 1183
894 if (irqst0) { 1184 if (irqst0) {
@@ -911,10 +1201,13 @@ static irqreturn_t vpe_irq(int irq_vpe, void *data)
911 1201
912 vpdma_reset_desc_list(&ctx->desc_list); 1202 vpdma_reset_desc_list(&ctx->desc_list);
913 1203
1204 /* the previous dst mv buffer becomes the next src mv buffer */
1205 ctx->src_mv_buf_selector = !ctx->src_mv_buf_selector;
1206
914 if (ctx->aborting) 1207 if (ctx->aborting)
915 goto finished; 1208 goto finished;
916 1209
917 s_vb = ctx->src_vb; 1210 s_vb = ctx->src_vbs[0];
918 d_vb = ctx->dst_vb; 1211 d_vb = ctx->dst_vb;
919 s_buf = &s_vb->v4l2_buf; 1212 s_buf = &s_vb->v4l2_buf;
920 d_buf = &d_vb->v4l2_buf; 1213 d_buf = &d_vb->v4l2_buf;
@@ -924,16 +1217,35 @@ static irqreturn_t vpe_irq(int irq_vpe, void *data)
924 d_buf->flags |= V4L2_BUF_FLAG_TIMECODE; 1217 d_buf->flags |= V4L2_BUF_FLAG_TIMECODE;
925 d_buf->timecode = s_buf->timecode; 1218 d_buf->timecode = s_buf->timecode;
926 } 1219 }
927
928 d_buf->sequence = ctx->sequence; 1220 d_buf->sequence = ctx->sequence;
1221 d_buf->field = ctx->field;
1222
1223 d_q_data = &ctx->q_data[Q_DATA_DST];
1224 if (d_q_data->flags & Q_DATA_INTERLACED) {
1225 if (ctx->field == V4L2_FIELD_BOTTOM) {
1226 ctx->sequence++;
1227 ctx->field = V4L2_FIELD_TOP;
1228 } else {
1229 WARN_ON(ctx->field != V4L2_FIELD_TOP);
1230 ctx->field = V4L2_FIELD_BOTTOM;
1231 }
1232 } else {
1233 ctx->sequence++;
1234 }
929 1235
930 ctx->sequence++; 1236 if (ctx->deinterlacing)
1237 s_vb = ctx->src_vbs[2];
931 1238
932 spin_lock_irqsave(&dev->lock, flags); 1239 spin_lock_irqsave(&dev->lock, flags);
933 v4l2_m2m_buf_done(s_vb, VB2_BUF_STATE_DONE); 1240 v4l2_m2m_buf_done(s_vb, VB2_BUF_STATE_DONE);
934 v4l2_m2m_buf_done(d_vb, VB2_BUF_STATE_DONE); 1241 v4l2_m2m_buf_done(d_vb, VB2_BUF_STATE_DONE);
935 spin_unlock_irqrestore(&dev->lock, flags); 1242 spin_unlock_irqrestore(&dev->lock, flags);
936 1243
1244 if (ctx->deinterlacing) {
1245 ctx->src_vbs[2] = ctx->src_vbs[1];
1246 ctx->src_vbs[1] = ctx->src_vbs[0];
1247 }
1248
937 ctx->bufs_completed++; 1249 ctx->bufs_completed++;
938 if (ctx->bufs_completed < ctx->bufs_per_job) { 1250 if (ctx->bufs_completed < ctx->bufs_per_job) {
939 device_run(ctx); 1251 device_run(ctx);
@@ -1012,6 +1324,7 @@ static int vpe_g_fmt(struct file *file, void *priv, struct v4l2_format *f)
1012 pix->width = q_data->width; 1324 pix->width = q_data->width;
1013 pix->height = q_data->height; 1325 pix->height = q_data->height;
1014 pix->pixelformat = q_data->fmt->fourcc; 1326 pix->pixelformat = q_data->fmt->fourcc;
1327 pix->field = q_data->field;
1015 1328
1016 if (V4L2_TYPE_IS_OUTPUT(f->type)) { 1329 if (V4L2_TYPE_IS_OUTPUT(f->type)) {
1017 pix->colorspace = q_data->colorspace; 1330 pix->colorspace = q_data->colorspace;
@@ -1047,7 +1360,8 @@ static int __vpe_try_fmt(struct vpe_ctx *ctx, struct v4l2_format *f,
1047 return -EINVAL; 1360 return -EINVAL;
1048 } 1361 }
1049 1362
1050 pix->field = V4L2_FIELD_NONE; 1363 if (pix->field != V4L2_FIELD_NONE && pix->field != V4L2_FIELD_ALTERNATE)
1364 pix->field = V4L2_FIELD_NONE;
1051 1365
1052 v4l_bound_align_image(&pix->width, MIN_W, MAX_W, W_ALIGN, 1366 v4l_bound_align_image(&pix->width, MIN_W, MAX_W, W_ALIGN,
1053 &pix->height, MIN_H, MAX_H, H_ALIGN, 1367 &pix->height, MIN_H, MAX_H, H_ALIGN,
@@ -1124,6 +1438,7 @@ static int __vpe_s_fmt(struct vpe_ctx *ctx, struct v4l2_format *f)
1124 q_data->width = pix->width; 1438 q_data->width = pix->width;
1125 q_data->height = pix->height; 1439 q_data->height = pix->height;
1126 q_data->colorspace = pix->colorspace; 1440 q_data->colorspace = pix->colorspace;
1441 q_data->field = pix->field;
1127 1442
1128 for (i = 0; i < pix->num_planes; i++) { 1443 for (i = 0; i < pix->num_planes; i++) {
1129 plane_fmt = &pix->plane_fmt[i]; 1444 plane_fmt = &pix->plane_fmt[i];
@@ -1137,6 +1452,11 @@ static int __vpe_s_fmt(struct vpe_ctx *ctx, struct v4l2_format *f)
1137 q_data->c_rect.width = q_data->width; 1452 q_data->c_rect.width = q_data->width;
1138 q_data->c_rect.height = q_data->height; 1453 q_data->c_rect.height = q_data->height;
1139 1454
1455 if (q_data->field == V4L2_FIELD_ALTERNATE)
1456 q_data->flags |= Q_DATA_INTERLACED;
1457 else
1458 q_data->flags &= ~Q_DATA_INTERLACED;
1459
1140 vpe_dbg(ctx->dev, "Setting format for type %d, wxh: %dx%d, fmt: %d bpl_y %d", 1460 vpe_dbg(ctx->dev, "Setting format for type %d, wxh: %dx%d, fmt: %d bpl_y %d",
1141 f->type, q_data->width, q_data->height, q_data->fmt->fourcc, 1461 f->type, q_data->width, q_data->height, q_data->fmt->fourcc,
1142 q_data->bytesperline[VPE_LUMA]); 1462 q_data->bytesperline[VPE_LUMA]);
@@ -1451,6 +1771,7 @@ static int vpe_open(struct file *file)
1451 s_q_data->sizeimage[VPE_LUMA] = (s_q_data->width * s_q_data->height * 1771 s_q_data->sizeimage[VPE_LUMA] = (s_q_data->width * s_q_data->height *
1452 s_q_data->fmt->vpdma_fmt[VPE_LUMA]->depth) >> 3; 1772 s_q_data->fmt->vpdma_fmt[VPE_LUMA]->depth) >> 3;
1453 s_q_data->colorspace = V4L2_COLORSPACE_SMPTE240M; 1773 s_q_data->colorspace = V4L2_COLORSPACE_SMPTE240M;
1774 s_q_data->field = V4L2_FIELD_NONE;
1454 s_q_data->c_rect.left = 0; 1775 s_q_data->c_rect.left = 0;
1455 s_q_data->c_rect.top = 0; 1776 s_q_data->c_rect.top = 0;
1456 s_q_data->c_rect.width = s_q_data->width; 1777 s_q_data->c_rect.width = s_q_data->width;
@@ -1459,6 +1780,7 @@ static int vpe_open(struct file *file)
1459 1780
1460 ctx->q_data[Q_DATA_DST] = *s_q_data; 1781 ctx->q_data[Q_DATA_DST] = *s_q_data;
1461 1782
1783 set_dei_shadow_registers(ctx);
1462 set_src_registers(ctx); 1784 set_src_registers(ctx);
1463 set_dst_registers(ctx); 1785 set_dst_registers(ctx);
1464 ret = set_srcdst_params(ctx); 1786 ret = set_srcdst_params(ctx);
@@ -1513,6 +1835,8 @@ static int vpe_release(struct file *file)
1513 vpe_dbg(dev, "releasing instance %p\n", ctx); 1835 vpe_dbg(dev, "releasing instance %p\n", ctx);
1514 1836
1515 mutex_lock(&dev->dev_mutex); 1837 mutex_lock(&dev->dev_mutex);
1838 free_vbs(ctx);
1839 free_mv_buffers(ctx);
1516 vpdma_free_desc_list(&ctx->desc_list); 1840 vpdma_free_desc_list(&ctx->desc_list);
1517 vpdma_free_desc_buf(&ctx->mmr_adb); 1841 vpdma_free_desc_buf(&ctx->mmr_adb);
1518 1842