aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/virtio
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/virtio')
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_display.c12
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_drv.c1
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_drv.h3
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_kms.c8
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_vq.c67
5 files changed, 91 insertions, 0 deletions
diff --git a/drivers/gpu/drm/virtio/virtgpu_display.c b/drivers/gpu/drm/virtio/virtgpu_display.c
index 8f8fed471e34..b5580b11a063 100644
--- a/drivers/gpu/drm/virtio/virtgpu_display.c
+++ b/drivers/gpu/drm/virtio/virtgpu_display.c
@@ -169,6 +169,12 @@ static int virtio_gpu_conn_get_modes(struct drm_connector *connector)
169 struct drm_display_mode *mode = NULL; 169 struct drm_display_mode *mode = NULL;
170 int count, width, height; 170 int count, width, height;
171 171
172 if (output->edid) {
173 count = drm_add_edid_modes(connector, output->edid);
174 if (count)
175 return count;
176 }
177
172 width = le32_to_cpu(output->info.r.width); 178 width = le32_to_cpu(output->info.r.width);
173 height = le32_to_cpu(output->info.r.height); 179 height = le32_to_cpu(output->info.r.height);
174 count = drm_add_modes_noedid(connector, XRES_MAX, YRES_MAX); 180 count = drm_add_modes_noedid(connector, XRES_MAX, YRES_MAX);
@@ -287,6 +293,8 @@ static int vgdev_output_init(struct virtio_gpu_device *vgdev, int index)
287 drm_connector_init(dev, connector, &virtio_gpu_connector_funcs, 293 drm_connector_init(dev, connector, &virtio_gpu_connector_funcs,
288 DRM_MODE_CONNECTOR_VIRTUAL); 294 DRM_MODE_CONNECTOR_VIRTUAL);
289 drm_connector_helper_add(connector, &virtio_gpu_conn_helper_funcs); 295 drm_connector_helper_add(connector, &virtio_gpu_conn_helper_funcs);
296 if (vgdev->has_edid)
297 drm_connector_attach_edid_property(connector);
290 298
291 drm_encoder_init(dev, encoder, &virtio_gpu_enc_funcs, 299 drm_encoder_init(dev, encoder, &virtio_gpu_enc_funcs,
292 DRM_MODE_ENCODER_VIRTUAL, NULL); 300 DRM_MODE_ENCODER_VIRTUAL, NULL);
@@ -378,6 +386,10 @@ int virtio_gpu_modeset_init(struct virtio_gpu_device *vgdev)
378 386
379void virtio_gpu_modeset_fini(struct virtio_gpu_device *vgdev) 387void virtio_gpu_modeset_fini(struct virtio_gpu_device *vgdev)
380{ 388{
389 int i;
390
391 for (i = 0 ; i < vgdev->num_scanouts; ++i)
392 kfree(vgdev->outputs[i].edid);
381 virtio_gpu_fbdev_fini(vgdev); 393 virtio_gpu_fbdev_fini(vgdev);
382 drm_mode_config_cleanup(vgdev->ddev); 394 drm_mode_config_cleanup(vgdev->ddev);
383} 395}
diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.c b/drivers/gpu/drm/virtio/virtgpu_drv.c
index d9287c144fe5..f7f32a885af7 100644
--- a/drivers/gpu/drm/virtio/virtgpu_drv.c
+++ b/drivers/gpu/drm/virtio/virtgpu_drv.c
@@ -80,6 +80,7 @@ static unsigned int features[] = {
80 */ 80 */
81 VIRTIO_GPU_F_VIRGL, 81 VIRTIO_GPU_F_VIRGL,
82#endif 82#endif
83 VIRTIO_GPU_F_EDID,
83}; 84};
84static struct virtio_driver virtio_gpu_driver = { 85static struct virtio_driver virtio_gpu_driver = {
85 .feature_table = features, 86 .feature_table = features,
diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.h b/drivers/gpu/drm/virtio/virtgpu_drv.h
index 9db568054d66..f7e877857c1f 100644
--- a/drivers/gpu/drm/virtio/virtgpu_drv.h
+++ b/drivers/gpu/drm/virtio/virtgpu_drv.h
@@ -115,6 +115,7 @@ struct virtio_gpu_output {
115 struct drm_encoder enc; 115 struct drm_encoder enc;
116 struct virtio_gpu_display_one info; 116 struct virtio_gpu_display_one info;
117 struct virtio_gpu_update_cursor cursor; 117 struct virtio_gpu_update_cursor cursor;
118 struct edid *edid;
118 int cur_x; 119 int cur_x;
119 int cur_y; 120 int cur_y;
120 bool enabled; 121 bool enabled;
@@ -201,6 +202,7 @@ struct virtio_gpu_device {
201 struct ida ctx_id_ida; 202 struct ida ctx_id_ida;
202 203
203 bool has_virgl_3d; 204 bool has_virgl_3d;
205 bool has_edid;
204 206
205 struct work_struct config_changed_work; 207 struct work_struct config_changed_work;
206 208
@@ -291,6 +293,7 @@ int virtio_gpu_cmd_get_capset_info(struct virtio_gpu_device *vgdev, int idx);
291int virtio_gpu_cmd_get_capset(struct virtio_gpu_device *vgdev, 293int virtio_gpu_cmd_get_capset(struct virtio_gpu_device *vgdev,
292 int idx, int version, 294 int idx, int version,
293 struct virtio_gpu_drv_cap_cache **cache_p); 295 struct virtio_gpu_drv_cap_cache **cache_p);
296int virtio_gpu_cmd_get_edids(struct virtio_gpu_device *vgdev);
294void virtio_gpu_cmd_context_create(struct virtio_gpu_device *vgdev, uint32_t id, 297void virtio_gpu_cmd_context_create(struct virtio_gpu_device *vgdev, uint32_t id,
295 uint32_t nlen, const char *name); 298 uint32_t nlen, const char *name);
296void virtio_gpu_cmd_context_destroy(struct virtio_gpu_device *vgdev, 299void virtio_gpu_cmd_context_destroy(struct virtio_gpu_device *vgdev,
diff --git a/drivers/gpu/drm/virtio/virtgpu_kms.c b/drivers/gpu/drm/virtio/virtgpu_kms.c
index 691b842d5f3a..3af6181c05a8 100644
--- a/drivers/gpu/drm/virtio/virtgpu_kms.c
+++ b/drivers/gpu/drm/virtio/virtgpu_kms.c
@@ -44,6 +44,8 @@ static void virtio_gpu_config_changed_work_func(struct work_struct *work)
44 virtio_cread(vgdev->vdev, struct virtio_gpu_config, 44 virtio_cread(vgdev->vdev, struct virtio_gpu_config,
45 events_read, &events_read); 45 events_read, &events_read);
46 if (events_read & VIRTIO_GPU_EVENT_DISPLAY) { 46 if (events_read & VIRTIO_GPU_EVENT_DISPLAY) {
47 if (vgdev->has_edid)
48 virtio_gpu_cmd_get_edids(vgdev);
47 virtio_gpu_cmd_get_display_info(vgdev); 49 virtio_gpu_cmd_get_display_info(vgdev);
48 drm_helper_hpd_irq_event(vgdev->ddev); 50 drm_helper_hpd_irq_event(vgdev->ddev);
49 events_clear |= VIRTIO_GPU_EVENT_DISPLAY; 51 events_clear |= VIRTIO_GPU_EVENT_DISPLAY;
@@ -156,6 +158,10 @@ int virtio_gpu_driver_load(struct drm_device *dev, unsigned long flags)
156#else 158#else
157 DRM_INFO("virgl 3d acceleration not supported by guest\n"); 159 DRM_INFO("virgl 3d acceleration not supported by guest\n");
158#endif 160#endif
161 if (virtio_has_feature(vgdev->vdev, VIRTIO_GPU_F_EDID)) {
162 vgdev->has_edid = true;
163 DRM_INFO("EDID support available.\n");
164 }
159 165
160 ret = virtio_find_vqs(vgdev->vdev, 2, vqs, callbacks, names, NULL); 166 ret = virtio_find_vqs(vgdev->vdev, 2, vqs, callbacks, names, NULL);
161 if (ret) { 167 if (ret) {
@@ -201,6 +207,8 @@ int virtio_gpu_driver_load(struct drm_device *dev, unsigned long flags)
201 207
202 if (num_capsets) 208 if (num_capsets)
203 virtio_gpu_get_capsets(vgdev, num_capsets); 209 virtio_gpu_get_capsets(vgdev, num_capsets);
210 if (vgdev->has_edid)
211 virtio_gpu_cmd_get_edids(vgdev);
204 virtio_gpu_cmd_get_display_info(vgdev); 212 virtio_gpu_cmd_get_display_info(vgdev);
205 wait_event_timeout(vgdev->resp_wq, !vgdev->display_info_pending, 213 wait_event_timeout(vgdev->resp_wq, !vgdev->display_info_pending,
206 5 * HZ); 214 5 * HZ);
diff --git a/drivers/gpu/drm/virtio/virtgpu_vq.c b/drivers/gpu/drm/virtio/virtgpu_vq.c
index 93f2c3a51ee8..2c6764f08f18 100644
--- a/drivers/gpu/drm/virtio/virtgpu_vq.c
+++ b/drivers/gpu/drm/virtio/virtgpu_vq.c
@@ -584,6 +584,45 @@ static void virtio_gpu_cmd_capset_cb(struct virtio_gpu_device *vgdev,
584 wake_up(&vgdev->resp_wq); 584 wake_up(&vgdev->resp_wq);
585} 585}
586 586
587static int virtio_get_edid_block(void *data, u8 *buf,
588 unsigned int block, size_t len)
589{
590 struct virtio_gpu_resp_edid *resp = data;
591 size_t start = block * EDID_LENGTH;
592
593 if (start + len > le32_to_cpu(resp->size))
594 return -1;
595 memcpy(buf, resp->edid + start, len);
596 return 0;
597}
598
599static void virtio_gpu_cmd_get_edid_cb(struct virtio_gpu_device *vgdev,
600 struct virtio_gpu_vbuffer *vbuf)
601{
602 struct virtio_gpu_cmd_get_edid *cmd =
603 (struct virtio_gpu_cmd_get_edid *)vbuf->buf;
604 struct virtio_gpu_resp_edid *resp =
605 (struct virtio_gpu_resp_edid *)vbuf->resp_buf;
606 uint32_t scanout = le32_to_cpu(cmd->scanout);
607 struct virtio_gpu_output *output;
608 struct edid *new_edid, *old_edid;
609
610 if (scanout >= vgdev->num_scanouts)
611 return;
612 output = vgdev->outputs + scanout;
613
614 new_edid = drm_do_get_edid(&output->conn, virtio_get_edid_block, resp);
615
616 spin_lock(&vgdev->display_info_lock);
617 old_edid = output->edid;
618 output->edid = new_edid;
619 drm_connector_update_edid_property(&output->conn, output->edid);
620 spin_unlock(&vgdev->display_info_lock);
621
622 kfree(old_edid);
623 wake_up(&vgdev->resp_wq);
624}
625
587int virtio_gpu_cmd_get_display_info(struct virtio_gpu_device *vgdev) 626int virtio_gpu_cmd_get_display_info(struct virtio_gpu_device *vgdev)
588{ 627{
589 struct virtio_gpu_ctrl_hdr *cmd_p; 628 struct virtio_gpu_ctrl_hdr *cmd_p;
@@ -686,6 +725,34 @@ int virtio_gpu_cmd_get_capset(struct virtio_gpu_device *vgdev,
686 return 0; 725 return 0;
687} 726}
688 727
728int virtio_gpu_cmd_get_edids(struct virtio_gpu_device *vgdev)
729{
730 struct virtio_gpu_cmd_get_edid *cmd_p;
731 struct virtio_gpu_vbuffer *vbuf;
732 void *resp_buf;
733 int scanout;
734
735 if (WARN_ON(!vgdev->has_edid))
736 return -EINVAL;
737
738 for (scanout = 0; scanout < vgdev->num_scanouts; scanout++) {
739 resp_buf = kzalloc(sizeof(struct virtio_gpu_resp_edid),
740 GFP_KERNEL);
741 if (!resp_buf)
742 return -ENOMEM;
743
744 cmd_p = virtio_gpu_alloc_cmd_resp
745 (vgdev, &virtio_gpu_cmd_get_edid_cb, &vbuf,
746 sizeof(*cmd_p), sizeof(struct virtio_gpu_resp_edid),
747 resp_buf);
748 cmd_p->hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_GET_EDID);
749 cmd_p->scanout = cpu_to_le32(scanout);
750 virtio_gpu_queue_ctrl_buffer(vgdev, vbuf);
751 }
752
753 return 0;
754}
755
689void virtio_gpu_cmd_context_create(struct virtio_gpu_device *vgdev, uint32_t id, 756void virtio_gpu_cmd_context_create(struct virtio_gpu_device *vgdev, uint32_t id,
690 uint32_t nlen, const char *name) 757 uint32_t nlen, const char *name)
691{ 758{