diff options
Diffstat (limited to 'drivers/gpu/drm/bochs')
-rw-r--r-- | drivers/gpu/drm/bochs/Makefile | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/bochs/bochs.h | 23 | ||||
-rw-r--r-- | drivers/gpu/drm/bochs/bochs_drv.c | 36 | ||||
-rw-r--r-- | drivers/gpu/drm/bochs/bochs_fbdev.c | 163 | ||||
-rw-r--r-- | drivers/gpu/drm/bochs/bochs_hw.c | 26 | ||||
-rw-r--r-- | drivers/gpu/drm/bochs/bochs_kms.c | 219 | ||||
-rw-r--r-- | drivers/gpu/drm/bochs/bochs_mm.c | 69 |
7 files changed, 208 insertions, 330 deletions
diff --git a/drivers/gpu/drm/bochs/Makefile b/drivers/gpu/drm/bochs/Makefile index 98ef60a19e8f..e9e0f8f5eb5b 100644 --- a/drivers/gpu/drm/bochs/Makefile +++ b/drivers/gpu/drm/bochs/Makefile @@ -1,3 +1,3 @@ -bochs-drm-y := bochs_drv.o bochs_mm.o bochs_kms.o bochs_fbdev.o bochs_hw.o +bochs-drm-y := bochs_drv.o bochs_mm.o bochs_kms.o bochs_hw.o obj-$(CONFIG_DRM_BOCHS) += bochs-drm.o diff --git a/drivers/gpu/drm/bochs/bochs.h b/drivers/gpu/drm/bochs/bochs.h index fb38c8b857b5..03711394f1ed 100644 --- a/drivers/gpu/drm/bochs/bochs.h +++ b/drivers/gpu/drm/bochs/bochs.h @@ -80,12 +80,6 @@ struct bochs_device { struct ttm_bo_device bdev; bool initialized; } ttm; - - /* fbdev */ - struct { - struct drm_framebuffer *fb; - struct drm_fb_helper helper; - } fb; }; struct bochs_bo { @@ -121,8 +115,9 @@ int bochs_hw_init(struct drm_device *dev); void bochs_hw_fini(struct drm_device *dev); void bochs_hw_setmode(struct bochs_device *bochs, - struct drm_display_mode *mode, - const struct drm_format_info *format); + struct drm_display_mode *mode); +void bochs_hw_setformat(struct bochs_device *bochs, + const struct drm_format_info *format); void bochs_hw_setbase(struct bochs_device *bochs, int x, int y, u64 addr); int bochs_hw_load_edid(struct bochs_device *bochs); @@ -141,15 +136,19 @@ int bochs_dumb_create(struct drm_file *file, struct drm_device *dev, int bochs_dumb_mmap_offset(struct drm_file *file, struct drm_device *dev, uint32_t handle, uint64_t *offset); -int bochs_bo_pin(struct bochs_bo *bo, u32 pl_flag, u64 *gpu_addr); +int bochs_bo_pin(struct bochs_bo *bo, u32 pl_flag); int bochs_bo_unpin(struct bochs_bo *bo); +int bochs_gem_prime_pin(struct drm_gem_object *obj); +void bochs_gem_prime_unpin(struct drm_gem_object *obj); +void *bochs_gem_prime_vmap(struct drm_gem_object *obj); +void bochs_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr); +int bochs_gem_prime_mmap(struct drm_gem_object *obj, + struct vm_area_struct *vma); + /* bochs_kms.c */ int bochs_kms_init(struct bochs_device *bochs); void bochs_kms_fini(struct bochs_device *bochs); /* bochs_fbdev.c */ -int bochs_fbdev_init(struct bochs_device *bochs); -void bochs_fbdev_fini(struct bochs_device *bochs); - extern const struct drm_mode_config_funcs bochs_mode_funcs; diff --git a/drivers/gpu/drm/bochs/bochs_drv.c b/drivers/gpu/drm/bochs/bochs_drv.c index aa35007262cd..6b6e037258c3 100644 --- a/drivers/gpu/drm/bochs/bochs_drv.c +++ b/drivers/gpu/drm/bochs/bochs_drv.c @@ -9,6 +9,7 @@ #include <linux/module.h> #include <linux/slab.h> #include <drm/drm_fb_helper.h> +#include <drm/drm_probe_helper.h> #include "bochs.h" @@ -16,10 +17,6 @@ static int bochs_modeset = -1; module_param_named(modeset, bochs_modeset, int, 0444); MODULE_PARM_DESC(modeset, "enable/disable kernel modesetting"); -static bool enable_fbdev = true; -module_param_named(fbdev, enable_fbdev, bool, 0444); -MODULE_PARM_DESC(fbdev, "register fbdev device"); - /* ---------------------------------------------------------------------- */ /* drm interface */ @@ -27,7 +24,6 @@ static void bochs_unload(struct drm_device *dev) { struct bochs_device *bochs = dev->dev_private; - bochs_fbdev_fini(bochs); bochs_kms_fini(bochs); bochs_mm_fini(bochs); bochs_hw_fini(dev); @@ -58,9 +54,6 @@ static int bochs_load(struct drm_device *dev) if (ret) goto err; - if (enable_fbdev) - bochs_fbdev_init(bochs); - return 0; err: @@ -81,7 +74,8 @@ static const struct file_operations bochs_fops = { }; static struct drm_driver bochs_driver = { - .driver_features = DRIVER_GEM | DRIVER_MODESET, + .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC | + DRIVER_PRIME, .fops = &bochs_fops, .name = "bochs-drm", .desc = "bochs dispi vga interface (qemu stdvga)", @@ -91,6 +85,14 @@ static struct drm_driver bochs_driver = { .gem_free_object_unlocked = bochs_gem_free_object, .dumb_create = bochs_dumb_create, .dumb_map_offset = bochs_dumb_mmap_offset, + + .gem_prime_export = drm_gem_prime_export, + .gem_prime_import = drm_gem_prime_import, + .gem_prime_pin = bochs_gem_prime_pin, + .gem_prime_unpin = bochs_gem_prime_unpin, + .gem_prime_vmap = bochs_gem_prime_vmap, + .gem_prime_vunmap = bochs_gem_prime_vunmap, + .gem_prime_mmap = bochs_gem_prime_mmap, }; /* ---------------------------------------------------------------------- */ @@ -101,27 +103,16 @@ static int bochs_pm_suspend(struct device *dev) { struct pci_dev *pdev = to_pci_dev(dev); struct drm_device *drm_dev = pci_get_drvdata(pdev); - struct bochs_device *bochs = drm_dev->dev_private; - - drm_kms_helper_poll_disable(drm_dev); - - drm_fb_helper_set_suspend_unlocked(&bochs->fb.helper, 1); - return 0; + return drm_mode_config_helper_suspend(drm_dev); } static int bochs_pm_resume(struct device *dev) { struct pci_dev *pdev = to_pci_dev(dev); struct drm_device *drm_dev = pci_get_drvdata(pdev); - struct bochs_device *bochs = drm_dev->dev_private; - - drm_helper_resume_force_mode(drm_dev); - drm_fb_helper_set_suspend_unlocked(&bochs->fb.helper, 0); - - drm_kms_helper_poll_enable(drm_dev); - return 0; + return drm_mode_config_helper_resume(drm_dev); } #endif @@ -169,6 +160,7 @@ static int bochs_pci_probe(struct pci_dev *pdev, if (ret) goto err_unload; + drm_fbdev_generic_setup(dev, 32); return ret; err_unload: diff --git a/drivers/gpu/drm/bochs/bochs_fbdev.c b/drivers/gpu/drm/bochs/bochs_fbdev.c deleted file mode 100644 index dd3c7df267da..000000000000 --- a/drivers/gpu/drm/bochs/bochs_fbdev.c +++ /dev/null @@ -1,163 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include "bochs.h" -#include <drm/drm_gem_framebuffer_helper.h> - -/* ---------------------------------------------------------------------- */ - -static int bochsfb_mmap(struct fb_info *info, - struct vm_area_struct *vma) -{ - struct drm_fb_helper *fb_helper = info->par; - struct bochs_bo *bo = gem_to_bochs_bo(fb_helper->fb->obj[0]); - - return ttm_fbdev_mmap(vma, &bo->bo); -} - -static struct fb_ops bochsfb_ops = { - .owner = THIS_MODULE, - DRM_FB_HELPER_DEFAULT_OPS, - .fb_fillrect = drm_fb_helper_cfb_fillrect, - .fb_copyarea = drm_fb_helper_cfb_copyarea, - .fb_imageblit = drm_fb_helper_cfb_imageblit, - .fb_mmap = bochsfb_mmap, -}; - -static int bochsfb_create_object(struct bochs_device *bochs, - const struct drm_mode_fb_cmd2 *mode_cmd, - struct drm_gem_object **gobj_p) -{ - struct drm_device *dev = bochs->dev; - struct drm_gem_object *gobj; - u32 size; - int ret = 0; - - size = mode_cmd->pitches[0] * mode_cmd->height; - ret = bochs_gem_create(dev, size, true, &gobj); - if (ret) - return ret; - - *gobj_p = gobj; - return ret; -} - -static int bochsfb_create(struct drm_fb_helper *helper, - struct drm_fb_helper_surface_size *sizes) -{ - struct bochs_device *bochs = - container_of(helper, struct bochs_device, fb.helper); - struct fb_info *info; - struct drm_framebuffer *fb; - struct drm_mode_fb_cmd2 mode_cmd; - struct drm_gem_object *gobj = NULL; - struct bochs_bo *bo = NULL; - int size, ret; - - if (sizes->surface_bpp != 32) - return -EINVAL; - - mode_cmd.width = sizes->surface_width; - mode_cmd.height = sizes->surface_height; - mode_cmd.pitches[0] = sizes->surface_width * 4; - mode_cmd.pixel_format = DRM_FORMAT_HOST_XRGB8888; - size = mode_cmd.pitches[0] * mode_cmd.height; - - /* alloc, pin & map bo */ - ret = bochsfb_create_object(bochs, &mode_cmd, &gobj); - if (ret) { - DRM_ERROR("failed to create fbcon backing object %d\n", ret); - return ret; - } - - bo = gem_to_bochs_bo(gobj); - - ret = ttm_bo_reserve(&bo->bo, true, false, NULL); - if (ret) - return ret; - - ret = bochs_bo_pin(bo, TTM_PL_FLAG_VRAM, NULL); - if (ret) { - DRM_ERROR("failed to pin fbcon\n"); - ttm_bo_unreserve(&bo->bo); - return ret; - } - - ret = ttm_bo_kmap(&bo->bo, 0, bo->bo.num_pages, - &bo->kmap); - if (ret) { - DRM_ERROR("failed to kmap fbcon\n"); - ttm_bo_unreserve(&bo->bo); - return ret; - } - - ttm_bo_unreserve(&bo->bo); - - /* init fb device */ - info = drm_fb_helper_alloc_fbi(helper); - if (IS_ERR(info)) { - DRM_ERROR("Failed to allocate fbi: %ld\n", PTR_ERR(info)); - return PTR_ERR(info); - } - - info->par = &bochs->fb.helper; - - fb = drm_gem_fbdev_fb_create(bochs->dev, sizes, 0, gobj, NULL); - if (IS_ERR(fb)) { - DRM_ERROR("Failed to create framebuffer: %ld\n", PTR_ERR(fb)); - return PTR_ERR(fb); - } - - /* setup helper */ - bochs->fb.helper.fb = fb; - - strcpy(info->fix.id, "bochsdrmfb"); - - info->fbops = &bochsfb_ops; - - drm_fb_helper_fill_fix(info, fb->pitches[0], fb->format->depth); - drm_fb_helper_fill_var(info, &bochs->fb.helper, sizes->fb_width, - sizes->fb_height); - - info->screen_base = bo->kmap.virtual; - info->screen_size = size; - - drm_vma_offset_remove(&bo->bo.bdev->vma_manager, &bo->bo.vma_node); - info->fix.smem_start = 0; - info->fix.smem_len = size; - return 0; -} - -static const struct drm_fb_helper_funcs bochs_fb_helper_funcs = { - .fb_probe = bochsfb_create, -}; - -static struct drm_framebuffer * -bochs_gem_fb_create(struct drm_device *dev, struct drm_file *file, - const struct drm_mode_fb_cmd2 *mode_cmd) -{ - if (mode_cmd->pixel_format != DRM_FORMAT_XRGB8888 && - mode_cmd->pixel_format != DRM_FORMAT_BGRX8888) - return ERR_PTR(-EINVAL); - - return drm_gem_fb_create(dev, file, mode_cmd); -} - -const struct drm_mode_config_funcs bochs_mode_funcs = { - .fb_create = bochs_gem_fb_create, -}; - -int bochs_fbdev_init(struct bochs_device *bochs) -{ - return drm_fb_helper_fbdev_setup(bochs->dev, &bochs->fb.helper, - &bochs_fb_helper_funcs, 32, 1); -} - -void bochs_fbdev_fini(struct bochs_device *bochs) -{ - drm_fb_helper_fbdev_teardown(bochs->dev); -} diff --git a/drivers/gpu/drm/bochs/bochs_hw.c b/drivers/gpu/drm/bochs/bochs_hw.c index c90a0d492fd5..3e04b2f0ec08 100644 --- a/drivers/gpu/drm/bochs/bochs_hw.c +++ b/drivers/gpu/drm/bochs/bochs_hw.c @@ -86,9 +86,16 @@ static int bochs_get_edid_block(void *data, u8 *buf, int bochs_hw_load_edid(struct bochs_device *bochs) { + u8 header[8]; + if (!bochs->mmio) return -1; + /* check header to detect whenever edid support is enabled in qemu */ + bochs_get_edid_block(bochs, header, 0, ARRAY_SIZE(header)); + if (drm_edid_header_is_valid(header) != 8) + return -1; + kfree(bochs->edid); bochs->edid = drm_do_get_edid(&bochs->connector, bochs_get_edid_block, bochs); @@ -197,8 +204,7 @@ void bochs_hw_fini(struct drm_device *dev) } void bochs_hw_setmode(struct bochs_device *bochs, - struct drm_display_mode *mode, - const struct drm_format_info *format) + struct drm_display_mode *mode) { bochs->xres = mode->hdisplay; bochs->yres = mode->vdisplay; @@ -206,12 +212,8 @@ void bochs_hw_setmode(struct bochs_device *bochs, bochs->stride = mode->hdisplay * (bochs->bpp / 8); bochs->yres_virtual = bochs->fb_size / bochs->stride; - DRM_DEBUG_DRIVER("%dx%d @ %d bpp, format %c%c%c%c, vy %d\n", + DRM_DEBUG_DRIVER("%dx%d @ %d bpp, vy %d\n", bochs->xres, bochs->yres, bochs->bpp, - (format->format >> 0) & 0xff, - (format->format >> 8) & 0xff, - (format->format >> 16) & 0xff, - (format->format >> 24) & 0xff, bochs->yres_virtual); bochs_vga_writeb(bochs, 0x3c0, 0x20); /* unblank */ @@ -229,6 +231,16 @@ void bochs_hw_setmode(struct bochs_device *bochs, bochs_dispi_write(bochs, VBE_DISPI_INDEX_ENABLE, VBE_DISPI_ENABLED | VBE_DISPI_LFB_ENABLED); +} + +void bochs_hw_setformat(struct bochs_device *bochs, + const struct drm_format_info *format) +{ + DRM_DEBUG_DRIVER("format %c%c%c%c\n", + (format->format >> 0) & 0xff, + (format->format >> 8) & 0xff, + (format->format >> 16) & 0xff, + (format->format >> 24) & 0xff); switch (format->format) { case DRM_FORMAT_XRGB8888: diff --git a/drivers/gpu/drm/bochs/bochs_kms.c b/drivers/gpu/drm/bochs/bochs_kms.c index f87c284dd93d..9cd82e3631fb 100644 --- a/drivers/gpu/drm/bochs/bochs_kms.c +++ b/drivers/gpu/drm/bochs/bochs_kms.c @@ -6,7 +6,11 @@ */ #include "bochs.h" +#include <drm/drm_atomic_helper.h> #include <drm/drm_plane_helper.h> +#include <drm/drm_atomic_uapi.h> +#include <drm/drm_gem_framebuffer_helper.h> +#include <drm/drm_probe_helper.h> static int defx = 1024; static int defy = 768; @@ -18,115 +22,51 @@ MODULE_PARM_DESC(defy, "default y resolution"); /* ---------------------------------------------------------------------- */ -static void bochs_crtc_dpms(struct drm_crtc *crtc, int mode) -{ - switch (mode) { - case DRM_MODE_DPMS_ON: - case DRM_MODE_DPMS_STANDBY: - case DRM_MODE_DPMS_SUSPEND: - case DRM_MODE_DPMS_OFF: - default: - return; - } -} - -static int bochs_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, - struct drm_framebuffer *old_fb) -{ - struct bochs_device *bochs = - container_of(crtc, struct bochs_device, crtc); - struct bochs_bo *bo; - u64 gpu_addr = 0; - int ret; - - if (old_fb) { - bo = gem_to_bochs_bo(old_fb->obj[0]); - ret = ttm_bo_reserve(&bo->bo, true, false, NULL); - if (ret) { - DRM_ERROR("failed to reserve old_fb bo\n"); - } else { - bochs_bo_unpin(bo); - ttm_bo_unreserve(&bo->bo); - } - } - - if (WARN_ON(crtc->primary->fb == NULL)) - return -EINVAL; - - bo = gem_to_bochs_bo(crtc->primary->fb->obj[0]); - ret = ttm_bo_reserve(&bo->bo, true, false, NULL); - if (ret) - return ret; - - ret = bochs_bo_pin(bo, TTM_PL_FLAG_VRAM, &gpu_addr); - if (ret) { - ttm_bo_unreserve(&bo->bo); - return ret; - } - - ttm_bo_unreserve(&bo->bo); - bochs_hw_setbase(bochs, x, y, gpu_addr); - return 0; -} - -static int bochs_crtc_mode_set(struct drm_crtc *crtc, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode, - int x, int y, struct drm_framebuffer *old_fb) +static void bochs_crtc_mode_set_nofb(struct drm_crtc *crtc) { struct bochs_device *bochs = container_of(crtc, struct bochs_device, crtc); - if (WARN_ON(crtc->primary->fb == NULL)) - return -EINVAL; - - bochs_hw_setmode(bochs, mode, crtc->primary->fb->format); - bochs_crtc_mode_set_base(crtc, x, y, old_fb); - return 0; + bochs_hw_setmode(bochs, &crtc->mode); } -static void bochs_crtc_prepare(struct drm_crtc *crtc) +static void bochs_crtc_atomic_enable(struct drm_crtc *crtc, + struct drm_crtc_state *old_crtc_state) { } -static void bochs_crtc_commit(struct drm_crtc *crtc) +static void bochs_crtc_atomic_flush(struct drm_crtc *crtc, + struct drm_crtc_state *old_crtc_state) { -} + struct drm_device *dev = crtc->dev; + struct drm_pending_vblank_event *event; -static int bochs_crtc_page_flip(struct drm_crtc *crtc, - struct drm_framebuffer *fb, - struct drm_pending_vblank_event *event, - uint32_t page_flip_flags, - struct drm_modeset_acquire_ctx *ctx) -{ - struct bochs_device *bochs = - container_of(crtc, struct bochs_device, crtc); - struct drm_framebuffer *old_fb = crtc->primary->fb; - unsigned long irqflags; + if (crtc->state && crtc->state->event) { + unsigned long irqflags; - crtc->primary->fb = fb; - bochs_crtc_mode_set_base(crtc, 0, 0, old_fb); - if (event) { - spin_lock_irqsave(&bochs->dev->event_lock, irqflags); + spin_lock_irqsave(&dev->event_lock, irqflags); + event = crtc->state->event; + crtc->state->event = NULL; drm_crtc_send_vblank_event(crtc, event); - spin_unlock_irqrestore(&bochs->dev->event_lock, irqflags); + spin_unlock_irqrestore(&dev->event_lock, irqflags); } - return 0; } + /* These provide the minimum set of functions required to handle a CRTC */ static const struct drm_crtc_funcs bochs_crtc_funcs = { - .set_config = drm_crtc_helper_set_config, + .set_config = drm_atomic_helper_set_config, .destroy = drm_crtc_cleanup, - .page_flip = bochs_crtc_page_flip, + .page_flip = drm_atomic_helper_page_flip, + .reset = drm_atomic_helper_crtc_reset, + .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, }; static const struct drm_crtc_helper_funcs bochs_helper_funcs = { - .dpms = bochs_crtc_dpms, - .mode_set = bochs_crtc_mode_set, - .mode_set_base = bochs_crtc_mode_set_base, - .prepare = bochs_crtc_prepare, - .commit = bochs_crtc_commit, + .mode_set_nofb = bochs_crtc_mode_set_nofb, + .atomic_enable = bochs_crtc_atomic_enable, + .atomic_flush = bochs_crtc_atomic_flush, }; static const uint32_t bochs_formats[] = { @@ -134,6 +74,59 @@ static const uint32_t bochs_formats[] = { DRM_FORMAT_BGRX8888, }; +static void bochs_plane_atomic_update(struct drm_plane *plane, + struct drm_plane_state *old_state) +{ + struct bochs_device *bochs = plane->dev->dev_private; + struct bochs_bo *bo; + + if (!plane->state->fb) + return; + bo = gem_to_bochs_bo(plane->state->fb->obj[0]); + bochs_hw_setbase(bochs, + plane->state->crtc_x, + plane->state->crtc_y, + bo->bo.offset); + bochs_hw_setformat(bochs, plane->state->fb->format); +} + +static int bochs_plane_prepare_fb(struct drm_plane *plane, + struct drm_plane_state *new_state) +{ + struct bochs_bo *bo; + + if (!new_state->fb) + return 0; + bo = gem_to_bochs_bo(new_state->fb->obj[0]); + return bochs_bo_pin(bo, TTM_PL_FLAG_VRAM); +} + +static void bochs_plane_cleanup_fb(struct drm_plane *plane, + struct drm_plane_state *old_state) +{ + struct bochs_bo *bo; + + if (!old_state->fb) + return; + bo = gem_to_bochs_bo(old_state->fb->obj[0]); + bochs_bo_unpin(bo); +} + +static const struct drm_plane_helper_funcs bochs_plane_helper_funcs = { + .atomic_update = bochs_plane_atomic_update, + .prepare_fb = bochs_plane_prepare_fb, + .cleanup_fb = bochs_plane_cleanup_fb, +}; + +static const struct drm_plane_funcs bochs_plane_funcs = { + .update_plane = drm_atomic_helper_update_plane, + .disable_plane = drm_atomic_helper_disable_plane, + .destroy = drm_primary_helper_destroy, + .reset = drm_atomic_helper_plane_reset, + .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, +}; + static struct drm_plane *bochs_primary_plane(struct drm_device *dev) { struct drm_plane *primary; @@ -146,16 +139,17 @@ static struct drm_plane *bochs_primary_plane(struct drm_device *dev) } ret = drm_universal_plane_init(dev, primary, 0, - &drm_primary_helper_funcs, + &bochs_plane_funcs, bochs_formats, ARRAY_SIZE(bochs_formats), NULL, DRM_PLANE_TYPE_PRIMARY, NULL); if (ret) { kfree(primary); - primary = NULL; + return NULL; } + drm_plane_helper_add(primary, &bochs_plane_helper_funcs); return primary; } @@ -170,31 +164,6 @@ static void bochs_crtc_init(struct drm_device *dev) drm_crtc_helper_add(crtc, &bochs_helper_funcs); } -static void bochs_encoder_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ -} - -static void bochs_encoder_dpms(struct drm_encoder *encoder, int state) -{ -} - -static void bochs_encoder_prepare(struct drm_encoder *encoder) -{ -} - -static void bochs_encoder_commit(struct drm_encoder *encoder) -{ -} - -static const struct drm_encoder_helper_funcs bochs_encoder_helper_funcs = { - .dpms = bochs_encoder_dpms, - .mode_set = bochs_encoder_mode_set, - .prepare = bochs_encoder_prepare, - .commit = bochs_encoder_commit, -}; - static const struct drm_encoder_funcs bochs_encoder_encoder_funcs = { .destroy = drm_encoder_cleanup, }; @@ -207,7 +176,6 @@ static void bochs_encoder_init(struct drm_device *dev) encoder->possible_crtcs = 0x1; drm_encoder_init(dev, encoder, &bochs_encoder_encoder_funcs, DRM_MODE_ENCODER_DAC, NULL); - drm_encoder_helper_add(encoder, &bochs_encoder_helper_funcs); } @@ -266,6 +234,9 @@ static const struct drm_connector_funcs bochs_connector_connector_funcs = { .dpms = drm_helper_connector_dpms, .fill_modes = drm_helper_probe_single_connector_modes, .destroy = drm_connector_cleanup, + .reset = drm_atomic_helper_connector_reset, + .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, }; static void bochs_connector_init(struct drm_device *dev) @@ -287,6 +258,22 @@ static void bochs_connector_init(struct drm_device *dev) } } +static struct drm_framebuffer * +bochs_gem_fb_create(struct drm_device *dev, struct drm_file *file, + const struct drm_mode_fb_cmd2 *mode_cmd) +{ + if (mode_cmd->pixel_format != DRM_FORMAT_XRGB8888 && + mode_cmd->pixel_format != DRM_FORMAT_BGRX8888) + return ERR_PTR(-EINVAL); + + return drm_gem_fb_create(dev, file, mode_cmd); +} + +const struct drm_mode_config_funcs bochs_mode_funcs = { + .fb_create = bochs_gem_fb_create, + .atomic_check = drm_atomic_helper_check, + .atomic_commit = drm_atomic_helper_commit, +}; int bochs_kms_init(struct bochs_device *bochs) { @@ -309,6 +296,8 @@ int bochs_kms_init(struct bochs_device *bochs) drm_connector_attach_encoder(&bochs->connector, &bochs->encoder); + drm_mode_config_reset(bochs->dev); + return 0; } diff --git a/drivers/gpu/drm/bochs/bochs_mm.c b/drivers/gpu/drm/bochs/bochs_mm.c index 0980411e41bf..49463348a07a 100644 --- a/drivers/gpu/drm/bochs/bochs_mm.c +++ b/drivers/gpu/drm/bochs/bochs_mm.c @@ -210,33 +210,28 @@ static void bochs_ttm_placement(struct bochs_bo *bo, int domain) bo->placement.num_busy_placement = c; } -static inline u64 bochs_bo_gpu_offset(struct bochs_bo *bo) -{ - return bo->bo.offset; -} - -int bochs_bo_pin(struct bochs_bo *bo, u32 pl_flag, u64 *gpu_addr) +int bochs_bo_pin(struct bochs_bo *bo, u32 pl_flag) { struct ttm_operation_ctx ctx = { false, false }; int i, ret; if (bo->pin_count) { bo->pin_count++; - if (gpu_addr) - *gpu_addr = bochs_bo_gpu_offset(bo); return 0; } bochs_ttm_placement(bo, pl_flag); for (i = 0; i < bo->placement.num_placement; i++) bo->placements[i].flags |= TTM_PL_FLAG_NO_EVICT; + ret = ttm_bo_reserve(&bo->bo, true, false, NULL); + if (ret) + return ret; ret = ttm_bo_validate(&bo->bo, &bo->placement, &ctx); + ttm_bo_unreserve(&bo->bo); if (ret) return ret; bo->pin_count = 1; - if (gpu_addr) - *gpu_addr = bochs_bo_gpu_offset(bo); return 0; } @@ -256,7 +251,11 @@ int bochs_bo_unpin(struct bochs_bo *bo) for (i = 0; i < bo->placement.num_placement; i++) bo->placements[i].flags &= ~TTM_PL_FLAG_NO_EVICT; + ret = ttm_bo_reserve(&bo->bo, true, false, NULL); + if (ret) + return ret; ret = ttm_bo_validate(&bo->bo, &bo->placement, &ctx); + ttm_bo_unreserve(&bo->bo); if (ret) return ret; @@ -396,3 +395,53 @@ int bochs_dumb_mmap_offset(struct drm_file *file, struct drm_device *dev, drm_gem_object_put_unlocked(obj); return 0; } + +/* ---------------------------------------------------------------------- */ + +int bochs_gem_prime_pin(struct drm_gem_object *obj) +{ + struct bochs_bo *bo = gem_to_bochs_bo(obj); + + return bochs_bo_pin(bo, TTM_PL_FLAG_VRAM); +} + +void bochs_gem_prime_unpin(struct drm_gem_object *obj) +{ + struct bochs_bo *bo = gem_to_bochs_bo(obj); + + bochs_bo_unpin(bo); +} + +void *bochs_gem_prime_vmap(struct drm_gem_object *obj) +{ + struct bochs_bo *bo = gem_to_bochs_bo(obj); + bool is_iomem; + int ret; + + ret = bochs_bo_pin(bo, TTM_PL_FLAG_VRAM); + if (ret) + return NULL; + ret = ttm_bo_kmap(&bo->bo, 0, bo->bo.num_pages, &bo->kmap); + if (ret) { + bochs_bo_unpin(bo); + return NULL; + } + return ttm_kmap_obj_virtual(&bo->kmap, &is_iomem); +} + +void bochs_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr) +{ + struct bochs_bo *bo = gem_to_bochs_bo(obj); + + ttm_bo_kunmap(&bo->kmap); + bochs_bo_unpin(bo); +} + +int bochs_gem_prime_mmap(struct drm_gem_object *obj, + struct vm_area_struct *vma) +{ + struct bochs_bo *bo = gem_to_bochs_bo(obj); + + bo->gem.vma_node.vm_node.start = bo->bo.vma_node.vm_node.start; + return drm_gem_prime_mmap(obj, vma); +} |