Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/hyperv: Replace simple-KMS with regular atomic helpers

Drop simple-KMS in favor of regular atomic helpers to make the code more
modular. The simple-KMS helper mix up plane and CRTC state, so it is
obsolete and should go away [1]. Since it just split the simple-pipe
functions into per-plane and per-CRTC, no functional changes is
expected.

[1] https://lore.kernel.org/lkml/dae5089d-e214-4518-b927-5c4149babad8@suse.de/

Acked-by: Javier Martinez Canillas <javierm@redhat.com>
Signed-off-by: Ryosuke Yasuoka <ryasuoka@redhat.com>
Link: https://lore.kernel.org/r/20250427101825.812766-1-ryasuoka@redhat.com
Signed-off-by: Jocelyn Falempe <jfalempe@redhat.com>

authored by

Ryosuke Yasuoka and committed by
Jocelyn Falempe
4963049e 9934ab18

+116 -62
+3 -1
drivers/gpu/drm/hyperv/hyperv_drm.h
··· 11 11 struct hyperv_drm_device { 12 12 /* drm */ 13 13 struct drm_device dev; 14 - struct drm_simple_display_pipe pipe; 14 + struct drm_plane plane; 15 + struct drm_crtc crtc; 16 + struct drm_encoder encoder; 15 17 struct drm_connector connector; 16 18 17 19 /* mode */
+113 -61
drivers/gpu/drm/hyperv/hyperv_drm_modeset.c
··· 5 5 6 6 #include <linux/hyperv.h> 7 7 8 + #include <drm/drm_atomic.h> 9 + #include <drm/drm_crtc_helper.h> 8 10 #include <drm/drm_damage_helper.h> 9 11 #include <drm/drm_drv.h> 10 12 #include <drm/drm_edid.h> ··· 17 15 #include <drm/drm_gem_framebuffer_helper.h> 18 16 #include <drm/drm_gem_shmem_helper.h> 19 17 #include <drm/drm_probe_helper.h> 20 - #include <drm/drm_simple_kms_helper.h> 18 + #include <drm/drm_plane.h> 21 19 22 20 #include "hyperv_drm.h" 23 21 ··· 38 36 drm_dev_exit(idx); 39 37 40 38 return 0; 41 - } 42 - 43 - static int hyperv_blit_to_vram_fullscreen(struct drm_framebuffer *fb, 44 - const struct iosys_map *map) 45 - { 46 - struct drm_rect fullscreen = { 47 - .x1 = 0, 48 - .x2 = fb->width, 49 - .y1 = 0, 50 - .y2 = fb->height, 51 - }; 52 - return hyperv_blit_to_vram_rect(fb, map, &fullscreen); 53 39 } 54 40 55 41 static int hyperv_connector_get_modes(struct drm_connector *connector) ··· 88 98 return 0; 89 99 } 90 100 91 - static void hyperv_pipe_enable(struct drm_simple_display_pipe *pipe, 92 - struct drm_crtc_state *crtc_state, 93 - struct drm_plane_state *plane_state) 101 + static const uint32_t hyperv_formats[] = { 102 + DRM_FORMAT_XRGB8888, 103 + }; 104 + 105 + static const uint64_t hyperv_modifiers[] = { 106 + DRM_FORMAT_MOD_LINEAR, 107 + DRM_FORMAT_MOD_INVALID 108 + }; 109 + 110 + static void hyperv_crtc_helper_atomic_enable(struct drm_crtc *crtc, 111 + struct drm_atomic_state *state) 94 112 { 95 - struct hyperv_drm_device *hv = to_hv(pipe->crtc.dev); 96 - struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state); 113 + struct hyperv_drm_device *hv = to_hv(crtc->dev); 114 + struct drm_plane *plane = &hv->plane; 115 + struct drm_plane_state *plane_state = plane->state; 116 + struct drm_crtc_state *crtc_state = crtc->state; 97 117 98 118 hyperv_hide_hw_ptr(hv->hdev); 99 119 hyperv_update_situation(hv->hdev, 1, hv->screen_depth, 100 120 crtc_state->mode.hdisplay, 101 121 crtc_state->mode.vdisplay, 102 122 plane_state->fb->pitches[0]); 103 - hyperv_blit_to_vram_fullscreen(plane_state->fb, &shadow_plane_state->data[0]); 104 123 } 105 124 106 - static int hyperv_pipe_check(struct drm_simple_display_pipe *pipe, 107 - struct drm_plane_state *plane_state, 108 - struct drm_crtc_state *crtc_state) 109 - { 110 - struct hyperv_drm_device *hv = to_hv(pipe->crtc.dev); 111 - struct drm_framebuffer *fb = plane_state->fb; 125 + static const struct drm_crtc_helper_funcs hyperv_crtc_helper_funcs = { 126 + .atomic_check = drm_crtc_helper_atomic_check, 127 + .atomic_enable = hyperv_crtc_helper_atomic_enable, 128 + }; 112 129 113 - if (fb->format->format != DRM_FORMAT_XRGB8888) 114 - return -EINVAL; 130 + static const struct drm_crtc_funcs hyperv_crtc_funcs = { 131 + .reset = drm_atomic_helper_crtc_reset, 132 + .destroy = drm_crtc_cleanup, 133 + .set_config = drm_atomic_helper_set_config, 134 + .page_flip = drm_atomic_helper_page_flip, 135 + .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state, 136 + .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, 137 + }; 138 + 139 + static int hyperv_plane_atomic_check(struct drm_plane *plane, 140 + struct drm_atomic_state *state) 141 + { 142 + struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane); 143 + struct hyperv_drm_device *hv = to_hv(plane->dev); 144 + struct drm_framebuffer *fb = plane_state->fb; 145 + struct drm_crtc *crtc = plane_state->crtc; 146 + struct drm_crtc_state *crtc_state = NULL; 147 + int ret; 148 + 149 + if (crtc) 150 + crtc_state = drm_atomic_get_new_crtc_state(state, crtc); 151 + 152 + ret = drm_atomic_helper_check_plane_state(plane_state, crtc_state, 153 + DRM_PLANE_NO_SCALING, 154 + DRM_PLANE_NO_SCALING, 155 + false, false); 156 + if (ret) 157 + return ret; 158 + 159 + if (!plane_state->visible) 160 + return 0; 115 161 116 162 if (fb->pitches[0] * fb->height > hv->fb_size) { 117 163 drm_err(&hv->dev, "fb size requested by %s for %dX%d (pitch %d) greater than %ld\n", ··· 158 132 return 0; 159 133 } 160 134 161 - static void hyperv_pipe_update(struct drm_simple_display_pipe *pipe, 162 - struct drm_plane_state *old_state) 135 + static void hyperv_plane_atomic_update(struct drm_plane *plane, 136 + struct drm_atomic_state *state) 163 137 { 164 - struct hyperv_drm_device *hv = to_hv(pipe->crtc.dev); 165 - struct drm_plane_state *state = pipe->plane.state; 166 - struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(state); 167 - struct drm_rect rect; 138 + struct hyperv_drm_device *hv = to_hv(plane->dev); 139 + struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(state, plane); 140 + struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state, plane); 141 + struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(new_state); 142 + struct drm_rect damage; 143 + struct drm_rect dst_clip; 144 + struct drm_atomic_helper_damage_iter iter; 168 145 169 - if (drm_atomic_helper_damage_merged(old_state, state, &rect)) { 170 - hyperv_blit_to_vram_rect(state->fb, &shadow_plane_state->data[0], &rect); 171 - hyperv_update_dirt(hv->hdev, &rect); 146 + drm_atomic_helper_damage_iter_init(&iter, old_state, new_state); 147 + drm_atomic_for_each_plane_damage(&iter, &damage) { 148 + dst_clip = new_state->dst; 149 + 150 + if (!drm_rect_intersect(&dst_clip, &damage)) 151 + continue; 152 + 153 + hyperv_blit_to_vram_rect(new_state->fb, &shadow_plane_state->data[0], &damage); 154 + hyperv_update_dirt(hv->hdev, &damage); 172 155 } 173 156 } 174 157 175 - static const struct drm_simple_display_pipe_funcs hyperv_pipe_funcs = { 176 - .enable = hyperv_pipe_enable, 177 - .check = hyperv_pipe_check, 178 - .update = hyperv_pipe_update, 179 - DRM_GEM_SIMPLE_DISPLAY_PIPE_SHADOW_PLANE_FUNCS, 158 + static const struct drm_plane_helper_funcs hyperv_plane_helper_funcs = { 159 + DRM_GEM_SHADOW_PLANE_HELPER_FUNCS, 160 + .atomic_check = hyperv_plane_atomic_check, 161 + .atomic_update = hyperv_plane_atomic_update, 180 162 }; 181 163 182 - static const uint32_t hyperv_formats[] = { 183 - DRM_FORMAT_XRGB8888, 164 + static const struct drm_plane_funcs hyperv_plane_funcs = { 165 + .update_plane = drm_atomic_helper_update_plane, 166 + .disable_plane = drm_atomic_helper_disable_plane, 167 + .destroy = drm_plane_cleanup, 168 + DRM_GEM_SHADOW_PLANE_FUNCS, 184 169 }; 185 170 186 - static const uint64_t hyperv_modifiers[] = { 187 - DRM_FORMAT_MOD_LINEAR, 188 - DRM_FORMAT_MOD_INVALID 171 + static const struct drm_encoder_funcs hyperv_drm_simple_encoder_funcs_cleanup = { 172 + .destroy = drm_encoder_cleanup, 189 173 }; 190 174 191 175 static inline int hyperv_pipe_init(struct hyperv_drm_device *hv) 192 176 { 177 + struct drm_device *dev = &hv->dev; 178 + struct drm_encoder *encoder = &hv->encoder; 179 + struct drm_plane *plane = &hv->plane; 180 + struct drm_crtc *crtc = &hv->crtc; 181 + struct drm_connector *connector = &hv->connector; 193 182 int ret; 194 183 195 - ret = drm_simple_display_pipe_init(&hv->dev, 196 - &hv->pipe, 197 - &hyperv_pipe_funcs, 198 - hyperv_formats, 199 - ARRAY_SIZE(hyperv_formats), 200 - hyperv_modifiers, 201 - &hv->connector); 184 + ret = drm_universal_plane_init(dev, plane, 0, 185 + &hyperv_plane_funcs, 186 + hyperv_formats, ARRAY_SIZE(hyperv_formats), 187 + hyperv_modifiers, 188 + DRM_PLANE_TYPE_PRIMARY, NULL); 189 + if (ret) 190 + return ret; 191 + drm_plane_helper_add(plane, &hyperv_plane_helper_funcs); 192 + drm_plane_enable_fb_damage_clips(plane); 193 + 194 + ret = drm_crtc_init_with_planes(dev, crtc, plane, NULL, 195 + &hyperv_crtc_funcs, NULL); 196 + if (ret) 197 + return ret; 198 + drm_crtc_helper_add(crtc, &hyperv_crtc_helper_funcs); 199 + 200 + encoder->possible_crtcs = drm_crtc_mask(crtc); 201 + ret = drm_encoder_init(dev, encoder, 202 + &hyperv_drm_simple_encoder_funcs_cleanup, 203 + DRM_MODE_ENCODER_NONE, NULL); 202 204 if (ret) 203 205 return ret; 204 206 205 - drm_plane_enable_fb_damage_clips(&hv->pipe.plane); 207 + ret = hyperv_conn_init(hv); 208 + if (ret) { 209 + drm_err(dev, "Failed to initialized connector.\n"); 210 + return ret; 211 + } 206 212 207 - return 0; 213 + return drm_connector_attach_encoder(connector, encoder); 208 214 } 209 215 210 216 static enum drm_mode_status ··· 278 220 dev->mode_config.prefer_shadow = 0; 279 221 280 222 dev->mode_config.funcs = &hyperv_mode_config_funcs; 281 - 282 - ret = hyperv_conn_init(hv); 283 - if (ret) { 284 - drm_err(dev, "Failed to initialized connector.\n"); 285 - return ret; 286 - } 287 223 288 224 ret = hyperv_pipe_init(hv); 289 225 if (ret) {