Merge tag 'topic/drm-misc-2015-08-13' of git://anongit.freedesktop.org/drm-intel into drm-next
Final drm-misc pull for 4.3: - fbdev emulation Kconfig option for everyone thanks to Archit. It's not everything yet bit this is fairly tricky since it spawns all drivers. - vgaarb & vgaswitcheroo polish from Thierry - some drm_irq.c cleanups (Thierry) - struct_mutex crusade from me - more fbdev panic handling removal - various things all over in drm core&helpers * tag 'topic/drm-misc-2015-08-13' of git://anongit.freedesktop.org/drm-intel: (65 commits) drm/atomic: Use KMS VBLANK API drm/irq: Document return values more consistently drm/irq: Make pipe unsigned and name consistent drm/irq: Check for valid VBLANK before dereference drm/irq: Remove negative CRTC index special-case drm/plane: Remove redundant extern drm/plane: Use consistent data types for format count vga_switcheroo: Remove unnecessary checks vga_switcheroo: Wrap overly long lines vga_switcheroo: Use pr_fmt() vga_switcheroo: Cleanup header comment vga_switcheroo: Use pr_*() instead of printk() vgaarb: Fix a few checkpatch errors and warnings vgaarb: Use vgaarb: prefix consistently in messages vgaarb: Stop complaining about absent devices drm/atomic: fix null pointer access to mode_fixup callback drm/i915: Use CONFIG_DRM_FBDEV_EMULATION drm/core: Set mode to NULL when connectors in a set drops to 0. drm/atomic: Call ww_acquire_done after check phase is complete drm/atomic: Paper over locking WARN in default_state_clear ...
This commit is contained in:
commit
1ce4200df0
@ -37,9 +37,29 @@ config DRM_KMS_FB_HELPER
|
||||
select FB
|
||||
select FRAMEBUFFER_CONSOLE if !EXPERT
|
||||
select FRAMEBUFFER_CONSOLE_DETECT_PRIMARY if FRAMEBUFFER_CONSOLE
|
||||
select FB_SYS_FOPS
|
||||
select FB_SYS_FILLRECT
|
||||
select FB_SYS_COPYAREA
|
||||
select FB_SYS_IMAGEBLIT
|
||||
select FB_CFB_FILLRECT
|
||||
select FB_CFB_COPYAREA
|
||||
select FB_CFB_IMAGEBLIT
|
||||
help
|
||||
FBDEV helpers for KMS drivers.
|
||||
|
||||
config DRM_FBDEV_EMULATION
|
||||
bool "Enable legacy fbdev support for your modesetting driver"
|
||||
depends on DRM
|
||||
select DRM_KMS_HELPER
|
||||
select DRM_KMS_FB_HELPER
|
||||
default y
|
||||
help
|
||||
Choose this option if you have a need for the legacy fbdev
|
||||
support. Note that this support also provides the linux console
|
||||
support on top of your modesetting driver.
|
||||
|
||||
If in doubt, say "Y".
|
||||
|
||||
config DRM_LOAD_EDID_FIRMWARE
|
||||
bool "Allow to specify an EDID data set instead of probing for it"
|
||||
depends on DRM_KMS_HELPER
|
||||
|
@ -23,7 +23,7 @@ drm-$(CONFIG_OF) += drm_of.o
|
||||
drm_kms_helper-y := drm_crtc_helper.o drm_dp_helper.o drm_probe_helper.o \
|
||||
drm_plane_helper.o drm_dp_mst_topology.o drm_atomic_helper.o
|
||||
drm_kms_helper-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o
|
||||
drm_kms_helper-$(CONFIG_DRM_KMS_FB_HELPER) += drm_fb_helper.o
|
||||
drm_kms_helper-$(CONFIG_DRM_FBDEV_EMULATION) += drm_fb_helper.o
|
||||
drm_kms_helper-$(CONFIG_DRM_KMS_CMA_HELPER) += drm_fb_cma_helper.o
|
||||
|
||||
obj-$(CONFIG_DRM_KMS_HELPER) += drm_kms_helper.o
|
||||
|
@ -53,9 +53,9 @@ static struct fb_ops amdgpufb_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.fb_check_var = drm_fb_helper_check_var,
|
||||
.fb_set_par = drm_fb_helper_set_par,
|
||||
.fb_fillrect = cfb_fillrect,
|
||||
.fb_copyarea = cfb_copyarea,
|
||||
.fb_imageblit = cfb_imageblit,
|
||||
.fb_fillrect = drm_fb_helper_cfb_fillrect,
|
||||
.fb_copyarea = drm_fb_helper_cfb_copyarea,
|
||||
.fb_imageblit = drm_fb_helper_cfb_imageblit,
|
||||
.fb_pan_display = drm_fb_helper_pan_display,
|
||||
.fb_blank = drm_fb_helper_blank,
|
||||
.fb_setcmap = drm_fb_helper_setcmap,
|
||||
@ -179,7 +179,6 @@ static int amdgpufb_create(struct drm_fb_helper *helper,
|
||||
struct drm_mode_fb_cmd2 mode_cmd;
|
||||
struct drm_gem_object *gobj = NULL;
|
||||
struct amdgpu_bo *rbo = NULL;
|
||||
struct device *device = &adev->pdev->dev;
|
||||
int ret;
|
||||
unsigned long tmp;
|
||||
|
||||
@ -201,9 +200,9 @@ static int amdgpufb_create(struct drm_fb_helper *helper,
|
||||
rbo = gem_to_amdgpu_bo(gobj);
|
||||
|
||||
/* okay we have an object now allocate the framebuffer */
|
||||
info = framebuffer_alloc(0, device);
|
||||
if (info == NULL) {
|
||||
ret = -ENOMEM;
|
||||
info = drm_fb_helper_alloc_fbi(helper);
|
||||
if (IS_ERR(info)) {
|
||||
ret = PTR_ERR(info);
|
||||
goto out_unref;
|
||||
}
|
||||
|
||||
@ -212,14 +211,13 @@ static int amdgpufb_create(struct drm_fb_helper *helper,
|
||||
ret = amdgpu_framebuffer_init(adev->ddev, &rfbdev->rfb, &mode_cmd, gobj);
|
||||
if (ret) {
|
||||
DRM_ERROR("failed to initialize framebuffer %d\n", ret);
|
||||
goto out_unref;
|
||||
goto out_destroy_fbi;
|
||||
}
|
||||
|
||||
fb = &rfbdev->rfb.base;
|
||||
|
||||
/* setup helper */
|
||||
rfbdev->helper.fb = fb;
|
||||
rfbdev->helper.fbdev = info;
|
||||
|
||||
memset_io(rbo->kptr, 0x0, amdgpu_bo_size(rbo));
|
||||
|
||||
@ -239,11 +237,6 @@ static int amdgpufb_create(struct drm_fb_helper *helper,
|
||||
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 = adev->ddev->mode_config.fb_base;
|
||||
info->apertures->ranges[0].size = adev->mc.aper_size;
|
||||
|
||||
@ -251,13 +244,7 @@ static int amdgpufb_create(struct drm_fb_helper *helper,
|
||||
|
||||
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;
|
||||
goto out_destroy_fbi;
|
||||
}
|
||||
|
||||
DRM_INFO("fb mappable at 0x%lX\n", info->fix.smem_start);
|
||||
@ -269,6 +256,8 @@ static int amdgpufb_create(struct drm_fb_helper *helper,
|
||||
vga_switcheroo_client_fb_set(adev->ddev->pdev, info);
|
||||
return 0;
|
||||
|
||||
out_destroy_fbi:
|
||||
drm_fb_helper_release_fbi(helper);
|
||||
out_unref:
|
||||
if (rbo) {
|
||||
|
||||
@ -290,17 +279,10 @@ void amdgpu_fb_output_poll_changed(struct amdgpu_device *adev)
|
||||
|
||||
static int amdgpu_fbdev_destroy(struct drm_device *dev, struct amdgpu_fbdev *rfbdev)
|
||||
{
|
||||
struct fb_info *info;
|
||||
struct amdgpu_framebuffer *rfb = &rfbdev->rfb;
|
||||
|
||||
if (rfbdev->helper.fbdev) {
|
||||
info = rfbdev->helper.fbdev;
|
||||
|
||||
unregister_framebuffer(info);
|
||||
if (info->cmap.len)
|
||||
fb_dealloc_cmap(&info->cmap);
|
||||
framebuffer_release(info);
|
||||
}
|
||||
drm_fb_helper_unregister_fbi(&rfbdev->helper);
|
||||
drm_fb_helper_release_fbi(&rfbdev->helper);
|
||||
|
||||
if (rfb->obj) {
|
||||
amdgpufb_destroy_pinned_object(rfb->obj);
|
||||
@ -395,7 +377,8 @@ void amdgpu_fbdev_fini(struct amdgpu_device *adev)
|
||||
void amdgpu_fbdev_set_suspend(struct amdgpu_device *adev, int state)
|
||||
{
|
||||
if (adev->mode_info.rfbdev)
|
||||
fb_set_suspend(adev->mode_info.rfbdev->helper.fbdev, state);
|
||||
drm_fb_helper_set_suspend(&adev->mode_info.rfbdev->helper,
|
||||
state);
|
||||
}
|
||||
|
||||
int amdgpu_fbdev_total_size(struct amdgpu_device *adev)
|
||||
|
@ -22,9 +22,9 @@ static /*const*/ struct fb_ops armada_fb_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.fb_check_var = drm_fb_helper_check_var,
|
||||
.fb_set_par = drm_fb_helper_set_par,
|
||||
.fb_fillrect = cfb_fillrect,
|
||||
.fb_copyarea = cfb_copyarea,
|
||||
.fb_imageblit = cfb_imageblit,
|
||||
.fb_fillrect = drm_fb_helper_cfb_fillrect,
|
||||
.fb_copyarea = drm_fb_helper_cfb_copyarea,
|
||||
.fb_imageblit = drm_fb_helper_cfb_imageblit,
|
||||
.fb_pan_display = drm_fb_helper_pan_display,
|
||||
.fb_blank = drm_fb_helper_blank,
|
||||
.fb_setcmap = drm_fb_helper_setcmap,
|
||||
@ -80,18 +80,12 @@ static int armada_fb_create(struct drm_fb_helper *fbh,
|
||||
if (IS_ERR(dfb))
|
||||
return PTR_ERR(dfb);
|
||||
|
||||
info = framebuffer_alloc(0, dev->dev);
|
||||
if (!info) {
|
||||
ret = -ENOMEM;
|
||||
info = drm_fb_helper_alloc_fbi(fbh);
|
||||
if (IS_ERR(info)) {
|
||||
ret = PTR_ERR(info);
|
||||
goto err_fballoc;
|
||||
}
|
||||
|
||||
ret = fb_alloc_cmap(&info->cmap, 256, 0);
|
||||
if (ret) {
|
||||
ret = -ENOMEM;
|
||||
goto err_fbcmap;
|
||||
}
|
||||
|
||||
strlcpy(info->fix.id, "armada-drmfb", sizeof(info->fix.id));
|
||||
info->par = fbh;
|
||||
info->flags = FBINFO_DEFAULT | FBINFO_CAN_FORCE_OUTPUT;
|
||||
@ -101,7 +95,7 @@ static int armada_fb_create(struct drm_fb_helper *fbh,
|
||||
info->screen_size = obj->obj.size;
|
||||
info->screen_base = ptr;
|
||||
fbh->fb = &dfb->fb;
|
||||
fbh->fbdev = info;
|
||||
|
||||
drm_fb_helper_fill_fix(info, dfb->fb.pitches[0], dfb->fb.depth);
|
||||
drm_fb_helper_fill_var(info, fbh, sizes->fb_width, sizes->fb_height);
|
||||
|
||||
@ -111,8 +105,6 @@ static int armada_fb_create(struct drm_fb_helper *fbh,
|
||||
|
||||
return 0;
|
||||
|
||||
err_fbcmap:
|
||||
framebuffer_release(info);
|
||||
err_fballoc:
|
||||
dfb->fb.funcs->destroy(&dfb->fb);
|
||||
return ret;
|
||||
@ -171,6 +163,7 @@ int armada_fbdev_init(struct drm_device *dev)
|
||||
|
||||
return 0;
|
||||
err_fb_setup:
|
||||
drm_fb_helper_release_fbi(fbh);
|
||||
drm_fb_helper_fini(fbh);
|
||||
err_fb_helper:
|
||||
priv->fbdev = NULL;
|
||||
@ -191,14 +184,8 @@ void armada_fbdev_fini(struct drm_device *dev)
|
||||
struct drm_fb_helper *fbh = priv->fbdev;
|
||||
|
||||
if (fbh) {
|
||||
struct fb_info *info = fbh->fbdev;
|
||||
|
||||
if (info) {
|
||||
unregister_framebuffer(info);
|
||||
if (info->cmap.len)
|
||||
fb_dealloc_cmap(&info->cmap);
|
||||
framebuffer_release(info);
|
||||
}
|
||||
drm_fb_helper_unregister_fbi(fbh);
|
||||
drm_fb_helper_release_fbi(fbh);
|
||||
|
||||
drm_fb_helper_fini(fbh);
|
||||
|
||||
|
@ -125,7 +125,7 @@ static void ast_fillrect(struct fb_info *info,
|
||||
const struct fb_fillrect *rect)
|
||||
{
|
||||
struct ast_fbdev *afbdev = info->par;
|
||||
sys_fillrect(info, rect);
|
||||
drm_fb_helper_sys_fillrect(info, rect);
|
||||
ast_dirty_update(afbdev, rect->dx, rect->dy, rect->width,
|
||||
rect->height);
|
||||
}
|
||||
@ -134,7 +134,7 @@ static void ast_copyarea(struct fb_info *info,
|
||||
const struct fb_copyarea *area)
|
||||
{
|
||||
struct ast_fbdev *afbdev = info->par;
|
||||
sys_copyarea(info, area);
|
||||
drm_fb_helper_sys_copyarea(info, area);
|
||||
ast_dirty_update(afbdev, area->dx, area->dy, area->width,
|
||||
area->height);
|
||||
}
|
||||
@ -143,7 +143,7 @@ static void ast_imageblit(struct fb_info *info,
|
||||
const struct fb_image *image)
|
||||
{
|
||||
struct ast_fbdev *afbdev = info->par;
|
||||
sys_imageblit(info, image);
|
||||
drm_fb_helper_sys_imageblit(info, image);
|
||||
ast_dirty_update(afbdev, image->dx, image->dy, image->width,
|
||||
image->height);
|
||||
}
|
||||
@ -193,7 +193,6 @@ static int astfb_create(struct drm_fb_helper *helper,
|
||||
struct drm_framebuffer *fb;
|
||||
struct fb_info *info;
|
||||
int size, ret;
|
||||
struct device *device = &dev->pdev->dev;
|
||||
void *sysram;
|
||||
struct drm_gem_object *gobj = NULL;
|
||||
struct ast_bo *bo = NULL;
|
||||
@ -217,40 +216,28 @@ static int astfb_create(struct drm_fb_helper *helper,
|
||||
if (!sysram)
|
||||
return -ENOMEM;
|
||||
|
||||
info = framebuffer_alloc(0, device);
|
||||
if (!info) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
info = drm_fb_helper_alloc_fbi(helper);
|
||||
if (IS_ERR(info)) {
|
||||
ret = PTR_ERR(info);
|
||||
goto err_free_vram;
|
||||
}
|
||||
info->par = afbdev;
|
||||
|
||||
ret = ast_framebuffer_init(dev, &afbdev->afb, &mode_cmd, gobj);
|
||||
if (ret)
|
||||
goto out;
|
||||
goto err_release_fbi;
|
||||
|
||||
afbdev->sysram = sysram;
|
||||
afbdev->size = size;
|
||||
|
||||
fb = &afbdev->afb.base;
|
||||
afbdev->helper.fb = fb;
|
||||
afbdev->helper.fbdev = info;
|
||||
|
||||
strcpy(info->fix.id, "astdrmfb");
|
||||
|
||||
info->flags = FBINFO_DEFAULT | FBINFO_CAN_FORCE_OUTPUT;
|
||||
info->fbops = &astfb_ops;
|
||||
|
||||
ret = fb_alloc_cmap(&info->cmap, 256, 0);
|
||||
if (ret) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
info->apertures = alloc_apertures(1);
|
||||
if (!info->apertures) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
info->apertures->ranges[0].base = pci_resource_start(dev->pdev, 0);
|
||||
info->apertures->ranges[0].size = pci_resource_len(dev->pdev, 0);
|
||||
|
||||
@ -266,7 +253,11 @@ static int astfb_create(struct drm_fb_helper *helper,
|
||||
fb->width, fb->height);
|
||||
|
||||
return 0;
|
||||
out:
|
||||
|
||||
err_release_fbi:
|
||||
drm_fb_helper_release_fbi(helper);
|
||||
err_free_vram:
|
||||
vfree(afbdev->sysram);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -297,15 +288,10 @@ static const struct drm_fb_helper_funcs ast_fb_helper_funcs = {
|
||||
static void ast_fbdev_destroy(struct drm_device *dev,
|
||||
struct ast_fbdev *afbdev)
|
||||
{
|
||||
struct fb_info *info;
|
||||
struct ast_framebuffer *afb = &afbdev->afb;
|
||||
if (afbdev->helper.fbdev) {
|
||||
info = afbdev->helper.fbdev;
|
||||
unregister_framebuffer(info);
|
||||
if (info->cmap.len)
|
||||
fb_dealloc_cmap(&info->cmap);
|
||||
framebuffer_release(info);
|
||||
}
|
||||
|
||||
drm_fb_helper_unregister_fbi(&afbdev->helper);
|
||||
drm_fb_helper_release_fbi(&afbdev->helper);
|
||||
|
||||
if (afb->obj) {
|
||||
drm_gem_object_unreference_unlocked(afb->obj);
|
||||
@ -377,5 +363,5 @@ void ast_fbdev_set_suspend(struct drm_device *dev, int state)
|
||||
if (!ast->fbdev)
|
||||
return;
|
||||
|
||||
fb_set_suspend(ast->fbdev->helper.fbdev, state);
|
||||
drm_fb_helper_set_suspend(&ast->fbdev->helper, state);
|
||||
}
|
||||
|
@ -571,24 +571,18 @@ ast_dumb_mmap_offset(struct drm_file *file,
|
||||
uint64_t *offset)
|
||||
{
|
||||
struct drm_gem_object *obj;
|
||||
int ret;
|
||||
struct ast_bo *bo;
|
||||
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
obj = drm_gem_object_lookup(dev, file, handle);
|
||||
if (obj == NULL) {
|
||||
ret = -ENOENT;
|
||||
goto out_unlock;
|
||||
}
|
||||
if (obj == NULL)
|
||||
return -ENOENT;
|
||||
|
||||
bo = gem_to_ast_bo(obj);
|
||||
*offset = ast_bo_mmap_offset(bo);
|
||||
|
||||
drm_gem_object_unreference(obj);
|
||||
ret = 0;
|
||||
out_unlock:
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
return ret;
|
||||
drm_gem_object_unreference_unlocked(obj);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
@ -109,7 +109,7 @@ static int bochs_pm_suspend(struct device *dev)
|
||||
|
||||
if (bochs->fb.initialized) {
|
||||
console_lock();
|
||||
fb_set_suspend(bochs->fb.helper.fbdev, 1);
|
||||
drm_fb_helper_set_suspend(&bochs->fb.helper, 1);
|
||||
console_unlock();
|
||||
}
|
||||
|
||||
@ -126,7 +126,7 @@ static int bochs_pm_resume(struct device *dev)
|
||||
|
||||
if (bochs->fb.initialized) {
|
||||
console_lock();
|
||||
fb_set_suspend(bochs->fb.helper.fbdev, 0);
|
||||
drm_fb_helper_set_suspend(&bochs->fb.helper, 0);
|
||||
console_unlock();
|
||||
}
|
||||
|
||||
|
@ -24,9 +24,9 @@ static struct fb_ops bochsfb_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.fb_check_var = drm_fb_helper_check_var,
|
||||
.fb_set_par = drm_fb_helper_set_par,
|
||||
.fb_fillrect = sys_fillrect,
|
||||
.fb_copyarea = sys_copyarea,
|
||||
.fb_imageblit = sys_imageblit,
|
||||
.fb_fillrect = drm_fb_helper_sys_fillrect,
|
||||
.fb_copyarea = drm_fb_helper_sys_copyarea,
|
||||
.fb_imageblit = drm_fb_helper_sys_imageblit,
|
||||
.fb_pan_display = drm_fb_helper_pan_display,
|
||||
.fb_blank = drm_fb_helper_blank,
|
||||
.fb_setcmap = drm_fb_helper_setcmap,
|
||||
@ -56,11 +56,9 @@ static int bochsfb_create(struct drm_fb_helper *helper,
|
||||
{
|
||||
struct bochs_device *bochs =
|
||||
container_of(helper, struct bochs_device, fb.helper);
|
||||
struct drm_device *dev = bochs->dev;
|
||||
struct fb_info *info;
|
||||
struct drm_framebuffer *fb;
|
||||
struct drm_mode_fb_cmd2 mode_cmd;
|
||||
struct device *device = &dev->pdev->dev;
|
||||
struct drm_gem_object *gobj = NULL;
|
||||
struct bochs_bo *bo = NULL;
|
||||
int size, ret;
|
||||
@ -106,22 +104,23 @@ static int bochsfb_create(struct drm_fb_helper *helper,
|
||||
ttm_bo_unreserve(&bo->bo);
|
||||
|
||||
/* init fb device */
|
||||
info = framebuffer_alloc(0, device);
|
||||
if (info == NULL)
|
||||
return -ENOMEM;
|
||||
info = drm_fb_helper_alloc_fbi(helper);
|
||||
if (IS_ERR(info))
|
||||
return PTR_ERR(info);
|
||||
|
||||
info->par = &bochs->fb.helper;
|
||||
|
||||
ret = bochs_framebuffer_init(bochs->dev, &bochs->fb.gfb, &mode_cmd, gobj);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
drm_fb_helper_release_fbi(helper);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bochs->fb.size = size;
|
||||
|
||||
/* setup helper */
|
||||
fb = &bochs->fb.gfb.base;
|
||||
bochs->fb.helper.fb = fb;
|
||||
bochs->fb.helper.fbdev = info;
|
||||
|
||||
strcpy(info->fix.id, "bochsdrmfb");
|
||||
|
||||
@ -139,30 +138,17 @@ static int bochsfb_create(struct drm_fb_helper *helper,
|
||||
info->fix.smem_start = 0;
|
||||
info->fix.smem_len = size;
|
||||
|
||||
ret = fb_alloc_cmap(&info->cmap, 256, 0);
|
||||
if (ret) {
|
||||
DRM_ERROR("%s: can't allocate color map\n", info->fix.id);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bochs_fbdev_destroy(struct bochs_device *bochs)
|
||||
{
|
||||
struct bochs_framebuffer *gfb = &bochs->fb.gfb;
|
||||
struct fb_info *info;
|
||||
|
||||
DRM_DEBUG_DRIVER("\n");
|
||||
|
||||
if (bochs->fb.helper.fbdev) {
|
||||
info = bochs->fb.helper.fbdev;
|
||||
|
||||
unregister_framebuffer(info);
|
||||
if (info->cmap.len)
|
||||
fb_dealloc_cmap(&info->cmap);
|
||||
framebuffer_release(info);
|
||||
}
|
||||
drm_fb_helper_unregister_fbi(&bochs->fb.helper);
|
||||
drm_fb_helper_release_fbi(&bochs->fb.helper);
|
||||
|
||||
if (gfb->obj) {
|
||||
drm_gem_object_unreference_unlocked(gfb->obj);
|
||||
|
@ -454,25 +454,17 @@ int bochs_dumb_mmap_offset(struct drm_file *file, struct drm_device *dev,
|
||||
uint32_t handle, uint64_t *offset)
|
||||
{
|
||||
struct drm_gem_object *obj;
|
||||
int ret;
|
||||
struct bochs_bo *bo;
|
||||
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
obj = drm_gem_object_lookup(dev, file, handle);
|
||||
if (obj == NULL) {
|
||||
ret = -ENOENT;
|
||||
goto out_unlock;
|
||||
}
|
||||
if (obj == NULL)
|
||||
return -ENOENT;
|
||||
|
||||
bo = gem_to_bochs_bo(obj);
|
||||
*offset = bochs_bo_mmap_offset(bo);
|
||||
|
||||
drm_gem_object_unreference(obj);
|
||||
ret = 0;
|
||||
out_unlock:
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
return ret;
|
||||
|
||||
drm_gem_object_unreference_unlocked(obj);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
@ -92,7 +92,7 @@ static int cirrus_pm_suspend(struct device *dev)
|
||||
|
||||
if (cdev->mode_info.gfbdev) {
|
||||
console_lock();
|
||||
fb_set_suspend(cdev->mode_info.gfbdev->helper.fbdev, 1);
|
||||
drm_fb_helper_set_suspend(&cdev->mode_info.gfbdev->helper, 1);
|
||||
console_unlock();
|
||||
}
|
||||
|
||||
@ -109,7 +109,7 @@ static int cirrus_pm_resume(struct device *dev)
|
||||
|
||||
if (cdev->mode_info.gfbdev) {
|
||||
console_lock();
|
||||
fb_set_suspend(cdev->mode_info.gfbdev->helper.fbdev, 0);
|
||||
drm_fb_helper_set_suspend(&cdev->mode_info.gfbdev->helper, 0);
|
||||
console_unlock();
|
||||
}
|
||||
|
||||
|
@ -98,7 +98,7 @@ static void cirrus_fillrect(struct fb_info *info,
|
||||
const struct fb_fillrect *rect)
|
||||
{
|
||||
struct cirrus_fbdev *afbdev = info->par;
|
||||
sys_fillrect(info, rect);
|
||||
drm_fb_helper_sys_fillrect(info, rect);
|
||||
cirrus_dirty_update(afbdev, rect->dx, rect->dy, rect->width,
|
||||
rect->height);
|
||||
}
|
||||
@ -107,7 +107,7 @@ static void cirrus_copyarea(struct fb_info *info,
|
||||
const struct fb_copyarea *area)
|
||||
{
|
||||
struct cirrus_fbdev *afbdev = info->par;
|
||||
sys_copyarea(info, area);
|
||||
drm_fb_helper_sys_copyarea(info, area);
|
||||
cirrus_dirty_update(afbdev, area->dx, area->dy, area->width,
|
||||
area->height);
|
||||
}
|
||||
@ -116,7 +116,7 @@ static void cirrus_imageblit(struct fb_info *info,
|
||||
const struct fb_image *image)
|
||||
{
|
||||
struct cirrus_fbdev *afbdev = info->par;
|
||||
sys_imageblit(info, image);
|
||||
drm_fb_helper_sys_imageblit(info, image);
|
||||
cirrus_dirty_update(afbdev, image->dx, image->dy, image->width,
|
||||
image->height);
|
||||
}
|
||||
@ -165,12 +165,10 @@ static int cirrusfb_create(struct drm_fb_helper *helper,
|
||||
{
|
||||
struct cirrus_fbdev *gfbdev =
|
||||
container_of(helper, struct cirrus_fbdev, helper);
|
||||
struct drm_device *dev = gfbdev->helper.dev;
|
||||
struct cirrus_device *cdev = gfbdev->helper.dev->dev_private;
|
||||
struct fb_info *info;
|
||||
struct drm_framebuffer *fb;
|
||||
struct drm_mode_fb_cmd2 mode_cmd;
|
||||
struct device *device = &dev->pdev->dev;
|
||||
void *sysram;
|
||||
struct drm_gem_object *gobj = NULL;
|
||||
struct cirrus_bo *bo = NULL;
|
||||
@ -195,9 +193,9 @@ static int cirrusfb_create(struct drm_fb_helper *helper,
|
||||
if (!sysram)
|
||||
return -ENOMEM;
|
||||
|
||||
info = framebuffer_alloc(0, device);
|
||||
if (info == NULL)
|
||||
return -ENOMEM;
|
||||
info = drm_fb_helper_alloc_fbi(helper);
|
||||
if (IS_ERR(info))
|
||||
return PTR_ERR(info);
|
||||
|
||||
info->par = gfbdev;
|
||||
|
||||
@ -216,11 +214,9 @@ static int cirrusfb_create(struct drm_fb_helper *helper,
|
||||
|
||||
/* setup helper */
|
||||
gfbdev->helper.fb = fb;
|
||||
gfbdev->helper.fbdev = info;
|
||||
|
||||
strcpy(info->fix.id, "cirrusdrmfb");
|
||||
|
||||
|
||||
info->flags = FBINFO_DEFAULT;
|
||||
info->fbops = &cirrusfb_ops;
|
||||
|
||||
@ -229,11 +225,6 @@ static int cirrusfb_create(struct drm_fb_helper *helper,
|
||||
sizes->fb_height);
|
||||
|
||||
/* setup aperture base/size for vesafb takeover */
|
||||
info->apertures = alloc_apertures(1);
|
||||
if (!info->apertures) {
|
||||
ret = -ENOMEM;
|
||||
goto out_iounmap;
|
||||
}
|
||||
info->apertures->ranges[0].base = cdev->dev->mode_config.fb_base;
|
||||
info->apertures->ranges[0].size = cdev->mc.vram_size;
|
||||
|
||||
@ -246,13 +237,6 @@ static int cirrusfb_create(struct drm_fb_helper *helper,
|
||||
info->fix.mmio_start = 0;
|
||||
info->fix.mmio_len = 0;
|
||||
|
||||
ret = fb_alloc_cmap(&info->cmap, 256, 0);
|
||||
if (ret) {
|
||||
DRM_ERROR("%s: can't allocate color map\n", info->fix.id);
|
||||
ret = -ENOMEM;
|
||||
goto out_iounmap;
|
||||
}
|
||||
|
||||
DRM_INFO("fb mappable at 0x%lX\n", info->fix.smem_start);
|
||||
DRM_INFO("vram aper at 0x%lX\n", (unsigned long)info->fix.smem_start);
|
||||
DRM_INFO("size %lu\n", (unsigned long)info->fix.smem_len);
|
||||
@ -260,24 +244,15 @@ static int cirrusfb_create(struct drm_fb_helper *helper,
|
||||
DRM_INFO(" pitch is %d\n", fb->pitches[0]);
|
||||
|
||||
return 0;
|
||||
out_iounmap:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int cirrus_fbdev_destroy(struct drm_device *dev,
|
||||
struct cirrus_fbdev *gfbdev)
|
||||
{
|
||||
struct fb_info *info;
|
||||
struct cirrus_framebuffer *gfb = &gfbdev->gfb;
|
||||
|
||||
if (gfbdev->helper.fbdev) {
|
||||
info = gfbdev->helper.fbdev;
|
||||
|
||||
unregister_framebuffer(info);
|
||||
if (info->cmap.len)
|
||||
fb_dealloc_cmap(&info->cmap);
|
||||
framebuffer_release(info);
|
||||
}
|
||||
drm_fb_helper_unregister_fbi(&gfbdev->helper);
|
||||
drm_fb_helper_release_fbi(&gfbdev->helper);
|
||||
|
||||
if (gfb->obj) {
|
||||
drm_gem_object_unreference_unlocked(gfb->obj);
|
||||
|
@ -293,25 +293,18 @@ cirrus_dumb_mmap_offset(struct drm_file *file,
|
||||
uint64_t *offset)
|
||||
{
|
||||
struct drm_gem_object *obj;
|
||||
int ret;
|
||||
struct cirrus_bo *bo;
|
||||
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
obj = drm_gem_object_lookup(dev, file, handle);
|
||||
if (obj == NULL) {
|
||||
ret = -ENOENT;
|
||||
goto out_unlock;
|
||||
}
|
||||
if (obj == NULL)
|
||||
return -ENOENT;
|
||||
|
||||
bo = gem_to_cirrus_bo(obj);
|
||||
*offset = cirrus_bo_mmap_offset(bo);
|
||||
|
||||
drm_gem_object_unreference(obj);
|
||||
ret = 0;
|
||||
out_unlock:
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
return ret;
|
||||
drm_gem_object_unreference_unlocked(obj);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool cirrus_check_framebuffer(struct cirrus_device *cdev, int width, int height,
|
||||
|
@ -153,9 +153,15 @@ void drm_atomic_state_default_clear(struct drm_atomic_state *state)
|
||||
if (!connector)
|
||||
continue;
|
||||
|
||||
WARN_ON(!drm_modeset_is_locked(&config->connection_mutex));
|
||||
|
||||
connector->funcs->atomic_destroy_state(connector,
|
||||
/*
|
||||
* FIXME: Async commits can race with connector unplugging and
|
||||
* there's currently nothing that prevents cleanup up state for
|
||||
* deleted connectors. As long as the callback doesn't look at
|
||||
* the connector we'll be fine though, so make sure that's the
|
||||
* case by setting all connector pointers to NULL.
|
||||
*/
|
||||
state->connector_states[i]->connector = NULL;
|
||||
connector->funcs->atomic_destroy_state(NULL,
|
||||
state->connector_states[i]);
|
||||
state->connectors[i] = NULL;
|
||||
state->connector_states[i] = NULL;
|
||||
@ -1224,6 +1230,9 @@ int drm_atomic_check_only(struct drm_atomic_state *state)
|
||||
}
|
||||
}
|
||||
|
||||
if (ret == 0)
|
||||
ww_acquire_done(&state->acquire_ctx->ww_ctx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_atomic_check_only);
|
||||
|
@ -299,7 +299,7 @@ mode_fixup(struct drm_atomic_state *state)
|
||||
encoder->base.id, encoder->name);
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
} else if (funcs->mode_fixup) {
|
||||
ret = funcs->mode_fixup(encoder, &crtc_state->mode,
|
||||
&crtc_state->adjusted_mode);
|
||||
if (!ret) {
|
||||
@ -958,7 +958,7 @@ drm_atomic_helper_wait_for_vblanks(struct drm_device *dev,
|
||||
continue;
|
||||
|
||||
old_crtc_state->enable = true;
|
||||
old_crtc_state->last_vblank_count = drm_vblank_count(dev, i);
|
||||
old_crtc_state->last_vblank_count = drm_crtc_vblank_count(crtc);
|
||||
}
|
||||
|
||||
for_each_crtc_in_state(old_state, crtc, old_crtc_state, i) {
|
||||
@ -967,7 +967,7 @@ drm_atomic_helper_wait_for_vblanks(struct drm_device *dev,
|
||||
|
||||
ret = wait_event_timeout(dev->vblank[i].queue,
|
||||
old_crtc_state->last_vblank_count !=
|
||||
drm_vblank_count(dev, i),
|
||||
drm_crtc_vblank_count(crtc),
|
||||
msecs_to_jiffies(50));
|
||||
|
||||
drm_crtc_vblank_put(crtc);
|
||||
|
@ -1151,7 +1151,7 @@ EXPORT_SYMBOL(drm_encoder_cleanup);
|
||||
int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane,
|
||||
unsigned long possible_crtcs,
|
||||
const struct drm_plane_funcs *funcs,
|
||||
const uint32_t *formats, uint32_t format_count,
|
||||
const uint32_t *formats, unsigned int format_count,
|
||||
enum drm_plane_type type)
|
||||
{
|
||||
struct drm_mode_config *config = &dev->mode_config;
|
||||
@ -1225,7 +1225,7 @@ EXPORT_SYMBOL(drm_universal_plane_init);
|
||||
int drm_plane_init(struct drm_device *dev, struct drm_plane *plane,
|
||||
unsigned long possible_crtcs,
|
||||
const struct drm_plane_funcs *funcs,
|
||||
const uint32_t *formats, uint32_t format_count,
|
||||
const uint32_t *formats, unsigned int format_count,
|
||||
bool is_primary)
|
||||
{
|
||||
enum drm_plane_type type;
|
||||
@ -5273,12 +5273,14 @@ void drm_mode_config_reset(struct drm_device *dev)
|
||||
if (encoder->funcs->reset)
|
||||
encoder->funcs->reset(encoder);
|
||||
|
||||
mutex_lock(&dev->mode_config.mutex);
|
||||
drm_for_each_connector(connector, dev) {
|
||||
connector->status = connector_status_unknown;
|
||||
|
||||
if (connector->funcs->reset)
|
||||
connector->funcs->reset(connector);
|
||||
}
|
||||
mutex_unlock(&dev->mode_config.mutex);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_mode_config_reset);
|
||||
|
||||
|
@ -3802,7 +3802,7 @@ int drm_add_modes_noedid(struct drm_connector *connector,
|
||||
struct drm_display_mode *mode;
|
||||
struct drm_device *dev = connector->dev;
|
||||
|
||||
count = sizeof(drm_dmt_modes) / sizeof(struct drm_display_mode);
|
||||
count = ARRAY_SIZE(drm_dmt_modes);
|
||||
if (hdisplay < 0)
|
||||
hdisplay = 0;
|
||||
if (vdisplay < 0)
|
||||
|
@ -222,9 +222,9 @@ EXPORT_SYMBOL_GPL(drm_fb_cma_debugfs_show);
|
||||
|
||||
static struct fb_ops drm_fbdev_cma_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.fb_fillrect = sys_fillrect,
|
||||
.fb_copyarea = sys_copyarea,
|
||||
.fb_imageblit = sys_imageblit,
|
||||
.fb_fillrect = drm_fb_helper_sys_fillrect,
|
||||
.fb_copyarea = drm_fb_helper_sys_copyarea,
|
||||
.fb_imageblit = drm_fb_helper_sys_imageblit,
|
||||
.fb_check_var = drm_fb_helper_check_var,
|
||||
.fb_set_par = drm_fb_helper_set_par,
|
||||
.fb_blank = drm_fb_helper_blank,
|
||||
@ -263,10 +263,9 @@ static int drm_fbdev_cma_create(struct drm_fb_helper *helper,
|
||||
if (IS_ERR(obj))
|
||||
return -ENOMEM;
|
||||
|
||||
fbi = framebuffer_alloc(0, dev->dev);
|
||||
if (!fbi) {
|
||||
dev_err(dev->dev, "Failed to allocate framebuffer info.\n");
|
||||
ret = -ENOMEM;
|
||||
fbi = drm_fb_helper_alloc_fbi(helper);
|
||||
if (IS_ERR(fbi)) {
|
||||
ret = PTR_ERR(fbi);
|
||||
goto err_drm_gem_cma_free_object;
|
||||
}
|
||||
|
||||
@ -274,23 +273,16 @@ static int drm_fbdev_cma_create(struct drm_fb_helper *helper,
|
||||
if (IS_ERR(fbdev_cma->fb)) {
|
||||
dev_err(dev->dev, "Failed to allocate DRM framebuffer.\n");
|
||||
ret = PTR_ERR(fbdev_cma->fb);
|
||||
goto err_framebuffer_release;
|
||||
goto err_fb_info_destroy;
|
||||
}
|
||||
|
||||
fb = &fbdev_cma->fb->fb;
|
||||
helper->fb = fb;
|
||||
helper->fbdev = fbi;
|
||||
|
||||
fbi->par = helper;
|
||||
fbi->flags = FBINFO_FLAG_DEFAULT;
|
||||
fbi->fbops = &drm_fbdev_cma_ops;
|
||||
|
||||
ret = fb_alloc_cmap(&fbi->cmap, 256, 0);
|
||||
if (ret) {
|
||||
dev_err(dev->dev, "Failed to allocate color map.\n");
|
||||
goto err_drm_fb_cma_destroy;
|
||||
}
|
||||
|
||||
drm_fb_helper_fill_fix(fbi, fb->pitches[0], fb->depth);
|
||||
drm_fb_helper_fill_var(fbi, helper, sizes->fb_width, sizes->fb_height);
|
||||
|
||||
@ -305,11 +297,8 @@ static int drm_fbdev_cma_create(struct drm_fb_helper *helper,
|
||||
|
||||
return 0;
|
||||
|
||||
err_drm_fb_cma_destroy:
|
||||
drm_framebuffer_unregister_private(fb);
|
||||
drm_fb_cma_destroy(fb);
|
||||
err_framebuffer_release:
|
||||
framebuffer_release(fbi);
|
||||
err_fb_info_destroy:
|
||||
drm_fb_helper_release_fbi(helper);
|
||||
err_drm_gem_cma_free_object:
|
||||
drm_gem_cma_free_object(&obj->base);
|
||||
return ret;
|
||||
@ -385,20 +374,8 @@ EXPORT_SYMBOL_GPL(drm_fbdev_cma_init);
|
||||
*/
|
||||
void drm_fbdev_cma_fini(struct drm_fbdev_cma *fbdev_cma)
|
||||
{
|
||||
if (fbdev_cma->fb_helper.fbdev) {
|
||||
struct fb_info *info;
|
||||
int ret;
|
||||
|
||||
info = fbdev_cma->fb_helper.fbdev;
|
||||
ret = unregister_framebuffer(info);
|
||||
if (ret < 0)
|
||||
DRM_DEBUG_KMS("failed unregister_framebuffer()\n");
|
||||
|
||||
if (info->cmap.len)
|
||||
fb_dealloc_cmap(&info->cmap);
|
||||
|
||||
framebuffer_release(info);
|
||||
}
|
||||
drm_fb_helper_unregister_fbi(&fbdev_cma->fb_helper);
|
||||
drm_fb_helper_release_fbi(&fbdev_cma->fb_helper);
|
||||
|
||||
if (fbdev_cma->fb) {
|
||||
drm_framebuffer_unregister_private(&fbdev_cma->fb->fb);
|
||||
|
@ -56,8 +56,8 @@ static LIST_HEAD(kernel_fb_helper_list);
|
||||
* Teardown is done with drm_fb_helper_fini().
|
||||
*
|
||||
* At runtime drivers should restore the fbdev console by calling
|
||||
* drm_fb_helper_restore_fbdev_mode() from their ->lastclose callback. They
|
||||
* should also notify the fb helper code from updates to the output
|
||||
* drm_fb_helper_restore_fbdev_mode_unlocked() from their ->lastclose callback.
|
||||
* They should also notify the fb helper code from updates to the output
|
||||
* configuration by calling drm_fb_helper_hotplug_event(). For easier
|
||||
* integration with the output polling code in drm_crtc_helper.c the modeset
|
||||
* code provides a ->output_poll_changed callback.
|
||||
@ -168,11 +168,14 @@ static void remove_from_modeset(struct drm_mode_set *set,
|
||||
}
|
||||
set->num_connectors--;
|
||||
|
||||
/* because i915 is pissy about this..
|
||||
/*
|
||||
* TODO maybe need to makes sure we set it back to !=NULL somewhere?
|
||||
*/
|
||||
if (set->num_connectors == 0)
|
||||
if (set->num_connectors == 0) {
|
||||
set->fb = NULL;
|
||||
drm_mode_destroy(connector->dev, set->mode);
|
||||
set->mode = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper,
|
||||
@ -354,21 +357,6 @@ static bool restore_fbdev_mode(struct drm_fb_helper *fb_helper)
|
||||
}
|
||||
return error;
|
||||
}
|
||||
/**
|
||||
* drm_fb_helper_restore_fbdev_mode - restore fbdev configuration
|
||||
* @fb_helper: fbcon to restore
|
||||
*
|
||||
* This should be called from driver's drm ->lastclose callback
|
||||
* when implementing an fbcon on top of kms using this helper. This ensures that
|
||||
* the user isn't greeted with a black screen when e.g. X dies.
|
||||
*
|
||||
* Use this variant if you need to bypass locking (panic), or already
|
||||
* hold all modeset locks. Otherwise use drm_fb_helper_restore_fbdev_mode_unlocked()
|
||||
*/
|
||||
static bool drm_fb_helper_restore_fbdev_mode(struct drm_fb_helper *fb_helper)
|
||||
{
|
||||
return restore_fbdev_mode(fb_helper);
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_fb_helper_restore_fbdev_mode_unlocked - restore fbdev configuration
|
||||
@ -398,42 +386,6 @@ bool drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper)
|
||||
}
|
||||
EXPORT_SYMBOL(drm_fb_helper_restore_fbdev_mode_unlocked);
|
||||
|
||||
/*
|
||||
* restore fbcon display for all kms driver's using this helper, used for sysrq
|
||||
* and panic handling.
|
||||
*/
|
||||
static bool drm_fb_helper_force_kernel_mode(void)
|
||||
{
|
||||
bool ret, error = false;
|
||||
struct drm_fb_helper *helper;
|
||||
|
||||
if (list_empty(&kernel_fb_helper_list))
|
||||
return false;
|
||||
|
||||
list_for_each_entry(helper, &kernel_fb_helper_list, kernel_fb_list) {
|
||||
struct drm_device *dev = helper->dev;
|
||||
|
||||
if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* NOTE: Use trylock mode to avoid deadlocks and sleeping in
|
||||
* panic context.
|
||||
*/
|
||||
if (__drm_modeset_lock_all(dev, true) != 0) {
|
||||
error = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
ret = drm_fb_helper_restore_fbdev_mode(helper);
|
||||
if (ret)
|
||||
error = true;
|
||||
|
||||
drm_modeset_unlock_all(dev);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
static bool drm_fb_helper_is_bound(struct drm_fb_helper *fb_helper)
|
||||
{
|
||||
struct drm_device *dev = fb_helper->dev;
|
||||
@ -459,6 +411,33 @@ static bool drm_fb_helper_is_bound(struct drm_fb_helper *fb_helper)
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MAGIC_SYSRQ
|
||||
/*
|
||||
* restore fbcon display for all kms driver's using this helper, used for sysrq
|
||||
* and panic handling.
|
||||
*/
|
||||
static bool drm_fb_helper_force_kernel_mode(void)
|
||||
{
|
||||
bool ret, error = false;
|
||||
struct drm_fb_helper *helper;
|
||||
|
||||
if (list_empty(&kernel_fb_helper_list))
|
||||
return false;
|
||||
|
||||
list_for_each_entry(helper, &kernel_fb_helper_list, kernel_fb_list) {
|
||||
struct drm_device *dev = helper->dev;
|
||||
|
||||
if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
|
||||
continue;
|
||||
|
||||
drm_modeset_lock_all(dev);
|
||||
ret = restore_fbdev_mode(helper);
|
||||
if (ret)
|
||||
error = true;
|
||||
drm_modeset_unlock_all(dev);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
static void drm_fb_helper_restore_work_fn(struct work_struct *ignored)
|
||||
{
|
||||
bool ret;
|
||||
@ -490,14 +469,6 @@ static void drm_fb_helper_dpms(struct fb_info *info, int dpms_mode)
|
||||
struct drm_connector *connector;
|
||||
int i, j;
|
||||
|
||||
/*
|
||||
* fbdev->blank can be called from irq context in case of a panic.
|
||||
* Since we already have our own special panic handler which will
|
||||
* restore the fbdev console mode completely, just bail out early.
|
||||
*/
|
||||
if (oops_in_progress)
|
||||
return;
|
||||
|
||||
/*
|
||||
* For each CRTC in this fb, turn the connectors on/off.
|
||||
*/
|
||||
@ -531,6 +502,9 @@ static void drm_fb_helper_dpms(struct fb_info *info, int dpms_mode)
|
||||
*/
|
||||
int drm_fb_helper_blank(int blank, struct fb_info *info)
|
||||
{
|
||||
if (oops_in_progress)
|
||||
return -EBUSY;
|
||||
|
||||
switch (blank) {
|
||||
/* Display: On; HSync: On, VSync: On */
|
||||
case FB_BLANK_UNBLANK:
|
||||
@ -654,6 +628,86 @@ out_free:
|
||||
}
|
||||
EXPORT_SYMBOL(drm_fb_helper_init);
|
||||
|
||||
/**
|
||||
* drm_fb_helper_alloc_fbi - allocate fb_info and some of its members
|
||||
* @fb_helper: driver-allocated fbdev helper
|
||||
*
|
||||
* A helper to alloc fb_info and the members cmap and apertures. Called
|
||||
* by the driver within the fb_probe fb_helper callback function.
|
||||
*
|
||||
* RETURNS:
|
||||
* fb_info pointer if things went okay, pointer containing error code
|
||||
* otherwise
|
||||
*/
|
||||
struct fb_info *drm_fb_helper_alloc_fbi(struct drm_fb_helper *fb_helper)
|
||||
{
|
||||
struct device *dev = fb_helper->dev->dev;
|
||||
struct fb_info *info;
|
||||
int ret;
|
||||
|
||||
info = framebuffer_alloc(0, dev);
|
||||
if (!info)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
ret = fb_alloc_cmap(&info->cmap, 256, 0);
|
||||
if (ret)
|
||||
goto err_release;
|
||||
|
||||
info->apertures = alloc_apertures(1);
|
||||
if (!info->apertures) {
|
||||
ret = -ENOMEM;
|
||||
goto err_free_cmap;
|
||||
}
|
||||
|
||||
fb_helper->fbdev = info;
|
||||
|
||||
return info;
|
||||
|
||||
err_free_cmap:
|
||||
fb_dealloc_cmap(&info->cmap);
|
||||
err_release:
|
||||
framebuffer_release(info);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_fb_helper_alloc_fbi);
|
||||
|
||||
/**
|
||||
* drm_fb_helper_unregister_fbi - unregister fb_info framebuffer device
|
||||
* @fb_helper: driver-allocated fbdev helper
|
||||
*
|
||||
* A wrapper around unregister_framebuffer, to release the fb_info
|
||||
* framebuffer device
|
||||
*/
|
||||
void drm_fb_helper_unregister_fbi(struct drm_fb_helper *fb_helper)
|
||||
{
|
||||
if (fb_helper && fb_helper->fbdev)
|
||||
unregister_framebuffer(fb_helper->fbdev);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_fb_helper_unregister_fbi);
|
||||
|
||||
/**
|
||||
* drm_fb_helper_release_fbi - dealloc fb_info and its members
|
||||
* @fb_helper: driver-allocated fbdev helper
|
||||
*
|
||||
* A helper to free memory taken by fb_info and the members cmap and
|
||||
* apertures
|
||||
*/
|
||||
void drm_fb_helper_release_fbi(struct drm_fb_helper *fb_helper)
|
||||
{
|
||||
if (fb_helper) {
|
||||
struct fb_info *info = fb_helper->fbdev;
|
||||
|
||||
if (info) {
|
||||
if (info->cmap.len)
|
||||
fb_dealloc_cmap(&info->cmap);
|
||||
framebuffer_release(info);
|
||||
}
|
||||
|
||||
fb_helper->fbdev = NULL;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(drm_fb_helper_release_fbi);
|
||||
|
||||
void drm_fb_helper_fini(struct drm_fb_helper *fb_helper)
|
||||
{
|
||||
if (!list_empty(&fb_helper->kernel_fb_list)) {
|
||||
@ -668,6 +722,149 @@ void drm_fb_helper_fini(struct drm_fb_helper *fb_helper)
|
||||
}
|
||||
EXPORT_SYMBOL(drm_fb_helper_fini);
|
||||
|
||||
/**
|
||||
* drm_fb_helper_unlink_fbi - wrapper around unlink_framebuffer
|
||||
* @fb_helper: driver-allocated fbdev helper
|
||||
*
|
||||
* A wrapper around unlink_framebuffer implemented by fbdev core
|
||||
*/
|
||||
void drm_fb_helper_unlink_fbi(struct drm_fb_helper *fb_helper)
|
||||
{
|
||||
if (fb_helper && fb_helper->fbdev)
|
||||
unlink_framebuffer(fb_helper->fbdev);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_fb_helper_unlink_fbi);
|
||||
|
||||
/**
|
||||
* drm_fb_helper_sys_read - wrapper around fb_sys_read
|
||||
* @info: fb_info struct pointer
|
||||
* @buf: userspace buffer to read from framebuffer memory
|
||||
* @count: number of bytes to read from framebuffer memory
|
||||
* @ppos: read offset within framebuffer memory
|
||||
*
|
||||
* A wrapper around fb_sys_read implemented by fbdev core
|
||||
*/
|
||||
ssize_t drm_fb_helper_sys_read(struct fb_info *info, char __user *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
return fb_sys_read(info, buf, count, ppos);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_fb_helper_sys_read);
|
||||
|
||||
/**
|
||||
* drm_fb_helper_sys_write - wrapper around fb_sys_write
|
||||
* @info: fb_info struct pointer
|
||||
* @buf: userspace buffer to write to framebuffer memory
|
||||
* @count: number of bytes to write to framebuffer memory
|
||||
* @ppos: write offset within framebuffer memory
|
||||
*
|
||||
* A wrapper around fb_sys_write implemented by fbdev core
|
||||
*/
|
||||
ssize_t drm_fb_helper_sys_write(struct fb_info *info, const char __user *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
return fb_sys_write(info, buf, count, ppos);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_fb_helper_sys_write);
|
||||
|
||||
/**
|
||||
* drm_fb_helper_sys_fillrect - wrapper around sys_fillrect
|
||||
* @info: fbdev registered by the helper
|
||||
* @rect: info about rectangle to fill
|
||||
*
|
||||
* A wrapper around sys_fillrect implemented by fbdev core
|
||||
*/
|
||||
void drm_fb_helper_sys_fillrect(struct fb_info *info,
|
||||
const struct fb_fillrect *rect)
|
||||
{
|
||||
sys_fillrect(info, rect);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_fb_helper_sys_fillrect);
|
||||
|
||||
/**
|
||||
* drm_fb_helper_sys_copyarea - wrapper around sys_copyarea
|
||||
* @info: fbdev registered by the helper
|
||||
* @area: info about area to copy
|
||||
*
|
||||
* A wrapper around sys_copyarea implemented by fbdev core
|
||||
*/
|
||||
void drm_fb_helper_sys_copyarea(struct fb_info *info,
|
||||
const struct fb_copyarea *area)
|
||||
{
|
||||
sys_copyarea(info, area);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_fb_helper_sys_copyarea);
|
||||
|
||||
/**
|
||||
* drm_fb_helper_sys_imageblit - wrapper around sys_imageblit
|
||||
* @info: fbdev registered by the helper
|
||||
* @image: info about image to blit
|
||||
*
|
||||
* A wrapper around sys_imageblit implemented by fbdev core
|
||||
*/
|
||||
void drm_fb_helper_sys_imageblit(struct fb_info *info,
|
||||
const struct fb_image *image)
|
||||
{
|
||||
sys_imageblit(info, image);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_fb_helper_sys_imageblit);
|
||||
|
||||
/**
|
||||
* drm_fb_helper_cfb_fillrect - wrapper around cfb_fillrect
|
||||
* @info: fbdev registered by the helper
|
||||
* @rect: info about rectangle to fill
|
||||
*
|
||||
* A wrapper around cfb_imageblit implemented by fbdev core
|
||||
*/
|
||||
void drm_fb_helper_cfb_fillrect(struct fb_info *info,
|
||||
const struct fb_fillrect *rect)
|
||||
{
|
||||
cfb_fillrect(info, rect);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_fb_helper_cfb_fillrect);
|
||||
|
||||
/**
|
||||
* drm_fb_helper_cfb_copyarea - wrapper around cfb_copyarea
|
||||
* @info: fbdev registered by the helper
|
||||
* @area: info about area to copy
|
||||
*
|
||||
* A wrapper around cfb_copyarea implemented by fbdev core
|
||||
*/
|
||||
void drm_fb_helper_cfb_copyarea(struct fb_info *info,
|
||||
const struct fb_copyarea *area)
|
||||
{
|
||||
cfb_copyarea(info, area);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_fb_helper_cfb_copyarea);
|
||||
|
||||
/**
|
||||
* drm_fb_helper_cfb_imageblit - wrapper around cfb_imageblit
|
||||
* @info: fbdev registered by the helper
|
||||
* @image: info about image to blit
|
||||
*
|
||||
* A wrapper around cfb_imageblit implemented by fbdev core
|
||||
*/
|
||||
void drm_fb_helper_cfb_imageblit(struct fb_info *info,
|
||||
const struct fb_image *image)
|
||||
{
|
||||
cfb_imageblit(info, image);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_fb_helper_cfb_imageblit);
|
||||
|
||||
/**
|
||||
* drm_fb_helper_set_suspend - wrapper around fb_set_suspend
|
||||
* @fb_helper: driver-allocated fbdev helper
|
||||
* @state: desired state, zero to resume, non-zero to suspend
|
||||
*
|
||||
* A wrapper around fb_set_suspend implemented by fbdev core
|
||||
*/
|
||||
void drm_fb_helper_set_suspend(struct drm_fb_helper *fb_helper, int state)
|
||||
{
|
||||
if (fb_helper && fb_helper->fbdev)
|
||||
fb_set_suspend(fb_helper->fbdev, state);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_fb_helper_set_suspend);
|
||||
|
||||
static int setcolreg(struct drm_crtc *crtc, u16 red, u16 green,
|
||||
u16 blue, u16 regno, struct fb_info *info)
|
||||
{
|
||||
@ -755,9 +952,10 @@ int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info)
|
||||
int i, j, rc = 0;
|
||||
int start;
|
||||
|
||||
if (__drm_modeset_lock_all(dev, !!oops_in_progress)) {
|
||||
if (oops_in_progress)
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
drm_modeset_lock_all(dev);
|
||||
if (!drm_fb_helper_is_bound(fb_helper)) {
|
||||
drm_modeset_unlock_all(dev);
|
||||
return -EBUSY;
|
||||
@ -906,6 +1104,9 @@ int drm_fb_helper_set_par(struct fb_info *info)
|
||||
struct drm_fb_helper *fb_helper = info->par;
|
||||
struct fb_var_screeninfo *var = &info->var;
|
||||
|
||||
if (oops_in_progress)
|
||||
return -EBUSY;
|
||||
|
||||
if (var->pixclock != 0) {
|
||||
DRM_ERROR("PIXEL CLOCK SET\n");
|
||||
return -EINVAL;
|
||||
@ -931,9 +1132,10 @@ int drm_fb_helper_pan_display(struct fb_var_screeninfo *var,
|
||||
int ret = 0;
|
||||
int i;
|
||||
|
||||
if (__drm_modeset_lock_all(dev, !!oops_in_progress)) {
|
||||
if (oops_in_progress)
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
drm_modeset_lock_all(dev);
|
||||
if (!drm_fb_helper_is_bound(fb_helper)) {
|
||||
drm_modeset_unlock_all(dev);
|
||||
return -EBUSY;
|
||||
|
@ -766,7 +766,7 @@ drm_gem_object_free(struct kref *kref)
|
||||
struct drm_gem_object *obj = (struct drm_gem_object *) kref;
|
||||
struct drm_device *dev = obj->dev;
|
||||
|
||||
BUG_ON(!mutex_is_locked(&dev->struct_mutex));
|
||||
WARN_ON(!mutex_is_locked(&dev->struct_mutex));
|
||||
|
||||
if (dev->driver->gem_free_object != NULL)
|
||||
dev->driver->gem_free_object(obj);
|
||||
|
@ -289,20 +289,15 @@ int drm_gem_cma_dumb_map_offset(struct drm_file *file_priv,
|
||||
{
|
||||
struct drm_gem_object *gem_obj;
|
||||
|
||||
mutex_lock(&drm->struct_mutex);
|
||||
|
||||
gem_obj = drm_gem_object_lookup(drm, file_priv, handle);
|
||||
if (!gem_obj) {
|
||||
dev_err(drm->dev, "failed to lookup GEM object\n");
|
||||
mutex_unlock(&drm->struct_mutex);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
*offset = drm_vma_node_offset_addr(&gem_obj->vma_node);
|
||||
|
||||
drm_gem_object_unreference(gem_obj);
|
||||
|
||||
mutex_unlock(&drm->struct_mutex);
|
||||
drm_gem_object_unreference_unlocked(gem_obj);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -43,8 +43,8 @@
|
||||
#include <linux/export.h>
|
||||
|
||||
/* Access macro for slots in vblank timestamp ringbuffer. */
|
||||
#define vblanktimestamp(dev, crtc, count) \
|
||||
((dev)->vblank[crtc].time[(count) % DRM_VBLANKTIME_RBSIZE])
|
||||
#define vblanktimestamp(dev, pipe, count) \
|
||||
((dev)->vblank[pipe].time[(count) % DRM_VBLANKTIME_RBSIZE])
|
||||
|
||||
/* Retry timestamp calculation up to 3 times to satisfy
|
||||
* drm_timestamp_precision before giving up.
|
||||
@ -57,7 +57,7 @@
|
||||
#define DRM_REDUNDANT_VBLIRQ_THRESH_NS 1000000
|
||||
|
||||
static bool
|
||||
drm_get_last_vbltimestamp(struct drm_device *dev, int crtc,
|
||||
drm_get_last_vbltimestamp(struct drm_device *dev, unsigned int pipe,
|
||||
struct timeval *tvblank, unsigned flags);
|
||||
|
||||
static unsigned int drm_timestamp_precision = 20; /* Default to 20 usecs. */
|
||||
@ -107,7 +107,7 @@ static void store_vblank(struct drm_device *dev, int crtc,
|
||||
/**
|
||||
* drm_update_vblank_count - update the master vblank counter
|
||||
* @dev: DRM device
|
||||
* @crtc: counter to update
|
||||
* @pipe: counter to update
|
||||
*
|
||||
* Call back into the driver to update the appropriate vblank counter
|
||||
* (specified by @crtc). Deal with wraparound, if it occurred, and
|
||||
@ -120,9 +120,9 @@ static void store_vblank(struct drm_device *dev, int crtc,
|
||||
* Note: caller must hold dev->vbl_lock since this reads & writes
|
||||
* device vblank fields.
|
||||
*/
|
||||
static void drm_update_vblank_count(struct drm_device *dev, int crtc)
|
||||
static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe)
|
||||
{
|
||||
struct drm_vblank_crtc *vblank = &dev->vblank[crtc];
|
||||
struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
|
||||
u32 cur_vblank, diff;
|
||||
bool rc;
|
||||
struct timeval t_vblank;
|
||||
@ -140,21 +140,21 @@ static void drm_update_vblank_count(struct drm_device *dev, int crtc)
|
||||
* corresponding vblank timestamp.
|
||||
*/
|
||||
do {
|
||||
cur_vblank = dev->driver->get_vblank_counter(dev, crtc);
|
||||
rc = drm_get_last_vbltimestamp(dev, crtc, &t_vblank, 0);
|
||||
} while (cur_vblank != dev->driver->get_vblank_counter(dev, crtc));
|
||||
cur_vblank = dev->driver->get_vblank_counter(dev, pipe);
|
||||
rc = drm_get_last_vbltimestamp(dev, pipe, &t_vblank, 0);
|
||||
} while (cur_vblank != dev->driver->get_vblank_counter(dev, pipe));
|
||||
|
||||
/* Deal with counter wrap */
|
||||
diff = cur_vblank - vblank->last;
|
||||
if (cur_vblank < vblank->last) {
|
||||
diff += dev->max_vblank_count + 1;
|
||||
|
||||
DRM_DEBUG("last_vblank[%d]=0x%x, cur_vblank=0x%x => diff=0x%x\n",
|
||||
crtc, vblank->last, cur_vblank, diff);
|
||||
DRM_DEBUG("last_vblank[%u]=0x%x, cur_vblank=0x%x => diff=0x%x\n",
|
||||
pipe, vblank->last, cur_vblank, diff);
|
||||
}
|
||||
|
||||
DRM_DEBUG("updating vblank count on crtc %d, missed %d\n",
|
||||
crtc, diff);
|
||||
DRM_DEBUG("updating vblank count on crtc %u, missed %d\n",
|
||||
pipe, diff);
|
||||
|
||||
if (diff == 0)
|
||||
return;
|
||||
@ -167,7 +167,7 @@ static void drm_update_vblank_count(struct drm_device *dev, int crtc)
|
||||
if (!rc)
|
||||
t_vblank = (struct timeval) {0, 0};
|
||||
|
||||
store_vblank(dev, crtc, diff, &t_vblank);
|
||||
store_vblank(dev, pipe, diff, &t_vblank);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -176,9 +176,9 @@ static void drm_update_vblank_count(struct drm_device *dev, int crtc)
|
||||
* are preserved, even if there are any spurious vblank irq's after
|
||||
* disable.
|
||||
*/
|
||||
static void vblank_disable_and_save(struct drm_device *dev, int crtc)
|
||||
static void vblank_disable_and_save(struct drm_device *dev, unsigned int pipe)
|
||||
{
|
||||
struct drm_vblank_crtc *vblank = &dev->vblank[crtc];
|
||||
struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
|
||||
unsigned long irqflags;
|
||||
u32 vblcount;
|
||||
s64 diff_ns;
|
||||
@ -206,8 +206,8 @@ static void vblank_disable_and_save(struct drm_device *dev, int crtc)
|
||||
* vblank interrupt is disabled.
|
||||
*/
|
||||
if (!vblank->enabled &&
|
||||
drm_get_last_vbltimestamp(dev, crtc, &tvblank, 0)) {
|
||||
drm_update_vblank_count(dev, crtc);
|
||||
drm_get_last_vbltimestamp(dev, pipe, &tvblank, 0)) {
|
||||
drm_update_vblank_count(dev, pipe);
|
||||
spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags);
|
||||
return;
|
||||
}
|
||||
@ -218,7 +218,7 @@ static void vblank_disable_and_save(struct drm_device *dev, int crtc)
|
||||
* hardware potentially runtime suspended.
|
||||
*/
|
||||
if (vblank->enabled) {
|
||||
dev->driver->disable_vblank(dev, crtc);
|
||||
dev->driver->disable_vblank(dev, pipe);
|
||||
vblank->enabled = false;
|
||||
}
|
||||
|
||||
@ -235,9 +235,9 @@ static void vblank_disable_and_save(struct drm_device *dev, int crtc)
|
||||
* delayed gpu counter increment.
|
||||
*/
|
||||
do {
|
||||
vblank->last = dev->driver->get_vblank_counter(dev, crtc);
|
||||
vblrc = drm_get_last_vbltimestamp(dev, crtc, &tvblank, 0);
|
||||
} while (vblank->last != dev->driver->get_vblank_counter(dev, crtc) && (--count) && vblrc);
|
||||
vblank->last = dev->driver->get_vblank_counter(dev, pipe);
|
||||
vblrc = drm_get_last_vbltimestamp(dev, pipe, &tvblank, 0);
|
||||
} while (vblank->last != dev->driver->get_vblank_counter(dev, pipe) && (--count) && vblrc);
|
||||
|
||||
if (!count)
|
||||
vblrc = 0;
|
||||
@ -247,7 +247,7 @@ static void vblank_disable_and_save(struct drm_device *dev, int crtc)
|
||||
*/
|
||||
vblcount = vblank->count;
|
||||
diff_ns = timeval_to_ns(&tvblank) -
|
||||
timeval_to_ns(&vblanktimestamp(dev, crtc, vblcount));
|
||||
timeval_to_ns(&vblanktimestamp(dev, pipe, vblcount));
|
||||
|
||||
/* If there is at least 1 msec difference between the last stored
|
||||
* timestamp and tvblank, then we are currently executing our
|
||||
@ -262,7 +262,7 @@ static void vblank_disable_and_save(struct drm_device *dev, int crtc)
|
||||
* hope for the best.
|
||||
*/
|
||||
if (vblrc && (abs64(diff_ns) > 1000000))
|
||||
store_vblank(dev, crtc, 1, &tvblank);
|
||||
store_vblank(dev, pipe, 1, &tvblank);
|
||||
|
||||
spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags);
|
||||
}
|
||||
@ -271,16 +271,16 @@ static void vblank_disable_fn(unsigned long arg)
|
||||
{
|
||||
struct drm_vblank_crtc *vblank = (void *)arg;
|
||||
struct drm_device *dev = vblank->dev;
|
||||
unsigned int pipe = vblank->pipe;
|
||||
unsigned long irqflags;
|
||||
int crtc = vblank->crtc;
|
||||
|
||||
if (!dev->vblank_disable_allowed)
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&dev->vbl_lock, irqflags);
|
||||
if (atomic_read(&vblank->refcount) == 0 && vblank->enabled) {
|
||||
DRM_DEBUG("disabling vblank on crtc %d\n", crtc);
|
||||
vblank_disable_and_save(dev, crtc);
|
||||
DRM_DEBUG("disabling vblank on crtc %u\n", pipe);
|
||||
vblank_disable_and_save(dev, pipe);
|
||||
}
|
||||
spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
|
||||
}
|
||||
@ -293,14 +293,14 @@ static void vblank_disable_fn(unsigned long arg)
|
||||
*/
|
||||
void drm_vblank_cleanup(struct drm_device *dev)
|
||||
{
|
||||
int crtc;
|
||||
unsigned int pipe;
|
||||
|
||||
/* Bail if the driver didn't call drm_vblank_init() */
|
||||
if (dev->num_crtcs == 0)
|
||||
return;
|
||||
|
||||
for (crtc = 0; crtc < dev->num_crtcs; crtc++) {
|
||||
struct drm_vblank_crtc *vblank = &dev->vblank[crtc];
|
||||
for (pipe = 0; pipe < dev->num_crtcs; pipe++) {
|
||||
struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
|
||||
|
||||
WARN_ON(vblank->enabled &&
|
||||
drm_core_check_feature(dev, DRIVER_MODESET));
|
||||
@ -316,17 +316,18 @@ EXPORT_SYMBOL(drm_vblank_cleanup);
|
||||
|
||||
/**
|
||||
* drm_vblank_init - initialize vblank support
|
||||
* @dev: drm_device
|
||||
* @num_crtcs: number of crtcs supported by @dev
|
||||
* @dev: DRM device
|
||||
* @num_crtcs: number of CRTCs supported by @dev
|
||||
*
|
||||
* This function initializes vblank support for @num_crtcs display pipelines.
|
||||
*
|
||||
* Returns:
|
||||
* Zero on success or a negative error code on failure.
|
||||
*/
|
||||
int drm_vblank_init(struct drm_device *dev, int num_crtcs)
|
||||
int drm_vblank_init(struct drm_device *dev, unsigned int num_crtcs)
|
||||
{
|
||||
int i, ret = -ENOMEM;
|
||||
int ret = -ENOMEM;
|
||||
unsigned int i;
|
||||
|
||||
spin_lock_init(&dev->vbl_lock);
|
||||
spin_lock_init(&dev->vblank_time_lock);
|
||||
@ -341,7 +342,7 @@ int drm_vblank_init(struct drm_device *dev, int num_crtcs)
|
||||
struct drm_vblank_crtc *vblank = &dev->vblank[i];
|
||||
|
||||
vblank->dev = dev;
|
||||
vblank->crtc = i;
|
||||
vblank->pipe = i;
|
||||
init_waitqueue_head(&vblank->queue);
|
||||
setup_timer(&vblank->disable_timer, vblank_disable_fn,
|
||||
(unsigned long)vblank);
|
||||
@ -624,17 +625,17 @@ void drm_calc_timestamping_constants(struct drm_crtc *crtc,
|
||||
if (mode->flags & DRM_MODE_FLAG_INTERLACE)
|
||||
framedur_ns /= 2;
|
||||
} else
|
||||
DRM_ERROR("crtc %d: Can't calculate constants, dotclock = 0!\n",
|
||||
DRM_ERROR("crtc %u: Can't calculate constants, dotclock = 0!\n",
|
||||
crtc->base.id);
|
||||
|
||||
crtc->pixeldur_ns = pixeldur_ns;
|
||||
crtc->linedur_ns = linedur_ns;
|
||||
crtc->framedur_ns = framedur_ns;
|
||||
|
||||
DRM_DEBUG("crtc %d: hwmode: htotal %d, vtotal %d, vdisplay %d\n",
|
||||
DRM_DEBUG("crtc %u: hwmode: htotal %d, vtotal %d, vdisplay %d\n",
|
||||
crtc->base.id, mode->crtc_htotal,
|
||||
mode->crtc_vtotal, mode->crtc_vdisplay);
|
||||
DRM_DEBUG("crtc %d: clock %d kHz framedur %d linedur %d, pixeldur %d\n",
|
||||
DRM_DEBUG("crtc %u: clock %d kHz framedur %d linedur %d, pixeldur %d\n",
|
||||
crtc->base.id, dotclock, framedur_ns,
|
||||
linedur_ns, pixeldur_ns);
|
||||
}
|
||||
@ -643,7 +644,7 @@ EXPORT_SYMBOL(drm_calc_timestamping_constants);
|
||||
/**
|
||||
* drm_calc_vbltimestamp_from_scanoutpos - precise vblank timestamp helper
|
||||
* @dev: DRM device
|
||||
* @crtc: Which CRTC's vblank timestamp to retrieve
|
||||
* @pipe: index of CRTC whose vblank timestamp to retrieve
|
||||
* @max_error: Desired maximum allowable error in timestamps (nanosecs)
|
||||
* On return contains true maximum error of timestamp
|
||||
* @vblank_time: Pointer to struct timeval which should receive the timestamp
|
||||
@ -686,7 +687,8 @@ EXPORT_SYMBOL(drm_calc_timestamping_constants);
|
||||
* DRM_VBLANKTIME_INVBL - Timestamp taken while scanout was in vblank interval.
|
||||
*
|
||||
*/
|
||||
int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc,
|
||||
int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev,
|
||||
unsigned int pipe,
|
||||
int *max_error,
|
||||
struct timeval *vblank_time,
|
||||
unsigned flags,
|
||||
@ -700,8 +702,8 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc,
|
||||
int framedur_ns, linedur_ns, pixeldur_ns, delta_ns, duration_ns;
|
||||
bool invbl;
|
||||
|
||||
if (crtc < 0 || crtc >= dev->num_crtcs) {
|
||||
DRM_ERROR("Invalid crtc %d\n", crtc);
|
||||
if (pipe >= dev->num_crtcs) {
|
||||
DRM_ERROR("Invalid crtc %u\n", pipe);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -720,7 +722,7 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc,
|
||||
* Happens during initial modesetting of a crtc.
|
||||
*/
|
||||
if (framedur_ns == 0) {
|
||||
DRM_DEBUG("crtc %d: Noop due to uninitialized mode.\n", crtc);
|
||||
DRM_DEBUG("crtc %u: Noop due to uninitialized mode.\n", pipe);
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
@ -736,13 +738,13 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc,
|
||||
* Get vertical and horizontal scanout position vpos, hpos,
|
||||
* and bounding timestamps stime, etime, pre/post query.
|
||||
*/
|
||||
vbl_status = dev->driver->get_scanout_position(dev, crtc, flags, &vpos,
|
||||
vbl_status = dev->driver->get_scanout_position(dev, pipe, flags, &vpos,
|
||||
&hpos, &stime, &etime);
|
||||
|
||||
/* Return as no-op if scanout query unsupported or failed. */
|
||||
if (!(vbl_status & DRM_SCANOUTPOS_VALID)) {
|
||||
DRM_DEBUG("crtc %d : scanoutpos query failed [%d].\n",
|
||||
crtc, vbl_status);
|
||||
DRM_DEBUG("crtc %u : scanoutpos query failed [%d].\n",
|
||||
pipe, vbl_status);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
@ -756,8 +758,8 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc,
|
||||
|
||||
/* Noisy system timing? */
|
||||
if (i == DRM_TIMESTAMP_MAXRETRIES) {
|
||||
DRM_DEBUG("crtc %d: Noisy timestamp %d us > %d us [%d reps].\n",
|
||||
crtc, duration_ns/1000, *max_error/1000, i);
|
||||
DRM_DEBUG("crtc %u: Noisy timestamp %d us > %d us [%d reps].\n",
|
||||
pipe, duration_ns/1000, *max_error/1000, i);
|
||||
}
|
||||
|
||||
/* Return upper bound of timestamp precision error. */
|
||||
@ -790,8 +792,8 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc,
|
||||
etime = ktime_sub_ns(etime, delta_ns);
|
||||
*vblank_time = ktime_to_timeval(etime);
|
||||
|
||||
DRM_DEBUG("crtc %d : v %d p(%d,%d)@ %ld.%ld -> %ld.%ld [e %d us, %d rep]\n",
|
||||
crtc, (int)vbl_status, hpos, vpos,
|
||||
DRM_DEBUG("crtc %u : v %d p(%d,%d)@ %ld.%ld -> %ld.%ld [e %d us, %d rep]\n",
|
||||
pipe, (int)vbl_status, hpos, vpos,
|
||||
(long)tv_etime.tv_sec, (long)tv_etime.tv_usec,
|
||||
(long)vblank_time->tv_sec, (long)vblank_time->tv_usec,
|
||||
duration_ns/1000, i);
|
||||
@ -816,7 +818,7 @@ static struct timeval get_drm_timestamp(void)
|
||||
* drm_get_last_vbltimestamp - retrieve raw timestamp for the most recent
|
||||
* vblank interval
|
||||
* @dev: DRM device
|
||||
* @crtc: which CRTC's vblank timestamp to retrieve
|
||||
* @pipe: index of CRTC whose vblank timestamp to retrieve
|
||||
* @tvblank: Pointer to target struct timeval which should receive the timestamp
|
||||
* @flags: Flags to pass to driver:
|
||||
* 0 = Default,
|
||||
@ -833,7 +835,7 @@ static struct timeval get_drm_timestamp(void)
|
||||
* True if timestamp is considered to be very precise, false otherwise.
|
||||
*/
|
||||
static bool
|
||||
drm_get_last_vbltimestamp(struct drm_device *dev, int crtc,
|
||||
drm_get_last_vbltimestamp(struct drm_device *dev, unsigned int pipe,
|
||||
struct timeval *tvblank, unsigned flags)
|
||||
{
|
||||
int ret;
|
||||
@ -843,7 +845,7 @@ drm_get_last_vbltimestamp(struct drm_device *dev, int crtc,
|
||||
|
||||
/* Query driver if possible and precision timestamping enabled. */
|
||||
if (dev->driver->get_vblank_timestamp && (max_error > 0)) {
|
||||
ret = dev->driver->get_vblank_timestamp(dev, crtc, &max_error,
|
||||
ret = dev->driver->get_vblank_timestamp(dev, pipe, &max_error,
|
||||
tvblank, flags);
|
||||
if (ret > 0)
|
||||
return true;
|
||||
@ -860,7 +862,7 @@ drm_get_last_vbltimestamp(struct drm_device *dev, int crtc,
|
||||
/**
|
||||
* drm_vblank_count - retrieve "cooked" vblank counter value
|
||||
* @dev: DRM device
|
||||
* @crtc: which counter to retrieve
|
||||
* @pipe: index of CRTC for which to retrieve the counter
|
||||
*
|
||||
* Fetches the "cooked" vblank count value that represents the number of
|
||||
* vblank events since the system was booted, including lost events due to
|
||||
@ -871,12 +873,13 @@ drm_get_last_vbltimestamp(struct drm_device *dev, int crtc,
|
||||
* Returns:
|
||||
* The software vblank counter.
|
||||
*/
|
||||
u32 drm_vblank_count(struct drm_device *dev, int crtc)
|
||||
u32 drm_vblank_count(struct drm_device *dev, int pipe)
|
||||
{
|
||||
struct drm_vblank_crtc *vblank = &dev->vblank[crtc];
|
||||
struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
|
||||
|
||||
if (WARN_ON(crtc >= dev->num_crtcs))
|
||||
if (WARN_ON(pipe >= dev->num_crtcs))
|
||||
return 0;
|
||||
|
||||
return vblank->count;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_vblank_count);
|
||||
@ -901,11 +904,10 @@ u32 drm_crtc_vblank_count(struct drm_crtc *crtc)
|
||||
EXPORT_SYMBOL(drm_crtc_vblank_count);
|
||||
|
||||
/**
|
||||
* drm_vblank_count_and_time - retrieve "cooked" vblank counter value
|
||||
* and the system timestamp corresponding to that vblank counter value.
|
||||
*
|
||||
* drm_vblank_count_and_time - retrieve "cooked" vblank counter value and the
|
||||
* system timestamp corresponding to that vblank counter value.
|
||||
* @dev: DRM device
|
||||
* @crtc: which counter to retrieve
|
||||
* @pipe: index of CRTC whose counter to retrieve
|
||||
* @vblanktime: Pointer to struct timeval to receive the vblank timestamp.
|
||||
*
|
||||
* Fetches the "cooked" vblank count value that represents the number of
|
||||
@ -913,13 +915,13 @@ EXPORT_SYMBOL(drm_crtc_vblank_count);
|
||||
* modesetting activity. Returns corresponding system timestamp of the time
|
||||
* of the vblank interval that corresponds to the current vblank counter value.
|
||||
*/
|
||||
u32 drm_vblank_count_and_time(struct drm_device *dev, int crtc,
|
||||
u32 drm_vblank_count_and_time(struct drm_device *dev, unsigned int pipe,
|
||||
struct timeval *vblanktime)
|
||||
{
|
||||
struct drm_vblank_crtc *vblank = &dev->vblank[crtc];
|
||||
struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
|
||||
u32 cur_vblank;
|
||||
|
||||
if (WARN_ON(crtc >= dev->num_crtcs))
|
||||
if (WARN_ON(pipe >= dev->num_crtcs))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
@ -930,7 +932,7 @@ u32 drm_vblank_count_and_time(struct drm_device *dev, int crtc,
|
||||
do {
|
||||
cur_vblank = vblank->count;
|
||||
smp_rmb();
|
||||
*vblanktime = vblanktimestamp(dev, crtc, cur_vblank);
|
||||
*vblanktime = vblanktimestamp(dev, pipe, cur_vblank);
|
||||
smp_rmb();
|
||||
} while (cur_vblank != vblank->count);
|
||||
|
||||
@ -957,7 +959,7 @@ static void send_vblank_event(struct drm_device *dev,
|
||||
/**
|
||||
* drm_send_vblank_event - helper to send vblank event after pageflip
|
||||
* @dev: DRM device
|
||||
* @crtc: CRTC in question
|
||||
* @pipe: CRTC index
|
||||
* @e: the event to send
|
||||
*
|
||||
* Updates sequence # and timestamp on event, and sends it to userspace.
|
||||
@ -965,20 +967,20 @@ static void send_vblank_event(struct drm_device *dev,
|
||||
*
|
||||
* This is the legacy version of drm_crtc_send_vblank_event().
|
||||
*/
|
||||
void drm_send_vblank_event(struct drm_device *dev, int crtc,
|
||||
struct drm_pending_vblank_event *e)
|
||||
void drm_send_vblank_event(struct drm_device *dev, unsigned int pipe,
|
||||
struct drm_pending_vblank_event *e)
|
||||
{
|
||||
struct timeval now;
|
||||
unsigned int seq;
|
||||
|
||||
if (crtc >= 0) {
|
||||
seq = drm_vblank_count_and_time(dev, crtc, &now);
|
||||
if (dev->num_crtcs > 0) {
|
||||
seq = drm_vblank_count_and_time(dev, pipe, &now);
|
||||
} else {
|
||||
seq = 0;
|
||||
|
||||
now = get_drm_timestamp();
|
||||
}
|
||||
e->pipe = crtc;
|
||||
e->pipe = pipe;
|
||||
send_vblank_event(dev, e, seq, &now);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_send_vblank_event);
|
||||
@ -1003,11 +1005,14 @@ EXPORT_SYMBOL(drm_crtc_send_vblank_event);
|
||||
/**
|
||||
* drm_vblank_enable - enable the vblank interrupt on a CRTC
|
||||
* @dev: DRM device
|
||||
* @crtc: CRTC in question
|
||||
* @pipe: CRTC index
|
||||
*
|
||||
* Returns:
|
||||
* Zero on success or a negative error code on failure.
|
||||
*/
|
||||
static int drm_vblank_enable(struct drm_device *dev, int crtc)
|
||||
static int drm_vblank_enable(struct drm_device *dev, unsigned int pipe)
|
||||
{
|
||||
struct drm_vblank_crtc *vblank = &dev->vblank[crtc];
|
||||
struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
|
||||
int ret = 0;
|
||||
|
||||
assert_spin_locked(&dev->vbl_lock);
|
||||
@ -1022,13 +1027,13 @@ static int drm_vblank_enable(struct drm_device *dev, int crtc)
|
||||
* timestamps. Filtercode in drm_handle_vblank() will
|
||||
* prevent double-accounting of same vblank interval.
|
||||
*/
|
||||
ret = dev->driver->enable_vblank(dev, crtc);
|
||||
DRM_DEBUG("enabling vblank on crtc %d, ret: %d\n", crtc, ret);
|
||||
ret = dev->driver->enable_vblank(dev, pipe);
|
||||
DRM_DEBUG("enabling vblank on crtc %u, ret: %d\n", pipe, ret);
|
||||
if (ret)
|
||||
atomic_dec(&vblank->refcount);
|
||||
else {
|
||||
vblank->enabled = true;
|
||||
drm_update_vblank_count(dev, crtc);
|
||||
drm_update_vblank_count(dev, pipe);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1040,7 +1045,7 @@ static int drm_vblank_enable(struct drm_device *dev, int crtc)
|
||||
/**
|
||||
* drm_vblank_get - get a reference count on vblank events
|
||||
* @dev: DRM device
|
||||
* @crtc: which CRTC to own
|
||||
* @pipe: index of CRTC to own
|
||||
*
|
||||
* Acquire a reference count on vblank events to avoid having them disabled
|
||||
* while in use.
|
||||
@ -1048,24 +1053,24 @@ static int drm_vblank_enable(struct drm_device *dev, int crtc)
|
||||
* This is the legacy version of drm_crtc_vblank_get().
|
||||
*
|
||||
* Returns:
|
||||
* Zero on success, nonzero on failure.
|
||||
* Zero on success or a negative error code on failure.
|
||||
*/
|
||||
int drm_vblank_get(struct drm_device *dev, int crtc)
|
||||
int drm_vblank_get(struct drm_device *dev, unsigned int pipe)
|
||||
{
|
||||
struct drm_vblank_crtc *vblank = &dev->vblank[crtc];
|
||||
struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
|
||||
unsigned long irqflags;
|
||||
int ret = 0;
|
||||
|
||||
if (!dev->num_crtcs)
|
||||
return -EINVAL;
|
||||
|
||||
if (WARN_ON(crtc >= dev->num_crtcs))
|
||||
if (WARN_ON(pipe >= dev->num_crtcs))
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock_irqsave(&dev->vbl_lock, irqflags);
|
||||
/* Going from 0->1 means we have to enable interrupts again */
|
||||
if (atomic_add_return(1, &vblank->refcount) == 1) {
|
||||
ret = drm_vblank_enable(dev, crtc);
|
||||
ret = drm_vblank_enable(dev, pipe);
|
||||
} else {
|
||||
if (!vblank->enabled) {
|
||||
atomic_dec(&vblank->refcount);
|
||||
@ -1088,7 +1093,7 @@ EXPORT_SYMBOL(drm_vblank_get);
|
||||
* This is the native kms version of drm_vblank_get().
|
||||
*
|
||||
* Returns:
|
||||
* Zero on success, nonzero on failure.
|
||||
* Zero on success or a negative error code on failure.
|
||||
*/
|
||||
int drm_crtc_vblank_get(struct drm_crtc *crtc)
|
||||
{
|
||||
@ -1097,23 +1102,23 @@ int drm_crtc_vblank_get(struct drm_crtc *crtc)
|
||||
EXPORT_SYMBOL(drm_crtc_vblank_get);
|
||||
|
||||
/**
|
||||
* drm_vblank_put - give up ownership of vblank events
|
||||
* drm_vblank_put - release ownership of vblank events
|
||||
* @dev: DRM device
|
||||
* @crtc: which counter to give up
|
||||
* @pipe: index of CRTC to release
|
||||
*
|
||||
* Release ownership of a given vblank counter, turning off interrupts
|
||||
* if possible. Disable interrupts after drm_vblank_offdelay milliseconds.
|
||||
*
|
||||
* This is the legacy version of drm_crtc_vblank_put().
|
||||
*/
|
||||
void drm_vblank_put(struct drm_device *dev, int crtc)
|
||||
void drm_vblank_put(struct drm_device *dev, unsigned int pipe)
|
||||
{
|
||||
struct drm_vblank_crtc *vblank = &dev->vblank[crtc];
|
||||
struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
|
||||
|
||||
if (WARN_ON(atomic_read(&vblank->refcount) == 0))
|
||||
if (WARN_ON(pipe >= dev->num_crtcs))
|
||||
return;
|
||||
|
||||
if (WARN_ON(crtc >= dev->num_crtcs))
|
||||
if (WARN_ON(atomic_read(&vblank->refcount) == 0))
|
||||
return;
|
||||
|
||||
/* Last user schedules interrupt disable */
|
||||
@ -1147,30 +1152,34 @@ EXPORT_SYMBOL(drm_crtc_vblank_put);
|
||||
/**
|
||||
* drm_wait_one_vblank - wait for one vblank
|
||||
* @dev: DRM device
|
||||
* @crtc: crtc index
|
||||
* @pipe: CRTC index
|
||||
*
|
||||
* This waits for one vblank to pass on @crtc, using the irq driver interfaces.
|
||||
* It is a failure to call this when the vblank irq for @crtc is disabled, e.g.
|
||||
* due to lack of driver support or because the crtc is off.
|
||||
*/
|
||||
void drm_wait_one_vblank(struct drm_device *dev, int crtc)
|
||||
void drm_wait_one_vblank(struct drm_device *dev, unsigned int pipe)
|
||||
{
|
||||
struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
|
||||
int ret;
|
||||
u32 last;
|
||||
|
||||
ret = drm_vblank_get(dev, crtc);
|
||||
if (WARN(ret, "vblank not available on crtc %i, ret=%i\n", crtc, ret))
|
||||
if (WARN_ON(pipe >= dev->num_crtcs))
|
||||
return;
|
||||
|
||||
last = drm_vblank_count(dev, crtc);
|
||||
ret = drm_vblank_get(dev, pipe);
|
||||
if (WARN(ret, "vblank not available on crtc %i, ret=%i\n", pipe, ret))
|
||||
return;
|
||||
|
||||
ret = wait_event_timeout(dev->vblank[crtc].queue,
|
||||
last != drm_vblank_count(dev, crtc),
|
||||
last = drm_vblank_count(dev, pipe);
|
||||
|
||||
ret = wait_event_timeout(vblank->queue,
|
||||
last != drm_vblank_count(dev, pipe),
|
||||
msecs_to_jiffies(100));
|
||||
|
||||
WARN(ret == 0, "vblank wait timed out on crtc %i\n", crtc);
|
||||
WARN(ret == 0, "vblank wait timed out on crtc %i\n", pipe);
|
||||
|
||||
drm_vblank_put(dev, crtc);
|
||||
drm_vblank_put(dev, pipe);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_wait_one_vblank);
|
||||
|
||||
@ -1191,7 +1200,7 @@ EXPORT_SYMBOL(drm_crtc_wait_one_vblank);
|
||||
/**
|
||||
* drm_vblank_off - disable vblank events on a CRTC
|
||||
* @dev: DRM device
|
||||
* @crtc: CRTC in question
|
||||
* @pipe: CRTC index
|
||||
*
|
||||
* Drivers can use this function to shut down the vblank interrupt handling when
|
||||
* disabling a crtc. This function ensures that the latest vblank frame count is
|
||||
@ -1202,21 +1211,21 @@ EXPORT_SYMBOL(drm_crtc_wait_one_vblank);
|
||||
*
|
||||
* This is the legacy version of drm_crtc_vblank_off().
|
||||
*/
|
||||
void drm_vblank_off(struct drm_device *dev, int crtc)
|
||||
void drm_vblank_off(struct drm_device *dev, unsigned int pipe)
|
||||
{
|
||||
struct drm_vblank_crtc *vblank = &dev->vblank[crtc];
|
||||
struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
|
||||
struct drm_pending_vblank_event *e, *t;
|
||||
struct timeval now;
|
||||
unsigned long irqflags;
|
||||
unsigned int seq;
|
||||
|
||||
if (WARN_ON(crtc >= dev->num_crtcs))
|
||||
if (WARN_ON(pipe >= dev->num_crtcs))
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&dev->event_lock, irqflags);
|
||||
|
||||
spin_lock(&dev->vbl_lock);
|
||||
vblank_disable_and_save(dev, crtc);
|
||||
vblank_disable_and_save(dev, pipe);
|
||||
wake_up(&vblank->queue);
|
||||
|
||||
/*
|
||||
@ -1230,16 +1239,16 @@ void drm_vblank_off(struct drm_device *dev, int crtc)
|
||||
spin_unlock(&dev->vbl_lock);
|
||||
|
||||
/* Send any queued vblank events, lest the natives grow disquiet */
|
||||
seq = drm_vblank_count_and_time(dev, crtc, &now);
|
||||
seq = drm_vblank_count_and_time(dev, pipe, &now);
|
||||
|
||||
list_for_each_entry_safe(e, t, &dev->vblank_event_list, base.link) {
|
||||
if (e->pipe != crtc)
|
||||
if (e->pipe != pipe)
|
||||
continue;
|
||||
DRM_DEBUG("Sending premature vblank event on disable: \
|
||||
wanted %d, current %d\n",
|
||||
e->event.sequence, seq);
|
||||
list_del(&e->base.link);
|
||||
drm_vblank_put(dev, e->pipe);
|
||||
drm_vblank_put(dev, pipe);
|
||||
send_vblank_event(dev, e, seq, &now);
|
||||
}
|
||||
spin_unlock_irqrestore(&dev->event_lock, irqflags);
|
||||
@ -1300,7 +1309,7 @@ EXPORT_SYMBOL(drm_crtc_vblank_reset);
|
||||
/**
|
||||
* drm_vblank_on - enable vblank events on a CRTC
|
||||
* @dev: DRM device
|
||||
* @crtc: CRTC in question
|
||||
* @pipe: CRTC index
|
||||
*
|
||||
* This functions restores the vblank interrupt state captured with
|
||||
* drm_vblank_off() again. Note that calls to drm_vblank_on() and
|
||||
@ -1309,12 +1318,12 @@ EXPORT_SYMBOL(drm_crtc_vblank_reset);
|
||||
*
|
||||
* This is the legacy version of drm_crtc_vblank_on().
|
||||
*/
|
||||
void drm_vblank_on(struct drm_device *dev, int crtc)
|
||||
void drm_vblank_on(struct drm_device *dev, unsigned int pipe)
|
||||
{
|
||||
struct drm_vblank_crtc *vblank = &dev->vblank[crtc];
|
||||
struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
|
||||
unsigned long irqflags;
|
||||
|
||||
if (WARN_ON(crtc >= dev->num_crtcs))
|
||||
if (WARN_ON(pipe >= dev->num_crtcs))
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&dev->vbl_lock, irqflags);
|
||||
@ -1332,7 +1341,7 @@ void drm_vblank_on(struct drm_device *dev, int crtc)
|
||||
* vblank counter value before and after a modeset
|
||||
*/
|
||||
vblank->last =
|
||||
(dev->driver->get_vblank_counter(dev, crtc) - 1) &
|
||||
(dev->driver->get_vblank_counter(dev, pipe) - 1) &
|
||||
dev->max_vblank_count;
|
||||
/*
|
||||
* re-enable interrupts if there are users left, or the
|
||||
@ -1340,7 +1349,7 @@ void drm_vblank_on(struct drm_device *dev, int crtc)
|
||||
*/
|
||||
if (atomic_read(&vblank->refcount) != 0 ||
|
||||
(!dev->vblank_disable_immediate && drm_vblank_offdelay == 0))
|
||||
WARN_ON(drm_vblank_enable(dev, crtc));
|
||||
WARN_ON(drm_vblank_enable(dev, pipe));
|
||||
spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_vblank_on);
|
||||
@ -1365,7 +1374,7 @@ EXPORT_SYMBOL(drm_crtc_vblank_on);
|
||||
/**
|
||||
* drm_vblank_pre_modeset - account for vblanks across mode sets
|
||||
* @dev: DRM device
|
||||
* @crtc: CRTC in question
|
||||
* @pipe: CRTC index
|
||||
*
|
||||
* Account for vblank events across mode setting events, which will likely
|
||||
* reset the hardware frame counter.
|
||||
@ -1385,15 +1394,15 @@ EXPORT_SYMBOL(drm_crtc_vblank_on);
|
||||
* Drivers must call drm_vblank_post_modeset() when re-enabling the same crtc
|
||||
* again.
|
||||
*/
|
||||
void drm_vblank_pre_modeset(struct drm_device *dev, int crtc)
|
||||
void drm_vblank_pre_modeset(struct drm_device *dev, unsigned int pipe)
|
||||
{
|
||||
struct drm_vblank_crtc *vblank = &dev->vblank[crtc];
|
||||
struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
|
||||
|
||||
/* vblank is not initialized (IRQ not installed ?), or has been freed */
|
||||
if (!dev->num_crtcs)
|
||||
return;
|
||||
|
||||
if (WARN_ON(crtc >= dev->num_crtcs))
|
||||
if (WARN_ON(pipe >= dev->num_crtcs))
|
||||
return;
|
||||
|
||||
/*
|
||||
@ -1405,7 +1414,7 @@ void drm_vblank_pre_modeset(struct drm_device *dev, int crtc)
|
||||
*/
|
||||
if (!vblank->inmodeset) {
|
||||
vblank->inmodeset = 0x1;
|
||||
if (drm_vblank_get(dev, crtc) == 0)
|
||||
if (drm_vblank_get(dev, pipe) == 0)
|
||||
vblank->inmodeset |= 0x2;
|
||||
}
|
||||
}
|
||||
@ -1414,27 +1423,30 @@ EXPORT_SYMBOL(drm_vblank_pre_modeset);
|
||||
/**
|
||||
* drm_vblank_post_modeset - undo drm_vblank_pre_modeset changes
|
||||
* @dev: DRM device
|
||||
* @crtc: CRTC in question
|
||||
* @pipe: CRTC index
|
||||
*
|
||||
* This function again drops the temporary vblank reference acquired in
|
||||
* drm_vblank_pre_modeset.
|
||||
*/
|
||||
void drm_vblank_post_modeset(struct drm_device *dev, int crtc)
|
||||
void drm_vblank_post_modeset(struct drm_device *dev, unsigned int pipe)
|
||||
{
|
||||
struct drm_vblank_crtc *vblank = &dev->vblank[crtc];
|
||||
struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
|
||||
unsigned long irqflags;
|
||||
|
||||
/* vblank is not initialized (IRQ not installed ?), or has been freed */
|
||||
if (!dev->num_crtcs)
|
||||
return;
|
||||
|
||||
if (WARN_ON(pipe >= dev->num_crtcs))
|
||||
return;
|
||||
|
||||
if (vblank->inmodeset) {
|
||||
spin_lock_irqsave(&dev->vbl_lock, irqflags);
|
||||
dev->vblank_disable_allowed = true;
|
||||
spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
|
||||
|
||||
if (vblank->inmodeset & 0x2)
|
||||
drm_vblank_put(dev, crtc);
|
||||
drm_vblank_put(dev, pipe);
|
||||
|
||||
vblank->inmodeset = 0;
|
||||
}
|
||||
@ -1456,7 +1468,7 @@ int drm_modeset_ctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_modeset_ctl *modeset = data;
|
||||
unsigned int crtc;
|
||||
unsigned int pipe;
|
||||
|
||||
/* If drm_vblank_init() hasn't been called yet, just no-op */
|
||||
if (!dev->num_crtcs)
|
||||
@ -1466,16 +1478,16 @@ int drm_modeset_ctl(struct drm_device *dev, void *data,
|
||||
if (drm_core_check_feature(dev, DRIVER_MODESET))
|
||||
return 0;
|
||||
|
||||
crtc = modeset->crtc;
|
||||
if (crtc >= dev->num_crtcs)
|
||||
pipe = modeset->crtc;
|
||||
if (pipe >= dev->num_crtcs)
|
||||
return -EINVAL;
|
||||
|
||||
switch (modeset->cmd) {
|
||||
case _DRM_PRE_MODESET:
|
||||
drm_vblank_pre_modeset(dev, crtc);
|
||||
drm_vblank_pre_modeset(dev, pipe);
|
||||
break;
|
||||
case _DRM_POST_MODESET:
|
||||
drm_vblank_post_modeset(dev, crtc);
|
||||
drm_vblank_post_modeset(dev, pipe);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
@ -1484,7 +1496,7 @@ int drm_modeset_ctl(struct drm_device *dev, void *data,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int drm_queue_vblank_event(struct drm_device *dev, int pipe,
|
||||
static int drm_queue_vblank_event(struct drm_device *dev, unsigned int pipe,
|
||||
union drm_wait_vblank *vblwait,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
@ -1538,7 +1550,7 @@ static int drm_queue_vblank_event(struct drm_device *dev, int pipe,
|
||||
vblwait->reply.sequence = vblwait->request.sequence;
|
||||
}
|
||||
|
||||
DRM_DEBUG("event on vblank count %d, current %d, crtc %d\n",
|
||||
DRM_DEBUG("event on vblank count %d, current %d, crtc %u\n",
|
||||
vblwait->request.sequence, seq, pipe);
|
||||
|
||||
trace_drm_vblank_event_queued(current->pid, pipe,
|
||||
@ -1587,7 +1599,7 @@ int drm_wait_vblank(struct drm_device *dev, void *data,
|
||||
struct drm_vblank_crtc *vblank;
|
||||
union drm_wait_vblank *vblwait = data;
|
||||
int ret;
|
||||
unsigned int flags, seq, crtc, high_crtc;
|
||||
unsigned int flags, seq, pipe, high_pipe;
|
||||
|
||||
if (!dev->irq_enabled)
|
||||
return -EINVAL;
|
||||
@ -1606,22 +1618,22 @@ int drm_wait_vblank(struct drm_device *dev, void *data,
|
||||
}
|
||||
|
||||
flags = vblwait->request.type & _DRM_VBLANK_FLAGS_MASK;
|
||||
high_crtc = (vblwait->request.type & _DRM_VBLANK_HIGH_CRTC_MASK);
|
||||
if (high_crtc)
|
||||
crtc = high_crtc >> _DRM_VBLANK_HIGH_CRTC_SHIFT;
|
||||
high_pipe = (vblwait->request.type & _DRM_VBLANK_HIGH_CRTC_MASK);
|
||||
if (high_pipe)
|
||||
pipe = high_pipe >> _DRM_VBLANK_HIGH_CRTC_SHIFT;
|
||||
else
|
||||
crtc = flags & _DRM_VBLANK_SECONDARY ? 1 : 0;
|
||||
if (crtc >= dev->num_crtcs)
|
||||
pipe = flags & _DRM_VBLANK_SECONDARY ? 1 : 0;
|
||||
if (pipe >= dev->num_crtcs)
|
||||
return -EINVAL;
|
||||
|
||||
vblank = &dev->vblank[crtc];
|
||||
vblank = &dev->vblank[pipe];
|
||||
|
||||
ret = drm_vblank_get(dev, crtc);
|
||||
ret = drm_vblank_get(dev, pipe);
|
||||
if (ret) {
|
||||
DRM_DEBUG("failed to acquire vblank counter, %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
seq = drm_vblank_count(dev, crtc);
|
||||
seq = drm_vblank_count(dev, pipe);
|
||||
|
||||
switch (vblwait->request.type & _DRM_VBLANK_TYPES_MASK) {
|
||||
case _DRM_VBLANK_RELATIVE:
|
||||
@ -1638,7 +1650,7 @@ int drm_wait_vblank(struct drm_device *dev, void *data,
|
||||
/* must hold on to the vblank ref until the event fires
|
||||
* drm_vblank_put will be called asynchronously
|
||||
*/
|
||||
return drm_queue_vblank_event(dev, crtc, vblwait, file_priv);
|
||||
return drm_queue_vblank_event(dev, pipe, vblwait, file_priv);
|
||||
}
|
||||
|
||||
if ((flags & _DRM_VBLANK_NEXTONMISS) &&
|
||||
@ -1646,11 +1658,11 @@ int drm_wait_vblank(struct drm_device *dev, void *data,
|
||||
vblwait->request.sequence = seq + 1;
|
||||
}
|
||||
|
||||
DRM_DEBUG("waiting on vblank count %d, crtc %d\n",
|
||||
vblwait->request.sequence, crtc);
|
||||
DRM_DEBUG("waiting on vblank count %d, crtc %u\n",
|
||||
vblwait->request.sequence, pipe);
|
||||
vblank->last_wait = vblwait->request.sequence;
|
||||
DRM_WAIT_ON(ret, vblank->queue, 3 * HZ,
|
||||
(((drm_vblank_count(dev, crtc) -
|
||||
(((drm_vblank_count(dev, pipe) -
|
||||
vblwait->request.sequence) <= (1 << 23)) ||
|
||||
!vblank->enabled ||
|
||||
!dev->irq_enabled));
|
||||
@ -1658,7 +1670,7 @@ int drm_wait_vblank(struct drm_device *dev, void *data,
|
||||
if (ret != -EINTR) {
|
||||
struct timeval now;
|
||||
|
||||
vblwait->reply.sequence = drm_vblank_count_and_time(dev, crtc, &now);
|
||||
vblwait->reply.sequence = drm_vblank_count_and_time(dev, pipe, &now);
|
||||
vblwait->reply.tval_sec = now.tv_sec;
|
||||
vblwait->reply.tval_usec = now.tv_usec;
|
||||
|
||||
@ -1669,11 +1681,11 @@ int drm_wait_vblank(struct drm_device *dev, void *data,
|
||||
}
|
||||
|
||||
done:
|
||||
drm_vblank_put(dev, crtc);
|
||||
drm_vblank_put(dev, pipe);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void drm_handle_vblank_events(struct drm_device *dev, int crtc)
|
||||
static void drm_handle_vblank_events(struct drm_device *dev, unsigned int pipe)
|
||||
{
|
||||
struct drm_pending_vblank_event *e, *t;
|
||||
struct timeval now;
|
||||
@ -1681,10 +1693,10 @@ static void drm_handle_vblank_events(struct drm_device *dev, int crtc)
|
||||
|
||||
assert_spin_locked(&dev->event_lock);
|
||||
|
||||
seq = drm_vblank_count_and_time(dev, crtc, &now);
|
||||
seq = drm_vblank_count_and_time(dev, pipe, &now);
|
||||
|
||||
list_for_each_entry_safe(e, t, &dev->vblank_event_list, base.link) {
|
||||
if (e->pipe != crtc)
|
||||
if (e->pipe != pipe)
|
||||
continue;
|
||||
if ((seq - e->event.sequence) > (1<<23))
|
||||
continue;
|
||||
@ -1693,26 +1705,26 @@ static void drm_handle_vblank_events(struct drm_device *dev, int crtc)
|
||||
e->event.sequence, seq);
|
||||
|
||||
list_del(&e->base.link);
|
||||
drm_vblank_put(dev, e->pipe);
|
||||
drm_vblank_put(dev, pipe);
|
||||
send_vblank_event(dev, e, seq, &now);
|
||||
}
|
||||
|
||||
trace_drm_vblank_event(crtc, seq);
|
||||
trace_drm_vblank_event(pipe, seq);
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_handle_vblank - handle a vblank event
|
||||
* @dev: DRM device
|
||||
* @crtc: where this event occurred
|
||||
* @pipe: index of CRTC where this event occurred
|
||||
*
|
||||
* Drivers should call this routine in their vblank interrupt handlers to
|
||||
* update the vblank counter and send any signals that may be pending.
|
||||
*
|
||||
* This is the legacy version of drm_crtc_handle_vblank().
|
||||
*/
|
||||
bool drm_handle_vblank(struct drm_device *dev, int crtc)
|
||||
bool drm_handle_vblank(struct drm_device *dev, unsigned int pipe)
|
||||
{
|
||||
struct drm_vblank_crtc *vblank = &dev->vblank[crtc];
|
||||
struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
|
||||
u32 vblcount;
|
||||
s64 diff_ns;
|
||||
struct timeval tvblank;
|
||||
@ -1721,7 +1733,7 @@ bool drm_handle_vblank(struct drm_device *dev, int crtc)
|
||||
if (WARN_ON_ONCE(!dev->num_crtcs))
|
||||
return false;
|
||||
|
||||
if (WARN_ON(crtc >= dev->num_crtcs))
|
||||
if (WARN_ON(pipe >= dev->num_crtcs))
|
||||
return false;
|
||||
|
||||
spin_lock_irqsave(&dev->event_lock, irqflags);
|
||||
@ -1745,11 +1757,11 @@ bool drm_handle_vblank(struct drm_device *dev, int crtc)
|
||||
|
||||
/* Get current timestamp and count. */
|
||||
vblcount = vblank->count;
|
||||
drm_get_last_vbltimestamp(dev, crtc, &tvblank, DRM_CALLED_FROM_VBLIRQ);
|
||||
drm_get_last_vbltimestamp(dev, pipe, &tvblank, DRM_CALLED_FROM_VBLIRQ);
|
||||
|
||||
/* Compute time difference to timestamp of last vblank */
|
||||
diff_ns = timeval_to_ns(&tvblank) -
|
||||
timeval_to_ns(&vblanktimestamp(dev, crtc, vblcount));
|
||||
timeval_to_ns(&vblanktimestamp(dev, pipe, vblcount));
|
||||
|
||||
/* Update vblank timestamp and count if at least
|
||||
* DRM_REDUNDANT_VBLIRQ_THRESH_NS nanoseconds
|
||||
@ -1761,15 +1773,15 @@ bool drm_handle_vblank(struct drm_device *dev, int crtc)
|
||||
* ignore those for accounting.
|
||||
*/
|
||||
if (abs64(diff_ns) > DRM_REDUNDANT_VBLIRQ_THRESH_NS)
|
||||
store_vblank(dev, crtc, 1, &tvblank);
|
||||
store_vblank(dev, pipe, 1, &tvblank);
|
||||
else
|
||||
DRM_DEBUG("crtc %d: Redundant vblirq ignored. diff_ns = %d\n",
|
||||
crtc, (int) diff_ns);
|
||||
DRM_DEBUG("crtc %u: Redundant vblirq ignored. diff_ns = %d\n",
|
||||
pipe, (int) diff_ns);
|
||||
|
||||
spin_unlock(&dev->vblank_time_lock);
|
||||
|
||||
wake_up(&vblank->queue);
|
||||
drm_handle_vblank_events(dev, crtc);
|
||||
drm_handle_vblank_events(dev, pipe);
|
||||
|
||||
spin_unlock_irqrestore(&dev->event_lock, irqflags);
|
||||
|
||||
|
@ -55,41 +55,27 @@
|
||||
* drm_modeset_acquire_fini(&ctx);
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* __drm_modeset_lock_all - internal helper to grab all modeset locks
|
||||
* @dev: DRM device
|
||||
* @trylock: trylock mode for atomic contexts
|
||||
* drm_modeset_lock_all - take all modeset locks
|
||||
* @dev: drm device
|
||||
*
|
||||
* This is a special version of drm_modeset_lock_all() which can also be used in
|
||||
* atomic contexts. Then @trylock must be set to true.
|
||||
*
|
||||
* Returns:
|
||||
* 0 on success or negative error code on failure.
|
||||
* This function takes all modeset locks, suitable where a more fine-grained
|
||||
* scheme isn't (yet) implemented. Locks must be dropped with
|
||||
* drm_modeset_unlock_all.
|
||||
*/
|
||||
int __drm_modeset_lock_all(struct drm_device *dev,
|
||||
bool trylock)
|
||||
void drm_modeset_lock_all(struct drm_device *dev)
|
||||
{
|
||||
struct drm_mode_config *config = &dev->mode_config;
|
||||
struct drm_modeset_acquire_ctx *ctx;
|
||||
int ret;
|
||||
|
||||
ctx = kzalloc(sizeof(*ctx),
|
||||
trylock ? GFP_ATOMIC : GFP_KERNEL);
|
||||
if (!ctx)
|
||||
return -ENOMEM;
|
||||
ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
|
||||
if (WARN_ON(!ctx))
|
||||
return;
|
||||
|
||||
if (trylock) {
|
||||
if (!mutex_trylock(&config->mutex)) {
|
||||
ret = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
mutex_lock(&config->mutex);
|
||||
}
|
||||
mutex_lock(&config->mutex);
|
||||
|
||||
drm_modeset_acquire_init(ctx, 0);
|
||||
ctx->trylock_only = trylock;
|
||||
|
||||
retry:
|
||||
ret = drm_modeset_lock(&config->connection_mutex, ctx);
|
||||
@ -108,7 +94,7 @@ retry:
|
||||
|
||||
drm_warn_on_modeset_not_all_locked(dev);
|
||||
|
||||
return 0;
|
||||
return;
|
||||
|
||||
fail:
|
||||
if (ret == -EDEADLK) {
|
||||
@ -116,23 +102,7 @@ fail:
|
||||
goto retry;
|
||||
}
|
||||
|
||||
out:
|
||||
kfree(ctx);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(__drm_modeset_lock_all);
|
||||
|
||||
/**
|
||||
* drm_modeset_lock_all - take all modeset locks
|
||||
* @dev: drm device
|
||||
*
|
||||
* This function takes all modeset locks, suitable where a more fine-grained
|
||||
* scheme isn't (yet) implemented. Locks must be dropped with
|
||||
* drm_modeset_unlock_all.
|
||||
*/
|
||||
void drm_modeset_lock_all(struct drm_device *dev)
|
||||
{
|
||||
WARN_ON(__drm_modeset_lock_all(dev, false) != 0);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_modeset_lock_all);
|
||||
|
||||
|
@ -65,9 +65,9 @@ static int exynos_drm_fb_mmap(struct fb_info *info,
|
||||
static struct fb_ops exynos_drm_fb_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.fb_mmap = exynos_drm_fb_mmap,
|
||||
.fb_fillrect = cfb_fillrect,
|
||||
.fb_copyarea = cfb_copyarea,
|
||||
.fb_imageblit = cfb_imageblit,
|
||||
.fb_fillrect = drm_fb_helper_cfb_fillrect,
|
||||
.fb_copyarea = drm_fb_helper_cfb_copyarea,
|
||||
.fb_imageblit = drm_fb_helper_cfb_imageblit,
|
||||
.fb_check_var = drm_fb_helper_check_var,
|
||||
.fb_set_par = drm_fb_helper_set_par,
|
||||
.fb_blank = drm_fb_helper_blank,
|
||||
@ -142,10 +142,10 @@ static int exynos_drm_fbdev_create(struct drm_fb_helper *helper,
|
||||
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
|
||||
fbi = framebuffer_alloc(0, &pdev->dev);
|
||||
if (!fbi) {
|
||||
fbi = drm_fb_helper_alloc_fbi(helper);
|
||||
if (IS_ERR(fbi)) {
|
||||
DRM_ERROR("failed to allocate fb info.\n");
|
||||
ret = -ENOMEM;
|
||||
ret = PTR_ERR(fbi);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@ -165,7 +165,7 @@ static int exynos_drm_fbdev_create(struct drm_fb_helper *helper,
|
||||
|
||||
if (IS_ERR(exynos_gem_obj)) {
|
||||
ret = PTR_ERR(exynos_gem_obj);
|
||||
goto err_release_framebuffer;
|
||||
goto err_release_fbi;
|
||||
}
|
||||
|
||||
exynos_fbdev->exynos_gem_obj = exynos_gem_obj;
|
||||
@ -178,33 +178,23 @@ static int exynos_drm_fbdev_create(struct drm_fb_helper *helper,
|
||||
goto err_destroy_gem;
|
||||
}
|
||||
|
||||
helper->fbdev = fbi;
|
||||
|
||||
fbi->par = helper;
|
||||
fbi->flags = FBINFO_FLAG_DEFAULT;
|
||||
fbi->fbops = &exynos_drm_fb_ops;
|
||||
|
||||
ret = fb_alloc_cmap(&fbi->cmap, 256, 0);
|
||||
if (ret) {
|
||||
DRM_ERROR("failed to allocate cmap.\n");
|
||||
goto err_destroy_framebuffer;
|
||||
}
|
||||
|
||||
ret = exynos_drm_fbdev_update(helper, sizes, helper->fb);
|
||||
if (ret < 0)
|
||||
goto err_dealloc_cmap;
|
||||
goto err_destroy_framebuffer;
|
||||
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
return ret;
|
||||
|
||||
err_dealloc_cmap:
|
||||
fb_dealloc_cmap(&fbi->cmap);
|
||||
err_destroy_framebuffer:
|
||||
drm_framebuffer_cleanup(helper->fb);
|
||||
err_destroy_gem:
|
||||
exynos_drm_gem_destroy(exynos_gem_obj);
|
||||
err_release_framebuffer:
|
||||
framebuffer_release(fbi);
|
||||
err_release_fbi:
|
||||
drm_fb_helper_release_fbi(helper);
|
||||
|
||||
/*
|
||||
* if failed, all resources allocated above would be released by
|
||||
@ -312,21 +302,8 @@ static void exynos_drm_fbdev_destroy(struct drm_device *dev,
|
||||
}
|
||||
}
|
||||
|
||||
/* release linux framebuffer */
|
||||
if (fb_helper->fbdev) {
|
||||
struct fb_info *info;
|
||||
int ret;
|
||||
|
||||
info = fb_helper->fbdev;
|
||||
ret = unregister_framebuffer(info);
|
||||
if (ret < 0)
|
||||
DRM_DEBUG_KMS("failed unregister_framebuffer()\n");
|
||||
|
||||
if (info->cmap.len)
|
||||
fb_dealloc_cmap(&info->cmap);
|
||||
|
||||
framebuffer_release(info);
|
||||
}
|
||||
drm_fb_helper_unregister_fbi(fb_helper);
|
||||
drm_fb_helper_release_fbi(fb_helper);
|
||||
|
||||
drm_fb_helper_fini(fb_helper);
|
||||
}
|
||||
|
@ -276,12 +276,12 @@ static void psbfb_copyarea_accel(struct fb_info *info,
|
||||
break;
|
||||
default:
|
||||
/* software fallback */
|
||||
cfb_copyarea(info, a);
|
||||
drm_fb_helper_cfb_copyarea(info, a);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!gma_power_begin(dev, false)) {
|
||||
cfb_copyarea(info, a);
|
||||
drm_fb_helper_cfb_copyarea(info, a);
|
||||
return;
|
||||
}
|
||||
psb_accel_2d_copy(dev_priv,
|
||||
@ -308,7 +308,7 @@ void psbfb_copyarea(struct fb_info *info,
|
||||
/* Avoid the 8 pixel erratum */
|
||||
if (region->width == 8 || region->height == 8 ||
|
||||
(info->flags & FBINFO_HWACCEL_DISABLED))
|
||||
return cfb_copyarea(info, region);
|
||||
return drm_fb_helper_cfb_copyarea(info, region);
|
||||
|
||||
psbfb_copyarea_accel(info, region);
|
||||
}
|
||||
|
@ -194,9 +194,9 @@ static struct fb_ops psbfb_ops = {
|
||||
.fb_set_par = drm_fb_helper_set_par,
|
||||
.fb_blank = drm_fb_helper_blank,
|
||||
.fb_setcolreg = psbfb_setcolreg,
|
||||
.fb_fillrect = cfb_fillrect,
|
||||
.fb_fillrect = drm_fb_helper_cfb_fillrect,
|
||||
.fb_copyarea = psbfb_copyarea,
|
||||
.fb_imageblit = cfb_imageblit,
|
||||
.fb_imageblit = drm_fb_helper_cfb_imageblit,
|
||||
.fb_mmap = psbfb_mmap,
|
||||
.fb_sync = psbfb_sync,
|
||||
.fb_ioctl = psbfb_ioctl,
|
||||
@ -208,9 +208,9 @@ static struct fb_ops psbfb_roll_ops = {
|
||||
.fb_set_par = drm_fb_helper_set_par,
|
||||
.fb_blank = drm_fb_helper_blank,
|
||||
.fb_setcolreg = psbfb_setcolreg,
|
||||
.fb_fillrect = cfb_fillrect,
|
||||
.fb_copyarea = cfb_copyarea,
|
||||
.fb_imageblit = cfb_imageblit,
|
||||
.fb_fillrect = drm_fb_helper_cfb_fillrect,
|
||||
.fb_copyarea = drm_fb_helper_cfb_copyarea,
|
||||
.fb_imageblit = drm_fb_helper_cfb_imageblit,
|
||||
.fb_pan_display = psbfb_pan,
|
||||
.fb_mmap = psbfb_mmap,
|
||||
.fb_ioctl = psbfb_ioctl,
|
||||
@ -222,9 +222,9 @@ static struct fb_ops psbfb_unaccel_ops = {
|
||||
.fb_set_par = drm_fb_helper_set_par,
|
||||
.fb_blank = drm_fb_helper_blank,
|
||||
.fb_setcolreg = psbfb_setcolreg,
|
||||
.fb_fillrect = cfb_fillrect,
|
||||
.fb_copyarea = cfb_copyarea,
|
||||
.fb_imageblit = cfb_imageblit,
|
||||
.fb_fillrect = drm_fb_helper_cfb_fillrect,
|
||||
.fb_copyarea = drm_fb_helper_cfb_copyarea,
|
||||
.fb_imageblit = drm_fb_helper_cfb_imageblit,
|
||||
.fb_mmap = psbfb_mmap,
|
||||
.fb_ioctl = psbfb_ioctl,
|
||||
};
|
||||
@ -343,7 +343,6 @@ static int psbfb_create(struct psb_fbdev *fbdev,
|
||||
struct drm_framebuffer *fb;
|
||||
struct psb_framebuffer *psbfb = &fbdev->pfb;
|
||||
struct drm_mode_fb_cmd2 mode_cmd;
|
||||
struct device *device = &dev->pdev->dev;
|
||||
int size;
|
||||
int ret;
|
||||
struct gtt_range *backing;
|
||||
@ -409,9 +408,9 @@ static int psbfb_create(struct psb_fbdev *fbdev,
|
||||
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
|
||||
info = framebuffer_alloc(0, device);
|
||||
if (!info) {
|
||||
ret = -ENOMEM;
|
||||
info = drm_fb_helper_alloc_fbi(&fbdev->psb_fb_helper);
|
||||
if (IS_ERR(info)) {
|
||||
ret = PTR_ERR(info);
|
||||
goto out_err1;
|
||||
}
|
||||
info->par = fbdev;
|
||||
@ -426,7 +425,6 @@ static int psbfb_create(struct psb_fbdev *fbdev,
|
||||
psbfb->fbdev = info;
|
||||
|
||||
fbdev->psb_fb_helper.fb = fb;
|
||||
fbdev->psb_fb_helper.fbdev = info;
|
||||
|
||||
drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth);
|
||||
strcpy(info->fix.id, "psbdrmfb");
|
||||
@ -440,12 +438,6 @@ static int psbfb_create(struct psb_fbdev *fbdev,
|
||||
} else /* Software */
|
||||
info->fbops = &psbfb_unaccel_ops;
|
||||
|
||||
ret = fb_alloc_cmap(&info->cmap, 256, 0);
|
||||
if (ret) {
|
||||
ret = -ENOMEM;
|
||||
goto out_unref;
|
||||
}
|
||||
|
||||
info->fix.smem_start = dev->mode_config.fb_base;
|
||||
info->fix.smem_len = size;
|
||||
info->fix.ywrapstep = gtt_roll;
|
||||
@ -456,11 +448,6 @@ static int psbfb_create(struct psb_fbdev *fbdev,
|
||||
info->screen_size = size;
|
||||
|
||||
if (dev_priv->gtt.stolen_size) {
|
||||
info->apertures = alloc_apertures(1);
|
||||
if (!info->apertures) {
|
||||
ret = -ENOMEM;
|
||||
goto out_unref;
|
||||
}
|
||||
info->apertures->ranges[0].base = dev->mode_config.fb_base;
|
||||
info->apertures->ranges[0].size = dev_priv->gtt.stolen_size;
|
||||
}
|
||||
@ -483,6 +470,8 @@ out_unref:
|
||||
psb_gtt_free_range(dev, backing);
|
||||
else
|
||||
drm_gem_object_unreference(&backing->gem);
|
||||
|
||||
drm_fb_helper_release_fbi(&fbdev->psb_fb_helper);
|
||||
out_err1:
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
psb_gtt_free_range(dev, backing);
|
||||
@ -570,16 +559,11 @@ static const struct drm_fb_helper_funcs psb_fb_helper_funcs = {
|
||||
|
||||
static int psb_fbdev_destroy(struct drm_device *dev, struct psb_fbdev *fbdev)
|
||||
{
|
||||
struct fb_info *info;
|
||||
struct psb_framebuffer *psbfb = &fbdev->pfb;
|
||||
|
||||
if (fbdev->psb_fb_helper.fbdev) {
|
||||
info = fbdev->psb_fb_helper.fbdev;
|
||||
unregister_framebuffer(info);
|
||||
if (info->cmap.len)
|
||||
fb_dealloc_cmap(&info->cmap);
|
||||
framebuffer_release(info);
|
||||
}
|
||||
drm_fb_helper_unregister_fbi(&fbdev->psb_fb_helper);
|
||||
drm_fb_helper_release_fbi(&fbdev->psb_fb_helper);
|
||||
|
||||
drm_fb_helper_fini(&fbdev->psb_fb_helper);
|
||||
drm_framebuffer_unregister_private(&psbfb->base);
|
||||
drm_framebuffer_cleanup(&psbfb->base);
|
||||
|
@ -36,21 +36,6 @@ config DRM_I915
|
||||
i810 driver instead, and the Atom z5xx series has an entirely
|
||||
different implementation.
|
||||
|
||||
config DRM_I915_FBDEV
|
||||
bool "Enable legacy fbdev support for the modesetting intel driver"
|
||||
depends on DRM_I915
|
||||
select DRM_KMS_FB_HELPER
|
||||
select FB_CFB_FILLRECT
|
||||
select FB_CFB_COPYAREA
|
||||
select FB_CFB_IMAGEBLIT
|
||||
default y
|
||||
help
|
||||
Choose this option if you have a need for the legacy fbdev
|
||||
support. Note that this support also provide the linux console
|
||||
support on top of the intel modesetting driver.
|
||||
|
||||
If in doubt, say "Y".
|
||||
|
||||
config DRM_I915_PRELIMINARY_HW_SUPPORT
|
||||
bool "Enable preliminary support for prerelease Intel hardware by default"
|
||||
depends on DRM_I915
|
||||
|
@ -59,7 +59,7 @@ i915-y += intel_audio.o \
|
||||
intel_sideband.o \
|
||||
intel_sprite.o
|
||||
i915-$(CONFIG_ACPI) += intel_acpi.o intel_opregion.o
|
||||
i915-$(CONFIG_DRM_I915_FBDEV) += intel_fbdev.o
|
||||
i915-$(CONFIG_DRM_FBDEV_EMULATION) += intel_fbdev.o
|
||||
|
||||
# modesetting output/encoder code
|
||||
i915-y += dvo_ch7017.o \
|
||||
|
@ -1868,7 +1868,7 @@ static int i915_gem_framebuffer_info(struct seq_file *m, void *data)
|
||||
struct intel_framebuffer *fb;
|
||||
struct drm_framebuffer *drm_fb;
|
||||
|
||||
#ifdef CONFIG_DRM_I915_FBDEV
|
||||
#ifdef CONFIG_DRM_FBDEV_EMULATION
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
|
||||
ifbdev = dev_priv->fbdev;
|
||||
|
@ -1854,7 +1854,7 @@ struct drm_i915_private {
|
||||
|
||||
struct drm_i915_gem_object *vlv_pctx;
|
||||
|
||||
#ifdef CONFIG_DRM_I915_FBDEV
|
||||
#ifdef CONFIG_DRM_FBDEV_EMULATION
|
||||
/* list of fbdev register on this device */
|
||||
struct intel_fbdev *fbdev;
|
||||
struct work_struct fbdev_suspend_work;
|
||||
|
@ -10221,7 +10221,7 @@ static struct drm_framebuffer *
|
||||
mode_fits_in_fbdev(struct drm_device *dev,
|
||||
struct drm_display_mode *mode)
|
||||
{
|
||||
#ifdef CONFIG_DRM_I915_FBDEV
|
||||
#ifdef CONFIG_DRM_FBDEV_EMULATION
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct drm_i915_gem_object *obj;
|
||||
struct drm_framebuffer *fb;
|
||||
@ -13681,7 +13681,7 @@ static struct drm_plane *intel_primary_plane_create(struct drm_device *dev,
|
||||
struct intel_plane *primary;
|
||||
struct intel_plane_state *state;
|
||||
const uint32_t *intel_primary_formats;
|
||||
int num_formats;
|
||||
unsigned int num_formats;
|
||||
|
||||
primary = kzalloc(sizeof(*primary), GFP_KERNEL);
|
||||
if (primary == NULL)
|
||||
@ -14475,7 +14475,7 @@ intel_user_framebuffer_create(struct drm_device *dev,
|
||||
return intel_framebuffer_create(dev, mode_cmd, obj);
|
||||
}
|
||||
|
||||
#ifndef CONFIG_DRM_I915_FBDEV
|
||||
#ifndef CONFIG_DRM_FBDEV_EMULATION
|
||||
static inline void intel_fbdev_output_poll_changed(struct drm_device *dev)
|
||||
{
|
||||
}
|
||||
|
@ -395,7 +395,7 @@ static bool intel_dp_mst_get_hw_state(struct intel_connector *connector)
|
||||
|
||||
static void intel_connector_add_to_fbdev(struct intel_connector *connector)
|
||||
{
|
||||
#ifdef CONFIG_DRM_I915_FBDEV
|
||||
#ifdef CONFIG_DRM_FBDEV_EMULATION
|
||||
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
|
||||
drm_fb_helper_add_one_connector(&dev_priv->fbdev->helper, &connector->base);
|
||||
#endif
|
||||
@ -403,7 +403,7 @@ static void intel_connector_add_to_fbdev(struct intel_connector *connector)
|
||||
|
||||
static void intel_connector_remove_from_fbdev(struct intel_connector *connector)
|
||||
{
|
||||
#ifdef CONFIG_DRM_I915_FBDEV
|
||||
#ifdef CONFIG_DRM_FBDEV_EMULATION
|
||||
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
|
||||
drm_fb_helper_remove_one_connector(&dev_priv->fbdev->helper, &connector->base);
|
||||
#endif
|
||||
|
@ -1203,7 +1203,7 @@ void intel_dvo_init(struct drm_device *dev);
|
||||
|
||||
|
||||
/* legacy fbdev emulation in intel_fbdev.c */
|
||||
#ifdef CONFIG_DRM_I915_FBDEV
|
||||
#ifdef CONFIG_DRM_FBDEV_EMULATION
|
||||
extern int intel_fbdev_init(struct drm_device *dev);
|
||||
extern void intel_fbdev_initial_config(void *data, async_cookie_t cookie);
|
||||
extern void intel_fbdev_fini(struct drm_device *dev);
|
||||
|
@ -55,13 +55,6 @@ static int intel_fbdev_set_par(struct fb_info *info)
|
||||
ret = drm_fb_helper_set_par(info);
|
||||
|
||||
if (ret == 0) {
|
||||
/*
|
||||
* FIXME: fbdev presumes that all callbacks also work from
|
||||
* atomic contexts and relies on that for emergency oops
|
||||
* printing. KMS totally doesn't do that and the locking here is
|
||||
* by far not the only place this goes wrong. Ignore this for
|
||||
* now until we solve this for real.
|
||||
*/
|
||||
mutex_lock(&fb_helper->dev->struct_mutex);
|
||||
intel_fb_obj_invalidate(ifbdev->fb->obj, ORIGIN_GTT);
|
||||
mutex_unlock(&fb_helper->dev->struct_mutex);
|
||||
@ -80,13 +73,6 @@ static int intel_fbdev_blank(int blank, struct fb_info *info)
|
||||
ret = drm_fb_helper_blank(blank, info);
|
||||
|
||||
if (ret == 0) {
|
||||
/*
|
||||
* FIXME: fbdev presumes that all callbacks also work from
|
||||
* atomic contexts and relies on that for emergency oops
|
||||
* printing. KMS totally doesn't do that and the locking here is
|
||||
* by far not the only place this goes wrong. Ignore this for
|
||||
* now until we solve this for real.
|
||||
*/
|
||||
mutex_lock(&fb_helper->dev->struct_mutex);
|
||||
intel_fb_obj_invalidate(ifbdev->fb->obj, ORIGIN_GTT);
|
||||
mutex_unlock(&fb_helper->dev->struct_mutex);
|
||||
@ -106,13 +92,6 @@ static int intel_fbdev_pan_display(struct fb_var_screeninfo *var,
|
||||
ret = drm_fb_helper_pan_display(var, info);
|
||||
|
||||
if (ret == 0) {
|
||||
/*
|
||||
* FIXME: fbdev presumes that all callbacks also work from
|
||||
* atomic contexts and relies on that for emergency oops
|
||||
* printing. KMS totally doesn't do that and the locking here is
|
||||
* by far not the only place this goes wrong. Ignore this for
|
||||
* now until we solve this for real.
|
||||
*/
|
||||
mutex_lock(&fb_helper->dev->struct_mutex);
|
||||
intel_fb_obj_invalidate(ifbdev->fb->obj, ORIGIN_GTT);
|
||||
mutex_unlock(&fb_helper->dev->struct_mutex);
|
||||
@ -125,9 +104,9 @@ static struct fb_ops intelfb_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.fb_check_var = drm_fb_helper_check_var,
|
||||
.fb_set_par = intel_fbdev_set_par,
|
||||
.fb_fillrect = cfb_fillrect,
|
||||
.fb_copyarea = cfb_copyarea,
|
||||
.fb_imageblit = cfb_imageblit,
|
||||
.fb_fillrect = drm_fb_helper_cfb_fillrect,
|
||||
.fb_copyarea = drm_fb_helper_cfb_copyarea,
|
||||
.fb_imageblit = drm_fb_helper_cfb_imageblit,
|
||||
.fb_pan_display = intel_fbdev_pan_display,
|
||||
.fb_blank = intel_fbdev_blank,
|
||||
.fb_setcmap = drm_fb_helper_setcmap,
|
||||
@ -236,9 +215,9 @@ static int intelfb_create(struct drm_fb_helper *helper,
|
||||
obj = intel_fb->obj;
|
||||
size = obj->base.size;
|
||||
|
||||
info = framebuffer_alloc(0, &dev->pdev->dev);
|
||||
if (!info) {
|
||||
ret = -ENOMEM;
|
||||
info = drm_fb_helper_alloc_fbi(helper);
|
||||
if (IS_ERR(info)) {
|
||||
ret = PTR_ERR(info);
|
||||
goto out_unpin;
|
||||
}
|
||||
|
||||
@ -247,24 +226,13 @@ static int intelfb_create(struct drm_fb_helper *helper,
|
||||
fb = &ifbdev->fb->base;
|
||||
|
||||
ifbdev->helper.fb = fb;
|
||||
ifbdev->helper.fbdev = info;
|
||||
|
||||
strcpy(info->fix.id, "inteldrmfb");
|
||||
|
||||
info->flags = FBINFO_DEFAULT | FBINFO_CAN_FORCE_OUTPUT;
|
||||
info->fbops = &intelfb_ops;
|
||||
|
||||
ret = fb_alloc_cmap(&info->cmap, 256, 0);
|
||||
if (ret) {
|
||||
ret = -ENOMEM;
|
||||
goto out_unpin;
|
||||
}
|
||||
/* setup aperture base/size for vesafb takeover */
|
||||
info->apertures = alloc_apertures(1);
|
||||
if (!info->apertures) {
|
||||
ret = -ENOMEM;
|
||||
goto out_unpin;
|
||||
}
|
||||
info->apertures->ranges[0].base = dev->mode_config.fb_base;
|
||||
info->apertures->ranges[0].size = dev_priv->gtt.mappable_end;
|
||||
|
||||
@ -276,7 +244,7 @@ static int intelfb_create(struct drm_fb_helper *helper,
|
||||
size);
|
||||
if (!info->screen_base) {
|
||||
ret = -ENOSPC;
|
||||
goto out_unpin;
|
||||
goto out_destroy_fbi;
|
||||
}
|
||||
info->screen_size = size;
|
||||
|
||||
@ -303,6 +271,8 @@ static int intelfb_create(struct drm_fb_helper *helper,
|
||||
vga_switcheroo_client_fb_set(dev->pdev, info);
|
||||
return 0;
|
||||
|
||||
out_destroy_fbi:
|
||||
drm_fb_helper_release_fbi(helper);
|
||||
out_unpin:
|
||||
i915_gem_object_ggtt_unpin(obj);
|
||||
drm_gem_object_unreference(&obj->base);
|
||||
@ -544,16 +514,9 @@ static const struct drm_fb_helper_funcs intel_fb_helper_funcs = {
|
||||
static void intel_fbdev_destroy(struct drm_device *dev,
|
||||
struct intel_fbdev *ifbdev)
|
||||
{
|
||||
if (ifbdev->helper.fbdev) {
|
||||
struct fb_info *info = ifbdev->helper.fbdev;
|
||||
|
||||
unregister_framebuffer(info);
|
||||
iounmap(info->screen_base);
|
||||
if (info->cmap.len)
|
||||
fb_dealloc_cmap(&info->cmap);
|
||||
|
||||
framebuffer_release(info);
|
||||
}
|
||||
drm_fb_helper_unregister_fbi(&ifbdev->helper);
|
||||
drm_fb_helper_release_fbi(&ifbdev->helper);
|
||||
|
||||
drm_fb_helper_fini(&ifbdev->helper);
|
||||
|
||||
@ -802,7 +765,7 @@ void intel_fbdev_set_suspend(struct drm_device *dev, int state, bool synchronous
|
||||
if (state == FBINFO_STATE_RUNNING && ifbdev->fb->obj->stolen)
|
||||
memset_io(info->screen_base, 0, info->screen_size);
|
||||
|
||||
fb_set_suspend(info, state);
|
||||
drm_fb_helper_set_suspend(&ifbdev->helper, state);
|
||||
console_unlock();
|
||||
}
|
||||
|
||||
|
@ -70,18 +70,22 @@ int mga_crtc_cursor_set(struct drm_crtc *crtc,
|
||||
BUG_ON(pixels_2 != pixels_current && pixels_2 != pixels_prev);
|
||||
BUG_ON(pixels_current == pixels_prev);
|
||||
|
||||
obj = drm_gem_object_lookup(dev, file_priv, handle);
|
||||
if (!obj)
|
||||
return -ENOENT;
|
||||
|
||||
ret = mgag200_bo_reserve(pixels_1, true);
|
||||
if (ret) {
|
||||
WREG8(MGA_CURPOSXL, 0);
|
||||
WREG8(MGA_CURPOSXH, 0);
|
||||
return ret;
|
||||
goto out_unref;
|
||||
}
|
||||
ret = mgag200_bo_reserve(pixels_2, true);
|
||||
if (ret) {
|
||||
WREG8(MGA_CURPOSXL, 0);
|
||||
WREG8(MGA_CURPOSXH, 0);
|
||||
mgag200_bo_unreserve(pixels_1);
|
||||
return ret;
|
||||
goto out_unreserve1;
|
||||
}
|
||||
|
||||
if (!handle) {
|
||||
@ -106,16 +110,6 @@ int mga_crtc_cursor_set(struct drm_crtc *crtc,
|
||||
}
|
||||
}
|
||||
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
obj = drm_gem_object_lookup(dev, file_priv, handle);
|
||||
if (!obj) {
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
ret = -ENOENT;
|
||||
goto out1;
|
||||
}
|
||||
drm_gem_object_unreference(obj);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
bo = gem_to_mga_bo(obj);
|
||||
ret = mgag200_bo_reserve(bo, true);
|
||||
if (ret) {
|
||||
@ -252,7 +246,11 @@ int mga_crtc_cursor_set(struct drm_crtc *crtc,
|
||||
if (ret)
|
||||
mga_hide_cursor(mdev);
|
||||
mgag200_bo_unreserve(pixels_1);
|
||||
out_unreserve1:
|
||||
mgag200_bo_unreserve(pixels_2);
|
||||
out_unref:
|
||||
drm_gem_object_unreference_unlocked(obj);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -101,7 +101,7 @@ static void mga_fillrect(struct fb_info *info,
|
||||
const struct fb_fillrect *rect)
|
||||
{
|
||||
struct mga_fbdev *mfbdev = info->par;
|
||||
sys_fillrect(info, rect);
|
||||
drm_fb_helper_sys_fillrect(info, rect);
|
||||
mga_dirty_update(mfbdev, rect->dx, rect->dy, rect->width,
|
||||
rect->height);
|
||||
}
|
||||
@ -110,7 +110,7 @@ static void mga_copyarea(struct fb_info *info,
|
||||
const struct fb_copyarea *area)
|
||||
{
|
||||
struct mga_fbdev *mfbdev = info->par;
|
||||
sys_copyarea(info, area);
|
||||
drm_fb_helper_sys_copyarea(info, area);
|
||||
mga_dirty_update(mfbdev, area->dx, area->dy, area->width,
|
||||
area->height);
|
||||
}
|
||||
@ -119,7 +119,7 @@ static void mga_imageblit(struct fb_info *info,
|
||||
const struct fb_image *image)
|
||||
{
|
||||
struct mga_fbdev *mfbdev = info->par;
|
||||
sys_imageblit(info, image);
|
||||
drm_fb_helper_sys_imageblit(info, image);
|
||||
mga_dirty_update(mfbdev, image->dx, image->dy, image->width,
|
||||
image->height);
|
||||
}
|
||||
@ -166,7 +166,6 @@ static int mgag200fb_create(struct drm_fb_helper *helper,
|
||||
struct fb_info *info;
|
||||
struct drm_framebuffer *fb;
|
||||
struct drm_gem_object *gobj = NULL;
|
||||
struct device *device = &dev->pdev->dev;
|
||||
int ret;
|
||||
void *sysram;
|
||||
int size;
|
||||
@ -189,9 +188,9 @@ static int mgag200fb_create(struct drm_fb_helper *helper,
|
||||
if (!sysram)
|
||||
return -ENOMEM;
|
||||
|
||||
info = framebuffer_alloc(0, device);
|
||||
if (info == NULL)
|
||||
return -ENOMEM;
|
||||
info = drm_fb_helper_alloc_fbi(helper);
|
||||
if (IS_ERR(info))
|
||||
return PTR_ERR(info);
|
||||
|
||||
info->par = mfbdev;
|
||||
|
||||
@ -206,14 +205,6 @@ static int mgag200fb_create(struct drm_fb_helper *helper,
|
||||
|
||||
/* setup helper */
|
||||
mfbdev->helper.fb = fb;
|
||||
mfbdev->helper.fbdev = info;
|
||||
|
||||
ret = fb_alloc_cmap(&info->cmap, 256, 0);
|
||||
if (ret) {
|
||||
DRM_ERROR("%s: can't allocate color map\n", info->fix.id);
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
strcpy(info->fix.id, "mgadrmfb");
|
||||
|
||||
@ -221,11 +212,6 @@ static int mgag200fb_create(struct drm_fb_helper *helper,
|
||||
info->fbops = &mgag200fb_ops;
|
||||
|
||||
/* setup aperture base/size for vesafb takeover */
|
||||
info->apertures = alloc_apertures(1);
|
||||
if (!info->apertures) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
info->apertures->ranges[0].base = mdev->dev->mode_config.fb_base;
|
||||
info->apertures->ranges[0].size = mdev->mc.vram_size;
|
||||
|
||||
@ -240,24 +226,15 @@ static int mgag200fb_create(struct drm_fb_helper *helper,
|
||||
DRM_DEBUG_KMS("allocated %dx%d\n",
|
||||
fb->width, fb->height);
|
||||
return 0;
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mga_fbdev_destroy(struct drm_device *dev,
|
||||
struct mga_fbdev *mfbdev)
|
||||
{
|
||||
struct fb_info *info;
|
||||
struct mga_framebuffer *mfb = &mfbdev->mfb;
|
||||
|
||||
if (mfbdev->helper.fbdev) {
|
||||
info = mfbdev->helper.fbdev;
|
||||
|
||||
unregister_framebuffer(info);
|
||||
if (info->cmap.len)
|
||||
fb_dealloc_cmap(&info->cmap);
|
||||
framebuffer_release(info);
|
||||
}
|
||||
drm_fb_helper_unregister_fbi(&mfbdev->helper);
|
||||
drm_fb_helper_release_fbi(&mfbdev->helper);
|
||||
|
||||
if (mfb->obj) {
|
||||
drm_gem_object_unreference_unlocked(mfb->obj);
|
||||
|
@ -345,23 +345,15 @@ mgag200_dumb_mmap_offset(struct drm_file *file,
|
||||
uint64_t *offset)
|
||||
{
|
||||
struct drm_gem_object *obj;
|
||||
int ret;
|
||||
struct mgag200_bo *bo;
|
||||
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
obj = drm_gem_object_lookup(dev, file, handle);
|
||||
if (obj == NULL) {
|
||||
ret = -ENOENT;
|
||||
goto out_unlock;
|
||||
}
|
||||
if (obj == NULL)
|
||||
return -ENOENT;
|
||||
|
||||
bo = gem_to_mga_bo(obj);
|
||||
*offset = mgag200_bo_mmap_offset(bo);
|
||||
|
||||
drm_gem_object_unreference(obj);
|
||||
ret = 0;
|
||||
out_unlock:
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
return ret;
|
||||
|
||||
drm_gem_object_unreference_unlocked(obj);
|
||||
return 0;
|
||||
}
|
||||
|
@ -43,11 +43,11 @@ static struct fb_ops msm_fb_ops = {
|
||||
/* Note: to properly handle manual update displays, we wrap the
|
||||
* basic fbdev ops which write to the framebuffer
|
||||
*/
|
||||
.fb_read = fb_sys_read,
|
||||
.fb_write = fb_sys_write,
|
||||
.fb_fillrect = sys_fillrect,
|
||||
.fb_copyarea = sys_copyarea,
|
||||
.fb_imageblit = sys_imageblit,
|
||||
.fb_read = drm_fb_helper_sys_read,
|
||||
.fb_write = drm_fb_helper_sys_write,
|
||||
.fb_fillrect = drm_fb_helper_sys_fillrect,
|
||||
.fb_copyarea = drm_fb_helper_sys_copyarea,
|
||||
.fb_imageblit = drm_fb_helper_sys_imageblit,
|
||||
.fb_mmap = msm_fbdev_mmap,
|
||||
|
||||
.fb_check_var = drm_fb_helper_check_var,
|
||||
@ -144,10 +144,10 @@ static int msm_fbdev_create(struct drm_fb_helper *helper,
|
||||
goto fail_unlock;
|
||||
}
|
||||
|
||||
fbi = framebuffer_alloc(0, dev->dev);
|
||||
if (!fbi) {
|
||||
fbi = drm_fb_helper_alloc_fbi(helper);
|
||||
if (IS_ERR(fbi)) {
|
||||
dev_err(dev->dev, "failed to allocate fb info\n");
|
||||
ret = -ENOMEM;
|
||||
ret = PTR_ERR(fbi);
|
||||
goto fail_unlock;
|
||||
}
|
||||
|
||||
@ -155,7 +155,6 @@ static int msm_fbdev_create(struct drm_fb_helper *helper,
|
||||
|
||||
fbdev->fb = fb;
|
||||
helper->fb = fb;
|
||||
helper->fbdev = fbi;
|
||||
|
||||
fbi->par = helper;
|
||||
fbi->flags = FBINFO_DEFAULT;
|
||||
@ -163,12 +162,6 @@ static int msm_fbdev_create(struct drm_fb_helper *helper,
|
||||
|
||||
strcpy(fbi->fix.id, "msm");
|
||||
|
||||
ret = fb_alloc_cmap(&fbi->cmap, 256, 0);
|
||||
if (ret) {
|
||||
ret = -ENOMEM;
|
||||
goto fail_unlock;
|
||||
}
|
||||
|
||||
drm_fb_helper_fill_fix(fbi, fb->pitches[0], fb->depth);
|
||||
drm_fb_helper_fill_var(fbi, helper, sizes->fb_width, sizes->fb_height);
|
||||
|
||||
@ -191,7 +184,6 @@ fail_unlock:
|
||||
fail:
|
||||
|
||||
if (ret) {
|
||||
framebuffer_release(fbi);
|
||||
if (fb) {
|
||||
drm_framebuffer_unregister_private(fb);
|
||||
drm_framebuffer_remove(fb);
|
||||
@ -266,17 +258,11 @@ void msm_fbdev_free(struct drm_device *dev)
|
||||
struct msm_drm_private *priv = dev->dev_private;
|
||||
struct drm_fb_helper *helper = priv->fbdev;
|
||||
struct msm_fbdev *fbdev;
|
||||
struct fb_info *fbi;
|
||||
|
||||
DBG();
|
||||
|
||||
fbi = helper->fbdev;
|
||||
|
||||
/* only cleanup framebuffer if it is present */
|
||||
if (fbi) {
|
||||
unregister_framebuffer(fbi);
|
||||
framebuffer_release(fbi);
|
||||
}
|
||||
drm_fb_helper_unregister_fbi(helper);
|
||||
drm_fb_helper_release_fbi(helper);
|
||||
|
||||
drm_fb_helper_fini(helper);
|
||||
|
||||
|
@ -261,7 +261,7 @@ nv10_overlay_init(struct drm_device *device)
|
||||
{
|
||||
struct nouveau_drm *drm = nouveau_drm(device);
|
||||
struct nouveau_plane *plane = kzalloc(sizeof(struct nouveau_plane), GFP_KERNEL);
|
||||
int num_formats = ARRAY_SIZE(formats);
|
||||
unsigned int num_formats = ARRAY_SIZE(formats);
|
||||
int ret;
|
||||
|
||||
if (!plane)
|
||||
|
@ -84,7 +84,7 @@ nouveau_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
|
||||
|
||||
if (ret != -ENODEV)
|
||||
nouveau_fbcon_gpu_lockup(info);
|
||||
cfb_fillrect(info, rect);
|
||||
drm_fb_helper_cfb_fillrect(info, rect);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -116,7 +116,7 @@ nouveau_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *image)
|
||||
|
||||
if (ret != -ENODEV)
|
||||
nouveau_fbcon_gpu_lockup(info);
|
||||
cfb_copyarea(info, image);
|
||||
drm_fb_helper_cfb_copyarea(info, image);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -148,7 +148,7 @@ nouveau_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
|
||||
|
||||
if (ret != -ENODEV)
|
||||
nouveau_fbcon_gpu_lockup(info);
|
||||
cfb_imageblit(info, image);
|
||||
drm_fb_helper_cfb_imageblit(info, image);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -197,9 +197,9 @@ static struct fb_ops nouveau_fbcon_sw_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.fb_check_var = drm_fb_helper_check_var,
|
||||
.fb_set_par = drm_fb_helper_set_par,
|
||||
.fb_fillrect = cfb_fillrect,
|
||||
.fb_copyarea = cfb_copyarea,
|
||||
.fb_imageblit = cfb_imageblit,
|
||||
.fb_fillrect = drm_fb_helper_cfb_fillrect,
|
||||
.fb_copyarea = drm_fb_helper_cfb_copyarea,
|
||||
.fb_imageblit = drm_fb_helper_cfb_imageblit,
|
||||
.fb_pan_display = drm_fb_helper_pan_display,
|
||||
.fb_blank = drm_fb_helper_blank,
|
||||
.fb_setcmap = drm_fb_helper_setcmap,
|
||||
@ -319,7 +319,6 @@ nouveau_fbcon_create(struct drm_fb_helper *helper,
|
||||
struct nouveau_channel *chan;
|
||||
struct nouveau_bo *nvbo;
|
||||
struct drm_mode_fb_cmd2 mode_cmd;
|
||||
struct pci_dev *pdev = dev->pdev;
|
||||
int size, ret;
|
||||
|
||||
mode_cmd.width = sizes->surface_width;
|
||||
@ -365,20 +364,13 @@ nouveau_fbcon_create(struct drm_fb_helper *helper,
|
||||
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
|
||||
info = framebuffer_alloc(0, &pdev->dev);
|
||||
if (!info) {
|
||||
ret = -ENOMEM;
|
||||
info = drm_fb_helper_alloc_fbi(helper);
|
||||
if (IS_ERR(info)) {
|
||||
ret = PTR_ERR(info);
|
||||
goto out_unlock;
|
||||
}
|
||||
info->skip_vt_switch = 1;
|
||||
|
||||
ret = fb_alloc_cmap(&info->cmap, 256, 0);
|
||||
if (ret) {
|
||||
ret = -ENOMEM;
|
||||
framebuffer_release(info);
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
info->par = fbcon;
|
||||
|
||||
nouveau_framebuffer_init(dev, &fbcon->nouveau_fb, &mode_cmd, nvbo);
|
||||
@ -388,7 +380,6 @@ nouveau_fbcon_create(struct drm_fb_helper *helper,
|
||||
|
||||
/* setup helper */
|
||||
fbcon->helper.fb = fb;
|
||||
fbcon->helper.fbdev = info;
|
||||
|
||||
strcpy(info->fix.id, "nouveaufb");
|
||||
if (!chan)
|
||||
@ -450,15 +441,9 @@ static int
|
||||
nouveau_fbcon_destroy(struct drm_device *dev, struct nouveau_fbdev *fbcon)
|
||||
{
|
||||
struct nouveau_framebuffer *nouveau_fb = &fbcon->nouveau_fb;
|
||||
struct fb_info *info;
|
||||
|
||||
if (fbcon->helper.fbdev) {
|
||||
info = fbcon->helper.fbdev;
|
||||
unregister_framebuffer(info);
|
||||
if (info->cmap.len)
|
||||
fb_dealloc_cmap(&info->cmap);
|
||||
framebuffer_release(info);
|
||||
}
|
||||
drm_fb_helper_unregister_fbi(&fbcon->helper);
|
||||
drm_fb_helper_release_fbi(&fbcon->helper);
|
||||
|
||||
if (nouveau_fb->nvbo) {
|
||||
nouveau_bo_unmap(nouveau_fb->nvbo);
|
||||
@ -496,7 +481,7 @@ nouveau_fbcon_set_suspend(struct drm_device *dev, int state)
|
||||
console_lock();
|
||||
if (state == FBINFO_STATE_RUNNING)
|
||||
nouveau_fbcon_accel_restore(dev);
|
||||
fb_set_suspend(drm->fbcon->helper.fbdev, state);
|
||||
drm_fb_helper_set_suspend(&drm->fbcon->helper, state);
|
||||
if (state != FBINFO_STATE_RUNNING)
|
||||
nouveau_fbcon_accel_save_disable(dev);
|
||||
console_unlock();
|
||||
|
@ -424,10 +424,8 @@ nouveau_ttm_init(struct nouveau_drm *drm)
|
||||
void
|
||||
nouveau_ttm_fini(struct nouveau_drm *drm)
|
||||
{
|
||||
mutex_lock(&drm->dev->struct_mutex);
|
||||
ttm_bo_clean_mm(&drm->ttm.bdev, TTM_PL_VRAM);
|
||||
ttm_bo_clean_mm(&drm->ttm.bdev, TTM_PL_TT);
|
||||
mutex_unlock(&drm->dev->struct_mutex);
|
||||
|
||||
ttm_bo_device_release(&drm->ttm.bdev);
|
||||
|
||||
|
@ -388,11 +388,13 @@ static void omap_crtc_mode_set_nofb(struct drm_crtc *crtc)
|
||||
copy_timings_drm_to_omap(&omap_crtc->timings, mode);
|
||||
}
|
||||
|
||||
static void omap_crtc_atomic_begin(struct drm_crtc *crtc)
|
||||
static void omap_crtc_atomic_begin(struct drm_crtc *crtc,
|
||||
struct drm_crtc_state *old_crtc_state)
|
||||
{
|
||||
}
|
||||
|
||||
static void omap_crtc_atomic_flush(struct drm_crtc *crtc)
|
||||
static void omap_crtc_atomic_flush(struct drm_crtc *crtc,
|
||||
struct drm_crtc_state *old_crtc_state)
|
||||
{
|
||||
struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
|
||||
|
||||
|
@ -86,11 +86,11 @@ static struct fb_ops omap_fb_ops = {
|
||||
/* Note: to properly handle manual update displays, we wrap the
|
||||
* basic fbdev ops which write to the framebuffer
|
||||
*/
|
||||
.fb_read = fb_sys_read,
|
||||
.fb_write = fb_sys_write,
|
||||
.fb_fillrect = sys_fillrect,
|
||||
.fb_copyarea = sys_copyarea,
|
||||
.fb_imageblit = sys_imageblit,
|
||||
.fb_read = drm_fb_helper_sys_read,
|
||||
.fb_write = drm_fb_helper_sys_write,
|
||||
.fb_fillrect = drm_fb_helper_sys_fillrect,
|
||||
.fb_copyarea = drm_fb_helper_sys_copyarea,
|
||||
.fb_imageblit = drm_fb_helper_sys_imageblit,
|
||||
|
||||
.fb_check_var = drm_fb_helper_check_var,
|
||||
.fb_set_par = drm_fb_helper_set_par,
|
||||
@ -179,10 +179,10 @@ static int omap_fbdev_create(struct drm_fb_helper *helper,
|
||||
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
|
||||
fbi = framebuffer_alloc(0, dev->dev);
|
||||
if (!fbi) {
|
||||
fbi = drm_fb_helper_alloc_fbi(helper);
|
||||
if (IS_ERR(fbi)) {
|
||||
dev_err(dev->dev, "failed to allocate fb info\n");
|
||||
ret = -ENOMEM;
|
||||
ret = PTR_ERR(fbi);
|
||||
goto fail_unlock;
|
||||
}
|
||||
|
||||
@ -190,7 +190,6 @@ static int omap_fbdev_create(struct drm_fb_helper *helper,
|
||||
|
||||
fbdev->fb = fb;
|
||||
helper->fb = fb;
|
||||
helper->fbdev = fbi;
|
||||
|
||||
fbi->par = helper;
|
||||
fbi->flags = FBINFO_DEFAULT;
|
||||
@ -198,12 +197,6 @@ static int omap_fbdev_create(struct drm_fb_helper *helper,
|
||||
|
||||
strcpy(fbi->fix.id, MODULE_NAME);
|
||||
|
||||
ret = fb_alloc_cmap(&fbi->cmap, 256, 0);
|
||||
if (ret) {
|
||||
ret = -ENOMEM;
|
||||
goto fail_unlock;
|
||||
}
|
||||
|
||||
drm_fb_helper_fill_fix(fbi, fb->pitches[0], fb->depth);
|
||||
drm_fb_helper_fill_var(fbi, helper, sizes->fb_width, sizes->fb_height);
|
||||
|
||||
@ -236,8 +229,9 @@ fail_unlock:
|
||||
fail:
|
||||
|
||||
if (ret) {
|
||||
if (fbi)
|
||||
framebuffer_release(fbi);
|
||||
|
||||
drm_fb_helper_release_fbi(helper);
|
||||
|
||||
if (fb) {
|
||||
drm_framebuffer_unregister_private(fb);
|
||||
drm_framebuffer_remove(fb);
|
||||
@ -312,17 +306,11 @@ void omap_fbdev_free(struct drm_device *dev)
|
||||
struct omap_drm_private *priv = dev->dev_private;
|
||||
struct drm_fb_helper *helper = priv->fbdev;
|
||||
struct omap_fbdev *fbdev;
|
||||
struct fb_info *fbi;
|
||||
|
||||
DBG();
|
||||
|
||||
fbi = helper->fbdev;
|
||||
|
||||
/* only cleanup framebuffer if it is present */
|
||||
if (fbi) {
|
||||
unregister_framebuffer(fbi);
|
||||
framebuffer_release(fbi);
|
||||
}
|
||||
drm_fb_helper_unregister_fbi(helper);
|
||||
drm_fb_helper_release_fbi(helper);
|
||||
|
||||
drm_fb_helper_fini(helper);
|
||||
|
||||
|
@ -197,7 +197,7 @@ static void qxl_fb_fillrect(struct fb_info *info,
|
||||
{
|
||||
struct qxl_fbdev *qfbdev = info->par;
|
||||
|
||||
sys_fillrect(info, rect);
|
||||
drm_fb_helper_sys_fillrect(info, rect);
|
||||
qxl_dirty_update(qfbdev, rect->dx, rect->dy, rect->width,
|
||||
rect->height);
|
||||
}
|
||||
@ -207,7 +207,7 @@ static void qxl_fb_copyarea(struct fb_info *info,
|
||||
{
|
||||
struct qxl_fbdev *qfbdev = info->par;
|
||||
|
||||
sys_copyarea(info, area);
|
||||
drm_fb_helper_sys_copyarea(info, area);
|
||||
qxl_dirty_update(qfbdev, area->dx, area->dy, area->width,
|
||||
area->height);
|
||||
}
|
||||
@ -217,7 +217,7 @@ static void qxl_fb_imageblit(struct fb_info *info,
|
||||
{
|
||||
struct qxl_fbdev *qfbdev = info->par;
|
||||
|
||||
sys_imageblit(info, image);
|
||||
drm_fb_helper_sys_imageblit(info, image);
|
||||
qxl_dirty_update(qfbdev, image->dx, image->dy, image->width,
|
||||
image->height);
|
||||
}
|
||||
@ -345,7 +345,6 @@ static int qxlfb_create(struct qxl_fbdev *qfbdev,
|
||||
struct drm_mode_fb_cmd2 mode_cmd;
|
||||
struct drm_gem_object *gobj = NULL;
|
||||
struct qxl_bo *qbo = NULL;
|
||||
struct device *device = &qdev->pdev->dev;
|
||||
int ret;
|
||||
int size;
|
||||
int bpp = sizes->surface_bpp;
|
||||
@ -374,9 +373,9 @@ static int qxlfb_create(struct qxl_fbdev *qfbdev,
|
||||
shadow);
|
||||
size = mode_cmd.pitches[0] * mode_cmd.height;
|
||||
|
||||
info = framebuffer_alloc(0, device);
|
||||
if (info == NULL) {
|
||||
ret = -ENOMEM;
|
||||
info = drm_fb_helper_alloc_fbi(&qfbdev->helper);
|
||||
if (IS_ERR(info)) {
|
||||
ret = PTR_ERR(info);
|
||||
goto out_unref;
|
||||
}
|
||||
|
||||
@ -388,7 +387,7 @@ static int qxlfb_create(struct qxl_fbdev *qfbdev,
|
||||
|
||||
/* setup helper with fb data */
|
||||
qfbdev->helper.fb = fb;
|
||||
qfbdev->helper.fbdev = info;
|
||||
|
||||
qfbdev->shadow = shadow;
|
||||
strcpy(info->fix.id, "qxldrmfb");
|
||||
|
||||
@ -410,11 +409,6 @@ static int qxlfb_create(struct qxl_fbdev *qfbdev,
|
||||
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 = qdev->ddev->mode_config.fb_base;
|
||||
info->apertures->ranges[0].size = qdev->vram_size;
|
||||
|
||||
@ -423,13 +417,7 @@ static int qxlfb_create(struct qxl_fbdev *qfbdev,
|
||||
|
||||
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;
|
||||
goto out_destroy_fbi;
|
||||
}
|
||||
|
||||
info->fbdefio = &qxl_defio;
|
||||
@ -441,6 +429,8 @@ static int qxlfb_create(struct qxl_fbdev *qfbdev,
|
||||
DRM_INFO("fb: depth %d, pitch %d, width %d, height %d\n", fb->depth, fb->pitches[0], fb->width, fb->height);
|
||||
return 0;
|
||||
|
||||
out_destroy_fbi:
|
||||
drm_fb_helper_release_fbi(&qfbdev->helper);
|
||||
out_unref:
|
||||
if (qbo) {
|
||||
ret = qxl_bo_reserve(qbo, false);
|
||||
@ -479,15 +469,11 @@ static int qxl_fb_find_or_create_single(
|
||||
|
||||
static int qxl_fbdev_destroy(struct drm_device *dev, struct qxl_fbdev *qfbdev)
|
||||
{
|
||||
struct fb_info *info;
|
||||
struct qxl_framebuffer *qfb = &qfbdev->qfb;
|
||||
|
||||
if (qfbdev->helper.fbdev) {
|
||||
info = qfbdev->helper.fbdev;
|
||||
drm_fb_helper_unregister_fbi(&qfbdev->helper);
|
||||
drm_fb_helper_release_fbi(&qfbdev->helper);
|
||||
|
||||
unregister_framebuffer(info);
|
||||
framebuffer_release(info);
|
||||
}
|
||||
if (qfb->obj) {
|
||||
qxlfb_destroy_pinned_object(qfb->obj);
|
||||
qfb->obj = NULL;
|
||||
@ -557,7 +543,7 @@ void qxl_fbdev_fini(struct qxl_device *qdev)
|
||||
|
||||
void qxl_fbdev_set_suspend(struct qxl_device *qdev, int state)
|
||||
{
|
||||
fb_set_suspend(qdev->mode_info.qfbdev->helper.fbdev, state);
|
||||
drm_fb_helper_set_suspend(&qdev->mode_info.qfbdev->helper, state);
|
||||
}
|
||||
|
||||
bool qxl_fbdev_qobj_is_fb(struct qxl_device *qdev, struct qxl_bo *qobj)
|
||||
|
@ -272,7 +272,6 @@ void qxl_bo_force_delete(struct qxl_device *qdev)
|
||||
return;
|
||||
dev_err(qdev->dev, "Userspace still has active objects !\n");
|
||||
list_for_each_entry_safe(bo, n, &qdev->gem.objects, list) {
|
||||
mutex_lock(&qdev->ddev->struct_mutex);
|
||||
dev_err(qdev->dev, "%p %p %lu %lu force free\n",
|
||||
&bo->gem_base, bo, (unsigned long)bo->gem_base.size,
|
||||
*((unsigned long *)&bo->gem_base.refcount));
|
||||
@ -280,8 +279,7 @@ void qxl_bo_force_delete(struct qxl_device *qdev)
|
||||
list_del_init(&bo->list);
|
||||
mutex_unlock(&qdev->gem.mutex);
|
||||
/* this should unref the ttm bo */
|
||||
drm_gem_object_unreference(&bo->gem_base);
|
||||
mutex_unlock(&qdev->ddev->struct_mutex);
|
||||
drm_gem_object_unreference_unlocked(&bo->gem_base);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -82,9 +82,9 @@ static struct fb_ops radeonfb_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.fb_check_var = drm_fb_helper_check_var,
|
||||
.fb_set_par = radeon_fb_helper_set_par,
|
||||
.fb_fillrect = cfb_fillrect,
|
||||
.fb_copyarea = cfb_copyarea,
|
||||
.fb_imageblit = cfb_imageblit,
|
||||
.fb_fillrect = drm_fb_helper_cfb_fillrect,
|
||||
.fb_copyarea = drm_fb_helper_cfb_copyarea,
|
||||
.fb_imageblit = drm_fb_helper_cfb_imageblit,
|
||||
.fb_pan_display = drm_fb_helper_pan_display,
|
||||
.fb_blank = drm_fb_helper_blank,
|
||||
.fb_setcmap = drm_fb_helper_setcmap,
|
||||
@ -227,7 +227,6 @@ static int radeonfb_create(struct drm_fb_helper *helper,
|
||||
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;
|
||||
|
||||
@ -250,9 +249,9 @@ static int radeonfb_create(struct drm_fb_helper *helper,
|
||||
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;
|
||||
info = drm_fb_helper_alloc_fbi(helper);
|
||||
if (IS_ERR(info)) {
|
||||
ret = PTR_ERR(info);
|
||||
goto out_unref;
|
||||
}
|
||||
|
||||
@ -262,14 +261,13 @@ static int radeonfb_create(struct drm_fb_helper *helper,
|
||||
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;
|
||||
goto out_destroy_fbi;
|
||||
}
|
||||
|
||||
fb = &rfbdev->rfb.base;
|
||||
|
||||
/* setup helper */
|
||||
rfbdev->helper.fb = fb;
|
||||
rfbdev->helper.fbdev = info;
|
||||
|
||||
memset_io(rbo->kptr, 0x0, radeon_bo_size(rbo));
|
||||
|
||||
@ -289,11 +287,6 @@ static int radeonfb_create(struct drm_fb_helper *helper,
|
||||
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;
|
||||
|
||||
@ -301,13 +294,7 @@ static int radeonfb_create(struct drm_fb_helper *helper,
|
||||
|
||||
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;
|
||||
goto out_destroy_fbi;
|
||||
}
|
||||
|
||||
DRM_INFO("fb mappable at 0x%lX\n", info->fix.smem_start);
|
||||
@ -319,6 +306,8 @@ static int radeonfb_create(struct drm_fb_helper *helper,
|
||||
vga_switcheroo_client_fb_set(rdev->ddev->pdev, info);
|
||||
return 0;
|
||||
|
||||
out_destroy_fbi:
|
||||
drm_fb_helper_release_fbi(helper);
|
||||
out_unref:
|
||||
if (rbo) {
|
||||
|
||||
@ -339,17 +328,10 @@ void radeon_fb_output_poll_changed(struct radeon_device *rdev)
|
||||
|
||||
static int radeon_fbdev_destroy(struct drm_device *dev, struct radeon_fbdev *rfbdev)
|
||||
{
|
||||
struct fb_info *info;
|
||||
struct radeon_framebuffer *rfb = &rfbdev->rfb;
|
||||
|
||||
if (rfbdev->helper.fbdev) {
|
||||
info = rfbdev->helper.fbdev;
|
||||
|
||||
unregister_framebuffer(info);
|
||||
if (info->cmap.len)
|
||||
fb_dealloc_cmap(&info->cmap);
|
||||
framebuffer_release(info);
|
||||
}
|
||||
drm_fb_helper_unregister_fbi(&rfbdev->helper);
|
||||
drm_fb_helper_release_fbi(&rfbdev->helper);
|
||||
|
||||
if (rfb->obj) {
|
||||
radeonfb_destroy_pinned_object(rfb->obj);
|
||||
|
@ -37,9 +37,9 @@ static int rockchip_fbdev_mmap(struct fb_info *info,
|
||||
static struct fb_ops rockchip_drm_fbdev_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.fb_mmap = rockchip_fbdev_mmap,
|
||||
.fb_fillrect = cfb_fillrect,
|
||||
.fb_copyarea = cfb_copyarea,
|
||||
.fb_imageblit = cfb_imageblit,
|
||||
.fb_fillrect = drm_fb_helper_cfb_fillrect,
|
||||
.fb_copyarea = drm_fb_helper_cfb_copyarea,
|
||||
.fb_imageblit = drm_fb_helper_cfb_imageblit,
|
||||
.fb_check_var = drm_fb_helper_check_var,
|
||||
.fb_set_par = drm_fb_helper_set_par,
|
||||
.fb_blank = drm_fb_helper_blank,
|
||||
@ -77,10 +77,10 @@ static int rockchip_drm_fbdev_create(struct drm_fb_helper *helper,
|
||||
|
||||
private->fbdev_bo = &rk_obj->base;
|
||||
|
||||
fbi = framebuffer_alloc(0, dev->dev);
|
||||
if (!fbi) {
|
||||
dev_err(dev->dev, "Failed to allocate framebuffer info.\n");
|
||||
ret = -ENOMEM;
|
||||
fbi = drm_fb_helper_alloc_fbi(helper);
|
||||
if (IS_ERR(fbi)) {
|
||||
dev_err(dev->dev, "Failed to create framebuffer info.\n");
|
||||
ret = PTR_ERR(fbi);
|
||||
goto err_rockchip_gem_free_object;
|
||||
}
|
||||
|
||||
@ -89,21 +89,13 @@ static int rockchip_drm_fbdev_create(struct drm_fb_helper *helper,
|
||||
if (IS_ERR(helper->fb)) {
|
||||
dev_err(dev->dev, "Failed to allocate DRM framebuffer.\n");
|
||||
ret = PTR_ERR(helper->fb);
|
||||
goto err_framebuffer_release;
|
||||
goto err_release_fbi;
|
||||
}
|
||||
|
||||
helper->fbdev = fbi;
|
||||
|
||||
fbi->par = helper;
|
||||
fbi->flags = FBINFO_FLAG_DEFAULT;
|
||||
fbi->fbops = &rockchip_drm_fbdev_ops;
|
||||
|
||||
ret = fb_alloc_cmap(&fbi->cmap, 256, 0);
|
||||
if (ret) {
|
||||
dev_err(dev->dev, "Failed to allocate color map.\n");
|
||||
goto err_drm_framebuffer_unref;
|
||||
}
|
||||
|
||||
fb = helper->fb;
|
||||
drm_fb_helper_fill_fix(fbi, fb->pitches[0], fb->depth);
|
||||
drm_fb_helper_fill_var(fbi, helper, sizes->fb_width, sizes->fb_height);
|
||||
@ -124,10 +116,8 @@ static int rockchip_drm_fbdev_create(struct drm_fb_helper *helper,
|
||||
|
||||
return 0;
|
||||
|
||||
err_drm_framebuffer_unref:
|
||||
drm_framebuffer_unreference(helper->fb);
|
||||
err_framebuffer_release:
|
||||
framebuffer_release(fbi);
|
||||
err_release_fbi:
|
||||
drm_fb_helper_release_fbi(helper);
|
||||
err_rockchip_gem_free_object:
|
||||
rockchip_gem_free_object(&rk_obj->base);
|
||||
return ret;
|
||||
@ -190,21 +180,8 @@ void rockchip_drm_fbdev_fini(struct drm_device *dev)
|
||||
|
||||
helper = &private->fbdev_helper;
|
||||
|
||||
if (helper->fbdev) {
|
||||
struct fb_info *info;
|
||||
int ret;
|
||||
|
||||
info = helper->fbdev;
|
||||
ret = unregister_framebuffer(info);
|
||||
if (ret < 0)
|
||||
DRM_DEBUG_KMS("failed unregister_framebuffer() - %d\n",
|
||||
ret);
|
||||
|
||||
if (info->cmap.len)
|
||||
fb_dealloc_cmap(&info->cmap);
|
||||
|
||||
framebuffer_release(info);
|
||||
}
|
||||
drm_fb_helper_unregister_fbi(helper);
|
||||
drm_fb_helper_release_fbi(helper);
|
||||
|
||||
if (helper->fb)
|
||||
drm_framebuffer_unreference(helper->fb);
|
||||
|
@ -200,13 +200,10 @@ int rockchip_gem_dumb_map_offset(struct drm_file *file_priv,
|
||||
struct drm_gem_object *obj;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
|
||||
obj = drm_gem_object_lookup(dev, file_priv, handle);
|
||||
if (!obj) {
|
||||
DRM_ERROR("failed to lookup gem object.\n");
|
||||
ret = -EINVAL;
|
||||
goto unlock;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = drm_gem_create_mmap_offset(obj);
|
||||
@ -217,10 +214,9 @@ int rockchip_gem_dumb_map_offset(struct drm_file *file_priv,
|
||||
DRM_DEBUG_KMS("offset = 0x%llx\n", *offset);
|
||||
|
||||
out:
|
||||
drm_gem_object_unreference(obj);
|
||||
unlock:
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
return ret;
|
||||
drm_gem_object_unreference_unlocked(obj);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -184,9 +184,9 @@ unreference:
|
||||
#ifdef CONFIG_DRM_TEGRA_FBDEV
|
||||
static struct fb_ops tegra_fb_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.fb_fillrect = sys_fillrect,
|
||||
.fb_copyarea = sys_copyarea,
|
||||
.fb_imageblit = sys_imageblit,
|
||||
.fb_fillrect = drm_fb_helper_sys_fillrect,
|
||||
.fb_copyarea = drm_fb_helper_sys_copyarea,
|
||||
.fb_imageblit = drm_fb_helper_sys_imageblit,
|
||||
.fb_check_var = drm_fb_helper_check_var,
|
||||
.fb_set_par = drm_fb_helper_set_par,
|
||||
.fb_blank = drm_fb_helper_blank,
|
||||
@ -224,11 +224,11 @@ static int tegra_fbdev_probe(struct drm_fb_helper *helper,
|
||||
if (IS_ERR(bo))
|
||||
return PTR_ERR(bo);
|
||||
|
||||
info = framebuffer_alloc(0, drm->dev);
|
||||
if (!info) {
|
||||
info = drm_fb_helper_alloc_fbi(helper);
|
||||
if (IS_ERR(info)) {
|
||||
dev_err(drm->dev, "failed to allocate framebuffer info\n");
|
||||
drm_gem_object_unreference_unlocked(&bo->gem);
|
||||
return -ENOMEM;
|
||||
return PTR_ERR(info);
|
||||
}
|
||||
|
||||
fbdev->fb = tegra_fb_alloc(drm, &cmd, &bo, 1);
|
||||
@ -248,12 +248,6 @@ static int tegra_fbdev_probe(struct drm_fb_helper *helper,
|
||||
info->flags = FBINFO_FLAG_DEFAULT;
|
||||
info->fbops = &tegra_fb_ops;
|
||||
|
||||
err = fb_alloc_cmap(&info->cmap, 256, 0);
|
||||
if (err < 0) {
|
||||
dev_err(drm->dev, "failed to allocate color map: %d\n", err);
|
||||
goto destroy;
|
||||
}
|
||||
|
||||
drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth);
|
||||
drm_fb_helper_fill_var(info, helper, fb->width, fb->height);
|
||||
|
||||
@ -282,7 +276,7 @@ destroy:
|
||||
drm_framebuffer_unregister_private(fb);
|
||||
tegra_fb_destroy(fb);
|
||||
release:
|
||||
framebuffer_release(info);
|
||||
drm_fb_helper_release_fbi(helper);
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -347,20 +341,9 @@ fini:
|
||||
|
||||
static void tegra_fbdev_exit(struct tegra_fbdev *fbdev)
|
||||
{
|
||||
struct fb_info *info = fbdev->base.fbdev;
|
||||
|
||||
if (info) {
|
||||
int err;
|
||||
|
||||
err = unregister_framebuffer(info);
|
||||
if (err < 0)
|
||||
DRM_DEBUG_KMS("failed to unregister framebuffer\n");
|
||||
|
||||
if (info->cmap.len)
|
||||
fb_dealloc_cmap(&info->cmap);
|
||||
|
||||
framebuffer_release(info);
|
||||
}
|
||||
drm_fb_helper_unregister_fbi(&fbdev->base);
|
||||
drm_fb_helper_release_fbi(&fbdev->base);
|
||||
|
||||
if (fbdev->fb) {
|
||||
drm_framebuffer_unregister_private(&fbdev->fb->base);
|
||||
|
@ -340,7 +340,7 @@ int ttm_tt_swapout(struct ttm_tt *ttm, struct file *persistent_swap_storage)
|
||||
swap_storage = shmem_file_setup("ttm swap",
|
||||
ttm->num_pages << PAGE_SHIFT,
|
||||
0);
|
||||
if (unlikely(IS_ERR(swap_storage))) {
|
||||
if (IS_ERR(swap_storage)) {
|
||||
pr_err("Failed allocating swap storage\n");
|
||||
return PTR_ERR(swap_storage);
|
||||
}
|
||||
@ -354,7 +354,7 @@ int ttm_tt_swapout(struct ttm_tt *ttm, struct file *persistent_swap_storage)
|
||||
if (unlikely(from_page == NULL))
|
||||
continue;
|
||||
to_page = shmem_read_mapping_page(swap_space, i);
|
||||
if (unlikely(IS_ERR(to_page))) {
|
||||
if (IS_ERR(to_page)) {
|
||||
ret = PTR_ERR(to_page);
|
||||
goto out_err;
|
||||
}
|
||||
|
@ -288,7 +288,7 @@ static void udl_fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect
|
||||
{
|
||||
struct udl_fbdev *ufbdev = info->par;
|
||||
|
||||
sys_fillrect(info, rect);
|
||||
drm_fb_helper_sys_fillrect(info, rect);
|
||||
|
||||
udl_handle_damage(&ufbdev->ufb, rect->dx, rect->dy, rect->width,
|
||||
rect->height);
|
||||
@ -298,7 +298,7 @@ static void udl_fb_copyarea(struct fb_info *info, const struct fb_copyarea *regi
|
||||
{
|
||||
struct udl_fbdev *ufbdev = info->par;
|
||||
|
||||
sys_copyarea(info, region);
|
||||
drm_fb_helper_sys_copyarea(info, region);
|
||||
|
||||
udl_handle_damage(&ufbdev->ufb, region->dx, region->dy, region->width,
|
||||
region->height);
|
||||
@ -308,7 +308,7 @@ static void udl_fb_imageblit(struct fb_info *info, const struct fb_image *image)
|
||||
{
|
||||
struct udl_fbdev *ufbdev = info->par;
|
||||
|
||||
sys_imageblit(info, image);
|
||||
drm_fb_helper_sys_imageblit(info, image);
|
||||
|
||||
udl_handle_damage(&ufbdev->ufb, image->dx, image->dy, image->width,
|
||||
image->height);
|
||||
@ -476,7 +476,6 @@ static int udlfb_create(struct drm_fb_helper *helper,
|
||||
container_of(helper, struct udl_fbdev, helper);
|
||||
struct drm_device *dev = ufbdev->helper.dev;
|
||||
struct fb_info *info;
|
||||
struct device *device = dev->dev;
|
||||
struct drm_framebuffer *fb;
|
||||
struct drm_mode_fb_cmd2 mode_cmd;
|
||||
struct udl_gem_object *obj;
|
||||
@ -506,21 +505,20 @@ static int udlfb_create(struct drm_fb_helper *helper,
|
||||
goto out_gfree;
|
||||
}
|
||||
|
||||
info = framebuffer_alloc(0, device);
|
||||
if (!info) {
|
||||
ret = -ENOMEM;
|
||||
info = drm_fb_helper_alloc_fbi(helper);
|
||||
if (IS_ERR(info)) {
|
||||
ret = PTR_ERR(info);
|
||||
goto out_gfree;
|
||||
}
|
||||
info->par = ufbdev;
|
||||
|
||||
ret = udl_framebuffer_init(dev, &ufbdev->ufb, &mode_cmd, obj);
|
||||
if (ret)
|
||||
goto out_gfree;
|
||||
goto out_destroy_fbi;
|
||||
|
||||
fb = &ufbdev->ufb.base;
|
||||
|
||||
ufbdev->helper.fb = fb;
|
||||
ufbdev->helper.fbdev = info;
|
||||
|
||||
strcpy(info->fix.id, "udldrmfb");
|
||||
|
||||
@ -533,18 +531,13 @@ static int udlfb_create(struct drm_fb_helper *helper,
|
||||
drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth);
|
||||
drm_fb_helper_fill_var(info, &ufbdev->helper, sizes->fb_width, sizes->fb_height);
|
||||
|
||||
ret = fb_alloc_cmap(&info->cmap, 256, 0);
|
||||
if (ret) {
|
||||
ret = -ENOMEM;
|
||||
goto out_gfree;
|
||||
}
|
||||
|
||||
|
||||
DRM_DEBUG_KMS("allocated %dx%d vmal %p\n",
|
||||
fb->width, fb->height,
|
||||
ufbdev->ufb.obj->vmapping);
|
||||
|
||||
return ret;
|
||||
out_destroy_fbi:
|
||||
drm_fb_helper_release_fbi(helper);
|
||||
out_gfree:
|
||||
drm_gem_object_unreference(&ufbdev->ufb.obj->base);
|
||||
out:
|
||||
@ -558,14 +551,8 @@ static const struct drm_fb_helper_funcs udl_fb_helper_funcs = {
|
||||
static void udl_fbdev_destroy(struct drm_device *dev,
|
||||
struct udl_fbdev *ufbdev)
|
||||
{
|
||||
struct fb_info *info;
|
||||
if (ufbdev->helper.fbdev) {
|
||||
info = ufbdev->helper.fbdev;
|
||||
unregister_framebuffer(info);
|
||||
if (info->cmap.len)
|
||||
fb_dealloc_cmap(&info->cmap);
|
||||
framebuffer_release(info);
|
||||
}
|
||||
drm_fb_helper_unregister_fbi(&ufbdev->helper);
|
||||
drm_fb_helper_release_fbi(&ufbdev->helper);
|
||||
drm_fb_helper_fini(&ufbdev->helper);
|
||||
drm_framebuffer_unregister_private(&ufbdev->ufb.base);
|
||||
drm_framebuffer_cleanup(&ufbdev->ufb.base);
|
||||
@ -631,11 +618,7 @@ void udl_fbdev_unplug(struct drm_device *dev)
|
||||
return;
|
||||
|
||||
ufbdev = udl->fbdev;
|
||||
if (ufbdev->helper.fbdev) {
|
||||
struct fb_info *info;
|
||||
info = ufbdev->helper.fbdev;
|
||||
unlink_framebuffer(info);
|
||||
}
|
||||
drm_fb_helper_unlink_fbi(&ufbdev->helper);
|
||||
}
|
||||
|
||||
struct drm_framebuffer *
|
||||
|
@ -173,7 +173,7 @@ static void virtio_gpu_3d_fillrect(struct fb_info *info,
|
||||
const struct fb_fillrect *rect)
|
||||
{
|
||||
struct virtio_gpu_fbdev *vfbdev = info->par;
|
||||
sys_fillrect(info, rect);
|
||||
drm_fb_helper_sys_fillrect(info, rect);
|
||||
virtio_gpu_dirty_update(&vfbdev->vgfb, true, rect->dx, rect->dy,
|
||||
rect->width, rect->height);
|
||||
schedule_delayed_work(&vfbdev->work, VIRTIO_GPU_FBCON_POLL_PERIOD);
|
||||
@ -183,7 +183,7 @@ static void virtio_gpu_3d_copyarea(struct fb_info *info,
|
||||
const struct fb_copyarea *area)
|
||||
{
|
||||
struct virtio_gpu_fbdev *vfbdev = info->par;
|
||||
sys_copyarea(info, area);
|
||||
drm_fb_helper_sys_copyarea(info, area);
|
||||
virtio_gpu_dirty_update(&vfbdev->vgfb, true, area->dx, area->dy,
|
||||
area->width, area->height);
|
||||
schedule_delayed_work(&vfbdev->work, VIRTIO_GPU_FBCON_POLL_PERIOD);
|
||||
@ -193,7 +193,7 @@ static void virtio_gpu_3d_imageblit(struct fb_info *info,
|
||||
const struct fb_image *image)
|
||||
{
|
||||
struct virtio_gpu_fbdev *vfbdev = info->par;
|
||||
sys_imageblit(info, image);
|
||||
drm_fb_helper_sys_imageblit(info, image);
|
||||
virtio_gpu_dirty_update(&vfbdev->vgfb, true, image->dx, image->dy,
|
||||
image->width, image->height);
|
||||
schedule_delayed_work(&vfbdev->work, VIRTIO_GPU_FBCON_POLL_PERIOD);
|
||||
@ -230,7 +230,6 @@ static int virtio_gpufb_create(struct drm_fb_helper *helper,
|
||||
struct drm_framebuffer *fb;
|
||||
struct drm_mode_fb_cmd2 mode_cmd = {};
|
||||
struct virtio_gpu_object *obj;
|
||||
struct device *device = vgdev->dev;
|
||||
uint32_t resid, format, size;
|
||||
int ret;
|
||||
|
||||
@ -317,18 +316,12 @@ static int virtio_gpufb_create(struct drm_fb_helper *helper,
|
||||
if (ret)
|
||||
goto err_obj_attach;
|
||||
|
||||
info = framebuffer_alloc(0, device);
|
||||
if (!info) {
|
||||
ret = -ENOMEM;
|
||||
info = drm_fb_helper_alloc_fbi(helper);
|
||||
if (IS_ERR(info)) {
|
||||
ret = PTR_ERR(info);
|
||||
goto err_fb_alloc;
|
||||
}
|
||||
|
||||
ret = fb_alloc_cmap(&info->cmap, 256, 0);
|
||||
if (ret) {
|
||||
ret = -ENOMEM;
|
||||
goto err_fb_alloc_cmap;
|
||||
}
|
||||
|
||||
info->par = helper;
|
||||
|
||||
ret = virtio_gpu_framebuffer_init(dev, &vfbdev->vgfb,
|
||||
@ -339,7 +332,6 @@ static int virtio_gpufb_create(struct drm_fb_helper *helper,
|
||||
fb = &vfbdev->vgfb.base;
|
||||
|
||||
vfbdev->helper.fb = fb;
|
||||
vfbdev->helper.fbdev = info;
|
||||
|
||||
strcpy(info->fix.id, "virtiodrmfb");
|
||||
info->flags = FBINFO_DEFAULT;
|
||||
@ -357,9 +349,7 @@ static int virtio_gpufb_create(struct drm_fb_helper *helper,
|
||||
return 0;
|
||||
|
||||
err_fb_init:
|
||||
fb_dealloc_cmap(&info->cmap);
|
||||
err_fb_alloc_cmap:
|
||||
framebuffer_release(info);
|
||||
drm_fb_helper_release_fbi(helper);
|
||||
err_fb_alloc:
|
||||
virtio_gpu_cmd_resource_inval_backing(vgdev, resid);
|
||||
err_obj_attach:
|
||||
@ -371,15 +361,11 @@ err_obj_vmap:
|
||||
static int virtio_gpu_fbdev_destroy(struct drm_device *dev,
|
||||
struct virtio_gpu_fbdev *vgfbdev)
|
||||
{
|
||||
struct fb_info *info;
|
||||
struct virtio_gpu_framebuffer *vgfb = &vgfbdev->vgfb;
|
||||
|
||||
if (vgfbdev->helper.fbdev) {
|
||||
info = vgfbdev->helper.fbdev;
|
||||
drm_fb_helper_unregister_fbi(&vgfbdev->helper);
|
||||
drm_fb_helper_release_fbi(&vgfbdev->helper);
|
||||
|
||||
unregister_framebuffer(info);
|
||||
framebuffer_release(info);
|
||||
}
|
||||
if (vgfb->obj)
|
||||
vgfb->obj = NULL;
|
||||
drm_fb_helper_fini(&vgfbdev->helper);
|
||||
|
@ -159,7 +159,7 @@ static int vmw_gb_context_init(struct vmw_private *dev_priv,
|
||||
|
||||
if (dev_priv->has_mob) {
|
||||
uctx->man = vmw_cmdbuf_res_man_create(dev_priv);
|
||||
if (unlikely(IS_ERR(uctx->man))) {
|
||||
if (IS_ERR(uctx->man)) {
|
||||
ret = PTR_ERR(uctx->man);
|
||||
uctx->man = NULL;
|
||||
goto out_err;
|
||||
|
@ -1054,7 +1054,7 @@ static long vmw_generic_ioctl(struct file *filp, unsigned int cmd,
|
||||
return -EINVAL;
|
||||
|
||||
vmaster = vmw_master_check(dev, file_priv, flags);
|
||||
if (unlikely(IS_ERR(vmaster))) {
|
||||
if (IS_ERR(vmaster)) {
|
||||
ret = PTR_ERR(vmaster);
|
||||
|
||||
if (ret != -ERESTARTSYS)
|
||||
|
@ -6,17 +6,19 @@
|
||||
* Licensed under GPLv2
|
||||
*
|
||||
* vga_switcheroo.c - Support for laptop with dual GPU using one set of outputs
|
||||
|
||||
Switcher interface - methods require for ATPX and DCM
|
||||
- switchto - this throws the output MUX switch
|
||||
- discrete_set_power - sets the power state for the discrete card
|
||||
|
||||
GPU driver interface
|
||||
- set_gpu_state - this should do the equiv of s/r for the card
|
||||
- this should *not* set the discrete power state
|
||||
- switch_check - check if the device is in a position to switch now
|
||||
*
|
||||
* Switcher interface - methods require for ATPX and DCM
|
||||
* - switchto - this throws the output MUX switch
|
||||
* - discrete_set_power - sets the power state for the discrete card
|
||||
*
|
||||
* GPU driver interface
|
||||
* - set_gpu_state - this should do the equiv of s/r for the card
|
||||
* - this should *not* set the discrete power state
|
||||
* - switch_check - check if the device is in a position to switch now
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) "vga_switcheroo: " fmt
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/uaccess.h>
|
||||
@ -111,7 +113,7 @@ int vga_switcheroo_register_handler(struct vga_switcheroo_handler *handler)
|
||||
|
||||
vgasr_priv.handler = handler;
|
||||
if (vga_switcheroo_ready()) {
|
||||
printk(KERN_INFO "vga_switcheroo: enabled\n");
|
||||
pr_info("enabled\n");
|
||||
vga_switcheroo_enable();
|
||||
}
|
||||
mutex_unlock(&vgasr_mutex);
|
||||
@ -124,7 +126,7 @@ void vga_switcheroo_unregister_handler(void)
|
||||
mutex_lock(&vgasr_mutex);
|
||||
vgasr_priv.handler = NULL;
|
||||
if (vgasr_priv.active) {
|
||||
pr_info("vga_switcheroo: disabled\n");
|
||||
pr_info("disabled\n");
|
||||
vga_switcheroo_debugfs_fini(&vgasr_priv);
|
||||
vgasr_priv.active = false;
|
||||
}
|
||||
@ -155,7 +157,7 @@ static int register_client(struct pci_dev *pdev,
|
||||
vgasr_priv.registered_clients++;
|
||||
|
||||
if (vga_switcheroo_ready()) {
|
||||
printk(KERN_INFO "vga_switcheroo: enabled\n");
|
||||
pr_info("enabled\n");
|
||||
vga_switcheroo_enable();
|
||||
}
|
||||
mutex_unlock(&vgasr_mutex);
|
||||
@ -167,7 +169,8 @@ int vga_switcheroo_register_client(struct pci_dev *pdev,
|
||||
bool driver_power_control)
|
||||
{
|
||||
return register_client(pdev, ops, -1,
|
||||
pdev == vga_default_device(), driver_power_control);
|
||||
pdev == vga_default_device(),
|
||||
driver_power_control);
|
||||
}
|
||||
EXPORT_SYMBOL(vga_switcheroo_register_client);
|
||||
|
||||
@ -183,6 +186,7 @@ static struct vga_switcheroo_client *
|
||||
find_client_from_pci(struct list_head *head, struct pci_dev *pdev)
|
||||
{
|
||||
struct vga_switcheroo_client *client;
|
||||
|
||||
list_for_each_entry(client, head, list)
|
||||
if (client->pdev == pdev)
|
||||
return client;
|
||||
@ -193,6 +197,7 @@ static struct vga_switcheroo_client *
|
||||
find_client_from_id(struct list_head *head, int client_id)
|
||||
{
|
||||
struct vga_switcheroo_client *client;
|
||||
|
||||
list_for_each_entry(client, head, list)
|
||||
if (client->id == client_id)
|
||||
return client;
|
||||
@ -203,6 +208,7 @@ static struct vga_switcheroo_client *
|
||||
find_active_client(struct list_head *head)
|
||||
{
|
||||
struct vga_switcheroo_client *client;
|
||||
|
||||
list_for_each_entry(client, head, list)
|
||||
if (client->active && client_is_vga(client))
|
||||
return client;
|
||||
@ -235,7 +241,7 @@ void vga_switcheroo_unregister_client(struct pci_dev *pdev)
|
||||
kfree(client);
|
||||
}
|
||||
if (vgasr_priv.active && vgasr_priv.registered_clients < 2) {
|
||||
printk(KERN_INFO "vga_switcheroo: disabled\n");
|
||||
pr_info("disabled\n");
|
||||
vga_switcheroo_debugfs_fini(&vgasr_priv);
|
||||
vgasr_priv.active = false;
|
||||
}
|
||||
@ -260,10 +266,12 @@ static int vga_switcheroo_show(struct seq_file *m, void *v)
|
||||
{
|
||||
struct vga_switcheroo_client *client;
|
||||
int i = 0;
|
||||
|
||||
mutex_lock(&vgasr_mutex);
|
||||
list_for_each_entry(client, &vgasr_priv.clients, list) {
|
||||
seq_printf(m, "%d:%s%s:%c:%s%s:%s\n", i,
|
||||
client_id(client) == VGA_SWITCHEROO_DIS ? "DIS" : "IGD",
|
||||
client_id(client) == VGA_SWITCHEROO_DIS ? "DIS" :
|
||||
"IGD",
|
||||
client_is_vga(client) ? "" : "-Audio",
|
||||
client->active ? '+' : ' ',
|
||||
client->driver_power_control ? "Dyn" : "",
|
||||
@ -347,6 +355,7 @@ static int vga_switchto_stage2(struct vga_switcheroo_client *new_client)
|
||||
|
||||
if (new_client->fb_info) {
|
||||
struct fb_event event;
|
||||
|
||||
console_lock();
|
||||
event.info = new_client->fb_info;
|
||||
fb_notifier_call_chain(FB_EVENT_REMAP_ALL_CONSOLE, &event);
|
||||
@ -375,7 +384,7 @@ static bool check_can_switch(void)
|
||||
|
||||
list_for_each_entry(client, &vgasr_priv.clients, list) {
|
||||
if (!client->ops->can_switch(client->pdev)) {
|
||||
printk(KERN_ERR "vga_switcheroo: client %x refused switch\n", client->id);
|
||||
pr_err("client %x refused switch\n", client->id);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -484,20 +493,20 @@ vga_switcheroo_debugfs_write(struct file *filp, const char __user *ubuf,
|
||||
if (can_switch) {
|
||||
ret = vga_switchto_stage1(client);
|
||||
if (ret)
|
||||
printk(KERN_ERR "vga_switcheroo: switching failed stage 1 %d\n", ret);
|
||||
pr_err("switching failed stage 1 %d\n", ret);
|
||||
|
||||
ret = vga_switchto_stage2(client);
|
||||
if (ret)
|
||||
printk(KERN_ERR "vga_switcheroo: switching failed stage 2 %d\n", ret);
|
||||
pr_err("switching failed stage 2 %d\n", ret);
|
||||
|
||||
} else {
|
||||
printk(KERN_INFO "vga_switcheroo: setting delayed switch to client %d\n", client->id);
|
||||
pr_info("setting delayed switch to client %d\n", client->id);
|
||||
vgasr_priv.delayed_switch_active = true;
|
||||
vgasr_priv.delayed_client_id = client_id;
|
||||
|
||||
ret = vga_switchto_stage1(client);
|
||||
if (ret)
|
||||
printk(KERN_ERR "vga_switcheroo: delayed switching stage 1 failed %d\n", ret);
|
||||
pr_err("delayed switching stage 1 failed %d\n", ret);
|
||||
}
|
||||
|
||||
out:
|
||||
@ -516,32 +525,32 @@ static const struct file_operations vga_switcheroo_debugfs_fops = {
|
||||
|
||||
static void vga_switcheroo_debugfs_fini(struct vgasr_priv *priv)
|
||||
{
|
||||
if (priv->switch_file) {
|
||||
debugfs_remove(priv->switch_file);
|
||||
priv->switch_file = NULL;
|
||||
}
|
||||
if (priv->debugfs_root) {
|
||||
debugfs_remove(priv->debugfs_root);
|
||||
priv->debugfs_root = NULL;
|
||||
}
|
||||
debugfs_remove(priv->switch_file);
|
||||
priv->switch_file = NULL;
|
||||
|
||||
debugfs_remove(priv->debugfs_root);
|
||||
priv->debugfs_root = NULL;
|
||||
}
|
||||
|
||||
static int vga_switcheroo_debugfs_init(struct vgasr_priv *priv)
|
||||
{
|
||||
static const char mp[] = "/sys/kernel/debug";
|
||||
|
||||
/* already initialised */
|
||||
if (priv->debugfs_root)
|
||||
return 0;
|
||||
priv->debugfs_root = debugfs_create_dir("vgaswitcheroo", NULL);
|
||||
|
||||
if (!priv->debugfs_root) {
|
||||
printk(KERN_ERR "vga_switcheroo: Cannot create /sys/kernel/debug/vgaswitcheroo\n");
|
||||
pr_err("Cannot create %s/vgaswitcheroo\n", mp);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
priv->switch_file = debugfs_create_file("switch", 0644,
|
||||
priv->debugfs_root, NULL, &vga_switcheroo_debugfs_fops);
|
||||
priv->debugfs_root, NULL,
|
||||
&vga_switcheroo_debugfs_fops);
|
||||
if (!priv->switch_file) {
|
||||
printk(KERN_ERR "vga_switcheroo: cannot create /sys/kernel/debug/vgaswitcheroo/switch\n");
|
||||
pr_err("cannot create %s/vgaswitcheroo/switch\n", mp);
|
||||
goto fail;
|
||||
}
|
||||
return 0;
|
||||
@ -560,7 +569,8 @@ int vga_switcheroo_process_delayed_switch(void)
|
||||
if (!vgasr_priv.delayed_switch_active)
|
||||
goto err;
|
||||
|
||||
printk(KERN_INFO "vga_switcheroo: processing delayed switch to %d\n", vgasr_priv.delayed_client_id);
|
||||
pr_info("processing delayed switch to %d\n",
|
||||
vgasr_priv.delayed_client_id);
|
||||
|
||||
client = find_client_from_id(&vgasr_priv.clients,
|
||||
vgasr_priv.delayed_client_id);
|
||||
@ -569,7 +579,7 @@ int vga_switcheroo_process_delayed_switch(void)
|
||||
|
||||
ret = vga_switchto_stage2(client);
|
||||
if (ret)
|
||||
printk(KERN_ERR "vga_switcheroo: delayed switching failed stage 2 %d\n", ret);
|
||||
pr_err("delayed switching failed stage 2 %d\n", ret);
|
||||
|
||||
vgasr_priv.delayed_switch_active = false;
|
||||
err = 0;
|
||||
@ -579,7 +589,8 @@ err:
|
||||
}
|
||||
EXPORT_SYMBOL(vga_switcheroo_process_delayed_switch);
|
||||
|
||||
static void vga_switcheroo_power_switch(struct pci_dev *pdev, enum vga_switcheroo_state state)
|
||||
static void vga_switcheroo_power_switch(struct pci_dev *pdev,
|
||||
enum vga_switcheroo_state state)
|
||||
{
|
||||
struct vga_switcheroo_client *client;
|
||||
|
||||
@ -598,7 +609,8 @@ static void vga_switcheroo_power_switch(struct pci_dev *pdev, enum vga_switchero
|
||||
|
||||
/* force a PCI device to a certain state - mainly to turn off audio clients */
|
||||
|
||||
void vga_switcheroo_set_dynamic_switch(struct pci_dev *pdev, enum vga_switcheroo_state dynamic)
|
||||
void vga_switcheroo_set_dynamic_switch(struct pci_dev *pdev,
|
||||
enum vga_switcheroo_state dynamic)
|
||||
{
|
||||
struct vga_switcheroo_client *client;
|
||||
|
||||
@ -644,7 +656,8 @@ static int vga_switcheroo_runtime_resume(struct device *dev)
|
||||
|
||||
/* this version is for the case where the power switch is separate
|
||||
to the device being powered down. */
|
||||
int vga_switcheroo_init_domain_pm_ops(struct device *dev, struct dev_pm_domain *domain)
|
||||
int vga_switcheroo_init_domain_pm_ops(struct device *dev,
|
||||
struct dev_pm_domain *domain)
|
||||
{
|
||||
/* copy over all the bus versions */
|
||||
if (dev->bus && dev->bus->pm) {
|
||||
@ -675,7 +688,8 @@ static int vga_switcheroo_runtime_resume_hdmi_audio(struct device *dev)
|
||||
/* we need to check if we have to switch back on the video
|
||||
device so the audio device can come back */
|
||||
list_for_each_entry(client, &vgasr_priv.clients, list) {
|
||||
if (PCI_SLOT(client->pdev->devfn) == PCI_SLOT(pdev->devfn) && client_is_vga(client)) {
|
||||
if (PCI_SLOT(client->pdev->devfn) == PCI_SLOT(pdev->devfn) &&
|
||||
client_is_vga(client)) {
|
||||
found = client;
|
||||
ret = pm_runtime_get_sync(&client->pdev->dev);
|
||||
if (ret) {
|
||||
@ -695,12 +709,15 @@ static int vga_switcheroo_runtime_resume_hdmi_audio(struct device *dev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int vga_switcheroo_init_domain_pm_optimus_hdmi_audio(struct device *dev, struct dev_pm_domain *domain)
|
||||
int
|
||||
vga_switcheroo_init_domain_pm_optimus_hdmi_audio(struct device *dev,
|
||||
struct dev_pm_domain *domain)
|
||||
{
|
||||
/* copy over all the bus versions */
|
||||
if (dev->bus && dev->bus->pm) {
|
||||
domain->ops = *dev->bus->pm;
|
||||
domain->ops.runtime_resume = vga_switcheroo_runtime_resume_hdmi_audio;
|
||||
domain->ops.runtime_resume =
|
||||
vga_switcheroo_runtime_resume_hdmi_audio;
|
||||
|
||||
dev->pm_domain = domain;
|
||||
return 0;
|
||||
|
@ -29,6 +29,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) "vgaarb: " fmt
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/pci.h>
|
||||
@ -134,7 +136,6 @@ struct pci_dev *vga_default_device(void)
|
||||
{
|
||||
return vga_default;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(vga_default_device);
|
||||
|
||||
void vga_set_default_device(struct pci_dev *pdev)
|
||||
@ -298,9 +299,9 @@ enable_them:
|
||||
|
||||
pci_set_vga_state(vgadev->pdev, true, pci_bits, flags);
|
||||
|
||||
if (!vgadev->bridge_has_one_vga) {
|
||||
if (!vgadev->bridge_has_one_vga)
|
||||
vga_irq_set_state(vgadev, true);
|
||||
}
|
||||
|
||||
vgadev->owns |= wants;
|
||||
lock_them:
|
||||
vgadev->locks |= (rsrc & VGA_RSRC_LEGACY_MASK);
|
||||
@ -452,15 +453,15 @@ bail:
|
||||
}
|
||||
EXPORT_SYMBOL(vga_put);
|
||||
|
||||
/* Rules for using a bridge to control a VGA descendant decoding:
|
||||
if a bridge has only one VGA descendant then it can be used
|
||||
to control the VGA routing for that device.
|
||||
It should always use the bridge closest to the device to control it.
|
||||
If a bridge has a direct VGA descendant, but also have a sub-bridge
|
||||
VGA descendant then we cannot use that bridge to control the direct VGA descendant.
|
||||
So for every device we register, we need to iterate all its parent bridges
|
||||
so we can invalidate any devices using them properly.
|
||||
*/
|
||||
/*
|
||||
* Rules for using a bridge to control a VGA descendant decoding: if a bridge
|
||||
* has only one VGA descendant then it can be used to control the VGA routing
|
||||
* for that device. It should always use the bridge closest to the device to
|
||||
* control it. If a bridge has a direct VGA descendant, but also have a sub-
|
||||
* bridge VGA descendant then we cannot use that bridge to control the direct
|
||||
* VGA descendant. So for every device we register, we need to iterate all
|
||||
* its parent bridges so we can invalidate any devices using them properly.
|
||||
*/
|
||||
static void vga_arbiter_check_bridge_sharing(struct vga_device *vgadev)
|
||||
{
|
||||
struct vga_device *same_bridge_vgadev;
|
||||
@ -484,21 +485,26 @@ static void vga_arbiter_check_bridge_sharing(struct vga_device *vgadev)
|
||||
|
||||
/* see if the share a bridge with this device */
|
||||
if (new_bridge == bridge) {
|
||||
/* if their direct parent bridge is the same
|
||||
as any bridge of this device then it can't be used
|
||||
for that device */
|
||||
/*
|
||||
* If their direct parent bridge is the same
|
||||
* as any bridge of this device then it can't
|
||||
* be used for that device.
|
||||
*/
|
||||
same_bridge_vgadev->bridge_has_one_vga = false;
|
||||
}
|
||||
|
||||
/* now iterate the previous devices bridge hierarchy */
|
||||
/* if the new devices parent bridge is in the other devices
|
||||
hierarchy then we can't use it to control this device */
|
||||
/*
|
||||
* Now iterate the previous devices bridge hierarchy.
|
||||
* If the new devices parent bridge is in the other
|
||||
* devices hierarchy then we can't use it to control
|
||||
* this device
|
||||
*/
|
||||
while (bus) {
|
||||
bridge = bus->self;
|
||||
if (bridge) {
|
||||
if (bridge == vgadev->pdev->bus->self)
|
||||
vgadev->bridge_has_one_vga = false;
|
||||
}
|
||||
|
||||
if (bridge && bridge == vgadev->pdev->bus->self)
|
||||
vgadev->bridge_has_one_vga = false;
|
||||
|
||||
bus = bus->parent;
|
||||
}
|
||||
}
|
||||
@ -527,10 +533,10 @@ static bool vga_arbiter_add_pci_device(struct pci_dev *pdev)
|
||||
/* Allocate structure */
|
||||
vgadev = kmalloc(sizeof(struct vga_device), GFP_KERNEL);
|
||||
if (vgadev == NULL) {
|
||||
pr_err("vgaarb: failed to allocate pci device\n");
|
||||
/* What to do on allocation failure ? For now, let's
|
||||
* just do nothing, I'm not sure there is anything saner
|
||||
* to be done
|
||||
pr_err("failed to allocate pci device\n");
|
||||
/*
|
||||
* What to do on allocation failure ? For now, let's just do
|
||||
* nothing, I'm not sure there is anything saner to be done.
|
||||
*/
|
||||
return false;
|
||||
}
|
||||
@ -566,8 +572,8 @@ static bool vga_arbiter_add_pci_device(struct pci_dev *pdev)
|
||||
bridge = bus->self;
|
||||
if (bridge) {
|
||||
u16 l;
|
||||
pci_read_config_word(bridge, PCI_BRIDGE_CONTROL,
|
||||
&l);
|
||||
|
||||
pci_read_config_word(bridge, PCI_BRIDGE_CONTROL, &l);
|
||||
if (!(l & PCI_BRIDGE_CTL_VGA)) {
|
||||
vgadev->owns = 0;
|
||||
break;
|
||||
@ -581,8 +587,7 @@ static bool vga_arbiter_add_pci_device(struct pci_dev *pdev)
|
||||
*/
|
||||
if (vga_default == NULL &&
|
||||
((vgadev->owns & VGA_RSRC_LEGACY_MASK) == VGA_RSRC_LEGACY_MASK)) {
|
||||
pr_info("vgaarb: setting as boot device: PCI:%s\n",
|
||||
pci_name(pdev));
|
||||
pr_info("setting as boot device: PCI:%s\n", pci_name(pdev));
|
||||
vga_set_default_device(pdev);
|
||||
}
|
||||
|
||||
@ -591,7 +596,7 @@ static bool vga_arbiter_add_pci_device(struct pci_dev *pdev)
|
||||
/* Add to the list */
|
||||
list_add(&vgadev->list, &vga_list);
|
||||
vga_count++;
|
||||
pr_info("vgaarb: device added: PCI:%s,decodes=%s,owns=%s,locks=%s\n",
|
||||
pr_info("device added: PCI:%s,decodes=%s,owns=%s,locks=%s\n",
|
||||
pci_name(pdev),
|
||||
vga_iostate_to_str(vgadev->decodes),
|
||||
vga_iostate_to_str(vgadev->owns),
|
||||
@ -651,7 +656,7 @@ static inline void vga_update_device_decodes(struct vga_device *vgadev,
|
||||
decodes_unlocked = vgadev->locks & decodes_removed;
|
||||
vgadev->decodes = new_decodes;
|
||||
|
||||
pr_info("vgaarb: device changed decodes: PCI:%s,olddecodes=%s,decodes=%s:owns=%s\n",
|
||||
pr_info("device changed decodes: PCI:%s,olddecodes=%s,decodes=%s:owns=%s\n",
|
||||
pci_name(vgadev->pdev),
|
||||
vga_iostate_to_str(old_decodes),
|
||||
vga_iostate_to_str(vgadev->decodes),
|
||||
@ -673,10 +678,12 @@ static inline void vga_update_device_decodes(struct vga_device *vgadev,
|
||||
if (!(old_decodes & VGA_RSRC_LEGACY_MASK) &&
|
||||
new_decodes & VGA_RSRC_LEGACY_MASK)
|
||||
vga_decode_count++;
|
||||
pr_debug("vgaarb: decoding count now is: %d\n", vga_decode_count);
|
||||
pr_debug("decoding count now is: %d\n", vga_decode_count);
|
||||
}
|
||||
|
||||
static void __vga_set_legacy_decoding(struct pci_dev *pdev, unsigned int decodes, bool userspace)
|
||||
static void __vga_set_legacy_decoding(struct pci_dev *pdev,
|
||||
unsigned int decodes,
|
||||
bool userspace)
|
||||
{
|
||||
struct vga_device *vgadev;
|
||||
unsigned long flags;
|
||||
@ -712,7 +719,8 @@ EXPORT_SYMBOL(vga_set_legacy_decoding);
|
||||
/* call with NULL to unregister */
|
||||
int vga_client_register(struct pci_dev *pdev, void *cookie,
|
||||
void (*irq_set_state)(void *cookie, bool state),
|
||||
unsigned int (*set_vga_decode)(void *cookie, bool decode))
|
||||
unsigned int (*set_vga_decode)(void *cookie,
|
||||
bool decode))
|
||||
{
|
||||
int ret = -ENODEV;
|
||||
struct vga_device *vgadev;
|
||||
@ -832,7 +840,7 @@ static int vga_pci_str_to_vars(char *buf, int count, unsigned int *domain,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static ssize_t vga_arb_read(struct file *file, char __user * buf,
|
||||
static ssize_t vga_arb_read(struct file *file, char __user *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct vga_arb_private *priv = file->private_data;
|
||||
@ -899,7 +907,7 @@ done:
|
||||
* TODO: To avoid parsing inside kernel and to improve the speed we may
|
||||
* consider use ioctl here
|
||||
*/
|
||||
static ssize_t vga_arb_write(struct file *file, const char __user * buf,
|
||||
static ssize_t vga_arb_write(struct file *file, const char __user *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct vga_arb_private *priv = file->private_data;
|
||||
@ -1075,13 +1083,13 @@ static ssize_t vga_arb_write(struct file *file, const char __user * buf,
|
||||
ret_val = -EPROTO;
|
||||
goto done;
|
||||
}
|
||||
pr_debug("vgaarb: %s ==> %x:%x:%x.%x\n", curr_pos,
|
||||
pr_debug("%s ==> %x:%x:%x.%x\n", curr_pos,
|
||||
domain, bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
|
||||
|
||||
pdev = pci_get_domain_bus_and_slot(domain, bus, devfn);
|
||||
pr_debug("vgaarb: pdev %p\n", pdev);
|
||||
pr_debug("pdev %p\n", pdev);
|
||||
if (!pdev) {
|
||||
pr_err("vgaarb: invalid PCI address %x:%x:%x\n",
|
||||
pr_err("invalid PCI address %x:%x:%x\n",
|
||||
domain, bus, devfn);
|
||||
ret_val = -ENODEV;
|
||||
goto done;
|
||||
@ -1089,10 +1097,13 @@ static ssize_t vga_arb_write(struct file *file, const char __user * buf,
|
||||
}
|
||||
|
||||
vgadev = vgadev_find(pdev);
|
||||
pr_debug("vgaarb: vgadev %p\n", vgadev);
|
||||
pr_debug("vgadev %p\n", vgadev);
|
||||
if (vgadev == NULL) {
|
||||
pr_err("vgaarb: this pci device is not a vga device\n");
|
||||
pci_dev_put(pdev);
|
||||
if (pdev) {
|
||||
pr_err("this pci device is not a vga device\n");
|
||||
pci_dev_put(pdev);
|
||||
}
|
||||
|
||||
ret_val = -ENODEV;
|
||||
goto done;
|
||||
}
|
||||
@ -1109,7 +1120,7 @@ static ssize_t vga_arb_write(struct file *file, const char __user * buf,
|
||||
}
|
||||
}
|
||||
if (i == MAX_USER_CARDS) {
|
||||
pr_err("vgaarb: maximum user cards (%d) number reached!\n",
|
||||
pr_err("maximum user cards (%d) number reached!\n",
|
||||
MAX_USER_CARDS);
|
||||
pci_dev_put(pdev);
|
||||
/* XXX: which value to return? */
|
||||
@ -1125,7 +1136,7 @@ static ssize_t vga_arb_write(struct file *file, const char __user * buf,
|
||||
} else if (strncmp(curr_pos, "decodes ", 8) == 0) {
|
||||
curr_pos += 8;
|
||||
remaining -= 8;
|
||||
pr_debug("vgaarb: client 0x%p called 'decodes'\n", priv);
|
||||
pr_debug("client 0x%p called 'decodes'\n", priv);
|
||||
|
||||
if (!vga_str_to_iostate(curr_pos, remaining, &io_state)) {
|
||||
ret_val = -EPROTO;
|
||||
@ -1150,7 +1161,7 @@ done:
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
static unsigned int vga_arb_fpoll(struct file *file, poll_table * wait)
|
||||
static unsigned int vga_arb_fpoll(struct file *file, poll_table *wait)
|
||||
{
|
||||
struct vga_arb_private *priv = file->private_data;
|
||||
|
||||
@ -1246,7 +1257,8 @@ static void vga_arbiter_notify_clients(void)
|
||||
else
|
||||
new_state = true;
|
||||
if (vgadev->set_vga_decode) {
|
||||
new_decodes = vgadev->set_vga_decode(vgadev->cookie, new_state);
|
||||
new_decodes = vgadev->set_vga_decode(vgadev->cookie,
|
||||
new_state);
|
||||
vga_update_device_decodes(vgadev, new_decodes);
|
||||
}
|
||||
}
|
||||
@ -1300,7 +1312,7 @@ static int __init vga_arb_device_init(void)
|
||||
|
||||
rc = misc_register(&vga_arb_device);
|
||||
if (rc < 0)
|
||||
pr_err("vgaarb: error %d registering device\n", rc);
|
||||
pr_err("error %d registering device\n", rc);
|
||||
|
||||
bus_register_notifier(&pci_bus_type, &pci_notifier);
|
||||
|
||||
@ -1312,21 +1324,29 @@ static int __init vga_arb_device_init(void)
|
||||
PCI_ANY_ID, pdev)) != NULL)
|
||||
vga_arbiter_add_pci_device(pdev);
|
||||
|
||||
pr_info("vgaarb: loaded\n");
|
||||
pr_info("loaded\n");
|
||||
|
||||
list_for_each_entry(vgadev, &vga_list, list) {
|
||||
#if defined(CONFIG_X86) || defined(CONFIG_IA64)
|
||||
/* Override I/O based detection done by vga_arbiter_add_pci_device()
|
||||
* as it may take the wrong device (e.g. on Apple system under EFI).
|
||||
/*
|
||||
* Override vga_arbiter_add_pci_device()'s I/O based detection
|
||||
* as it may take the wrong device (e.g. on Apple system under
|
||||
* EFI).
|
||||
*
|
||||
* Select the device owning the boot framebuffer if there is one.
|
||||
* Select the device owning the boot framebuffer if there is
|
||||
* one.
|
||||
*/
|
||||
resource_size_t start, end;
|
||||
resource_size_t start, end, limit;
|
||||
unsigned long flags;
|
||||
int i;
|
||||
|
||||
limit = screen_info.lfb_base + screen_info.lfb_size;
|
||||
|
||||
/* Does firmware framebuffer belong to us? */
|
||||
for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
|
||||
if (!(pci_resource_flags(vgadev->pdev, i) & IORESOURCE_MEM))
|
||||
flags = pci_resource_flags(vgadev->pdev, i);
|
||||
|
||||
if ((flags & IORESOURCE_MEM) == 0)
|
||||
continue;
|
||||
|
||||
start = pci_resource_start(vgadev->pdev, i);
|
||||
@ -1335,22 +1355,24 @@ static int __init vga_arb_device_init(void)
|
||||
if (!start || !end)
|
||||
continue;
|
||||
|
||||
if (screen_info.lfb_base < start ||
|
||||
(screen_info.lfb_base + screen_info.lfb_size) >= end)
|
||||
if (screen_info.lfb_base < start || limit >= end)
|
||||
continue;
|
||||
|
||||
if (!vga_default_device())
|
||||
pr_info("vgaarb: setting as boot device: PCI:%s\n",
|
||||
pr_info("setting as boot device: PCI:%s\n",
|
||||
pci_name(vgadev->pdev));
|
||||
else if (vgadev->pdev != vga_default_device())
|
||||
pr_info("vgaarb: overriding boot device: PCI:%s\n",
|
||||
pr_info("overriding boot device: PCI:%s\n",
|
||||
pci_name(vgadev->pdev));
|
||||
vga_set_default_device(vgadev->pdev);
|
||||
}
|
||||
#endif
|
||||
if (vgadev->bridge_has_one_vga)
|
||||
pr_info("vgaarb: bridge control possible %s\n", pci_name(vgadev->pdev));
|
||||
pr_info("bridge control possible %s\n",
|
||||
pci_name(vgadev->pdev));
|
||||
else
|
||||
pr_info("vgaarb: no bridge control possible %s\n", pci_name(vgadev->pdev));
|
||||
pr_info("no bridge control possible %s\n",
|
||||
pci_name(vgadev->pdev));
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
@ -22,9 +22,7 @@ source "drivers/gpu/vga/Kconfig"
|
||||
source "drivers/gpu/host1x/Kconfig"
|
||||
source "drivers/gpu/ipu-v3/Kconfig"
|
||||
|
||||
menu "Direct Rendering Manager"
|
||||
source "drivers/gpu/drm/Kconfig"
|
||||
endmenu
|
||||
|
||||
menu "Frame buffer Devices"
|
||||
source "drivers/video/fbdev/Kconfig"
|
||||
|
@ -681,7 +681,7 @@ struct drm_minor {
|
||||
|
||||
struct drm_pending_vblank_event {
|
||||
struct drm_pending_event base;
|
||||
int pipe;
|
||||
unsigned int pipe;
|
||||
struct drm_event_vblank event;
|
||||
};
|
||||
|
||||
@ -700,7 +700,7 @@ struct drm_vblank_crtc {
|
||||
/* for wraparound handling */
|
||||
u32 last_wait; /* Last vblank seqno waited per CRTC */
|
||||
unsigned int inmodeset; /* Display driver is setting mode */
|
||||
int crtc; /* crtc index */
|
||||
unsigned int pipe; /* crtc index */
|
||||
bool enabled; /* so we don't call enable more than
|
||||
once per disable */
|
||||
};
|
||||
@ -920,34 +920,34 @@ void drm_clflush_virt_range(void *addr, unsigned long length);
|
||||
extern int drm_irq_install(struct drm_device *dev, int irq);
|
||||
extern int drm_irq_uninstall(struct drm_device *dev);
|
||||
|
||||
extern int drm_vblank_init(struct drm_device *dev, int num_crtcs);
|
||||
extern int drm_vblank_init(struct drm_device *dev, unsigned int num_crtcs);
|
||||
extern int drm_wait_vblank(struct drm_device *dev, void *data,
|
||||
struct drm_file *filp);
|
||||
extern u32 drm_vblank_count(struct drm_device *dev, int crtc);
|
||||
extern u32 drm_vblank_count(struct drm_device *dev, int pipe);
|
||||
extern u32 drm_crtc_vblank_count(struct drm_crtc *crtc);
|
||||
extern u32 drm_vblank_count_and_time(struct drm_device *dev, int crtc,
|
||||
extern u32 drm_vblank_count_and_time(struct drm_device *dev, unsigned int pipe,
|
||||
struct timeval *vblanktime);
|
||||
extern void drm_send_vblank_event(struct drm_device *dev, int crtc,
|
||||
struct drm_pending_vblank_event *e);
|
||||
extern void drm_send_vblank_event(struct drm_device *dev, unsigned int pipe,
|
||||
struct drm_pending_vblank_event *e);
|
||||
extern void drm_crtc_send_vblank_event(struct drm_crtc *crtc,
|
||||
struct drm_pending_vblank_event *e);
|
||||
extern bool drm_handle_vblank(struct drm_device *dev, int crtc);
|
||||
extern bool drm_handle_vblank(struct drm_device *dev, unsigned int pipe);
|
||||
extern bool drm_crtc_handle_vblank(struct drm_crtc *crtc);
|
||||
extern int drm_vblank_get(struct drm_device *dev, int crtc);
|
||||
extern void drm_vblank_put(struct drm_device *dev, int crtc);
|
||||
extern int drm_vblank_get(struct drm_device *dev, unsigned int pipe);
|
||||
extern void drm_vblank_put(struct drm_device *dev, unsigned int pipe);
|
||||
extern int drm_crtc_vblank_get(struct drm_crtc *crtc);
|
||||
extern void drm_crtc_vblank_put(struct drm_crtc *crtc);
|
||||
extern void drm_wait_one_vblank(struct drm_device *dev, int crtc);
|
||||
extern void drm_wait_one_vblank(struct drm_device *dev, unsigned int pipe);
|
||||
extern void drm_crtc_wait_one_vblank(struct drm_crtc *crtc);
|
||||
extern void drm_vblank_off(struct drm_device *dev, int crtc);
|
||||
extern void drm_vblank_on(struct drm_device *dev, int crtc);
|
||||
extern void drm_vblank_off(struct drm_device *dev, unsigned int pipe);
|
||||
extern void drm_vblank_on(struct drm_device *dev, unsigned int pipe);
|
||||
extern void drm_crtc_vblank_off(struct drm_crtc *crtc);
|
||||
extern void drm_crtc_vblank_reset(struct drm_crtc *crtc);
|
||||
extern void drm_crtc_vblank_on(struct drm_crtc *crtc);
|
||||
extern void drm_vblank_cleanup(struct drm_device *dev);
|
||||
|
||||
extern int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev,
|
||||
int crtc, int *max_error,
|
||||
unsigned int pipe, int *max_error,
|
||||
struct timeval *vblank_time,
|
||||
unsigned flags,
|
||||
const struct drm_crtc *refcrtc,
|
||||
@ -968,8 +968,8 @@ static inline wait_queue_head_t *drm_crtc_vblank_waitqueue(struct drm_crtc *crtc
|
||||
}
|
||||
|
||||
/* Modesetting support */
|
||||
extern void drm_vblank_pre_modeset(struct drm_device *dev, int crtc);
|
||||
extern void drm_vblank_post_modeset(struct drm_device *dev, int crtc);
|
||||
extern void drm_vblank_pre_modeset(struct drm_device *dev, unsigned int pipe);
|
||||
extern void drm_vblank_post_modeset(struct drm_device *dev, unsigned int pipe);
|
||||
|
||||
/* Stub support (drm_stub.h) */
|
||||
extern struct drm_master *drm_master_get(struct drm_master *master);
|
||||
|
@ -865,7 +865,7 @@ struct drm_plane {
|
||||
|
||||
uint32_t possible_crtcs;
|
||||
uint32_t *format_types;
|
||||
uint32_t format_count;
|
||||
unsigned int format_count;
|
||||
bool format_default;
|
||||
|
||||
struct drm_crtc *crtc;
|
||||
@ -1270,13 +1270,13 @@ extern int drm_universal_plane_init(struct drm_device *dev,
|
||||
unsigned long possible_crtcs,
|
||||
const struct drm_plane_funcs *funcs,
|
||||
const uint32_t *formats,
|
||||
uint32_t format_count,
|
||||
unsigned int format_count,
|
||||
enum drm_plane_type type);
|
||||
extern int drm_plane_init(struct drm_device *dev,
|
||||
struct drm_plane *plane,
|
||||
unsigned long possible_crtcs,
|
||||
const struct drm_plane_funcs *funcs,
|
||||
const uint32_t *formats, uint32_t format_count,
|
||||
const uint32_t *formats, unsigned int format_count,
|
||||
bool is_primary);
|
||||
extern void drm_plane_cleanup(struct drm_plane *plane);
|
||||
extern unsigned int drm_plane_index(struct drm_plane *plane);
|
||||
|
@ -122,6 +122,7 @@ struct drm_fb_helper {
|
||||
bool delayed_hotplug;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_DRM_FBDEV_EMULATION
|
||||
void drm_fb_helper_prepare(struct drm_device *dev, struct drm_fb_helper *helper,
|
||||
const struct drm_fb_helper_funcs *funcs);
|
||||
int drm_fb_helper_init(struct drm_device *dev,
|
||||
@ -136,11 +137,38 @@ int drm_fb_helper_check_var(struct fb_var_screeninfo *var,
|
||||
struct fb_info *info);
|
||||
|
||||
bool drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper);
|
||||
|
||||
struct fb_info *drm_fb_helper_alloc_fbi(struct drm_fb_helper *fb_helper);
|
||||
void drm_fb_helper_unregister_fbi(struct drm_fb_helper *fb_helper);
|
||||
void drm_fb_helper_release_fbi(struct drm_fb_helper *fb_helper);
|
||||
void drm_fb_helper_fill_var(struct fb_info *info, struct drm_fb_helper *fb_helper,
|
||||
uint32_t fb_width, uint32_t fb_height);
|
||||
void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch,
|
||||
uint32_t depth);
|
||||
|
||||
void drm_fb_helper_unlink_fbi(struct drm_fb_helper *fb_helper);
|
||||
|
||||
ssize_t drm_fb_helper_sys_read(struct fb_info *info, char __user *buf,
|
||||
size_t count, loff_t *ppos);
|
||||
ssize_t drm_fb_helper_sys_write(struct fb_info *info, const char __user *buf,
|
||||
size_t count, loff_t *ppos);
|
||||
|
||||
void drm_fb_helper_sys_fillrect(struct fb_info *info,
|
||||
const struct fb_fillrect *rect);
|
||||
void drm_fb_helper_sys_copyarea(struct fb_info *info,
|
||||
const struct fb_copyarea *area);
|
||||
void drm_fb_helper_sys_imageblit(struct fb_info *info,
|
||||
const struct fb_image *image);
|
||||
|
||||
void drm_fb_helper_cfb_fillrect(struct fb_info *info,
|
||||
const struct fb_fillrect *rect);
|
||||
void drm_fb_helper_cfb_copyarea(struct fb_info *info,
|
||||
const struct fb_copyarea *area);
|
||||
void drm_fb_helper_cfb_imageblit(struct fb_info *info,
|
||||
const struct fb_image *image);
|
||||
|
||||
void drm_fb_helper_set_suspend(struct drm_fb_helper *fb_helper, int state);
|
||||
|
||||
int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info);
|
||||
|
||||
int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper);
|
||||
@ -158,4 +186,188 @@ drm_pick_cmdline_mode(struct drm_fb_helper_connector *fb_helper_conn,
|
||||
int drm_fb_helper_add_one_connector(struct drm_fb_helper *fb_helper, struct drm_connector *connector);
|
||||
int drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper,
|
||||
struct drm_connector *connector);
|
||||
#else
|
||||
static inline void drm_fb_helper_prepare(struct drm_device *dev,
|
||||
struct drm_fb_helper *helper,
|
||||
const struct drm_fb_helper_funcs *funcs)
|
||||
{
|
||||
}
|
||||
|
||||
static inline int drm_fb_helper_init(struct drm_device *dev,
|
||||
struct drm_fb_helper *helper, int crtc_count,
|
||||
int max_conn)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void drm_fb_helper_fini(struct drm_fb_helper *helper)
|
||||
{
|
||||
}
|
||||
|
||||
static inline int drm_fb_helper_blank(int blank, struct fb_info *info)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int drm_fb_helper_pan_display(struct fb_var_screeninfo *var,
|
||||
struct fb_info *info)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int drm_fb_helper_set_par(struct fb_info *info)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int drm_fb_helper_check_var(struct fb_var_screeninfo *var,
|
||||
struct fb_info *info)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline struct fb_info *
|
||||
drm_fb_helper_alloc_fbi(struct drm_fb_helper *fb_helper)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline void drm_fb_helper_unregister_fbi(struct drm_fb_helper *fb_helper)
|
||||
{
|
||||
}
|
||||
static inline void drm_fb_helper_release_fbi(struct drm_fb_helper *fb_helper)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void drm_fb_helper_fill_var(struct fb_info *info,
|
||||
struct drm_fb_helper *fb_helper,
|
||||
uint32_t fb_width, uint32_t fb_height)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch,
|
||||
uint32_t depth)
|
||||
{
|
||||
}
|
||||
|
||||
static inline int drm_fb_helper_setcmap(struct fb_cmap *cmap,
|
||||
struct fb_info *info)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void drm_fb_helper_unlink_fbi(struct drm_fb_helper *fb_helper)
|
||||
{
|
||||
}
|
||||
|
||||
static inline ssize_t drm_fb_helper_sys_read(struct fb_info *info,
|
||||
char __user *buf, size_t count,
|
||||
loff_t *ppos)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static inline ssize_t drm_fb_helper_sys_write(struct fb_info *info,
|
||||
const char __user *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static inline void drm_fb_helper_sys_fillrect(struct fb_info *info,
|
||||
const struct fb_fillrect *rect)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void drm_fb_helper_sys_copyarea(struct fb_info *info,
|
||||
const struct fb_copyarea *area)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void drm_fb_helper_sys_imageblit(struct fb_info *info,
|
||||
const struct fb_image *image)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void drm_fb_helper_cfb_fillrect(struct fb_info *info,
|
||||
const struct fb_fillrect *rect)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void drm_fb_helper_cfb_copyarea(struct fb_info *info,
|
||||
const struct fb_copyarea *area)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void drm_fb_helper_cfb_imageblit(struct fb_info *info,
|
||||
const struct fb_image *image)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void drm_fb_helper_set_suspend(struct drm_fb_helper *fb_helper,
|
||||
int state)
|
||||
{
|
||||
}
|
||||
|
||||
static inline int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper,
|
||||
int bpp_sel)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int drm_fb_helper_debug_enter(struct fb_info *info)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int drm_fb_helper_debug_leave(struct fb_info *info)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline struct drm_display_mode *
|
||||
drm_has_preferred_mode(struct drm_fb_helper_connector *fb_connector,
|
||||
int width, int height)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline struct drm_display_mode *
|
||||
drm_pick_cmdline_mode(struct drm_fb_helper_connector *fb_helper_conn,
|
||||
int width, int height)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline int
|
||||
drm_fb_helper_add_one_connector(struct drm_fb_helper *fb_helper,
|
||||
struct drm_connector *connector)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper,
|
||||
struct drm_connector *connector)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
@ -130,7 +130,6 @@ struct drm_crtc;
|
||||
struct drm_plane;
|
||||
|
||||
void drm_modeset_lock_all(struct drm_device *dev);
|
||||
int __drm_modeset_lock_all(struct drm_device *dev, bool trylock);
|
||||
void drm_modeset_unlock_all(struct drm_device *dev);
|
||||
void drm_modeset_lock_crtc(struct drm_crtc *crtc,
|
||||
struct drm_plane *plane);
|
||||
|
@ -43,9 +43,8 @@
|
||||
* planes.
|
||||
*/
|
||||
|
||||
extern int drm_crtc_init(struct drm_device *dev,
|
||||
struct drm_crtc *crtc,
|
||||
const struct drm_crtc_funcs *funcs);
|
||||
int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,
|
||||
const struct drm_crtc_funcs *funcs);
|
||||
|
||||
/**
|
||||
* drm_plane_helper_funcs - helper operations for CRTCs
|
||||
@ -79,26 +78,26 @@ static inline void drm_plane_helper_add(struct drm_plane *plane,
|
||||
plane->helper_private = funcs;
|
||||
}
|
||||
|
||||
extern int drm_plane_helper_check_update(struct drm_plane *plane,
|
||||
struct drm_crtc *crtc,
|
||||
struct drm_framebuffer *fb,
|
||||
struct drm_rect *src,
|
||||
struct drm_rect *dest,
|
||||
const struct drm_rect *clip,
|
||||
int min_scale,
|
||||
int max_scale,
|
||||
bool can_position,
|
||||
bool can_update_disabled,
|
||||
bool *visible);
|
||||
extern int drm_primary_helper_update(struct drm_plane *plane,
|
||||
struct drm_crtc *crtc,
|
||||
struct drm_framebuffer *fb,
|
||||
int crtc_x, int crtc_y,
|
||||
unsigned int crtc_w, unsigned int crtc_h,
|
||||
uint32_t src_x, uint32_t src_y,
|
||||
uint32_t src_w, uint32_t src_h);
|
||||
extern int drm_primary_helper_disable(struct drm_plane *plane);
|
||||
extern void drm_primary_helper_destroy(struct drm_plane *plane);
|
||||
int drm_plane_helper_check_update(struct drm_plane *plane,
|
||||
struct drm_crtc *crtc,
|
||||
struct drm_framebuffer *fb,
|
||||
struct drm_rect *src,
|
||||
struct drm_rect *dest,
|
||||
const struct drm_rect *clip,
|
||||
int min_scale,
|
||||
int max_scale,
|
||||
bool can_position,
|
||||
bool can_update_disabled,
|
||||
bool *visible);
|
||||
int drm_primary_helper_update(struct drm_plane *plane,
|
||||
struct drm_crtc *crtc,
|
||||
struct drm_framebuffer *fb,
|
||||
int crtc_x, int crtc_y,
|
||||
unsigned int crtc_w, unsigned int crtc_h,
|
||||
uint32_t src_x, uint32_t src_y,
|
||||
uint32_t src_w, uint32_t src_h);
|
||||
int drm_primary_helper_disable(struct drm_plane *plane);
|
||||
void drm_primary_helper_destroy(struct drm_plane *plane);
|
||||
extern const struct drm_plane_funcs drm_primary_helper_funcs;
|
||||
|
||||
int drm_plane_helper_update(struct drm_plane *plane, struct drm_crtc *crtc,
|
||||
|
Loading…
Reference in New Issue
Block a user