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

drm/udl: Convert to struct drm_simple_display_pipe

Udl has a single display pipeline with a primary plane; perfect for
simple-pipe helpers. Convert it over. The old encoder and CRTC code
becomes unused and obsolete.

Exported formats for the primary plane are RGB565 and XRGB8888, with
the latter being emulated. The 16-bit format is the default and what
is used when communicating with the device.

This patch enables atomic modesetting for udl devices.

v3:
* remove unused field crtc from struct udl_device
* set crtc_state->no_vblank at beginning of enable()
v2:
* move suspend/resume changes into separate patch
* remove non-atomic code

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Reviewed-by: Emil Velikov <emil.l.velikov@gmail.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20191210084905.5570-3-tzimmermann@suse.de

+92 -183
+1 -1
drivers/gpu/drm/udl/Makefile
··· 1 1 # SPDX-License-Identifier: GPL-2.0-only 2 - udl-y := udl_drv.o udl_modeset.o udl_connector.o udl_encoder.o udl_main.o udl_fb.o udl_transfer.o udl_gem.o 2 + udl-y := udl_drv.o udl_modeset.o udl_connector.o udl_main.o udl_fb.o udl_transfer.o udl_gem.o 3 3 4 4 obj-$(CONFIG_DRM_UDL) := udl.o
+4 -8
drivers/gpu/drm/udl/udl_connector.c
··· 7 7 * Copyright (C) 2009 Bernie Thompson <bernie@plugable.com> 8 8 */ 9 9 10 + #include <drm/drm_atomic_state_helper.h> 10 11 #include <drm/drm_crtc_helper.h> 11 12 #include <drm/drm_probe_helper.h> 12 13 ··· 91 90 return connector_status_connected; 92 91 } 93 92 94 - static int udl_connector_set_property(struct drm_connector *connector, 95 - struct drm_property *property, 96 - uint64_t val) 97 - { 98 - return 0; 99 - } 100 - 101 93 static void udl_connector_destroy(struct drm_connector *connector) 102 94 { 103 95 struct udl_drm_connector *udl_connector = ··· 110 116 111 117 static const struct drm_connector_funcs udl_connector_funcs = { 112 118 .dpms = drm_helper_connector_dpms, 119 + .reset = drm_atomic_helper_connector_reset, 113 120 .detect = udl_detect, 114 121 .fill_modes = drm_helper_probe_single_connector_modes, 115 122 .destroy = udl_connector_destroy, 116 - .set_property = udl_connector_set_property, 123 + .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, 124 + .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, 117 125 }; 118 126 119 127 struct drm_connector *udl_connector_init(struct drm_device *dev)
+1 -1
drivers/gpu/drm/udl/udl_drv.c
··· 45 45 } 46 46 47 47 static struct drm_driver driver = { 48 - .driver_features = DRIVER_MODESET | DRIVER_GEM, 48 + .driver_features = DRIVER_ATOMIC | DRIVER_GEM | DRIVER_MODESET, 49 49 .release = udl_driver_release, 50 50 51 51 /* gem hooks */
+3 -4
drivers/gpu/drm/udl/udl_drv.h
··· 17 17 #include <drm/drm_device.h> 18 18 #include <drm/drm_framebuffer.h> 19 19 #include <drm/drm_gem.h> 20 + #include <drm/drm_simple_kms_helper.h> 20 21 21 - struct drm_encoder; 22 22 struct drm_mode_create_dumb; 23 23 24 24 #define DRIVER_NAME "udl" ··· 51 51 struct drm_device drm; 52 52 struct device *dev; 53 53 struct usb_device *udev; 54 - struct drm_crtc *crtc; 54 + 55 + struct drm_simple_display_pipe display_pipe; 55 56 56 57 /* active framebuffer on the 16-bit channel */ 57 58 const struct drm_framebuffer *active_fb_16; ··· 75 74 void udl_modeset_restore(struct drm_device *dev); 76 75 void udl_modeset_cleanup(struct drm_device *dev); 77 76 struct drm_connector *udl_connector_init(struct drm_device *dev); 78 - 79 - struct drm_encoder *udl_encoder_init(struct drm_device *dev); 80 77 81 78 struct urb *udl_get_urb(struct drm_device *dev); 82 79
-70
drivers/gpu/drm/udl/udl_encoder.c
··· 1 - // SPDX-License-Identifier: GPL-2.0-only 2 - /* 3 - * Copyright (C) 2012 Red Hat 4 - * based in parts on udlfb.c: 5 - * Copyright (C) 2009 Roberto De Ioris <roberto@unbit.it> 6 - * Copyright (C) 2009 Jaya Kumar <jayakumar.lkml@gmail.com> 7 - * Copyright (C) 2009 Bernie Thompson <bernie@plugable.com> 8 - */ 9 - 10 - #include <drm/drm_encoder.h> 11 - #include <drm/drm_modeset_helper_vtables.h> 12 - 13 - #include "udl_drv.h" 14 - 15 - /* dummy encoder */ 16 - static void udl_enc_destroy(struct drm_encoder *encoder) 17 - { 18 - drm_encoder_cleanup(encoder); 19 - kfree(encoder); 20 - } 21 - 22 - static void udl_encoder_disable(struct drm_encoder *encoder) 23 - { 24 - } 25 - 26 - static void udl_encoder_prepare(struct drm_encoder *encoder) 27 - { 28 - } 29 - 30 - static void udl_encoder_commit(struct drm_encoder *encoder) 31 - { 32 - } 33 - 34 - static void udl_encoder_mode_set(struct drm_encoder *encoder, 35 - struct drm_display_mode *mode, 36 - struct drm_display_mode *adjusted_mode) 37 - { 38 - } 39 - 40 - static void 41 - udl_encoder_dpms(struct drm_encoder *encoder, int mode) 42 - { 43 - } 44 - 45 - static const struct drm_encoder_helper_funcs udl_helper_funcs = { 46 - .dpms = udl_encoder_dpms, 47 - .prepare = udl_encoder_prepare, 48 - .mode_set = udl_encoder_mode_set, 49 - .commit = udl_encoder_commit, 50 - .disable = udl_encoder_disable, 51 - }; 52 - 53 - static const struct drm_encoder_funcs udl_enc_funcs = { 54 - .destroy = udl_enc_destroy, 55 - }; 56 - 57 - struct drm_encoder *udl_encoder_init(struct drm_device *dev) 58 - { 59 - struct drm_encoder *encoder; 60 - 61 - encoder = kzalloc(sizeof(struct drm_encoder), GFP_KERNEL); 62 - if (!encoder) 63 - return NULL; 64 - 65 - drm_encoder_init(dev, encoder, &udl_enc_funcs, DRM_MODE_ENCODER_TMDS, 66 - NULL); 67 - drm_encoder_helper_add(encoder, &udl_helper_funcs); 68 - encoder->possible_crtcs = 1; 69 - return encoder; 70 - }
+83 -99
drivers/gpu/drm/udl/udl_modeset.c
··· 9 9 10 10 */ 11 11 12 + #include <drm/drm_atomic_helper.h> 12 13 #include <drm/drm_crtc_helper.h> 14 + #include <drm/drm_gem_framebuffer_helper.h> 13 15 #include <drm/drm_modeset_helper_vtables.h> 14 16 #include <drm/drm_vblank.h> 15 17 16 18 #include "udl_drv.h" 19 + 20 + #define UDL_COLOR_DEPTH_16BPP 0 17 21 18 22 /* 19 23 * All DisplayLink bulk operations start with 0xAF, followed by specific code ··· 281 277 282 278 } 283 279 284 - #if 0 285 - static int 286 - udl_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb, 287 - int x, int y, enum mode_set_atomic state) 280 + /* 281 + * Simple display pipeline 282 + */ 283 + 284 + static const uint32_t udl_simple_display_pipe_formats[] = { 285 + DRM_FORMAT_RGB565, 286 + DRM_FORMAT_XRGB8888, 287 + }; 288 + 289 + static enum drm_mode_status 290 + udl_simple_display_pipe_mode_valid(struct drm_simple_display_pipe *pipe, 291 + const struct drm_display_mode *mode) 288 292 { 289 - return 0; 293 + return MODE_OK; 290 294 } 291 295 292 - static int 293 - udl_pipe_set_base(struct drm_crtc *crtc, int x, int y, 294 - struct drm_framebuffer *old_fb) 296 + static void 297 + udl_simple_display_pipe_enable(struct drm_simple_display_pipe *pipe, 298 + struct drm_crtc_state *crtc_state, 299 + struct drm_plane_state *plane_state) 295 300 { 296 - return 0; 297 - } 298 - #endif 299 - 300 - static int udl_crtc_mode_set(struct drm_crtc *crtc, 301 - struct drm_display_mode *mode, 302 - struct drm_display_mode *adjusted_mode, 303 - int x, int y, 304 - struct drm_framebuffer *old_fb) 305 - 306 - { 301 + struct drm_crtc *crtc = &pipe->crtc; 307 302 struct drm_device *dev = crtc->dev; 308 - struct drm_framebuffer *fb = crtc->primary->fb; 303 + struct drm_framebuffer *fb = plane_state->fb; 309 304 struct udl_device *udl = dev->dev_private; 305 + struct drm_display_mode *mode = &crtc_state->mode; 310 306 char *buf; 311 307 char *wrptr; 312 - int color_depth = 0; 308 + int color_depth = UDL_COLOR_DEPTH_16BPP; 313 309 314 - udl->crtc = crtc; 310 + crtc_state->no_vblank = true; 315 311 316 312 buf = (char *)udl->mode_buf; 317 313 318 - /* for now we just clip 24 -> 16 - if we fix that fix this */ 319 - /*if (crtc->fb->bits_per_pixel != 16) 320 - color_depth = 1; */ 321 - 322 314 /* This first section has to do with setting the base address on the 323 - * controller * associated with the display. There are 2 base 324 - * pointers, currently, we only * use the 16 bpp segment. 325 - */ 315 + * controller associated with the display. There are 2 base 316 + * pointers, currently, we only use the 16 bpp segment. 317 + */ 326 318 wrptr = udl_vidreg_lock(buf); 327 319 wrptr = udl_set_color_depth(wrptr, color_depth); 328 320 /* set base for 16bpp segment to 0 */ ··· 326 326 /* set base for 8bpp segment to end of fb */ 327 327 wrptr = udl_set_base8bpp(wrptr, 2 * mode->vdisplay * mode->hdisplay); 328 328 329 - wrptr = udl_set_vid_cmds(wrptr, adjusted_mode); 329 + wrptr = udl_set_vid_cmds(wrptr, mode); 330 330 wrptr = udl_set_blank(wrptr, DRM_MODE_DPMS_ON); 331 331 wrptr = udl_vidreg_unlock(wrptr); 332 332 ··· 337 337 spin_unlock(&udl->active_fb_16_lock); 338 338 udl->mode_buf_len = wrptr - buf; 339 339 340 - /* damage all of it */ 341 340 udl_handle_damage(fb, 0, 0, fb->width, fb->height); 341 + 342 + udl_crtc_dpms(&pipe->crtc, DRM_MODE_DPMS_ON); 343 + } 344 + 345 + static void 346 + udl_simple_display_pipe_disable(struct drm_simple_display_pipe *pipe) 347 + { 348 + udl_crtc_dpms(&pipe->crtc, DRM_MODE_DPMS_OFF); 349 + } 350 + 351 + static int 352 + udl_simple_display_pipe_check(struct drm_simple_display_pipe *pipe, 353 + struct drm_plane_state *plane_state, 354 + struct drm_crtc_state *crtc_state) 355 + { 342 356 return 0; 343 357 } 344 358 345 - 346 - static void udl_crtc_disable(struct drm_crtc *crtc) 359 + static void 360 + udl_simple_display_pipe_update(struct drm_simple_display_pipe *pipe, 361 + struct drm_plane_state *old_plane_state) 347 362 { 348 - udl_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); 349 - } 350 - 351 - static void udl_crtc_destroy(struct drm_crtc *crtc) 352 - { 353 - drm_crtc_cleanup(crtc); 354 - kfree(crtc); 355 - } 356 - 357 - static int udl_crtc_page_flip(struct drm_crtc *crtc, 358 - struct drm_framebuffer *fb, 359 - struct drm_pending_vblank_event *event, 360 - uint32_t page_flip_flags, 361 - struct drm_modeset_acquire_ctx *ctx) 362 - { 363 - struct drm_device *dev = crtc->dev; 363 + struct drm_device *dev = pipe->crtc.dev; 364 364 struct udl_device *udl = dev->dev_private; 365 + struct drm_framebuffer *fb = pipe->plane.state->fb; 365 366 366 367 spin_lock(&udl->active_fb_16_lock); 367 368 udl->active_fb_16 = fb; 368 369 spin_unlock(&udl->active_fb_16_lock); 369 370 371 + if (!fb) 372 + return; 373 + 370 374 udl_handle_damage(fb, 0, 0, fb->width, fb->height); 371 - 372 - spin_lock_irq(&dev->event_lock); 373 - if (event) 374 - drm_crtc_send_vblank_event(crtc, event); 375 - spin_unlock_irq(&dev->event_lock); 376 - crtc->primary->fb = fb; 377 - 378 - return 0; 379 375 } 380 376 381 - static void udl_crtc_prepare(struct drm_crtc *crtc) 382 - { 383 - } 384 - 385 - static void udl_crtc_commit(struct drm_crtc *crtc) 386 - { 387 - udl_crtc_dpms(crtc, DRM_MODE_DPMS_ON); 388 - } 389 - 390 - static const struct drm_crtc_helper_funcs udl_helper_funcs = { 391 - .dpms = udl_crtc_dpms, 392 - .mode_set = udl_crtc_mode_set, 393 - .prepare = udl_crtc_prepare, 394 - .commit = udl_crtc_commit, 395 - .disable = udl_crtc_disable, 377 + static const 378 + struct drm_simple_display_pipe_funcs udl_simple_display_pipe_funcs = { 379 + .mode_valid = udl_simple_display_pipe_mode_valid, 380 + .enable = udl_simple_display_pipe_enable, 381 + .disable = udl_simple_display_pipe_disable, 382 + .check = udl_simple_display_pipe_check, 383 + .update = udl_simple_display_pipe_update, 384 + .prepare_fb = drm_gem_fb_simple_display_pipe_prepare_fb, 396 385 }; 397 386 398 - static const struct drm_crtc_funcs udl_crtc_funcs = { 399 - .set_config = drm_crtc_helper_set_config, 400 - .destroy = udl_crtc_destroy, 401 - .page_flip = udl_crtc_page_flip, 402 - }; 403 - 404 - static int udl_crtc_init(struct drm_device *dev) 405 - { 406 - struct drm_crtc *crtc; 407 - 408 - crtc = kzalloc(sizeof(struct drm_crtc) + sizeof(struct drm_connector *), GFP_KERNEL); 409 - if (crtc == NULL) 410 - return -ENOMEM; 411 - 412 - drm_crtc_init(dev, crtc, &udl_crtc_funcs); 413 - drm_crtc_helper_add(crtc, &udl_helper_funcs); 414 - 415 - return 0; 416 - } 387 + /* 388 + * Modesetting 389 + */ 417 390 418 391 static const struct drm_mode_config_funcs udl_mode_funcs = { 419 392 .fb_create = udl_fb_user_fb_create, 393 + .atomic_check = drm_atomic_helper_check, 394 + .atomic_commit = drm_atomic_helper_commit, 420 395 }; 421 396 422 397 int udl_modeset_init(struct drm_device *dev) 423 398 { 399 + size_t format_count = ARRAY_SIZE(udl_simple_display_pipe_formats); 400 + struct udl_device *udl = dev->dev_private; 424 401 struct drm_connector *connector; 425 - struct drm_encoder *encoder; 426 402 int ret; 427 403 428 404 drm_mode_config_init(dev); ··· 420 444 goto err_drm_mode_config_cleanup; 421 445 } 422 446 423 - udl_crtc_init(dev); 447 + format_count = ARRAY_SIZE(udl_simple_display_pipe_formats); 424 448 425 - encoder = udl_encoder_init(dev); 426 - drm_connector_attach_encoder(connector, encoder); 449 + ret = drm_simple_display_pipe_init(dev, &udl->display_pipe, 450 + &udl_simple_display_pipe_funcs, 451 + udl_simple_display_pipe_formats, 452 + format_count, NULL, connector); 453 + if (ret) 454 + goto err_drm_mode_config_cleanup; 455 + 456 + drm_mode_config_reset(dev); 427 457 428 458 return 0; 429 459 ··· 441 459 void udl_modeset_restore(struct drm_device *dev) 442 460 { 443 461 struct udl_device *udl = dev->dev_private; 444 - struct drm_framebuffer *fb; 462 + struct drm_crtc *crtc = &udl->display_pipe.crtc; 463 + struct drm_plane *primary = &udl->display_pipe.plane; 464 + struct drm_framebuffer *fb = primary->fb; 445 465 446 - if (!udl->crtc || !udl->crtc->primary->fb) 466 + if (!fb) 447 467 return; 448 - udl_crtc_commit(udl->crtc); 449 - fb = udl->crtc->primary->fb; 468 + 469 + udl_crtc_dpms(crtc, DRM_MODE_DPMS_ON); 450 470 udl_handle_damage(fb, 0, 0, fb->width, fb->height); 451 471 } 452 472