aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorGerd Hoffmann <kraxel@redhat.com>2018-12-13 08:49:15 -0500
committerGerd Hoffmann <kraxel@redhat.com>2018-12-14 03:40:27 -0500
commit48a77d66cb7f557635f4fccd5abfc1ac2f71b9de (patch)
treeddd8eb46822a95d5d00bf26b35b110b3040b08ee /drivers
parent18ce0906d96234d7932afc90ed7ce4a338de989e (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')
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_display.c1
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_drv.c9
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_drv.h14
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_fb.c191
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_kms.c8
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
43static int virtio_gpu_probe(struct virtio_device *vdev) 43static 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
54static void virtio_gpu_remove(struct virtio_device *vdev) 61static 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
140struct 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
147struct virtio_gpu_mman { 140struct virtio_gpu_mman {
148 struct ttm_bo_device bdev; 141 struct ttm_bo_device bdev;
149}; 142};
150 143
151struct virtio_gpu_fbdev;
152
153struct virtio_gpu_queue { 144struct 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
253int virtio_gpu_fbdev_init(struct virtio_gpu_device *vgdev);
254void virtio_gpu_fbdev_fini(struct virtio_gpu_device *vgdev);
255int virtio_gpu_surface_dirty(struct virtio_gpu_framebuffer *qfb, 241int 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
32static int virtio_gpu_dirty_update(struct virtio_gpu_framebuffer *fb, 30static 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
154static 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
165static 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
176static 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
187static 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
198static 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
206static 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
279err_fb_alloc:
280 virtio_gpu_object_detach(vgdev, obj);
281err_obj_attach:
282err_obj_vmap:
283 virtio_gpu_gem_free_object(&obj->gem_base);
284 return ret;
285}
286
287static 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}
301static const struct drm_fb_helper_funcs virtio_gpu_fb_helper_funcs = {
302 .fb_probe = virtio_gpufb_create,
303};
304
305int 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
333void 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
31static int virtio_gpu_fbdev = 1;
32
33MODULE_PARM_DESC(fbdev, "Disable/Enable framebuffer device & console");
34module_param_named(fbdev, virtio_gpu_fbdev, int, 0400);
35
36static void virtio_gpu_config_changed_work_func(struct work_struct *work) 31static 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
220err_modeset: 212err_modeset: