diff options
| author | Gerd Hoffmann <kraxel@redhat.com> | 2018-12-13 08:49:15 -0500 |
|---|---|---|
| committer | Gerd Hoffmann <kraxel@redhat.com> | 2018-12-14 03:40:27 -0500 |
| commit | 48a77d66cb7f557635f4fccd5abfc1ac2f71b9de (patch) | |
| tree | ddd8eb46822a95d5d00bf26b35b110b3040b08ee /drivers/gpu | |
| parent | 18ce0906d96234d7932afc90ed7ce4a338de989e (diff) | |
drm/virtio: switch to generic fbdev emulation
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Dave Airlie <airlied@redhat.com>
Link: http://patchwork.freedesktop.org/patch/msgid/20181213134915.24722-1-kraxel@redhat.com
Diffstat (limited to 'drivers/gpu')
| -rw-r--r-- | drivers/gpu/drm/virtio/virtgpu_display.c | 1 | ||||
| -rw-r--r-- | drivers/gpu/drm/virtio/virtgpu_drv.c | 9 | ||||
| -rw-r--r-- | drivers/gpu/drm/virtio/virtgpu_drv.h | 14 | ||||
| -rw-r--r-- | drivers/gpu/drm/virtio/virtgpu_fb.c | 191 | ||||
| -rw-r--r-- | drivers/gpu/drm/virtio/virtgpu_kms.c | 8 |
5 files changed, 8 insertions, 215 deletions
diff --git a/drivers/gpu/drm/virtio/virtgpu_display.c b/drivers/gpu/drm/virtio/virtgpu_display.c index b5580b11a063..e1c223e18d86 100644 --- a/drivers/gpu/drm/virtio/virtgpu_display.c +++ b/drivers/gpu/drm/virtio/virtgpu_display.c | |||
| @@ -390,6 +390,5 @@ void virtio_gpu_modeset_fini(struct virtio_gpu_device *vgdev) | |||
| 390 | 390 | ||
| 391 | for (i = 0 ; i < vgdev->num_scanouts; ++i) | 391 | for (i = 0 ; i < vgdev->num_scanouts; ++i) |
| 392 | kfree(vgdev->outputs[i].edid); | 392 | kfree(vgdev->outputs[i].edid); |
| 393 | virtio_gpu_fbdev_fini(vgdev); | ||
| 394 | drm_mode_config_cleanup(vgdev->ddev); | 393 | drm_mode_config_cleanup(vgdev->ddev); |
| 395 | } | 394 | } |
diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.c b/drivers/gpu/drm/virtio/virtgpu_drv.c index f7f32a885af7..7df50920c1e0 100644 --- a/drivers/gpu/drm/virtio/virtgpu_drv.c +++ b/drivers/gpu/drm/virtio/virtgpu_drv.c | |||
| @@ -42,13 +42,20 @@ module_param_named(modeset, virtio_gpu_modeset, int, 0400); | |||
| 42 | 42 | ||
| 43 | static int virtio_gpu_probe(struct virtio_device *vdev) | 43 | static int virtio_gpu_probe(struct virtio_device *vdev) |
| 44 | { | 44 | { |
| 45 | int ret; | ||
| 46 | |||
| 45 | if (vgacon_text_force() && virtio_gpu_modeset == -1) | 47 | if (vgacon_text_force() && virtio_gpu_modeset == -1) |
| 46 | return -EINVAL; | 48 | return -EINVAL; |
| 47 | 49 | ||
| 48 | if (virtio_gpu_modeset == 0) | 50 | if (virtio_gpu_modeset == 0) |
| 49 | return -EINVAL; | 51 | return -EINVAL; |
| 50 | 52 | ||
| 51 | return drm_virtio_init(&driver, vdev); | 53 | ret = drm_virtio_init(&driver, vdev); |
| 54 | if (ret) | ||
| 55 | return ret; | ||
| 56 | |||
| 57 | drm_fbdev_generic_setup(vdev->priv, 32); | ||
| 58 | return 0; | ||
| 52 | } | 59 | } |
| 53 | 60 | ||
| 54 | static void virtio_gpu_remove(struct virtio_device *vdev) | 61 | static void virtio_gpu_remove(struct virtio_device *vdev) |
diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.h b/drivers/gpu/drm/virtio/virtgpu_drv.h index 1deb41d42ea4..63704915f8ce 100644 --- a/drivers/gpu/drm/virtio/virtgpu_drv.h +++ b/drivers/gpu/drm/virtio/virtgpu_drv.h | |||
| @@ -137,19 +137,10 @@ struct virtio_gpu_framebuffer { | |||
| 137 | #define to_virtio_gpu_framebuffer(x) \ | 137 | #define to_virtio_gpu_framebuffer(x) \ |
| 138 | container_of(x, struct virtio_gpu_framebuffer, base) | 138 | container_of(x, struct virtio_gpu_framebuffer, base) |
| 139 | 139 | ||
| 140 | struct virtio_gpu_fbdev { | ||
| 141 | struct drm_fb_helper helper; | ||
| 142 | struct virtio_gpu_framebuffer vgfb; | ||
| 143 | struct virtio_gpu_device *vgdev; | ||
| 144 | struct delayed_work work; | ||
| 145 | }; | ||
| 146 | |||
| 147 | struct virtio_gpu_mman { | 140 | struct virtio_gpu_mman { |
| 148 | struct ttm_bo_device bdev; | 141 | struct ttm_bo_device bdev; |
| 149 | }; | 142 | }; |
| 150 | 143 | ||
| 151 | struct virtio_gpu_fbdev; | ||
| 152 | |||
| 153 | struct virtio_gpu_queue { | 144 | struct virtio_gpu_queue { |
| 154 | struct virtqueue *vq; | 145 | struct virtqueue *vq; |
| 155 | spinlock_t qlock; | 146 | spinlock_t qlock; |
| @@ -180,8 +171,6 @@ struct virtio_gpu_device { | |||
| 180 | 171 | ||
| 181 | struct virtio_gpu_mman mman; | 172 | struct virtio_gpu_mman mman; |
| 182 | 173 | ||
| 183 | /* pointer to fbdev info structure */ | ||
| 184 | struct virtio_gpu_fbdev *vgfbdev; | ||
| 185 | struct virtio_gpu_output outputs[VIRTIO_GPU_MAX_SCANOUTS]; | 174 | struct virtio_gpu_output outputs[VIRTIO_GPU_MAX_SCANOUTS]; |
| 186 | uint32_t num_scanouts; | 175 | uint32_t num_scanouts; |
| 187 | 176 | ||
| @@ -249,9 +238,6 @@ int virtio_gpu_mode_dumb_mmap(struct drm_file *file_priv, | |||
| 249 | uint32_t handle, uint64_t *offset_p); | 238 | uint32_t handle, uint64_t *offset_p); |
| 250 | 239 | ||
| 251 | /* virtio_fb */ | 240 | /* virtio_fb */ |
| 252 | #define VIRTIO_GPUFB_CONN_LIMIT 1 | ||
| 253 | int virtio_gpu_fbdev_init(struct virtio_gpu_device *vgdev); | ||
| 254 | void virtio_gpu_fbdev_fini(struct virtio_gpu_device *vgdev); | ||
| 255 | int virtio_gpu_surface_dirty(struct virtio_gpu_framebuffer *qfb, | 241 | int virtio_gpu_surface_dirty(struct virtio_gpu_framebuffer *qfb, |
| 256 | struct drm_clip_rect *clips, | 242 | struct drm_clip_rect *clips, |
| 257 | unsigned int num_clips); | 243 | unsigned int num_clips); |
diff --git a/drivers/gpu/drm/virtio/virtgpu_fb.c b/drivers/gpu/drm/virtio/virtgpu_fb.c index fb1cc8b2f119..b07584b1c2bf 100644 --- a/drivers/gpu/drm/virtio/virtgpu_fb.c +++ b/drivers/gpu/drm/virtio/virtgpu_fb.c | |||
| @@ -27,8 +27,6 @@ | |||
| 27 | #include <drm/drm_fb_helper.h> | 27 | #include <drm/drm_fb_helper.h> |
| 28 | #include "virtgpu_drv.h" | 28 | #include "virtgpu_drv.h" |
| 29 | 29 | ||
| 30 | #define VIRTIO_GPU_FBCON_POLL_PERIOD (HZ / 60) | ||
| 31 | |||
| 32 | static int virtio_gpu_dirty_update(struct virtio_gpu_framebuffer *fb, | 30 | static int virtio_gpu_dirty_update(struct virtio_gpu_framebuffer *fb, |
| 33 | bool store, int x, int y, | 31 | bool store, int x, int y, |
| 34 | int width, int height) | 32 | int width, int height) |
| @@ -150,192 +148,3 @@ int virtio_gpu_surface_dirty(struct virtio_gpu_framebuffer *vgfb, | |||
| 150 | left, top, right - left, bottom - top); | 148 | left, top, right - left, bottom - top); |
| 151 | return 0; | 149 | return 0; |
| 152 | } | 150 | } |
| 153 | |||
| 154 | static void virtio_gpu_fb_dirty_work(struct work_struct *work) | ||
| 155 | { | ||
| 156 | struct delayed_work *delayed_work = to_delayed_work(work); | ||
| 157 | struct virtio_gpu_fbdev *vfbdev = | ||
| 158 | container_of(delayed_work, struct virtio_gpu_fbdev, work); | ||
| 159 | struct virtio_gpu_framebuffer *vgfb = &vfbdev->vgfb; | ||
| 160 | |||
| 161 | virtio_gpu_dirty_update(&vfbdev->vgfb, false, vgfb->x1, vgfb->y1, | ||
| 162 | vgfb->x2 - vgfb->x1, vgfb->y2 - vgfb->y1); | ||
| 163 | } | ||
| 164 | |||
| 165 | static void virtio_gpu_3d_fillrect(struct fb_info *info, | ||
| 166 | const struct fb_fillrect *rect) | ||
| 167 | { | ||
| 168 | struct virtio_gpu_fbdev *vfbdev = info->par; | ||
| 169 | |||
| 170 | drm_fb_helper_sys_fillrect(info, rect); | ||
| 171 | virtio_gpu_dirty_update(&vfbdev->vgfb, true, rect->dx, rect->dy, | ||
| 172 | rect->width, rect->height); | ||
| 173 | schedule_delayed_work(&vfbdev->work, VIRTIO_GPU_FBCON_POLL_PERIOD); | ||
| 174 | } | ||
| 175 | |||
| 176 | static void virtio_gpu_3d_copyarea(struct fb_info *info, | ||
| 177 | const struct fb_copyarea *area) | ||
| 178 | { | ||
| 179 | struct virtio_gpu_fbdev *vfbdev = info->par; | ||
| 180 | |||
| 181 | drm_fb_helper_sys_copyarea(info, area); | ||
| 182 | virtio_gpu_dirty_update(&vfbdev->vgfb, true, area->dx, area->dy, | ||
| 183 | area->width, area->height); | ||
| 184 | schedule_delayed_work(&vfbdev->work, VIRTIO_GPU_FBCON_POLL_PERIOD); | ||
| 185 | } | ||
| 186 | |||
| 187 | static void virtio_gpu_3d_imageblit(struct fb_info *info, | ||
| 188 | const struct fb_image *image) | ||
| 189 | { | ||
| 190 | struct virtio_gpu_fbdev *vfbdev = info->par; | ||
| 191 | |||
| 192 | drm_fb_helper_sys_imageblit(info, image); | ||
| 193 | virtio_gpu_dirty_update(&vfbdev->vgfb, true, image->dx, image->dy, | ||
| 194 | image->width, image->height); | ||
| 195 | schedule_delayed_work(&vfbdev->work, VIRTIO_GPU_FBCON_POLL_PERIOD); | ||
| 196 | } | ||
| 197 | |||
| 198 | static struct fb_ops virtio_gpufb_ops = { | ||
| 199 | .owner = THIS_MODULE, | ||
| 200 | DRM_FB_HELPER_DEFAULT_OPS, | ||
| 201 | .fb_fillrect = virtio_gpu_3d_fillrect, | ||
| 202 | .fb_copyarea = virtio_gpu_3d_copyarea, | ||
| 203 | .fb_imageblit = virtio_gpu_3d_imageblit, | ||
| 204 | }; | ||
| 205 | |||
| 206 | static int virtio_gpufb_create(struct drm_fb_helper *helper, | ||
| 207 | struct drm_fb_helper_surface_size *sizes) | ||
| 208 | { | ||
| 209 | struct virtio_gpu_fbdev *vfbdev = | ||
| 210 | container_of(helper, struct virtio_gpu_fbdev, helper); | ||
| 211 | struct drm_device *dev = helper->dev; | ||
| 212 | struct virtio_gpu_device *vgdev = dev->dev_private; | ||
| 213 | struct fb_info *info; | ||
| 214 | struct drm_framebuffer *fb; | ||
| 215 | struct drm_mode_fb_cmd2 mode_cmd = {}; | ||
| 216 | struct virtio_gpu_object *obj; | ||
| 217 | uint32_t format, size; | ||
| 218 | int ret; | ||
| 219 | |||
| 220 | mode_cmd.width = sizes->surface_width; | ||
| 221 | mode_cmd.height = sizes->surface_height; | ||
| 222 | mode_cmd.pitches[0] = mode_cmd.width * 4; | ||
| 223 | mode_cmd.pixel_format = DRM_FORMAT_HOST_XRGB8888; | ||
| 224 | |||
| 225 | format = virtio_gpu_translate_format(mode_cmd.pixel_format); | ||
| 226 | if (format == 0) | ||
| 227 | return -EINVAL; | ||
| 228 | |||
| 229 | size = mode_cmd.pitches[0] * mode_cmd.height; | ||
| 230 | obj = virtio_gpu_alloc_object(dev, size, false, true); | ||
| 231 | if (IS_ERR(obj)) | ||
| 232 | return PTR_ERR(obj); | ||
| 233 | |||
| 234 | virtio_gpu_cmd_create_resource(vgdev, obj, format, | ||
| 235 | mode_cmd.width, mode_cmd.height); | ||
| 236 | |||
| 237 | ret = virtio_gpu_object_kmap(obj); | ||
| 238 | if (ret) { | ||
| 239 | DRM_ERROR("failed to kmap fb %d\n", ret); | ||
| 240 | goto err_obj_vmap; | ||
| 241 | } | ||
| 242 | |||
| 243 | /* attach the object to the resource */ | ||
| 244 | ret = virtio_gpu_object_attach(vgdev, obj, NULL); | ||
| 245 | if (ret) | ||
| 246 | goto err_obj_attach; | ||
| 247 | |||
| 248 | info = drm_fb_helper_alloc_fbi(helper); | ||
| 249 | if (IS_ERR(info)) { | ||
| 250 | ret = PTR_ERR(info); | ||
| 251 | goto err_fb_alloc; | ||
| 252 | } | ||
| 253 | |||
| 254 | info->par = helper; | ||
| 255 | |||
| 256 | ret = virtio_gpu_framebuffer_init(dev, &vfbdev->vgfb, | ||
| 257 | &mode_cmd, &obj->gem_base); | ||
| 258 | if (ret) | ||
| 259 | goto err_fb_alloc; | ||
| 260 | |||
| 261 | fb = &vfbdev->vgfb.base; | ||
| 262 | |||
| 263 | vfbdev->helper.fb = fb; | ||
| 264 | |||
| 265 | strcpy(info->fix.id, "virtiodrmfb"); | ||
| 266 | info->fbops = &virtio_gpufb_ops; | ||
| 267 | info->pixmap.flags = FB_PIXMAP_SYSTEM; | ||
| 268 | |||
| 269 | info->screen_buffer = obj->vmap; | ||
| 270 | info->screen_size = obj->gem_base.size; | ||
| 271 | drm_fb_helper_fill_fix(info, fb->pitches[0], fb->format->depth); | ||
| 272 | drm_fb_helper_fill_var(info, &vfbdev->helper, | ||
| 273 | sizes->fb_width, sizes->fb_height); | ||
| 274 | |||
| 275 | info->fix.mmio_start = 0; | ||
| 276 | info->fix.mmio_len = 0; | ||
| 277 | return 0; | ||
| 278 | |||
| 279 | err_fb_alloc: | ||
| 280 | virtio_gpu_object_detach(vgdev, obj); | ||
| 281 | err_obj_attach: | ||
| 282 | err_obj_vmap: | ||
| 283 | virtio_gpu_gem_free_object(&obj->gem_base); | ||
| 284 | return ret; | ||
| 285 | } | ||
| 286 | |||
| 287 | static int virtio_gpu_fbdev_destroy(struct drm_device *dev, | ||
| 288 | struct virtio_gpu_fbdev *vgfbdev) | ||
| 289 | { | ||
| 290 | struct virtio_gpu_framebuffer *vgfb = &vgfbdev->vgfb; | ||
| 291 | |||
| 292 | drm_fb_helper_unregister_fbi(&vgfbdev->helper); | ||
| 293 | |||
| 294 | if (vgfb->base.obj[0]) | ||
| 295 | vgfb->base.obj[0] = NULL; | ||
| 296 | drm_fb_helper_fini(&vgfbdev->helper); | ||
| 297 | drm_framebuffer_cleanup(&vgfb->base); | ||
| 298 | |||
| 299 | return 0; | ||
| 300 | } | ||
| 301 | static const struct drm_fb_helper_funcs virtio_gpu_fb_helper_funcs = { | ||
| 302 | .fb_probe = virtio_gpufb_create, | ||
| 303 | }; | ||
| 304 | |||
| 305 | int virtio_gpu_fbdev_init(struct virtio_gpu_device *vgdev) | ||
| 306 | { | ||
| 307 | struct virtio_gpu_fbdev *vgfbdev; | ||
| 308 | int bpp_sel = 32; /* TODO: parameter from somewhere? */ | ||
| 309 | int ret; | ||
| 310 | |||
| 311 | vgfbdev = kzalloc(sizeof(struct virtio_gpu_fbdev), GFP_KERNEL); | ||
| 312 | if (!vgfbdev) | ||
| 313 | return -ENOMEM; | ||
| 314 | |||
| 315 | vgfbdev->vgdev = vgdev; | ||
| 316 | vgdev->vgfbdev = vgfbdev; | ||
| 317 | INIT_DELAYED_WORK(&vgfbdev->work, virtio_gpu_fb_dirty_work); | ||
| 318 | |||
| 319 | drm_fb_helper_prepare(vgdev->ddev, &vgfbdev->helper, | ||
| 320 | &virtio_gpu_fb_helper_funcs); | ||
| 321 | ret = drm_fb_helper_init(vgdev->ddev, &vgfbdev->helper, | ||
| 322 | VIRTIO_GPUFB_CONN_LIMIT); | ||
| 323 | if (ret) { | ||
| 324 | kfree(vgfbdev); | ||
| 325 | return ret; | ||
| 326 | } | ||
| 327 | |||
| 328 | drm_fb_helper_single_add_all_connectors(&vgfbdev->helper); | ||
| 329 | drm_fb_helper_initial_config(&vgfbdev->helper, bpp_sel); | ||
| 330 | return 0; | ||
| 331 | } | ||
| 332 | |||
| 333 | void virtio_gpu_fbdev_fini(struct virtio_gpu_device *vgdev) | ||
| 334 | { | ||
| 335 | if (!vgdev->vgfbdev) | ||
| 336 | return; | ||
| 337 | |||
| 338 | virtio_gpu_fbdev_destroy(vgdev->ddev, vgdev->vgfbdev); | ||
| 339 | kfree(vgdev->vgfbdev); | ||
| 340 | vgdev->vgfbdev = NULL; | ||
| 341 | } | ||
diff --git a/drivers/gpu/drm/virtio/virtgpu_kms.c b/drivers/gpu/drm/virtio/virtgpu_kms.c index 3af6181c05a8..1072064a0db2 100644 --- a/drivers/gpu/drm/virtio/virtgpu_kms.c +++ b/drivers/gpu/drm/virtio/virtgpu_kms.c | |||
| @@ -28,11 +28,6 @@ | |||
| 28 | #include <drm/drmP.h> | 28 | #include <drm/drmP.h> |
| 29 | #include "virtgpu_drv.h" | 29 | #include "virtgpu_drv.h" |
| 30 | 30 | ||
| 31 | static int virtio_gpu_fbdev = 1; | ||
| 32 | |||
| 33 | MODULE_PARM_DESC(fbdev, "Disable/Enable framebuffer device & console"); | ||
| 34 | module_param_named(fbdev, virtio_gpu_fbdev, int, 0400); | ||
| 35 | |||
| 36 | static void virtio_gpu_config_changed_work_func(struct work_struct *work) | 31 | static void virtio_gpu_config_changed_work_func(struct work_struct *work) |
| 37 | { | 32 | { |
| 38 | struct virtio_gpu_device *vgdev = | 33 | struct virtio_gpu_device *vgdev = |
| @@ -212,9 +207,6 @@ int virtio_gpu_driver_load(struct drm_device *dev, unsigned long flags) | |||
| 212 | virtio_gpu_cmd_get_display_info(vgdev); | 207 | virtio_gpu_cmd_get_display_info(vgdev); |
| 213 | wait_event_timeout(vgdev->resp_wq, !vgdev->display_info_pending, | 208 | wait_event_timeout(vgdev->resp_wq, !vgdev->display_info_pending, |
| 214 | 5 * HZ); | 209 | 5 * HZ); |
| 215 | if (virtio_gpu_fbdev) | ||
| 216 | virtio_gpu_fbdev_init(vgdev); | ||
| 217 | |||
| 218 | return 0; | 210 | return 0; |
| 219 | 211 | ||
| 220 | err_modeset: | 212 | err_modeset: |
