int radeon_uvd_suspend(struct radeon_device *rdev) { unsigned size; void *ptr; int i; if (rdev->uvd.vcpu_bo == NULL) return 0; for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) if (atomic_read(&rdev->uvd.handles[i])) break; if (i == RADEON_MAX_UVD_HANDLES) return 0; size = radeon_bo_size(rdev->uvd.vcpu_bo); size -= rdev->uvd_fw->size; ptr = rdev->uvd.cpu_addr; ptr += rdev->uvd_fw->size; rdev->uvd.saved_bo = kmalloc(size, GFP_KERNEL); memcpy(rdev->uvd.saved_bo, ptr, size); return 0; }
int radeon_uvd_resume(struct radeon_device *rdev) { unsigned size; void *ptr; if (rdev->uvd.vcpu_bo == NULL) return -EINVAL; memcpy(rdev->uvd.cpu_addr, rdev->uvd_fw->data, rdev->uvd_fw->size); size = radeon_bo_size(rdev->uvd.vcpu_bo); size -= rdev->uvd_fw->size; ptr = rdev->uvd.cpu_addr; ptr += rdev->uvd_fw->size; if (rdev->uvd.saved_bo != NULL) { memcpy(ptr, rdev->uvd.saved_bo, size); kfree(rdev->uvd.saved_bo); rdev->uvd.saved_bo = NULL; } else memset(ptr, 0, size); return 0; }
/** * radeon_vce_resume - pin VCE fw memory * * @rdev: radeon_device pointer * */ int radeon_vce_resume(struct radeon_device *rdev) { void *cpu_addr; int r; if (rdev->vce.vcpu_bo == NULL) return -EINVAL; r = radeon_bo_reserve(rdev->vce.vcpu_bo, false); if (r) { dev_err(rdev->dev, "(%d) failed to reserve VCE bo\n", r); return r; } r = radeon_bo_kmap(rdev->vce.vcpu_bo, &cpu_addr); if (r) { radeon_bo_unreserve(rdev->vce.vcpu_bo); dev_err(rdev->dev, "(%d) VCE map failed\n", r); return r; } memset(cpu_addr, 0, radeon_bo_size(rdev->vce.vcpu_bo)); if (rdev->family < CHIP_BONAIRE) r = vce_v1_0_load_fw(rdev, cpu_addr); else memcpy(cpu_addr, rdev->vce_fw->data, rdev->vce_fw->size); radeon_bo_kunmap(rdev->vce.vcpu_bo); radeon_bo_unreserve(rdev->vce.vcpu_bo); return r; }
int radeon_fbdev_total_size(struct radeon_device *rdev) { struct radeon_bo *robj; int size = 0; robj = gem_to_radeon_bo(rdev->mode_info.rfbdev->rfb.obj); size += radeon_bo_size(robj); return size; }
/* * GEM ioctls. */ int radeon_gem_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) { struct radeon_device *rdev = dev->dev_private; struct drm_radeon_gem_info *args = data; args->vram_size = rdev->mc.real_vram_size; args->vram_visible = rdev->mc.real_vram_size; if (rdev->stollen_vga_memory) args->vram_visible -= radeon_bo_size(rdev->stollen_vga_memory); args->vram_visible -= radeon_fbdev_total_size(rdev); args->gart_size = rdev->mc.gtt_size - rdev->cp.ring_size - 4096 - RADEON_IB_POOL_SIZE*64*1024; return 0; }
/* * GEM ioctls. */ int radeon_gem_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) { struct radeon_device *rdev = dev->dev_private; struct drm_radeon_gem_info *args = data; struct ttm_mem_type_manager *man; man = &rdev->mman.bdev.man[TTM_PL_VRAM]; args->vram_size = rdev->mc.real_vram_size; args->vram_visible = (u64)man->size << PAGE_SHIFT; if (rdev->stollen_vga_memory) args->vram_visible -= radeon_bo_size(rdev->stollen_vga_memory); args->vram_visible -= radeon_fbdev_total_size(rdev); args->gart_size = rdev->mc.gtt_size - rdev->cp.ring_size - 4096 - RADEON_IB_POOL_SIZE*64*1024; return 0; }
/** * radeon_vce_cs_reloc - command submission relocation * * @p: parser context * @lo: address of lower dword * @hi: address of higher dword * @size: size of checker for relocation buffer * * Patch relocation inside command stream with real buffer address */ int radeon_vce_cs_reloc(struct radeon_cs_parser *p, int lo, int hi, unsigned size) { struct radeon_cs_chunk *relocs_chunk; struct radeon_cs_reloc *reloc; uint64_t start, end, offset; unsigned idx; relocs_chunk = &p->chunks[p->chunk_relocs_idx]; offset = radeon_get_ib_value(p, lo); idx = radeon_get_ib_value(p, hi); if (idx >= relocs_chunk->length_dw) { DRM_ERROR("Relocs at %d after relocations chunk end %d !\n", idx, relocs_chunk->length_dw); return -EINVAL; } reloc = p->relocs_ptr[(idx / 4)]; start = reloc->gpu_offset; end = start + radeon_bo_size(reloc->robj); start += offset; p->ib.ptr[lo] = start & 0xFFFFFFFF; p->ib.ptr[hi] = start >> 32; if (end <= start) { DRM_ERROR("invalid reloc offset %llX!\n", offset); return -EINVAL; } if ((end - start) < size) { DRM_ERROR("buffer to small (%d / %d)!\n", (unsigned)(end - start), size); return -EINVAL; } return 0; }
static int radeonfb_create(struct drm_fb_helper *helper, struct drm_fb_helper_surface_size *sizes) { struct radeon_fbdev *rfbdev = container_of(helper, struct radeon_fbdev, helper); struct radeon_device *rdev = rfbdev->rdev; struct fb_info *info; struct drm_framebuffer *fb = NULL; struct drm_mode_fb_cmd2 mode_cmd; struct drm_gem_object *gobj = NULL; struct radeon_bo *rbo = NULL; struct device *device = &rdev->pdev->dev; int ret; unsigned long tmp; mode_cmd.width = sizes->surface_width; mode_cmd.height = sizes->surface_height; /* avivo can't scanout real 24bpp */ if ((sizes->surface_bpp == 24) && ASIC_IS_AVIVO(rdev)) sizes->surface_bpp = 32; mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp, sizes->surface_depth); ret = radeonfb_create_pinned_object(rfbdev, &mode_cmd, &gobj); if (ret) { DRM_ERROR("failed to create fbcon object %d\n", ret); return ret; } rbo = gem_to_radeon_bo(gobj); /* okay we have an object now allocate the framebuffer */ info = framebuffer_alloc(0, device); if (info == NULL) { ret = -ENOMEM; goto out_unref; } info->par = rfbdev; ret = radeon_framebuffer_init(rdev->ddev, &rfbdev->rfb, &mode_cmd, gobj); if (ret) { DRM_ERROR("failed to initialize framebuffer %d\n", ret); goto out_unref; } fb = &rfbdev->rfb.base; /* setup helper */ rfbdev->helper.fb = fb; rfbdev->helper.fbdev = info; memset_io(rbo->kptr, 0x0, radeon_bo_size(rbo)); strcpy(info->fix.id, "radeondrmfb"); drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth); info->flags = FBINFO_DEFAULT | FBINFO_CAN_FORCE_OUTPUT; info->fbops = &radeonfb_ops; tmp = radeon_bo_gpu_offset(rbo) - rdev->mc.vram_start; info->fix.smem_start = rdev->mc.aper_base + tmp; info->fix.smem_len = radeon_bo_size(rbo); info->screen_base = rbo->kptr; info->screen_size = radeon_bo_size(rbo); drm_fb_helper_fill_var(info, &rfbdev->helper, sizes->fb_width, sizes->fb_height); /* setup aperture base/size for vesafb takeover */ info->apertures = alloc_apertures(1); if (!info->apertures) { ret = -ENOMEM; goto out_unref; } info->apertures->ranges[0].base = rdev->ddev->mode_config.fb_base; info->apertures->ranges[0].size = rdev->mc.aper_size; /* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */ if (info->screen_base == NULL) { ret = -ENOSPC; goto out_unref; } ret = fb_alloc_cmap(&info->cmap, 256, 0); if (ret) { ret = -ENOMEM; goto out_unref; } DRM_INFO("fb mappable at 0x%lX\n", info->fix.smem_start); DRM_INFO("vram apper at 0x%lX\n", (unsigned long)rdev->mc.aper_base); DRM_INFO("size %lu\n", (unsigned long)radeon_bo_size(rbo)); DRM_INFO("fb depth is %d\n", fb->depth); DRM_INFO(" pitch is %d\n", fb->pitches[0]); vga_switcheroo_client_fb_set(rdev->ddev->pdev, info); return 0; out_unref: if (rbo) { } if (fb && ret) { drm_gem_object_unreference(gobj); drm_framebuffer_unregister_private(fb); drm_framebuffer_cleanup(fb); kfree(fb); } return ret; }
static int radeonfb_create(struct drm_fb_helper *helper, struct drm_fb_helper_surface_size *sizes) { struct radeon_fbdev *rfbdev = container_of(helper, struct radeon_fbdev, helper); struct radeon_device *rdev = rfbdev->rdev; struct fb_info *info; struct drm_framebuffer *fb = NULL; struct drm_mode_fb_cmd2 mode_cmd; struct drm_gem_object *gobj = NULL; struct radeon_bo *rbo = NULL; int ret; unsigned long tmp; mode_cmd.width = sizes->surface_width; mode_cmd.height = sizes->surface_height; /* avivo can't scanout real 24bpp */ if ((sizes->surface_bpp == 24) && ASIC_IS_AVIVO(rdev)) sizes->surface_bpp = 32; mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp, sizes->surface_depth); ret = radeonfb_create_pinned_object(rfbdev, &mode_cmd, &gobj); if (ret) { DRM_ERROR("failed to create fbcon object %d\n", ret); return ret; } rbo = gem_to_radeon_bo(gobj); /* okay we have an object now allocate the framebuffer */ info = drm_fb_helper_alloc_fbi(helper); if (IS_ERR(info)) { ret = PTR_ERR(info); goto out; } /* radeon resume is fragile and needs a vt switch to help it along */ info->skip_vt_switch = false; ret = radeon_framebuffer_init(rdev->ddev, &rfbdev->fb, &mode_cmd, gobj); if (ret) { DRM_ERROR("failed to initialize framebuffer %d\n", ret); goto out; } fb = &rfbdev->fb; /* setup helper */ rfbdev->helper.fb = fb; memset_io(rbo->kptr, 0x0, radeon_bo_size(rbo)); info->fbops = &radeonfb_ops; tmp = radeon_bo_gpu_offset(rbo) - rdev->mc.vram_start; info->fix.smem_start = rdev->mc.aper_base + tmp; info->fix.smem_len = radeon_bo_size(rbo); info->screen_base = rbo->kptr; info->screen_size = radeon_bo_size(rbo); drm_fb_helper_fill_info(info, &rfbdev->helper, sizes); /* setup aperture base/size for vesafb takeover */ info->apertures->ranges[0].base = rdev->ddev->mode_config.fb_base; info->apertures->ranges[0].size = rdev->mc.aper_size; /* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */ if (info->screen_base == NULL) { ret = -ENOSPC; goto out; } DRM_INFO("fb mappable at 0x%lX\n", info->fix.smem_start); DRM_INFO("vram apper at 0x%lX\n", (unsigned long)rdev->mc.aper_base); DRM_INFO("size %lu\n", (unsigned long)radeon_bo_size(rbo)); DRM_INFO("fb depth is %d\n", fb->format->depth); DRM_INFO(" pitch is %d\n", fb->pitches[0]); vga_switcheroo_client_fb_set(rdev->ddev->pdev, info); return 0; out: if (rbo) { } if (fb && ret) { drm_gem_object_put_unlocked(gobj); drm_framebuffer_unregister_private(fb); drm_framebuffer_cleanup(fb); kfree(fb); } return ret; }