Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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

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