diff options
-rw-r--r-- | drivers/media/platform/ti-vpe/vpe.c | 392 |
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 | */ | ||
129 | struct 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 | */ | ||
141 | static 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 | */ |
119 | struct vpe_port_data { | 153 | struct 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 { | |||
133 | static const struct vpe_port_data port_data[11] = { | 174 | static 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 | ||
223 | enum { | 294 | enum { |
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 | */ | ||
472 | static 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 | |||
513 | static 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 | */ | ||
523 | static 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 | */ |
391 | static void vpe_set_clock_enable(struct vpe_dev *dev, bool on) | 542 | static 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) | |||
426 | static void set_us_coefficients(struct vpe_ctx *ctx) | 577 | static 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 | */ |
527 | static void set_dei_regs_bypass(struct vpe_ctx *ctx) | 696 | static 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 | ||
729 | static 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 | |||
553 | static void set_csc_coeff_bypass(struct vpe_ctx *ctx) | 745 | static 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 | */ |
579 | static int set_srcdst_params(struct vpe_ctx *ctx) | 771 | static 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) | |||
795 | static void enable_irqs(struct vpe_ctx *ctx) | 1031 | static 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 | ||
1133 | static void dei_error(struct vpe_ctx *ctx) | ||
1134 | { | ||
1135 | dev_warn(ctx->dev->v4l2_dev.dev, | ||
1136 | "received DEI error interrupt\n"); | ||
1137 | } | ||
1138 | |||
856 | static void ds1_uv_error(struct vpe_ctx *ctx) | 1139 | static 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 | ||