13 #include <linux/module.h>
14 #include <linux/slab.h>
25 #define DL_DEFIO_WRITE_DELAY 5
27 static int fb_defio = 1;
28 static int fb_bpp = 16;
40 #define DL_ALIGN_UP(x, a) ALIGN(x, a)
41 #define DL_ALIGN_DOWN(x, a) ALIGN(x-(a-1), a)
44 #define DLO_RGB_GETRED(col) (uint8_t)((col) & 0xFF)
47 #define DLO_RGB_GETGRN(col) (uint8_t)(((col) >> 8) & 0xFF)
50 #define DLO_RGB_GETBLU(col) (uint8_t)(((col) >> 16) & 0xFF)
53 #define DLO_RG16(red, grn) (uint8_t)((((red) & 0xF8) | ((grn) >> 5)) & 0xFF)
56 #define DLO_GB16(grn, blu) (uint8_t)(((((grn) & 0x1C) << 3) | ((blu) >> 3)) & 0xFF)
59 #define DLO_RGB8(red, grn, blu) ((((red) << 5) | (((grn) & 3) << 3) | ((blu) & 7)) & 0xFF)
87 static void udlfb_dpy_deferred_io(
struct fb_info *
info,
91 struct fb_deferred_io *fbdefio = info->fbdefio;
99 int bytes_identical = 0;
100 int bytes_rendered = 0;
111 cmd = urb->transfer_buffer;
117 &urb, (
char *) info->
fix.smem_start,
120 PAGE_SIZE, &bytes_identical, &bytes_sent))
125 if (cmd > (
char *) urb->transfer_buffer) {
127 int len = cmd - (
char *) urb->transfer_buffer;
138 atomic_add(((
unsigned int) ((end_cycles - start_cycles)
152 int bytes_identical = 0;
155 int bpp = (fb->
base.bits_per_pixel / 8);
160 if (!fb->
obj->vmapping) {
163 DRM_ERROR(
"failed to vmap fb\n");
166 if (!fb->
obj->vmapping) {
167 DRM_ERROR(
"failed to vmapping\n");
175 width =
DL_ALIGN_UP(width + (x-aligned_x),
sizeof(
unsigned long));
179 (x + width > fb->
base.width) ||
180 (y + height > fb->
base.height))
186 cmd = urb->transfer_buffer;
188 for (i = y; i < y +
height ; i++) {
189 const int line_offset = fb->
base.pitches[0] *
i;
191 const int dev_byte_offset = (fb->
base.width * bpp *
i) + (x * bpp);
193 (
char *) fb->
obj->vmapping,
196 &bytes_identical, &bytes_sent))
200 if (cmd > (
char *) urb->transfer_buffer) {
202 int len = cmd - (
char *) urb->transfer_buffer;
213 atomic_add(((
unsigned int) ((end_cycles - start_cycles)
227 if (offset + size > info->
fix.smem_len)
230 pos = (
unsigned long)info->
fix.smem_start + offset;
232 pr_notice(
"mmap() framebuffer addr:%lu size:%lu\n",
287 static int udl_fb_open(
struct fb_info *info,
int user)
294 if (drm_device_is_unplugged(udl->
ddev))
299 if (fb_defio && (info->fbdefio ==
NULL)) {
302 struct fb_deferred_io *fbdefio;
308 fbdefio->deferred_io = udlfb_dpy_deferred_io;
311 info->fbdefio = fbdefio;
315 pr_notice(
"open /dev/fb%d user=%d fb_info=%p count=%d\n",
325 static int udl_fb_release(
struct fb_info *info,
int user)
331 if ((ufbdev->
fb_count == 0) && (info->fbdefio)) {
333 kfree(info->fbdefio);
334 info->fbdefio =
NULL;
335 info->
fbops->fb_mmap = udl_fb_mmap;
338 pr_warn(
"released /dev/fb%d user=%d count=%d\n",
344 static struct fb_ops udlfb_ops = {
348 .fb_fillrect = udl_fb_fillrect,
349 .fb_copyarea = udl_fb_copyarea,
350 .fb_imageblit = udl_fb_imageblit,
356 .fb_mmap = udl_fb_mmap,
357 .fb_open = udl_fb_open,
358 .fb_release = udl_fb_release,
375 struct drm_file *
file,
387 if (ufb->
obj->base.import_attach) {
389 0, ufb->
obj->base.size,
395 for (i = 0; i < num_clips; i++) {
397 clips[i].x2 - clips[i].x1,
398 clips[i].y2 - clips[i].y1);
403 if (ufb->
obj->base.import_attach) {
405 0, ufb->
obj->base.size,
416 drm_gem_object_unreference_unlocked(&ufb->
obj->base);
423 .destroy = udl_user_framebuffer_destroy,
424 .dirty = udl_user_framebuffer_dirty,
425 .create_handle =
NULL,
444 static int udlfb_create(
struct udl_fbdev *ufbdev,
461 mode_cmd.pitches[0] = mode_cmd.width * ((sizes->
surface_bpp + 7) / 8);
466 size = mode_cmd.pitches[0] * mode_cmd.height;
475 DRM_ERROR(
"failed to vmap fb\n");
486 ret = udl_framebuffer_init(dev, &ufbdev->
ufb, &mode_cmd, obj);
490 fb = &ufbdev->
ufb.base;
499 info->
fix.smem_start = (
unsigned long)ufbdev->
ufb.obj->vmapping;
502 info->
fbops = &udlfb_ops;
513 DRM_DEBUG_KMS(
"allocated %dx%d vmal %p\n",
515 ufbdev->
ufb.obj->vmapping);
519 drm_gem_object_unreference(&ufbdev->
ufb.obj->base);
524 static int udl_fb_find_or_create_single(
struct drm_fb_helper *helper,
532 ret = udlfb_create(ufbdev, sizes);
542 .gamma_set = udl_crtc_fb_gamma_set,
543 .gamma_get = udl_crtc_fb_gamma_get,
544 .fb_probe = udl_fb_find_or_create_single,
547 static void udl_fbdev_destroy(
struct drm_device *dev,
551 if (ufbdev->
helper.fbdev) {
552 info = ufbdev->
helper.fbdev;
560 drm_gem_object_unreference_unlocked(&ufbdev->
ufb.obj->base);
566 int bpp_sel = fb_bpp;
575 ufbdev->
helper.funcs = &udl_fb_helper_funcs;
596 udl_fbdev_destroy(dev, udl->
fbdev);
609 if (ufbdev->
helper.fbdev) {
611 info = ufbdev->
helper.fbdev;
618 struct drm_file *file,
621 struct drm_gem_object *obj;
633 if (size > obj->size) {
634 DRM_ERROR(
"object size not sufficient for fb %d %zu %d %d\n", size, obj->size, mode_cmd->
pitches[0], mode_cmd->
height);
642 ret = udl_framebuffer_init(dev, ufb, mode_cmd,
to_udl_bo(obj));