diff options
| -rw-r--r-- | drivers/gpu/drm/arm/display/komeda/komeda_crtc.c | 52 |
1 files changed, 52 insertions, 0 deletions
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c b/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c index 40ee45d36ad6..902f3992083e 100644 --- a/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c +++ b/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c | |||
| @@ -94,9 +94,61 @@ komeda_crtc_atomic_flush(struct drm_crtc *crtc, | |||
| 94 | komeda_crtc_do_flush(crtc, old); | 94 | komeda_crtc_do_flush(crtc, old); |
| 95 | } | 95 | } |
| 96 | 96 | ||
| 97 | static enum drm_mode_status | ||
| 98 | komeda_crtc_mode_valid(struct drm_crtc *crtc, const struct drm_display_mode *m) | ||
| 99 | { | ||
| 100 | struct komeda_dev *mdev = crtc->dev->dev_private; | ||
| 101 | struct komeda_crtc *kcrtc = to_kcrtc(crtc); | ||
| 102 | struct komeda_pipeline *master = kcrtc->master; | ||
| 103 | long mode_clk, pxlclk; | ||
| 104 | |||
| 105 | if (m->flags & DRM_MODE_FLAG_INTERLACE) | ||
| 106 | return MODE_NO_INTERLACE; | ||
| 107 | |||
| 108 | /* main clock/AXI clk must be faster than pxlclk*/ | ||
| 109 | mode_clk = m->clock * 1000; | ||
| 110 | pxlclk = clk_round_rate(master->pxlclk, mode_clk); | ||
| 111 | if (pxlclk != mode_clk) { | ||
| 112 | DRM_DEBUG_ATOMIC("pxlclk doesn't support %ld Hz\n", mode_clk); | ||
| 113 | |||
| 114 | return MODE_NOCLOCK; | ||
| 115 | } | ||
| 116 | |||
| 117 | if (clk_round_rate(mdev->mclk, mode_clk) < pxlclk) { | ||
| 118 | DRM_DEBUG_ATOMIC("mclk can't satisfy the requirement of %s-clk: %ld.\n", | ||
| 119 | m->name, pxlclk); | ||
| 120 | |||
| 121 | return MODE_CLOCK_HIGH; | ||
| 122 | } | ||
| 123 | |||
| 124 | if (clk_round_rate(master->aclk, mode_clk) < pxlclk) { | ||
| 125 | DRM_DEBUG_ATOMIC("aclk can't satisfy the requirement of %s-clk: %ld.\n", | ||
| 126 | m->name, pxlclk); | ||
| 127 | |||
| 128 | return MODE_CLOCK_HIGH; | ||
| 129 | } | ||
| 130 | |||
| 131 | return MODE_OK; | ||
| 132 | } | ||
| 133 | |||
| 134 | static bool komeda_crtc_mode_fixup(struct drm_crtc *crtc, | ||
| 135 | const struct drm_display_mode *m, | ||
| 136 | struct drm_display_mode *adjusted_mode) | ||
| 137 | { | ||
| 138 | struct komeda_crtc *kcrtc = to_kcrtc(crtc); | ||
| 139 | struct komeda_pipeline *master = kcrtc->master; | ||
| 140 | long mode_clk = m->clock * 1000; | ||
| 141 | |||
| 142 | adjusted_mode->clock = clk_round_rate(master->pxlclk, mode_clk) / 1000; | ||
| 143 | |||
| 144 | return true; | ||
| 145 | } | ||
| 146 | |||
| 97 | struct drm_crtc_helper_funcs komeda_crtc_helper_funcs = { | 147 | struct drm_crtc_helper_funcs komeda_crtc_helper_funcs = { |
| 98 | .atomic_check = komeda_crtc_atomic_check, | 148 | .atomic_check = komeda_crtc_atomic_check, |
| 99 | .atomic_flush = komeda_crtc_atomic_flush, | 149 | .atomic_flush = komeda_crtc_atomic_flush, |
| 150 | .mode_valid = komeda_crtc_mode_valid, | ||
| 151 | .mode_fixup = komeda_crtc_mode_fixup, | ||
| 100 | }; | 152 | }; |
| 101 | 153 | ||
| 102 | static const struct drm_crtc_funcs komeda_crtc_funcs = { | 154 | static const struct drm_crtc_funcs komeda_crtc_funcs = { |
