diff options
Diffstat (limited to 'drivers/gpu/drm/bochs/bochs_kms.c')
-rw-r--r-- | drivers/gpu/drm/bochs/bochs_kms.c | 218 |
1 files changed, 103 insertions, 115 deletions
diff --git a/drivers/gpu/drm/bochs/bochs_kms.c b/drivers/gpu/drm/bochs/bochs_kms.c index f87c284dd93d..e9d5dbc34676 100644 --- a/drivers/gpu/drm/bochs/bochs_kms.c +++ b/drivers/gpu/drm/bochs/bochs_kms.c @@ -6,7 +6,10 @@ */ #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> static int defx = 1024; static int defy = 768; @@ -18,115 +21,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 +73,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 +138,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 +163,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 +175,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 +233,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 +257,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 +295,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; } |