On 10/27/2015 05:33 AM, Rob Clark wrote: > On Mon, Oct 26, 2015 at 5:54 AM, Archit Taneja <architt at codeaurora.org> > wrote: >> MDP5 has line count and frame count registers for each interface. Enable >> these counters and use them to implement the get_vblank_timestamp drm >> driver op. >> >> The line counter starts with the value 1 at the beginning of the VSYNC >> pulse and ends with value VTOTAL at the end of VFP. This value is used >> to determine whether we're in blanking period or not, and an adjusted >> value of this counter is used to get vpos as expected by >> get_scanout_position. Since there is no way to calculate hpos, we always >> set it to 0. > > What are the odds that mdp(n!=5) could support the same? If/when that > ever happens I could see making some of this helpers to duplicate a > bit less in mdpN backend.. but I guess also fine to cross that bridge > when we come to it. Other than that, lgtm, thanks
The MDP4 line counter only loops within the active region, making it sort of ineffective. That's the main reason why I didn't attempt to implement it for mdp4. There seems to be a 12 bit frame counter available to implement a vblank counter, but without the line counter, I'm not sure if that'll be any better than using the software vblank counter. Archit > > BR, > -R > >> Signed-off-by: Archit Taneja <architt at codeaurora.org> >> --- >> drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c | 18 ++++ >> drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c | 129 >> ++++++++++++++++++++++++++++ >> drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h | 2 + >> 3 files changed, 149 insertions(+) >> >> diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c >> b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c >> index c9e32b0..a019656 100644 >> --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c >> +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c >> @@ -293,6 +293,24 @@ static const struct drm_encoder_helper_funcs >> mdp5_encoder_helper_funcs = { >> .enable = mdp5_encoder_enable, >> }; >> >> +int mdp5_encoder_get_linecount(struct drm_encoder *encoder) >> +{ >> + struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder); >> + struct mdp5_kms *mdp5_kms = get_kms(encoder); >> + int intf = mdp5_encoder->intf.num; >> + >> + return mdp5_read(mdp5_kms, REG_MDP5_INTF_LINE_COUNT(intf)); >> +} >> + >> +u32 mdp5_encoder_get_framecount(struct drm_encoder *encoder) >> +{ >> + struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder); >> + struct mdp5_kms *mdp5_kms = get_kms(encoder); >> + int intf = mdp5_encoder->intf.num; >> + >> + return mdp5_read(mdp5_kms, REG_MDP5_INTF_FRAME_COUNT(intf)); >> +} >> + >> int mdp5_encoder_set_split_display(struct drm_encoder *encoder, >> struct drm_encoder *slave_encoder) >> { >> diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c >> b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c >> index b532faa..e115318 100644 >> --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c >> +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c >> @@ -468,6 +468,127 @@ static int get_clk(struct platform_device *pdev, >> struct clk **clkp, >> return 0; >> } >> >> +static struct drm_encoder *get_encoder_from_crtc(struct drm_crtc *crtc) >> +{ >> + struct drm_device *dev = crtc->dev; >> + struct drm_encoder *encoder; >> + >> + drm_for_each_encoder(encoder, dev) >> + if (encoder->crtc == crtc) >> + return encoder; >> + >> + return NULL; >> +} >> + >> +static int mdp5_get_scanoutpos(struct drm_device *dev, unsigned int pipe, >> + unsigned int flags, int *vpos, int *hpos, >> + ktime_t *stime, ktime_t *etime, >> + const struct drm_display_mode *mode) >> +{ >> + struct msm_drm_private *priv = dev->dev_private; >> + struct drm_crtc *crtc; >> + struct drm_encoder *encoder; >> + int line, vsw, vbp, vactive_start, vactive_end, vfp_end; >> + int ret = 0; >> + >> + crtc = priv->crtcs[pipe]; >> + if (!crtc) { >> + DRM_ERROR("Invalid crtc %d\n", pipe); >> + return 0; >> + } >> + >> + encoder = get_encoder_from_crtc(crtc); >> + if (!encoder) { >> + DRM_ERROR("no encoder found for crtc %d\n", pipe); >> + return 0; >> + } >> + >> + ret |= DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_ACCURATE; >> + >> + vsw = mode->crtc_vsync_end - mode->crtc_vsync_start; >> + vbp = mode->crtc_vtotal - mode->crtc_vsync_end; >> + >> + /* >> + * the line counter is 1 at the start of the VSYNC pulse and VTOTAL >> at >> + * the end of VFP. Translate the porch values relative to the line >> + * counter positions. >> + */ >> + >> + vactive_start = vsw + vbp + 1; >> + >> + vactive_end = vactive_start + mode->crtc_vdisplay; >> + >> + /* last scan line before VSYNC */ >> + vfp_end = mode->crtc_vtotal; >> + >> + if (stime) >> + *stime = ktime_get(); >> + >> + line = mdp5_encoder_get_linecount(encoder); >> + >> + if (line < vactive_start) { >> + line -= vactive_start; >> + ret |= DRM_SCANOUTPOS_IN_VBLANK; >> + } else if (line > vactive_end) { >> + line = line - vfp_end - vactive_start; >> + ret |= DRM_SCANOUTPOS_IN_VBLANK; >> + } else { >> + line -= vactive_start; >> + } >> + >> + *vpos = line; >> + *hpos = 0; >> + >> + if (etime) >> + *etime = ktime_get(); >> + >> + return ret; >> +} >> + >> +static int mdp5_get_vblank_timestamp(struct drm_device *dev, unsigned int >> pipe, >> + int *max_error, >> + struct timeval *vblank_time, >> + unsigned flags) >> +{ >> + struct msm_drm_private *priv = dev->dev_private; >> + struct drm_crtc *crtc; >> + >> + if (pipe < 0 || pipe >= priv->num_crtcs) { >> + DRM_ERROR("Invalid crtc %d\n", pipe); >> + return -EINVAL; >> + } >> + >> + crtc = priv->crtcs[pipe]; >> + if (!crtc) { >> + DRM_ERROR("Invalid crtc %d\n", pipe); >> + return -EINVAL; >> + } >> + >> + return drm_calc_vbltimestamp_from_scanoutpos(dev, pipe, max_error, >> + vblank_time, flags, >> + &crtc->mode); >> +} >> + >> +static u32 mdp5_get_vblank_counter(struct drm_device *dev, unsigned int >> pipe) >> +{ >> + struct msm_drm_private *priv = dev->dev_private; >> + struct drm_crtc *crtc; >> + struct drm_encoder *encoder; >> + >> + if (pipe < 0 || pipe >= priv->num_crtcs) >> + return 0; >> + >> + crtc = priv->crtcs[pipe]; >> + if (!crtc) >> + return 0; >> + >> + encoder = get_encoder_from_crtc(crtc); >> + if (!encoder) >> + return 0; >> + >> + return mdp5_encoder_get_framecount(encoder); >> +} >> + >> struct msm_kms *mdp5_kms_init(struct drm_device *dev) >> { >> struct platform_device *pdev = dev->platformdev; >> @@ -590,6 +711,8 @@ struct msm_kms *mdp5_kms_init(struct drm_device *dev) >> !config->hw->intf.base[i]) >> continue; >> mdp5_write(mdp5_kms, REG_MDP5_INTF_TIMING_ENGINE_EN(i), 0); >> + >> + mdp5_write(mdp5_kms, REG_MDP5_INTF_FRAME_LINE_COUNT_EN(i), >> 0x3); >> } >> mdp5_disable(mdp5_kms); >> mdelay(16); >> @@ -635,6 +758,12 @@ struct msm_kms *mdp5_kms_init(struct drm_device *dev) >> dev->mode_config.max_width = config->hw->lm.max_width; >> dev->mode_config.max_height = config->hw->lm.max_height; >> >> + dev->driver->get_vblank_timestamp = mdp5_get_vblank_timestamp; >> + dev->driver->get_scanout_position = mdp5_get_scanoutpos; >> + dev->driver->get_vblank_counter = mdp5_get_vblank_counter; >> + dev->max_vblank_count = 0xffffffff; >> + dev->vblank_disable_immediate = true; >> + >> return kms; >> >> fail: >> diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h >> b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h >> index 84f65d4..00730ba 100644 >> --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h >> +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h >> @@ -222,6 +222,8 @@ struct drm_encoder *mdp5_encoder_init(struct drm_device >> *dev, >> struct mdp5_interface *intf, struct mdp5_ctl *ctl); >> int mdp5_encoder_set_split_display(struct drm_encoder *encoder, >> struct drm_encoder *slave_encoder); >> +int mdp5_encoder_get_linecount(struct drm_encoder *encoder); >> +u32 mdp5_encoder_get_framecount(struct drm_encoder *encoder); >> >> #ifdef CONFIG_DRM_MSM_DSI >> struct drm_encoder *mdp5_cmd_encoder_init(struct drm_device *dev, >> -- >> The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, >> hosted by The Linux Foundation >> > -- > To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in > the body of a message to majordomo at vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html > -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation