Dne četrtek, 22. februar 2024 ob 19:14:21 CET je Maxime Ripard napisal(a): > atomic_check and mode_valid do not check for the same things which can > lead to surprising result if the userspace commits a mode that didn't go > through mode_valid. Let's merge the two implementations into a function > called by both. > > Acked-by: Sui Jingfeng <sui.jingfeng@xxxxxxxxx> > Signed-off-by: Maxime Ripard <mripard@xxxxxxxxxx> Reviewed-by: Jernej Skrabec <jernej.skrabec@xxxxxxxxx> Best regards, Jernej > --- > drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c | 74 +++++++++++++++++++++------------- > 1 file changed, 47 insertions(+), 27 deletions(-) > > diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c > index c276d984da6b..b7cf369b1906 100644 > --- a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c > +++ b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c > @@ -62,18 +62,6 @@ static int sun4i_hdmi_setup_avi_infoframes(struct sun4i_hdmi *hdmi, > return 0; > } > > -static int sun4i_hdmi_atomic_check(struct drm_encoder *encoder, > - struct drm_crtc_state *crtc_state, > - struct drm_connector_state *conn_state) > -{ > - struct drm_display_mode *mode = &crtc_state->mode; > - > - if (mode->flags & DRM_MODE_FLAG_DBLCLK) > - return -EINVAL; > - > - return 0; > -} > - > static void sun4i_hdmi_disable(struct drm_encoder *encoder, > struct drm_atomic_state *state) > { > @@ -166,31 +154,61 @@ static void sun4i_hdmi_enable(struct drm_encoder *encoder, > writel(val, hdmi->base + SUN4I_HDMI_VID_CTRL_REG); > } > > -static enum drm_mode_status sun4i_hdmi_mode_valid(struct drm_encoder *encoder, > - const struct drm_display_mode *mode) > +static const struct drm_encoder_helper_funcs sun4i_hdmi_helper_funcs = { > + .atomic_disable = sun4i_hdmi_disable, > + .atomic_enable = sun4i_hdmi_enable, > +}; > + > +static enum drm_mode_status > +sun4i_hdmi_connector_clock_valid(const struct drm_connector *connector, > + const struct drm_display_mode *mode, > + unsigned long long clock) > { > - struct sun4i_hdmi *hdmi = drm_encoder_to_sun4i_hdmi(encoder); > - unsigned long rate = mode->clock * 1000; > - unsigned long diff = rate / 200; /* +-0.5% allowed by HDMI spec */ > + const struct sun4i_hdmi *hdmi = drm_connector_to_sun4i_hdmi(connector); > + unsigned long diff = clock / 200; /* +-0.5% allowed by HDMI spec */ > long rounded_rate; > > + if (mode->flags & DRM_MODE_FLAG_DBLCLK) > + return MODE_BAD; > + > /* 165 MHz is the typical max pixelclock frequency for HDMI <= 1.2 */ > - if (rate > 165000000) > + if (clock > 165000000) > return MODE_CLOCK_HIGH; > - rounded_rate = clk_round_rate(hdmi->tmds_clk, rate); > + > + rounded_rate = clk_round_rate(hdmi->tmds_clk, clock); > if (rounded_rate > 0 && > - max_t(unsigned long, rounded_rate, rate) - > - min_t(unsigned long, rounded_rate, rate) < diff) > + max_t(unsigned long, rounded_rate, clock) - > + min_t(unsigned long, rounded_rate, clock) < diff) > return MODE_OK; > + > return MODE_NOCLOCK; > } > > -static const struct drm_encoder_helper_funcs sun4i_hdmi_helper_funcs = { > - .atomic_check = sun4i_hdmi_atomic_check, > - .atomic_disable = sun4i_hdmi_disable, > - .atomic_enable = sun4i_hdmi_enable, > - .mode_valid = sun4i_hdmi_mode_valid, > -}; > +static int sun4i_hdmi_connector_atomic_check(struct drm_connector *connector, > + struct drm_atomic_state *state) > +{ > + struct drm_connector_state *conn_state = > + drm_atomic_get_new_connector_state(state, connector); > + struct drm_crtc *crtc = conn_state->crtc; > + struct drm_crtc_state *crtc_state = crtc->state; > + struct drm_display_mode *mode = &crtc_state->adjusted_mode; > + enum drm_mode_status status; > + > + status = sun4i_hdmi_connector_clock_valid(connector, mode, > + mode->clock * 1000); > + if (status != MODE_OK) > + return -EINVAL; > + > + return 0; > +} > + > +static enum drm_mode_status > +sun4i_hdmi_connector_mode_valid(struct drm_connector *connector, > + struct drm_display_mode *mode) > +{ > + return sun4i_hdmi_connector_clock_valid(connector, mode, > + mode->clock * 1000); > +} > > static int sun4i_hdmi_get_modes(struct drm_connector *connector) > { > @@ -236,6 +254,8 @@ static struct i2c_adapter *sun4i_hdmi_get_ddc(struct device *dev) > } > > static const struct drm_connector_helper_funcs sun4i_hdmi_connector_helper_funcs = { > + .atomic_check = sun4i_hdmi_connector_atomic_check, > + .mode_valid = sun4i_hdmi_connector_mode_valid, > .get_modes = sun4i_hdmi_get_modes, > }; > > >