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 | |
| 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>
| -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, |
