| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Copyright (C) 2012 Red Hat |
|---|
| 3 | 4 | * |
|---|
| .. | .. |
|---|
| 6 | 7 | * Copyright (C) 2009 Jaya Kumar <jayakumar.lkml@gmail.com> |
|---|
| 7 | 8 | * Copyright (C) 2009 Bernie Thompson <bernie@plugable.com> |
|---|
| 8 | 9 | |
|---|
| 9 | | - * This file is subject to the terms and conditions of the GNU General Public |
|---|
| 10 | | - * License v2. See the file COPYING in the main directory of this archive for |
|---|
| 11 | | - * more details. |
|---|
| 12 | 10 | */ |
|---|
| 13 | 11 | |
|---|
| 14 | | -#include <drm/drmP.h> |
|---|
| 15 | | -#include <drm/drm_crtc.h> |
|---|
| 12 | +#include <linux/dma-buf.h> |
|---|
| 13 | + |
|---|
| 14 | +#include <drm/drm_atomic_helper.h> |
|---|
| 16 | 15 | #include <drm/drm_crtc_helper.h> |
|---|
| 17 | | -#include <drm/drm_plane_helper.h> |
|---|
| 16 | +#include <drm/drm_damage_helper.h> |
|---|
| 17 | +#include <drm/drm_fourcc.h> |
|---|
| 18 | +#include <drm/drm_gem_framebuffer_helper.h> |
|---|
| 19 | +#include <drm/drm_gem_shmem_helper.h> |
|---|
| 20 | +#include <drm/drm_modeset_helper_vtables.h> |
|---|
| 21 | +#include <drm/drm_vblank.h> |
|---|
| 22 | + |
|---|
| 18 | 23 | #include "udl_drv.h" |
|---|
| 24 | + |
|---|
| 25 | +#define UDL_COLOR_DEPTH_16BPP 0 |
|---|
| 19 | 26 | |
|---|
| 20 | 27 | /* |
|---|
| 21 | 28 | * All DisplayLink bulk operations start with 0xAF, followed by specific code |
|---|
| .. | .. |
|---|
| 40 | 47 | return udl_set_register(buf, 0xFF, 0xFF); |
|---|
| 41 | 48 | } |
|---|
| 42 | 49 | |
|---|
| 43 | | -/* |
|---|
| 44 | | - * On/Off for driving the DisplayLink framebuffer to the display |
|---|
| 45 | | - * 0x00 H and V sync on |
|---|
| 46 | | - * 0x01 H and V sync off (screen blank but powered) |
|---|
| 47 | | - * 0x07 DPMS powerdown (requires modeset to come back) |
|---|
| 48 | | - */ |
|---|
| 49 | | -static char *udl_set_blank(char *buf, int dpms_mode) |
|---|
| 50 | +static char *udl_set_blank_mode(char *buf, u8 mode) |
|---|
| 50 | 51 | { |
|---|
| 51 | | - u8 reg; |
|---|
| 52 | | - switch (dpms_mode) { |
|---|
| 53 | | - case DRM_MODE_DPMS_OFF: |
|---|
| 54 | | - reg = 0x07; |
|---|
| 55 | | - break; |
|---|
| 56 | | - case DRM_MODE_DPMS_STANDBY: |
|---|
| 57 | | - reg = 0x05; |
|---|
| 58 | | - break; |
|---|
| 59 | | - case DRM_MODE_DPMS_SUSPEND: |
|---|
| 60 | | - reg = 0x01; |
|---|
| 61 | | - break; |
|---|
| 62 | | - case DRM_MODE_DPMS_ON: |
|---|
| 63 | | - reg = 0x00; |
|---|
| 64 | | - break; |
|---|
| 65 | | - } |
|---|
| 66 | | - |
|---|
| 67 | | - return udl_set_register(buf, 0x1f, reg); |
|---|
| 52 | + return udl_set_register(buf, UDL_REG_BLANK_MODE, mode); |
|---|
| 68 | 53 | } |
|---|
| 69 | 54 | |
|---|
| 70 | 55 | static char *udl_set_color_depth(char *buf, u8 selection) |
|---|
| .. | .. |
|---|
| 230 | 215 | static int udl_crtc_write_mode_to_hw(struct drm_crtc *crtc) |
|---|
| 231 | 216 | { |
|---|
| 232 | 217 | struct drm_device *dev = crtc->dev; |
|---|
| 233 | | - struct udl_device *udl = dev->dev_private; |
|---|
| 218 | + struct udl_device *udl = to_udl(dev); |
|---|
| 234 | 219 | struct urb *urb; |
|---|
| 235 | 220 | char *buf; |
|---|
| 236 | 221 | int retval; |
|---|
| 222 | + |
|---|
| 223 | + if (udl->mode_buf_len == 0) { |
|---|
| 224 | + DRM_ERROR("No mode set\n"); |
|---|
| 225 | + return -EINVAL; |
|---|
| 226 | + } |
|---|
| 237 | 227 | |
|---|
| 238 | 228 | urb = udl_get_urb(dev); |
|---|
| 239 | 229 | if (!urb) |
|---|
| .. | .. |
|---|
| 247 | 237 | return retval; |
|---|
| 248 | 238 | } |
|---|
| 249 | 239 | |
|---|
| 250 | | - |
|---|
| 251 | | -static void udl_crtc_dpms(struct drm_crtc *crtc, int mode) |
|---|
| 240 | +static long udl_log_cpp(unsigned int cpp) |
|---|
| 252 | 241 | { |
|---|
| 253 | | - struct drm_device *dev = crtc->dev; |
|---|
| 254 | | - struct udl_device *udl = dev->dev_private; |
|---|
| 255 | | - int retval; |
|---|
| 242 | + if (WARN_ON(!is_power_of_2(cpp))) |
|---|
| 243 | + return -EINVAL; |
|---|
| 244 | + return __ffs(cpp); |
|---|
| 245 | +} |
|---|
| 256 | 246 | |
|---|
| 257 | | - if (mode == DRM_MODE_DPMS_OFF) { |
|---|
| 258 | | - char *buf; |
|---|
| 259 | | - struct urb *urb; |
|---|
| 260 | | - urb = udl_get_urb(dev); |
|---|
| 261 | | - if (!urb) |
|---|
| 262 | | - return; |
|---|
| 247 | +static int udl_aligned_damage_clip(struct drm_rect *clip, int x, int y, |
|---|
| 248 | + int width, int height) |
|---|
| 249 | +{ |
|---|
| 250 | + int x1, x2; |
|---|
| 263 | 251 | |
|---|
| 264 | | - buf = (char *)urb->transfer_buffer; |
|---|
| 265 | | - buf = udl_vidreg_lock(buf); |
|---|
| 266 | | - buf = udl_set_blank(buf, mode); |
|---|
| 267 | | - buf = udl_vidreg_unlock(buf); |
|---|
| 252 | + if (WARN_ON_ONCE(x < 0) || |
|---|
| 253 | + WARN_ON_ONCE(y < 0) || |
|---|
| 254 | + WARN_ON_ONCE(width < 0) || |
|---|
| 255 | + WARN_ON_ONCE(height < 0)) |
|---|
| 256 | + return -EINVAL; |
|---|
| 268 | 257 | |
|---|
| 269 | | - buf = udl_dummy_render(buf); |
|---|
| 270 | | - retval = udl_submit_urb(dev, urb, buf - (char *) |
|---|
| 271 | | - urb->transfer_buffer); |
|---|
| 272 | | - } else { |
|---|
| 273 | | - if (udl->mode_buf_len == 0) { |
|---|
| 274 | | - DRM_ERROR("Trying to enable DPMS with no mode\n"); |
|---|
| 275 | | - return; |
|---|
| 276 | | - } |
|---|
| 277 | | - udl_crtc_write_mode_to_hw(crtc); |
|---|
| 258 | + x1 = ALIGN_DOWN(x, sizeof(unsigned long)); |
|---|
| 259 | + x2 = ALIGN(width + (x - x1), sizeof(unsigned long)) + x1; |
|---|
| 260 | + |
|---|
| 261 | + clip->x1 = x1; |
|---|
| 262 | + clip->y1 = y; |
|---|
| 263 | + clip->x2 = x2; |
|---|
| 264 | + clip->y2 = y + height; |
|---|
| 265 | + |
|---|
| 266 | + return 0; |
|---|
| 267 | +} |
|---|
| 268 | + |
|---|
| 269 | +static int udl_handle_damage(struct drm_framebuffer *fb, int x, int y, |
|---|
| 270 | + int width, int height) |
|---|
| 271 | +{ |
|---|
| 272 | + struct drm_device *dev = fb->dev; |
|---|
| 273 | + struct dma_buf_attachment *import_attach = fb->obj[0]->import_attach; |
|---|
| 274 | + int i, ret, tmp_ret; |
|---|
| 275 | + char *cmd; |
|---|
| 276 | + struct urb *urb; |
|---|
| 277 | + struct drm_rect clip; |
|---|
| 278 | + int log_bpp; |
|---|
| 279 | + void *vaddr; |
|---|
| 280 | + |
|---|
| 281 | + ret = udl_log_cpp(fb->format->cpp[0]); |
|---|
| 282 | + if (ret < 0) |
|---|
| 283 | + return ret; |
|---|
| 284 | + log_bpp = ret; |
|---|
| 285 | + |
|---|
| 286 | + ret = udl_aligned_damage_clip(&clip, x, y, width, height); |
|---|
| 287 | + if (ret) |
|---|
| 288 | + return ret; |
|---|
| 289 | + else if ((clip.x2 > fb->width) || (clip.y2 > fb->height)) |
|---|
| 290 | + return -EINVAL; |
|---|
| 291 | + |
|---|
| 292 | + if (import_attach) { |
|---|
| 293 | + ret = dma_buf_begin_cpu_access(import_attach->dmabuf, |
|---|
| 294 | + DMA_FROM_DEVICE); |
|---|
| 295 | + if (ret) |
|---|
| 296 | + return ret; |
|---|
| 278 | 297 | } |
|---|
| 279 | 298 | |
|---|
| 299 | + vaddr = drm_gem_shmem_vmap(fb->obj[0]); |
|---|
| 300 | + if (IS_ERR(vaddr)) { |
|---|
| 301 | + DRM_ERROR("failed to vmap fb\n"); |
|---|
| 302 | + goto out_dma_buf_end_cpu_access; |
|---|
| 303 | + } |
|---|
| 304 | + |
|---|
| 305 | + urb = udl_get_urb(dev); |
|---|
| 306 | + if (!urb) { |
|---|
| 307 | + ret = -ENOMEM; |
|---|
| 308 | + goto out_drm_gem_shmem_vunmap; |
|---|
| 309 | + } |
|---|
| 310 | + cmd = urb->transfer_buffer; |
|---|
| 311 | + |
|---|
| 312 | + for (i = clip.y1; i < clip.y2; i++) { |
|---|
| 313 | + const int line_offset = fb->pitches[0] * i; |
|---|
| 314 | + const int byte_offset = line_offset + (clip.x1 << log_bpp); |
|---|
| 315 | + const int dev_byte_offset = (fb->width * i + clip.x1) << log_bpp; |
|---|
| 316 | + const int byte_width = (clip.x2 - clip.x1) << log_bpp; |
|---|
| 317 | + ret = udl_render_hline(dev, log_bpp, &urb, (char *)vaddr, |
|---|
| 318 | + &cmd, byte_offset, dev_byte_offset, |
|---|
| 319 | + byte_width); |
|---|
| 320 | + if (ret) |
|---|
| 321 | + goto out_drm_gem_shmem_vunmap; |
|---|
| 322 | + } |
|---|
| 323 | + |
|---|
| 324 | + if (cmd > (char *)urb->transfer_buffer) { |
|---|
| 325 | + /* Send partial buffer remaining before exiting */ |
|---|
| 326 | + int len; |
|---|
| 327 | + if (cmd < (char *)urb->transfer_buffer + urb->transfer_buffer_length) |
|---|
| 328 | + *cmd++ = 0xAF; |
|---|
| 329 | + len = cmd - (char *)urb->transfer_buffer; |
|---|
| 330 | + ret = udl_submit_urb(dev, urb, len); |
|---|
| 331 | + } else { |
|---|
| 332 | + udl_urb_completion(urb); |
|---|
| 333 | + } |
|---|
| 334 | + |
|---|
| 335 | + ret = 0; |
|---|
| 336 | + |
|---|
| 337 | +out_drm_gem_shmem_vunmap: |
|---|
| 338 | + drm_gem_shmem_vunmap(fb->obj[0], vaddr); |
|---|
| 339 | +out_dma_buf_end_cpu_access: |
|---|
| 340 | + if (import_attach) { |
|---|
| 341 | + tmp_ret = dma_buf_end_cpu_access(import_attach->dmabuf, |
|---|
| 342 | + DMA_FROM_DEVICE); |
|---|
| 343 | + if (tmp_ret && !ret) |
|---|
| 344 | + ret = tmp_ret; /* only update ret if not set yet */ |
|---|
| 345 | + } |
|---|
| 346 | + |
|---|
| 347 | + return ret; |
|---|
| 280 | 348 | } |
|---|
| 281 | 349 | |
|---|
| 282 | | -#if 0 |
|---|
| 283 | | -static int |
|---|
| 284 | | -udl_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb, |
|---|
| 285 | | - int x, int y, enum mode_set_atomic state) |
|---|
| 350 | +/* |
|---|
| 351 | + * Simple display pipeline |
|---|
| 352 | + */ |
|---|
| 353 | + |
|---|
| 354 | +static const uint32_t udl_simple_display_pipe_formats[] = { |
|---|
| 355 | + DRM_FORMAT_RGB565, |
|---|
| 356 | + DRM_FORMAT_XRGB8888, |
|---|
| 357 | +}; |
|---|
| 358 | + |
|---|
| 359 | +static enum drm_mode_status |
|---|
| 360 | +udl_simple_display_pipe_mode_valid(struct drm_simple_display_pipe *pipe, |
|---|
| 361 | + const struct drm_display_mode *mode) |
|---|
| 286 | 362 | { |
|---|
| 287 | | - return 0; |
|---|
| 363 | + return MODE_OK; |
|---|
| 288 | 364 | } |
|---|
| 289 | 365 | |
|---|
| 290 | | -static int |
|---|
| 291 | | -udl_pipe_set_base(struct drm_crtc *crtc, int x, int y, |
|---|
| 292 | | - struct drm_framebuffer *old_fb) |
|---|
| 366 | +static void |
|---|
| 367 | +udl_simple_display_pipe_enable(struct drm_simple_display_pipe *pipe, |
|---|
| 368 | + struct drm_crtc_state *crtc_state, |
|---|
| 369 | + struct drm_plane_state *plane_state) |
|---|
| 293 | 370 | { |
|---|
| 294 | | - return 0; |
|---|
| 295 | | -} |
|---|
| 296 | | -#endif |
|---|
| 297 | | - |
|---|
| 298 | | -static int udl_crtc_mode_set(struct drm_crtc *crtc, |
|---|
| 299 | | - struct drm_display_mode *mode, |
|---|
| 300 | | - struct drm_display_mode *adjusted_mode, |
|---|
| 301 | | - int x, int y, |
|---|
| 302 | | - struct drm_framebuffer *old_fb) |
|---|
| 303 | | - |
|---|
| 304 | | -{ |
|---|
| 371 | + struct drm_crtc *crtc = &pipe->crtc; |
|---|
| 305 | 372 | struct drm_device *dev = crtc->dev; |
|---|
| 306 | | - struct udl_framebuffer *ufb = to_udl_fb(crtc->primary->fb); |
|---|
| 307 | | - struct udl_device *udl = dev->dev_private; |
|---|
| 373 | + struct drm_framebuffer *fb = plane_state->fb; |
|---|
| 374 | + struct udl_device *udl = to_udl(dev); |
|---|
| 375 | + struct drm_display_mode *mode = &crtc_state->mode; |
|---|
| 308 | 376 | char *buf; |
|---|
| 309 | 377 | char *wrptr; |
|---|
| 310 | | - int color_depth = 0; |
|---|
| 311 | | - |
|---|
| 312 | | - udl->crtc = crtc; |
|---|
| 378 | + int color_depth = UDL_COLOR_DEPTH_16BPP; |
|---|
| 313 | 379 | |
|---|
| 314 | 380 | buf = (char *)udl->mode_buf; |
|---|
| 315 | 381 | |
|---|
| 316 | | - /* for now we just clip 24 -> 16 - if we fix that fix this */ |
|---|
| 317 | | - /*if (crtc->fb->bits_per_pixel != 16) |
|---|
| 318 | | - color_depth = 1; */ |
|---|
| 319 | | - |
|---|
| 320 | 382 | /* This first section has to do with setting the base address on the |
|---|
| 321 | | - * controller * associated with the display. There are 2 base |
|---|
| 322 | | - * pointers, currently, we only * use the 16 bpp segment. |
|---|
| 323 | | - */ |
|---|
| 383 | + * controller associated with the display. There are 2 base |
|---|
| 384 | + * pointers, currently, we only use the 16 bpp segment. |
|---|
| 385 | + */ |
|---|
| 324 | 386 | wrptr = udl_vidreg_lock(buf); |
|---|
| 325 | 387 | wrptr = udl_set_color_depth(wrptr, color_depth); |
|---|
| 326 | 388 | /* set base for 16bpp segment to 0 */ |
|---|
| .. | .. |
|---|
| 328 | 390 | /* set base for 8bpp segment to end of fb */ |
|---|
| 329 | 391 | wrptr = udl_set_base8bpp(wrptr, 2 * mode->vdisplay * mode->hdisplay); |
|---|
| 330 | 392 | |
|---|
| 331 | | - wrptr = udl_set_vid_cmds(wrptr, adjusted_mode); |
|---|
| 332 | | - wrptr = udl_set_blank(wrptr, DRM_MODE_DPMS_ON); |
|---|
| 393 | + wrptr = udl_set_vid_cmds(wrptr, mode); |
|---|
| 394 | + wrptr = udl_set_blank_mode(wrptr, UDL_BLANK_MODE_ON); |
|---|
| 333 | 395 | wrptr = udl_vidreg_unlock(wrptr); |
|---|
| 334 | 396 | |
|---|
| 335 | 397 | wrptr = udl_dummy_render(wrptr); |
|---|
| 336 | 398 | |
|---|
| 337 | | - if (old_fb) { |
|---|
| 338 | | - struct udl_framebuffer *uold_fb = to_udl_fb(old_fb); |
|---|
| 339 | | - uold_fb->active_16 = false; |
|---|
| 340 | | - } |
|---|
| 341 | | - ufb->active_16 = true; |
|---|
| 342 | 399 | udl->mode_buf_len = wrptr - buf; |
|---|
| 343 | 400 | |
|---|
| 344 | | - /* damage all of it */ |
|---|
| 345 | | - udl_handle_damage(ufb, 0, 0, ufb->base.width, ufb->base.height); |
|---|
| 346 | | - return 0; |
|---|
| 401 | + udl_handle_damage(fb, 0, 0, fb->width, fb->height); |
|---|
| 402 | + |
|---|
| 403 | + /* enable display */ |
|---|
| 404 | + udl_crtc_write_mode_to_hw(crtc); |
|---|
| 347 | 405 | } |
|---|
| 348 | 406 | |
|---|
| 349 | | - |
|---|
| 350 | | -static void udl_crtc_disable(struct drm_crtc *crtc) |
|---|
| 407 | +static void |
|---|
| 408 | +udl_simple_display_pipe_disable(struct drm_simple_display_pipe *pipe) |
|---|
| 351 | 409 | { |
|---|
| 352 | | - udl_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); |
|---|
| 353 | | -} |
|---|
| 354 | | - |
|---|
| 355 | | -static void udl_crtc_destroy(struct drm_crtc *crtc) |
|---|
| 356 | | -{ |
|---|
| 357 | | - drm_crtc_cleanup(crtc); |
|---|
| 358 | | - kfree(crtc); |
|---|
| 359 | | -} |
|---|
| 360 | | - |
|---|
| 361 | | -static int udl_crtc_page_flip(struct drm_crtc *crtc, |
|---|
| 362 | | - struct drm_framebuffer *fb, |
|---|
| 363 | | - struct drm_pending_vblank_event *event, |
|---|
| 364 | | - uint32_t page_flip_flags, |
|---|
| 365 | | - struct drm_modeset_acquire_ctx *ctx) |
|---|
| 366 | | -{ |
|---|
| 367 | | - struct udl_framebuffer *ufb = to_udl_fb(fb); |
|---|
| 410 | + struct drm_crtc *crtc = &pipe->crtc; |
|---|
| 368 | 411 | struct drm_device *dev = crtc->dev; |
|---|
| 412 | + struct urb *urb; |
|---|
| 413 | + char *buf; |
|---|
| 369 | 414 | |
|---|
| 370 | | - struct drm_framebuffer *old_fb = crtc->primary->fb; |
|---|
| 371 | | - if (old_fb) { |
|---|
| 372 | | - struct udl_framebuffer *uold_fb = to_udl_fb(old_fb); |
|---|
| 373 | | - uold_fb->active_16 = false; |
|---|
| 374 | | - } |
|---|
| 375 | | - ufb->active_16 = true; |
|---|
| 415 | + urb = udl_get_urb(dev); |
|---|
| 416 | + if (!urb) |
|---|
| 417 | + return; |
|---|
| 376 | 418 | |
|---|
| 377 | | - udl_handle_damage(ufb, 0, 0, fb->width, fb->height); |
|---|
| 419 | + buf = (char *)urb->transfer_buffer; |
|---|
| 420 | + buf = udl_vidreg_lock(buf); |
|---|
| 421 | + buf = udl_set_blank_mode(buf, UDL_BLANK_MODE_POWERDOWN); |
|---|
| 422 | + buf = udl_vidreg_unlock(buf); |
|---|
| 423 | + buf = udl_dummy_render(buf); |
|---|
| 378 | 424 | |
|---|
| 379 | | - spin_lock_irq(&dev->event_lock); |
|---|
| 380 | | - if (event) |
|---|
| 381 | | - drm_crtc_send_vblank_event(crtc, event); |
|---|
| 382 | | - spin_unlock_irq(&dev->event_lock); |
|---|
| 383 | | - crtc->primary->fb = fb; |
|---|
| 384 | | - |
|---|
| 385 | | - return 0; |
|---|
| 425 | + udl_submit_urb(dev, urb, buf - (char *)urb->transfer_buffer); |
|---|
| 386 | 426 | } |
|---|
| 387 | 427 | |
|---|
| 388 | | -static void udl_crtc_prepare(struct drm_crtc *crtc) |
|---|
| 428 | +static void |
|---|
| 429 | +udl_simple_display_pipe_update(struct drm_simple_display_pipe *pipe, |
|---|
| 430 | + struct drm_plane_state *old_plane_state) |
|---|
| 389 | 431 | { |
|---|
| 432 | + struct drm_plane_state *state = pipe->plane.state; |
|---|
| 433 | + struct drm_framebuffer *fb = state->fb; |
|---|
| 434 | + struct drm_rect rect; |
|---|
| 435 | + |
|---|
| 436 | + if (!fb) |
|---|
| 437 | + return; |
|---|
| 438 | + |
|---|
| 439 | + if (drm_atomic_helper_damage_merged(old_plane_state, state, &rect)) |
|---|
| 440 | + udl_handle_damage(fb, rect.x1, rect.y1, rect.x2 - rect.x1, |
|---|
| 441 | + rect.y2 - rect.y1); |
|---|
| 390 | 442 | } |
|---|
| 391 | 443 | |
|---|
| 392 | | -static void udl_crtc_commit(struct drm_crtc *crtc) |
|---|
| 393 | | -{ |
|---|
| 394 | | - udl_crtc_dpms(crtc, DRM_MODE_DPMS_ON); |
|---|
| 395 | | -} |
|---|
| 396 | | - |
|---|
| 397 | | -static const struct drm_crtc_helper_funcs udl_helper_funcs = { |
|---|
| 398 | | - .dpms = udl_crtc_dpms, |
|---|
| 399 | | - .mode_set = udl_crtc_mode_set, |
|---|
| 400 | | - .prepare = udl_crtc_prepare, |
|---|
| 401 | | - .commit = udl_crtc_commit, |
|---|
| 402 | | - .disable = udl_crtc_disable, |
|---|
| 444 | +static const |
|---|
| 445 | +struct drm_simple_display_pipe_funcs udl_simple_display_pipe_funcs = { |
|---|
| 446 | + .mode_valid = udl_simple_display_pipe_mode_valid, |
|---|
| 447 | + .enable = udl_simple_display_pipe_enable, |
|---|
| 448 | + .disable = udl_simple_display_pipe_disable, |
|---|
| 449 | + .update = udl_simple_display_pipe_update, |
|---|
| 450 | + .prepare_fb = drm_gem_fb_simple_display_pipe_prepare_fb, |
|---|
| 403 | 451 | }; |
|---|
| 404 | 452 | |
|---|
| 405 | | -static const struct drm_crtc_funcs udl_crtc_funcs = { |
|---|
| 406 | | - .set_config = drm_crtc_helper_set_config, |
|---|
| 407 | | - .destroy = udl_crtc_destroy, |
|---|
| 408 | | - .page_flip = udl_crtc_page_flip, |
|---|
| 409 | | -}; |
|---|
| 410 | | - |
|---|
| 411 | | -static int udl_crtc_init(struct drm_device *dev) |
|---|
| 412 | | -{ |
|---|
| 413 | | - struct drm_crtc *crtc; |
|---|
| 414 | | - |
|---|
| 415 | | - crtc = kzalloc(sizeof(struct drm_crtc) + sizeof(struct drm_connector *), GFP_KERNEL); |
|---|
| 416 | | - if (crtc == NULL) |
|---|
| 417 | | - return -ENOMEM; |
|---|
| 418 | | - |
|---|
| 419 | | - drm_crtc_init(dev, crtc, &udl_crtc_funcs); |
|---|
| 420 | | - drm_crtc_helper_add(crtc, &udl_helper_funcs); |
|---|
| 421 | | - |
|---|
| 422 | | - return 0; |
|---|
| 423 | | -} |
|---|
| 453 | +/* |
|---|
| 454 | + * Modesetting |
|---|
| 455 | + */ |
|---|
| 424 | 456 | |
|---|
| 425 | 457 | static const struct drm_mode_config_funcs udl_mode_funcs = { |
|---|
| 426 | | - .fb_create = udl_fb_user_fb_create, |
|---|
| 427 | | - .output_poll_changed = NULL, |
|---|
| 458 | + .fb_create = drm_gem_fb_create_with_dirty, |
|---|
| 459 | + .atomic_check = drm_atomic_helper_check, |
|---|
| 460 | + .atomic_commit = drm_atomic_helper_commit, |
|---|
| 428 | 461 | }; |
|---|
| 429 | 462 | |
|---|
| 430 | 463 | int udl_modeset_init(struct drm_device *dev) |
|---|
| 431 | 464 | { |
|---|
| 432 | | - struct drm_encoder *encoder; |
|---|
| 433 | | - drm_mode_config_init(dev); |
|---|
| 465 | + size_t format_count = ARRAY_SIZE(udl_simple_display_pipe_formats); |
|---|
| 466 | + struct udl_device *udl = to_udl(dev); |
|---|
| 467 | + struct drm_connector *connector; |
|---|
| 468 | + int ret; |
|---|
| 469 | + |
|---|
| 470 | + ret = drmm_mode_config_init(dev); |
|---|
| 471 | + if (ret) |
|---|
| 472 | + return ret; |
|---|
| 434 | 473 | |
|---|
| 435 | 474 | dev->mode_config.min_width = 640; |
|---|
| 436 | 475 | dev->mode_config.min_height = 480; |
|---|
| .. | .. |
|---|
| 439 | 478 | dev->mode_config.max_height = 2048; |
|---|
| 440 | 479 | |
|---|
| 441 | 480 | dev->mode_config.prefer_shadow = 0; |
|---|
| 442 | | - dev->mode_config.preferred_depth = 24; |
|---|
| 481 | + dev->mode_config.preferred_depth = 16; |
|---|
| 443 | 482 | |
|---|
| 444 | 483 | dev->mode_config.funcs = &udl_mode_funcs; |
|---|
| 445 | 484 | |
|---|
| 446 | | - udl_crtc_init(dev); |
|---|
| 485 | + connector = udl_connector_init(dev); |
|---|
| 486 | + if (IS_ERR(connector)) |
|---|
| 487 | + return PTR_ERR(connector); |
|---|
| 447 | 488 | |
|---|
| 448 | | - encoder = udl_encoder_init(dev); |
|---|
| 489 | + format_count = ARRAY_SIZE(udl_simple_display_pipe_formats); |
|---|
| 449 | 490 | |
|---|
| 450 | | - udl_connector_init(dev, encoder); |
|---|
| 491 | + ret = drm_simple_display_pipe_init(dev, &udl->display_pipe, |
|---|
| 492 | + &udl_simple_display_pipe_funcs, |
|---|
| 493 | + udl_simple_display_pipe_formats, |
|---|
| 494 | + format_count, NULL, connector); |
|---|
| 495 | + if (ret) |
|---|
| 496 | + return ret; |
|---|
| 497 | + |
|---|
| 498 | + drm_mode_config_reset(dev); |
|---|
| 451 | 499 | |
|---|
| 452 | 500 | return 0; |
|---|
| 453 | | -} |
|---|
| 454 | | - |
|---|
| 455 | | -void udl_modeset_restore(struct drm_device *dev) |
|---|
| 456 | | -{ |
|---|
| 457 | | - struct udl_device *udl = dev->dev_private; |
|---|
| 458 | | - struct udl_framebuffer *ufb; |
|---|
| 459 | | - |
|---|
| 460 | | - if (!udl->crtc || !udl->crtc->primary->fb) |
|---|
| 461 | | - return; |
|---|
| 462 | | - udl_crtc_commit(udl->crtc); |
|---|
| 463 | | - ufb = to_udl_fb(udl->crtc->primary->fb); |
|---|
| 464 | | - udl_handle_damage(ufb, 0, 0, ufb->base.width, ufb->base.height); |
|---|
| 465 | | -} |
|---|
| 466 | | - |
|---|
| 467 | | -void udl_modeset_cleanup(struct drm_device *dev) |
|---|
| 468 | | -{ |
|---|
| 469 | | - drm_mode_config_cleanup(dev); |
|---|
| 470 | 501 | } |
|---|