2 * 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>
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
13 #include <linux/module.h>
14 #include <linux/slab.h>
16 #include <linux/dma-buf.h>
17 #include <linux/mem_encrypt.h>
20 #include <drm/drm_crtc.h>
21 #include <drm/drm_crtc_helper.h>
24 #include <drm/drm_fb_helper.h>
26 #define DL_DEFIO_WRITE_DELAY (HZ/20) /* fb_deferred_io.delay in jiffies */
28 static int fb_defio
= 0; /* Optionally enable experimental fb_defio mmap support */
29 static int fb_bpp
= 16;
31 module_param(fb_bpp
, int, S_IWUSR
| S_IRUSR
| S_IWGRP
| S_IRGRP
);
32 module_param(fb_defio
, int, S_IWUSR
| S_IRUSR
| S_IWGRP
| S_IRGRP
);
35 struct drm_fb_helper helper
;
36 struct udl_framebuffer ufb
;
40 #define DL_ALIGN_UP(x, a) ALIGN(x, a)
41 #define DL_ALIGN_DOWN(x, a) ALIGN_DOWN(x, a)
43 /** Read the red component (0..255) of a 32 bpp colour. */
44 #define DLO_RGB_GETRED(col) (uint8_t)((col) & 0xFF)
46 /** Read the green component (0..255) of a 32 bpp colour. */
47 #define DLO_RGB_GETGRN(col) (uint8_t)(((col) >> 8) & 0xFF)
49 /** Read the blue component (0..255) of a 32 bpp colour. */
50 #define DLO_RGB_GETBLU(col) (uint8_t)(((col) >> 16) & 0xFF)
52 /** Return red/green component of a 16 bpp colour number. */
53 #define DLO_RG16(red, grn) (uint8_t)((((red) & 0xF8) | ((grn) >> 5)) & 0xFF)
55 /** Return green/blue component of a 16 bpp colour number. */
56 #define DLO_GB16(grn, blu) (uint8_t)(((((grn) & 0x1C) << 3) | ((blu) >> 3)) & 0xFF)
58 /** Return 8 bpp colour number from red, green and blue components. */
59 #define DLO_RGB8(red, grn, blu) ((((red) << 5) | (((grn) & 3) << 3) | ((blu) & 7)) & 0xFF)
62 static uint8_t rgb8(uint32_t col
)
64 uint8_t red
= DLO_RGB_GETRED(col
);
65 uint8_t grn
= DLO_RGB_GETGRN(col
);
66 uint8_t blu
= DLO_RGB_GETBLU(col
);
68 return DLO_RGB8(red
, grn
, blu
);
71 static uint16_t rgb16(uint32_t col
)
73 uint8_t red
= DLO_RGB_GETRED(col
);
74 uint8_t grn
= DLO_RGB_GETGRN(col
);
75 uint8_t blu
= DLO_RGB_GETBLU(col
);
77 return (DLO_RG16(red
, grn
) << 8) + DLO_GB16(grn
, blu
);
81 int udl_handle_damage(struct udl_framebuffer
*fb
, int x
, int y
,
82 int width
, int height
)
84 struct drm_device
*dev
= fb
->base
.dev
;
85 struct udl_device
*udl
= dev
->dev_private
;
88 cycles_t start_cycles
, end_cycles
;
90 int bytes_identical
= 0;
93 int bpp
= fb
->base
.format
->cpp
[0];
98 if (!fb
->obj
->vmapping
) {
99 ret
= udl_gem_vmap(fb
->obj
);
100 if (ret
== -ENOMEM
) {
101 DRM_ERROR("failed to vmap fb\n");
104 if (!fb
->obj
->vmapping
) {
105 DRM_ERROR("failed to vmapping\n");
110 aligned_x
= DL_ALIGN_DOWN(x
, sizeof(unsigned long));
111 width
= DL_ALIGN_UP(width
+ (x
-aligned_x
), sizeof(unsigned long));
115 (x
+ width
> fb
->base
.width
) ||
116 (y
+ height
> fb
->base
.height
))
119 start_cycles
= get_cycles();
121 urb
= udl_get_urb(dev
);
124 cmd
= urb
->transfer_buffer
;
126 for (i
= y
; i
< y
+ height
; i
++) {
127 const int line_offset
= fb
->base
.pitches
[0] * i
;
128 const int byte_offset
= line_offset
+ (x
* bpp
);
129 const int dev_byte_offset
= (fb
->base
.width
* bpp
* i
) + (x
* bpp
);
130 if (udl_render_hline(dev
, bpp
, &urb
,
131 (char *) fb
->obj
->vmapping
,
132 &cmd
, byte_offset
, dev_byte_offset
,
134 &bytes_identical
, &bytes_sent
))
138 if (cmd
> (char *) urb
->transfer_buffer
) {
139 /* Send partial buffer remaining before exiting */
140 int len
= cmd
- (char *) urb
->transfer_buffer
;
141 ret
= udl_submit_urb(dev
, urb
, len
);
144 udl_urb_completion(urb
);
147 atomic_add(bytes_sent
, &udl
->bytes_sent
);
148 atomic_add(bytes_identical
, &udl
->bytes_identical
);
149 atomic_add(width
*height
*bpp
, &udl
->bytes_rendered
);
150 end_cycles
= get_cycles();
151 atomic_add(((unsigned int) ((end_cycles
- start_cycles
)
152 >> 10)), /* Kcycles */
153 &udl
->cpu_kcycles_used
);
158 static int udl_fb_mmap(struct fb_info
*info
, struct vm_area_struct
*vma
)
160 unsigned long start
= vma
->vm_start
;
161 unsigned long size
= vma
->vm_end
- vma
->vm_start
;
162 unsigned long offset
= vma
->vm_pgoff
<< PAGE_SHIFT
;
163 unsigned long page
, pos
;
165 if (offset
+ size
> info
->fix
.smem_len
)
168 pos
= (unsigned long)info
->fix
.smem_start
+ offset
;
170 pr_notice("mmap() framebuffer addr:%lu size:%lu\n",
173 /* We don't want the framebuffer to be mapped encrypted */
174 vma
->vm_page_prot
= pgprot_decrypted(vma
->vm_page_prot
);
177 page
= vmalloc_to_pfn((void *)pos
);
178 if (remap_pfn_range(vma
, start
, page
, PAGE_SIZE
, PAGE_SHARED
))
183 if (size
> PAGE_SIZE
)
189 /* VM_IO | VM_DONTEXPAND | VM_DONTDUMP are set by remap_pfn_range() */
194 * It's common for several clients to have framebuffer open simultaneously.
195 * e.g. both fbcon and X. Makes things interesting.
196 * Assumes caller is holding info->lock (for open and release at least)
198 static int udl_fb_open(struct fb_info
*info
, int user
)
200 struct udl_fbdev
*ufbdev
= info
->par
;
201 struct drm_device
*dev
= ufbdev
->ufb
.base
.dev
;
202 struct udl_device
*udl
= dev
->dev_private
;
204 /* If the USB device is gone, we don't accept new opens */
205 if (drm_dev_is_unplugged(udl
->ddev
))
210 #ifdef CONFIG_DRM_FBDEV_EMULATION
211 if (fb_defio
&& (info
->fbdefio
== NULL
)) {
212 /* enable defio at last moment if not disabled by client */
214 struct fb_deferred_io
*fbdefio
;
216 fbdefio
= kmalloc(sizeof(struct fb_deferred_io
), GFP_KERNEL
);
219 fbdefio
->delay
= DL_DEFIO_WRITE_DELAY
;
220 fbdefio
->deferred_io
= drm_fb_helper_deferred_io
;
223 info
->fbdefio
= fbdefio
;
224 fb_deferred_io_init(info
);
228 pr_notice("open /dev/fb%d user=%d fb_info=%p count=%d\n",
229 info
->node
, user
, info
, ufbdev
->fb_count
);
236 * Assumes caller is holding info->lock mutex (for open and release at least)
238 static int udl_fb_release(struct fb_info
*info
, int user
)
240 struct udl_fbdev
*ufbdev
= info
->par
;
244 #ifdef CONFIG_DRM_FBDEV_EMULATION
245 if ((ufbdev
->fb_count
== 0) && (info
->fbdefio
)) {
246 fb_deferred_io_cleanup(info
);
247 kfree(info
->fbdefio
);
248 info
->fbdefio
= NULL
;
249 info
->fbops
->fb_mmap
= udl_fb_mmap
;
253 pr_warn("released /dev/fb%d user=%d count=%d\n",
254 info
->node
, user
, ufbdev
->fb_count
);
259 static struct fb_ops udlfb_ops
= {
260 .owner
= THIS_MODULE
,
261 DRM_FB_HELPER_DEFAULT_OPS
,
262 .fb_fillrect
= drm_fb_helper_sys_fillrect
,
263 .fb_copyarea
= drm_fb_helper_sys_copyarea
,
264 .fb_imageblit
= drm_fb_helper_sys_imageblit
,
265 .fb_mmap
= udl_fb_mmap
,
266 .fb_open
= udl_fb_open
,
267 .fb_release
= udl_fb_release
,
270 static int udl_user_framebuffer_dirty(struct drm_framebuffer
*fb
,
271 struct drm_file
*file
,
272 unsigned flags
, unsigned color
,
273 struct drm_clip_rect
*clips
,
276 struct udl_framebuffer
*ufb
= to_udl_fb(fb
);
280 drm_modeset_lock_all(fb
->dev
);
285 if (ufb
->obj
->base
.import_attach
) {
286 ret
= dma_buf_begin_cpu_access(ufb
->obj
->base
.import_attach
->dmabuf
,
292 for (i
= 0; i
< num_clips
; i
++) {
293 ret
= udl_handle_damage(ufb
, clips
[i
].x1
, clips
[i
].y1
,
294 clips
[i
].x2
- clips
[i
].x1
,
295 clips
[i
].y2
- clips
[i
].y1
);
300 if (ufb
->obj
->base
.import_attach
) {
301 ret
= dma_buf_end_cpu_access(ufb
->obj
->base
.import_attach
->dmabuf
,
306 drm_modeset_unlock_all(fb
->dev
);
311 static void udl_user_framebuffer_destroy(struct drm_framebuffer
*fb
)
313 struct udl_framebuffer
*ufb
= to_udl_fb(fb
);
316 drm_gem_object_put_unlocked(&ufb
->obj
->base
);
318 drm_framebuffer_cleanup(fb
);
322 static const struct drm_framebuffer_funcs udlfb_funcs
= {
323 .destroy
= udl_user_framebuffer_destroy
,
324 .dirty
= udl_user_framebuffer_dirty
,
329 udl_framebuffer_init(struct drm_device
*dev
,
330 struct udl_framebuffer
*ufb
,
331 const struct drm_mode_fb_cmd2
*mode_cmd
,
332 struct udl_gem_object
*obj
)
337 drm_helper_mode_fill_fb_struct(dev
, &ufb
->base
, mode_cmd
);
338 ret
= drm_framebuffer_init(dev
, &ufb
->base
, &udlfb_funcs
);
343 static int udlfb_create(struct drm_fb_helper
*helper
,
344 struct drm_fb_helper_surface_size
*sizes
)
346 struct udl_fbdev
*ufbdev
=
347 container_of(helper
, struct udl_fbdev
, helper
);
348 struct drm_device
*dev
= ufbdev
->helper
.dev
;
349 struct fb_info
*info
;
350 struct drm_framebuffer
*fb
;
351 struct drm_mode_fb_cmd2 mode_cmd
;
352 struct udl_gem_object
*obj
;
356 if (sizes
->surface_bpp
== 24)
357 sizes
->surface_bpp
= 32;
359 mode_cmd
.width
= sizes
->surface_width
;
360 mode_cmd
.height
= sizes
->surface_height
;
361 mode_cmd
.pitches
[0] = mode_cmd
.width
* ((sizes
->surface_bpp
+ 7) / 8);
363 mode_cmd
.pixel_format
= drm_mode_legacy_fb_format(sizes
->surface_bpp
,
364 sizes
->surface_depth
);
366 size
= mode_cmd
.pitches
[0] * mode_cmd
.height
;
367 size
= ALIGN(size
, PAGE_SIZE
);
369 obj
= udl_gem_alloc_object(dev
, size
);
373 ret
= udl_gem_vmap(obj
);
375 DRM_ERROR("failed to vmap fb\n");
379 info
= drm_fb_helper_alloc_fbi(helper
);
386 ret
= udl_framebuffer_init(dev
, &ufbdev
->ufb
, &mode_cmd
, obj
);
390 fb
= &ufbdev
->ufb
.base
;
392 ufbdev
->helper
.fb
= fb
;
394 strcpy(info
->fix
.id
, "udldrmfb");
396 info
->screen_base
= ufbdev
->ufb
.obj
->vmapping
;
397 info
->fix
.smem_len
= size
;
398 info
->fix
.smem_start
= (unsigned long)ufbdev
->ufb
.obj
->vmapping
;
400 info
->fbops
= &udlfb_ops
;
401 drm_fb_helper_fill_fix(info
, fb
->pitches
[0], fb
->format
->depth
);
402 drm_fb_helper_fill_var(info
, &ufbdev
->helper
, sizes
->fb_width
, sizes
->fb_height
);
404 DRM_DEBUG_KMS("allocated %dx%d vmal %p\n",
405 fb
->width
, fb
->height
,
406 ufbdev
->ufb
.obj
->vmapping
);
410 drm_gem_object_put_unlocked(&ufbdev
->ufb
.obj
->base
);
415 static const struct drm_fb_helper_funcs udl_fb_helper_funcs
= {
416 .fb_probe
= udlfb_create
,
419 static void udl_fbdev_destroy(struct drm_device
*dev
,
420 struct udl_fbdev
*ufbdev
)
422 drm_fb_helper_unregister_fbi(&ufbdev
->helper
);
423 drm_fb_helper_fini(&ufbdev
->helper
);
424 drm_framebuffer_unregister_private(&ufbdev
->ufb
.base
);
425 drm_framebuffer_cleanup(&ufbdev
->ufb
.base
);
426 drm_gem_object_put_unlocked(&ufbdev
->ufb
.obj
->base
);
429 int udl_fbdev_init(struct drm_device
*dev
)
431 struct udl_device
*udl
= dev
->dev_private
;
432 int bpp_sel
= fb_bpp
;
433 struct udl_fbdev
*ufbdev
;
436 ufbdev
= kzalloc(sizeof(struct udl_fbdev
), GFP_KERNEL
);
442 drm_fb_helper_prepare(dev
, &ufbdev
->helper
, &udl_fb_helper_funcs
);
444 ret
= drm_fb_helper_init(dev
, &ufbdev
->helper
, 1);
448 ret
= drm_fb_helper_single_add_all_connectors(&ufbdev
->helper
);
452 /* disable all the possible outputs/crtcs before entering KMS mode */
453 drm_helper_disable_unused_functions(dev
);
455 ret
= drm_fb_helper_initial_config(&ufbdev
->helper
, bpp_sel
);
462 drm_fb_helper_fini(&ufbdev
->helper
);
468 void udl_fbdev_cleanup(struct drm_device
*dev
)
470 struct udl_device
*udl
= dev
->dev_private
;
474 udl_fbdev_destroy(dev
, udl
->fbdev
);
479 void udl_fbdev_unplug(struct drm_device
*dev
)
481 struct udl_device
*udl
= dev
->dev_private
;
482 struct udl_fbdev
*ufbdev
;
487 drm_fb_helper_unlink_fbi(&ufbdev
->helper
);
490 struct drm_framebuffer
*
491 udl_fb_user_fb_create(struct drm_device
*dev
,
492 struct drm_file
*file
,
493 const struct drm_mode_fb_cmd2
*mode_cmd
)
495 struct drm_gem_object
*obj
;
496 struct udl_framebuffer
*ufb
;
500 obj
= drm_gem_object_lookup(file
, mode_cmd
->handles
[0]);
502 return ERR_PTR(-ENOENT
);
504 size
= mode_cmd
->pitches
[0] * mode_cmd
->height
;
505 size
= ALIGN(size
, PAGE_SIZE
);
507 if (size
> obj
->size
) {
508 DRM_ERROR("object size not sufficient for fb %d %zu %d %d\n", size
, obj
->size
, mode_cmd
->pitches
[0], mode_cmd
->height
);
509 return ERR_PTR(-ENOMEM
);
512 ufb
= kzalloc(sizeof(*ufb
), GFP_KERNEL
);
514 return ERR_PTR(-ENOMEM
);
516 ret
= udl_framebuffer_init(dev
, ufb
, mode_cmd
, to_udl_bo(obj
));
519 return ERR_PTR(-EINVAL
);