int radeon_mode_dumb_create(struct drm_file *file_priv, struct drm_device *dev, struct drm_mode_create_dumb *args) { struct radeon_device *rdev = dev->dev_private; struct drm_gem_object *gobj; uint32_t handle; int r; args->pitch = radeon_align_pitch(rdev, args->width, args->bpp, 0) * ((args->bpp + 1) / 8); args->size = args->pitch * args->height; args->size = roundup2(args->size, PAGE_SIZE); r = radeon_gem_object_create(rdev, args->size, 0, RADEON_GEM_DOMAIN_VRAM, false, ttm_bo_type_device, &gobj); if (r) return -ENOMEM; handle = 0; r = drm_gem_handle_create(file_priv, gobj, &handle); /* drop reference from allocate - handle holds it now */ drm_gem_object_unreference_unlocked(gobj); if (r) { return r; } args->handle = handle; return 0; }
int create_bitmap(bitmap_t **pbitmap, int width, int height) { size_t size; size_t pitch; bitmap_t *bitmap; uint64_t gaddr; void *uaddr; struct radeon_device *rdev = main_device; struct radeon_bo *sobj = NULL; int r; bitmap = CreateObject(GetPid(), sizeof(bitmap_t)); if( bitmap == NULL) { *pbitmap = NULL; return -1; } pitch = radeon_align_pitch(rdev, width, 32, false) * 4; size = pitch * height; r = radeon_bo_create(rdev, size, PAGE_SIZE, true, RADEON_GEM_DOMAIN_GTT, &sobj); if (r) { goto fail; } r = radeon_bo_reserve(sobj, false); if (unlikely(r != 0)) goto fail; r = radeon_bo_pin(sobj, RADEON_GEM_DOMAIN_GTT, &gaddr); if (r) { goto fail; } r = radeon_bo_user_map(sobj, &uaddr); if (r) { goto fail; } bitmap->width = width; bitmap->height = height; bitmap->stride = pitch; bitmap->gaddr = gaddr; bitmap->uaddr = uaddr; bitmap->robj = sobj; *pbitmap = bitmap; return 0; fail: DestroyObject(bitmap); return -1; };
static int radeonfb_create_pinned_object(struct radeon_fbdev *rfbdev, struct drm_mode_fb_cmd2 *mode_cmd, struct drm_gem_object **gobj_p) { struct radeon_device *rdev = rfbdev->rdev; struct drm_gem_object *gobj = NULL; struct radeon_bo *rbo = NULL; bool fb_tiled = false; /* useful for testing */ u32 tiling_flags = 0; int ret; int aligned_size, size; int height = mode_cmd->height; u32 bpp, depth; drm_fb_get_bpp_depth(mode_cmd->pixel_format, &depth, &bpp); /* need to align pitch with crtc limits */ mode_cmd->pitches[0] = radeon_align_pitch(rdev, mode_cmd->width, bpp, fb_tiled) * ((bpp + 1) / 8); if (rdev->family >= CHIP_R600) height = ALIGN(mode_cmd->height, 8); size = mode_cmd->pitches[0] * height; aligned_size = ALIGN(size, PAGE_SIZE); ret = radeon_gem_object_create(rdev, aligned_size, 0, RADEON_GEM_DOMAIN_VRAM, 0, true, &gobj); if (ret) { printk(KERN_ERR "failed to allocate framebuffer (%d)\n", aligned_size); return -ENOMEM; } rbo = gem_to_radeon_bo(gobj); if (fb_tiled) tiling_flags = RADEON_TILING_MACRO; #ifdef __BIG_ENDIAN switch (bpp) { case 32: tiling_flags |= RADEON_TILING_SWAP_32BIT; break; case 16: tiling_flags |= RADEON_TILING_SWAP_16BIT; default: break; } #endif if (tiling_flags) { ret = radeon_bo_set_tiling_flags(rbo, tiling_flags | RADEON_TILING_SURFACE, mode_cmd->pitches[0]); if (ret) dev_err(rdev->dev, "FB failed to set tiling flags\n"); } ret = radeon_bo_reserve(rbo, false); if (unlikely(ret != 0)) goto out_unref; /* Only 27 bit offset for legacy CRTC */ ret = radeon_bo_pin_restricted(rbo, RADEON_GEM_DOMAIN_VRAM, ASIC_IS_AVIVO(rdev) ? 0 : 1 << 27, NULL); if (ret) { radeon_bo_unreserve(rbo); goto out_unref; } if (fb_tiled) radeon_bo_check_tiling(rbo, 0, 0); ret = radeon_bo_kmap(rbo, NULL); radeon_bo_unreserve(rbo); if (ret) { goto out_unref; } *gobj_p = gobj; return 0; out_unref: radeonfb_destroy_pinned_object(gobj); *gobj_p = NULL; return ret; }