From: Fabien Dessenne <fabien.dessenne@xxxxxx> Support top field first and bottom field first interlaced buffers Signed-off-by: Fabien Dessenne <fabien.dessenne@xxxxxx> --- drivers/gpu/drm/sti/sti_hqvdp.c | 72 +++++++++++++++++++++++++---------------- 1 file changed, 44 insertions(+), 28 deletions(-) diff --git a/drivers/gpu/drm/sti/sti_hqvdp.c b/drivers/gpu/drm/sti/sti_hqvdp.c index e9c33fb..e024c13 100644 --- a/drivers/gpu/drm/sti/sti_hqvdp.c +++ b/drivers/gpu/drm/sti/sti_hqvdp.c @@ -325,7 +325,7 @@ struct sti_hqvdp_cmd { * @clk_pix_main: pix main clock * @reset: reset control * @vtg_nb: notifier to handle VTG Vsync - * @btm_field_pending: is there any bottom field (interlaced frame) to display + * @nxt_field_pending: is there any other field (interlaced frame) to display * @hqvdp_cmd: buffer of commands * @hqvdp_cmd_paddr: physical address of hqvdp_cmd * @vtg: vtg for main data path @@ -340,7 +340,7 @@ struct sti_hqvdp { struct clk *clk_pix_main; struct reset_control *reset; struct notifier_block vtg_nb; - bool btm_field_pending; + bool nxt_field_pending; void *hqvdp_cmd; dma_addr_t hqvdp_cmd_paddr; struct sti_vtg *vtg; @@ -784,7 +784,7 @@ static void sti_hqvdp_disable(struct sti_hqvdp *hqvdp) * @evt: event message * @data: private data * - * Handle VTG Vsync event, display pending bottom field + * Handle VTG Vsync event, display next field * * RETURNS: * 0 on success. @@ -792,8 +792,8 @@ static void sti_hqvdp_disable(struct sti_hqvdp *hqvdp) int sti_hqvdp_vtg_cb(struct notifier_block *nb, unsigned long evt, void *data) { struct sti_hqvdp *hqvdp = container_of(nb, struct sti_hqvdp, vtg_nb); - int btm_cmd_offset, top_cmd_offest; - struct sti_hqvdp_cmd *btm_cmd, *top_cmd; + int next_cmd_offset, curr_cmd_offest; + struct sti_hqvdp_cmd *next_cmd, *curr_cmd; if ((evt != VTG_TOP_FIELD_EVENT) && (evt != VTG_BOTTOM_FIELD_EVENT)) { DRM_DEBUG_DRIVER("Unknown event\n"); @@ -808,31 +808,41 @@ int sti_hqvdp_vtg_cb(struct notifier_block *nb, unsigned long evt, void *data) sti_hqvdp_disable(hqvdp); } - if (hqvdp->btm_field_pending) { - /* Create the btm field command from the current one */ - btm_cmd_offset = sti_hqvdp_get_free_cmd(hqvdp); - top_cmd_offest = sti_hqvdp_get_curr_cmd(hqvdp); - if ((btm_cmd_offset == -1) || (top_cmd_offest == -1)) { + if (hqvdp->nxt_field_pending) { + /* Create the next field command from the current one */ + next_cmd_offset = sti_hqvdp_get_free_cmd(hqvdp); + curr_cmd_offest = sti_hqvdp_get_curr_cmd(hqvdp); + if ((next_cmd_offset == -1) || (curr_cmd_offest == -1)) { DRM_DEBUG_DRIVER("Warning: no cmd, will skip field\n"); return -EBUSY; } - btm_cmd = hqvdp->hqvdp_cmd + btm_cmd_offset; - top_cmd = hqvdp->hqvdp_cmd + top_cmd_offest; - - memcpy(btm_cmd, top_cmd, sizeof(*btm_cmd)); - - btm_cmd->top.config = TOP_CONFIG_INTER_BTM; - btm_cmd->top.current_luma += - btm_cmd->top.luma_src_pitch / 2; - btm_cmd->top.current_chroma += - btm_cmd->top.chroma_src_pitch / 2; + next_cmd = hqvdp->hqvdp_cmd + next_cmd_offset; + curr_cmd = hqvdp->hqvdp_cmd + curr_cmd_offest; + + memcpy(next_cmd, curr_cmd, sizeof(*next_cmd)); + + if (curr_cmd->top.config == TOP_CONFIG_INTER_TOP) { + /* Display the bottom field now */ + next_cmd->top.config = TOP_CONFIG_INTER_BTM; + next_cmd->top.current_luma += + next_cmd->top.luma_src_pitch / 2; + next_cmd->top.current_chroma += + next_cmd->top.chroma_src_pitch / 2; + } else { + /* Display the top field now */ + next_cmd->top.config = TOP_CONFIG_INTER_TOP; + next_cmd->top.current_luma -= + next_cmd->top.luma_src_pitch / 2; + next_cmd->top.current_chroma -= + next_cmd->top.chroma_src_pitch / 2; + } /* Post the command to mailbox */ - writel(hqvdp->hqvdp_cmd_paddr + btm_cmd_offset, - hqvdp->regs + HQVDP_MBX_NEXT_CMD); + writel(hqvdp->hqvdp_cmd_paddr + next_cmd_offset, + hqvdp->regs + HQVDP_MBX_NEXT_CMD); - hqvdp->btm_field_pending = false; + hqvdp->nxt_field_pending = false; dev_dbg(hqvdp->dev, "%s Posted command:0x%x\n", __func__, hqvdp->hqvdp_cmd_paddr); @@ -1077,7 +1087,7 @@ static int sti_hqvdp_atomic_check(struct drm_plane *drm_plane, return -EINVAL; } - /* Register VTG Vsync callback to handle bottom fields */ + /* Register VTG Vsync callback to handle bottom/top fields */ if (sti_vtg_register_client(hqvdp->vtg, &hqvdp->vtg_nb, crtc)) { @@ -1175,8 +1185,14 @@ static void sti_hqvdp_atomic_update(struct drm_plane *drm_plane, /* Handle interlaced */ if (fb->flags & DRM_MODE_FB_INTERLACED) { - /* Top field to display */ - cmd->top.config = TOP_CONFIG_INTER_TOP; + /* Top or bottom field */ + if (fb->flags & DRM_MODE_FB_BFF) { + cmd->top.config = TOP_CONFIG_INTER_BTM; + cmd->top.current_luma += cmd->top.luma_src_pitch; + cmd->top.current_chroma += cmd->top.chroma_src_pitch; + } else { + cmd->top.config = TOP_CONFIG_INTER_TOP; + } /* Update pitches and vert size */ cmd->top.input_frame_size = (src_h / 2) << 16 | src_w; @@ -1201,9 +1217,9 @@ static void sti_hqvdp_atomic_update(struct drm_plane *drm_plane, writel(hqvdp->hqvdp_cmd_paddr + cmd_offset, hqvdp->regs + HQVDP_MBX_NEXT_CMD); - /* Interlaced : get ready to display the bottom field at next Vsync */ + /* Interlaced : get ready to display the next field at next Vsync */ if (fb->flags & DRM_MODE_FB_INTERLACED) - hqvdp->btm_field_pending = true; + hqvdp->nxt_field_pending = true; dev_dbg(hqvdp->dev, "%s Posted command:0x%x\n", __func__, hqvdp->hqvdp_cmd_paddr + cmd_offset); -- 1.9.1 _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/dri-devel