diff options
author | Robin Murphy <robin.murphy@arm.com> | 2019-05-17 12:37:21 -0400 |
---|---|---|
committer | Liviu Dudau <Liviu.Dudau@arm.com> | 2019-06-04 10:12:44 -0400 |
commit | b96151edced4edb6a18aa89a5fa02c7066efff45 (patch) | |
tree | 6be6878505c7fa48f980c91160df4a05fbdc46f2 /drivers/gpu/drm/arm/hdlcd_crtc.c | |
parent | 6a88e0c14813d00f8520d0e16cd4136c6cf8b4d4 (diff) |
drm/arm/hdlcd: Actually validate CRTC modes
Rather than allowing any old mode through, then subsequently refusing
unmatchable clock rates in atomic_check when it's too late to back out
and pick a different mode, let's do that validation up-front where it
will cause unsupported modes to be correctly pruned in the first place.
This also eliminates an issue whereby a perceived clock rate of 0 would
cause atomic disable to fail and prevent the module from being unloaded.
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
Signed-off-by: Liviu Dudau <liviu.dudau@arm.com>
Diffstat (limited to 'drivers/gpu/drm/arm/hdlcd_crtc.c')
-rw-r--r-- | drivers/gpu/drm/arm/hdlcd_crtc.c | 11 |
1 files changed, 5 insertions, 6 deletions
diff --git a/drivers/gpu/drm/arm/hdlcd_crtc.c b/drivers/gpu/drm/arm/hdlcd_crtc.c index 0b2b62f8fa3c..ecac6fe0b213 100644 --- a/drivers/gpu/drm/arm/hdlcd_crtc.c +++ b/drivers/gpu/drm/arm/hdlcd_crtc.c | |||
@@ -186,20 +186,19 @@ static void hdlcd_crtc_atomic_disable(struct drm_crtc *crtc, | |||
186 | clk_disable_unprepare(hdlcd->clk); | 186 | clk_disable_unprepare(hdlcd->clk); |
187 | } | 187 | } |
188 | 188 | ||
189 | static int hdlcd_crtc_atomic_check(struct drm_crtc *crtc, | 189 | static enum drm_mode_status hdlcd_crtc_mode_valid(struct drm_crtc *crtc, |
190 | struct drm_crtc_state *state) | 190 | const struct drm_display_mode *mode) |
191 | { | 191 | { |
192 | struct hdlcd_drm_private *hdlcd = crtc_to_hdlcd_priv(crtc); | 192 | struct hdlcd_drm_private *hdlcd = crtc_to_hdlcd_priv(crtc); |
193 | struct drm_display_mode *mode = &state->adjusted_mode; | ||
194 | long rate, clk_rate = mode->clock * 1000; | 193 | long rate, clk_rate = mode->clock * 1000; |
195 | 194 | ||
196 | rate = clk_round_rate(hdlcd->clk, clk_rate); | 195 | rate = clk_round_rate(hdlcd->clk, clk_rate); |
197 | if (rate != clk_rate) { | 196 | if (rate != clk_rate) { |
198 | /* clock required by mode not supported by hardware */ | 197 | /* clock required by mode not supported by hardware */ |
199 | return -EINVAL; | 198 | return MODE_NOCLOCK; |
200 | } | 199 | } |
201 | 200 | ||
202 | return 0; | 201 | return MODE_OK; |
203 | } | 202 | } |
204 | 203 | ||
205 | static void hdlcd_crtc_atomic_begin(struct drm_crtc *crtc, | 204 | static void hdlcd_crtc_atomic_begin(struct drm_crtc *crtc, |
@@ -220,7 +219,7 @@ static void hdlcd_crtc_atomic_begin(struct drm_crtc *crtc, | |||
220 | } | 219 | } |
221 | 220 | ||
222 | static const struct drm_crtc_helper_funcs hdlcd_crtc_helper_funcs = { | 221 | static const struct drm_crtc_helper_funcs hdlcd_crtc_helper_funcs = { |
223 | .atomic_check = hdlcd_crtc_atomic_check, | 222 | .mode_valid = hdlcd_crtc_mode_valid, |
224 | .atomic_begin = hdlcd_crtc_atomic_begin, | 223 | .atomic_begin = hdlcd_crtc_atomic_begin, |
225 | .atomic_enable = hdlcd_crtc_atomic_enable, | 224 | .atomic_enable = hdlcd_crtc_atomic_enable, |
226 | .atomic_disable = hdlcd_crtc_atomic_disable, | 225 | .atomic_disable = hdlcd_crtc_atomic_disable, |