VirtualBox

source: vbox/trunk/src/VBox/Additions/linux/drm/vbox_mode.c@ 59240

Last change on this file since 59240 was 59240, checked in by vboxsync, 9 years ago

bugref:8087: Additions/x11: support non-root X server: add host flags location reporting to the kernel graphics driver in preparation for adding IRQ handling. Among other things, the host uses the flags, which it places at the location reported/requested by the guest in video RAM, to tell the guest what event the IRQ was sent in response to.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 24.6 KB
Line 
1/* $Id: vbox_mode.c 59240 2016-01-01 20:20:34Z vboxsync $ */
2/** @file
3 * VirtualBox Additions Linux kernel video driver
4 */
5
6/*
7 * Copyright (C) 2013 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 * --------------------------------------------------------------------
17 *
18 * This code is based on
19 * ast_mode.c
20 * with the following copyright and permission notice:
21 *
22 * Copyright 2012 Red Hat Inc.
23 * Parts based on xf86-video-vbox
24 * Copyright (c) 2005 ASPEED Technology Inc.
25 *
26 * Permission is hereby granted, free of charge, to any person obtaining a
27 * copy of this software and associated documentation files (the
28 * "Software"), to deal in the Software without restriction, including
29 * without limitation the rights to use, copy, modify, merge, publish,
30 * distribute, sub license, and/or sell copies of the Software, and to
31 * permit persons to whom the Software is furnished to do so, subject to
32 * the following conditions:
33 *
34 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
35 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
36 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
37 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
38 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
39 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
40 * USE OR OTHER DEALINGS IN THE SOFTWARE.
41 *
42 * The above copyright notice and this permission notice (including the
43 * next paragraph) shall be included in all copies or substantial portions
44 * of the Software.
45 *
46 */
47/*
48 * Authors: Dave Airlie <[email protected]>
49 */
50#include "vbox_drv.h"
51
52#include <VBox/VBoxVideo.h>
53
54#include <linux/export.h>
55#include <drm/drm_crtc_helper.h>
56#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0)
57# include <drm/drm_plane_helper.h>
58#endif
59
60static int vbox_cursor_set2(struct drm_crtc *crtc, struct drm_file *file_priv,
61 uint32_t handle, uint32_t width, uint32_t height,
62 int32_t hot_x, int32_t hot_y);
63static int vbox_cursor_move(struct drm_crtc *crtc, int x, int y);
64
65/** Set a graphics mode. Poke any required values into registers, do an HGSMI
66 * mode set and tell the host we support advanced graphics functions.
67 */
68static void vbox_do_modeset(struct drm_crtc *crtc,
69 const struct drm_display_mode *mode)
70{
71 struct vbox_crtc *vbox_crtc = to_vbox_crtc(crtc);
72 struct vbox_private *vbox;
73 int width, height, cBPP, pitch;
74 unsigned iCrtc;
75 uint16_t fFlags;
76
77 LogFunc(("vboxvideo: %d: vbox_crtc=%p, CRTC_FB(crtc)=%p\n", __LINE__,
78 vbox_crtc, CRTC_FB(crtc)));
79 vbox = crtc->dev->dev_private;
80 width = mode->hdisplay ? mode->hdisplay : 640;
81 height = mode->vdisplay ? mode->vdisplay : 480;
82 iCrtc = vbox_crtc->crtc_id;
83 cBPP = crtc->enabled ? CRTC_FB(crtc)->bits_per_pixel : 32;
84#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0)
85 pitch = crtc->enabled ? CRTC_FB(crtc)->pitch : width * cBPP / 8;
86#else
87 pitch = crtc->enabled ? CRTC_FB(crtc)->pitches[0] : width * cBPP / 8;
88#endif
89 /* if (vbox_crtc->crtc_id == 0 && crtc->enabled)
90 VBoxVideoSetModeRegisters(width, height, pitch * 8 / cBPP,
91 CRTC_FB(crtc)->bits_per_pixel, 0,
92 crtc->x, crtc->y); */
93 fFlags = VBVA_SCREEN_F_ACTIVE;
94 fFlags |= (crtc->enabled ? 0 : VBVA_SCREEN_F_DISABLED);
95 VBoxHGSMIProcessDisplayInfo(&vbox->Ctx, vbox_crtc->crtc_id,
96 crtc->x, crtc->y,
97 crtc->x * cBPP / 8 + crtc->y * pitch,
98 pitch, width, height,
99 vbox_crtc->fBlanked ? 0 : cBPP, fFlags);
100 VBoxHGSMIReportFlagsLocation(&vbox->Ctx, vbox->offHostFlags);
101 VBoxHGSMISendCapsInfo(&vbox->Ctx, VBVACAPS_VIDEO_MODE_HINTS | VBVACAPS_DISABLE_CURSOR_INTEGRATION);
102 LogFunc(("vboxvideo: %d\n", __LINE__));
103}
104
105static int vbox_set_view(struct drm_crtc *crtc)
106{
107 struct vbox_crtc *vbox_crtc = to_vbox_crtc(crtc);
108 struct vbox_private *vbox = crtc->dev->dev_private;
109 void *p;
110
111 LogFunc(("vboxvideo: %d: vbox_crtc=%p\n", __LINE__, vbox_crtc));
112 /* Tell the host about the view. This design originally targeted the
113 * Windows XP driver architecture and assumed that each screen would have
114 * a dedicated frame buffer with the command buffer following it, the whole
115 * being a "view". The host works out which screen a command buffer belongs
116 * to by checking whether it is in the first view, then whether it is in the
117 * second and so on. The first match wins. We cheat around this by making
118 * the first view be the managed memory plus the first command buffer, the
119 * second the same plus the second buffer and so on. */
120 p = VBoxHGSMIBufferAlloc(&vbox->Ctx, sizeof(VBVAINFOVIEW), HGSMI_CH_VBVA,
121 VBVA_INFO_VIEW);
122 if (p)
123 {
124 VBVAINFOVIEW *pInfo = (VBVAINFOVIEW *)p;
125 pInfo->u32ViewIndex = vbox_crtc->crtc_id;
126 pInfo->u32ViewOffset = vbox_crtc->offFB;
127 pInfo->u32ViewSize = vbox->vram_size - vbox_crtc->offFB
128 + vbox_crtc->crtc_id * VBVA_MIN_BUFFER_SIZE;
129 pInfo->u32MaxScreenSize = vbox->vram_size - vbox_crtc->offFB;
130 VBoxHGSMIBufferSubmit(&vbox->Ctx, p);
131 VBoxHGSMIBufferFree(&vbox->Ctx, p);
132 }
133 else
134 return -ENOMEM;
135 LogFunc(("vboxvideo: %d: p=%p\n", __LINE__, p));
136 return 0;
137}
138
139static void vbox_crtc_load_lut(struct drm_crtc *crtc)
140{
141
142}
143
144static void vbox_crtc_dpms(struct drm_crtc *crtc, int mode)
145{
146 struct vbox_crtc *vbox_crtc = to_vbox_crtc(crtc);
147 struct vbox_private *vbox = crtc->dev->dev_private;
148 unsigned long flags;
149
150 LogFunc(("vboxvideo: %d: vbox_crtc=%p, mode=%d\n", __LINE__, vbox_crtc,
151 mode));
152 switch (mode)
153 {
154 case DRM_MODE_DPMS_ON:
155 vbox_crtc->fBlanked = false;
156 break;
157 case DRM_MODE_DPMS_STANDBY:
158 case DRM_MODE_DPMS_SUSPEND:
159 case DRM_MODE_DPMS_OFF:
160 vbox_crtc->fBlanked = true;
161 break;
162 }
163 spin_lock_irqsave(&vbox->dev_lock, flags);
164 vbox_do_modeset(crtc, &crtc->hwmode);
165 spin_unlock_irqrestore(&vbox->dev_lock, flags);
166 LogFunc(("vboxvideo: %d\n", __LINE__));
167}
168
169static bool vbox_crtc_mode_fixup(struct drm_crtc *crtc,
170 const struct drm_display_mode *mode,
171 struct drm_display_mode *adjusted_mode)
172{
173 return true;
174}
175
176static int vbox_crtc_do_set_base(struct drm_crtc *crtc,
177 struct drm_framebuffer *fb,
178 int x, int y, int atomic)
179{
180 struct vbox_private *vbox = crtc->dev->dev_private;
181 struct vbox_crtc *vbox_crtc = to_vbox_crtc(crtc);
182 struct drm_gem_object *obj;
183 struct vbox_framebuffer *vbox_fb;
184 struct vbox_bo *bo;
185 int ret;
186 u64 gpu_addr;
187
188 LogFunc(("vboxvideo: %d: fb=%p, vbox_crtc=%p\n", __LINE__, fb, vbox_crtc));
189
190 vbox_fb = to_vbox_framebuffer(CRTC_FB(crtc));
191 obj = vbox_fb->obj;
192 bo = gem_to_vbox_bo(obj);
193
194 ret = vbox_bo_reserve(bo, false);
195 if (ret)
196 return ret;
197
198 ret = vbox_bo_pin(bo, TTM_PL_FLAG_VRAM, &gpu_addr);
199 if (ret)
200 {
201 vbox_bo_unreserve(bo);
202 return ret;
203 }
204
205 if (&vbox->fbdev->afb == vbox_fb)
206 {
207 /* if pushing console in kmap it */
208 ret = ttm_bo_kmap(&bo->bo, 0, bo->bo.num_pages, &bo->kmap);
209 if (ret)
210 DRM_ERROR("failed to kmap fbcon\n");
211 }
212 vbox_bo_unreserve(bo);
213
214 /* vbox_set_start_address_crt1(crtc, (u32)gpu_addr); */
215 vbox_crtc->offFB = gpu_addr;
216
217 LogFunc(("vboxvideo: %d: vbox_fb=%p, obj=%p, bo=%p, gpu_addr=%u\n",
218 __LINE__, vbox_fb, obj, bo, (unsigned)gpu_addr));
219 return 0;
220}
221
222static int vbox_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
223 struct drm_framebuffer *old_fb)
224{
225 LogFunc(("vboxvideo: %d\n", __LINE__));
226 return vbox_crtc_do_set_base(crtc, old_fb, x, y, 0);
227}
228
229static int vbox_crtc_mode_set(struct drm_crtc *crtc,
230 struct drm_display_mode *mode,
231 struct drm_display_mode *adjusted_mode,
232 int x, int y,
233 struct drm_framebuffer *old_fb)
234{
235 struct vbox_private *vbox = crtc->dev->dev_private;
236 unsigned long flags;
237 int rc = 0;
238
239 LogFunc(("vboxvideo: %d: vbox=%p\n", __LINE__, vbox));
240 vbox_crtc_mode_set_base(crtc, x, y, old_fb);
241 spin_lock_irqsave(&vbox->dev_lock, flags);
242 rc = vbox_set_view(crtc);
243 if (!rc)
244 vbox_do_modeset(crtc, mode);
245 spin_unlock_irqrestore(&vbox->dev_lock, flags);
246 LogFunc(("vboxvideo: %d\n", __LINE__));
247 return rc;
248}
249
250static void vbox_crtc_disable(struct drm_crtc *crtc)
251{
252
253}
254
255static void vbox_crtc_prepare(struct drm_crtc *crtc)
256{
257
258}
259
260static void vbox_crtc_commit(struct drm_crtc *crtc)
261{
262
263}
264
265
266static const struct drm_crtc_helper_funcs vbox_crtc_helper_funcs =
267{
268 .dpms = vbox_crtc_dpms,
269 .mode_fixup = vbox_crtc_mode_fixup,
270 .mode_set = vbox_crtc_mode_set,
271 /* .mode_set_base = vbox_crtc_mode_set_base, */
272 .disable = vbox_crtc_disable,
273 .load_lut = vbox_crtc_load_lut,
274 .prepare = vbox_crtc_prepare,
275 .commit = vbox_crtc_commit,
276
277};
278
279static void vbox_crtc_reset(struct drm_crtc *crtc)
280{
281
282}
283
284
285static void vbox_crtc_destroy(struct drm_crtc *crtc)
286{
287 drm_crtc_cleanup(crtc);
288 kfree(crtc);
289}
290
291static const struct drm_crtc_funcs vbox_crtc_funcs =
292{
293 .cursor_move = vbox_cursor_move,
294#ifdef DRM_IOCTL_MODE_CURSOR2
295 .cursor_set2 = vbox_cursor_set2,
296#endif
297 .reset = vbox_crtc_reset,
298 .set_config = drm_crtc_helper_set_config,
299 /* .gamma_set = vbox_crtc_gamma_set, */
300 .destroy = vbox_crtc_destroy,
301};
302
303int vbox_crtc_init(struct drm_device *pDev, unsigned i)
304{
305 struct vbox_crtc *pCrtc;
306
307 LogFunc(("vboxvideo: %d\n", __LINE__));
308 pCrtc = kzalloc(sizeof(struct vbox_crtc), GFP_KERNEL);
309 if (!pCrtc)
310 return -ENOMEM;
311 pCrtc->crtc_id = i;
312
313 drm_crtc_init(pDev, &pCrtc->base, &vbox_crtc_funcs);
314 drm_mode_crtc_set_gamma_size(&pCrtc->base, 256);
315 drm_crtc_helper_add(&pCrtc->base, &vbox_crtc_helper_funcs);
316 LogFunc(("vboxvideo: %d: pCrtc=%p\n", __LINE__, pCrtc));
317
318 return 0;
319}
320
321
322static void vbox_encoder_destroy(struct drm_encoder *encoder)
323{
324 LogFunc(("vboxvideo: %d: encoder=%p\n", __LINE__, encoder));
325 drm_encoder_cleanup(encoder);
326 kfree(encoder);
327}
328
329
330static struct drm_encoder *vbox_best_single_encoder(struct drm_connector *connector)
331{
332 int enc_id = connector->encoder_ids[0];
333 struct drm_mode_object *obj;
334 struct drm_encoder *encoder;
335
336 LogFunc(("vboxvideo: %d: connector=%p\n", __LINE__, connector));
337 /* pick the encoder ids */
338 if (enc_id)
339 {
340 obj = drm_mode_object_find(connector->dev, enc_id, DRM_MODE_OBJECT_ENCODER);
341 if (!obj)
342 return NULL;
343 encoder = obj_to_encoder(obj);
344 LogFunc(("vboxvideo: %d: encoder=%p\n", __LINE__, encoder));
345 return encoder;
346 }
347 LogFunc(("vboxvideo: %d\n", __LINE__));
348 return NULL;
349}
350
351
352static const struct drm_encoder_funcs vbox_enc_funcs =
353{
354 .destroy = vbox_encoder_destroy,
355};
356
357static void vbox_encoder_dpms(struct drm_encoder *encoder, int mode)
358{
359
360}
361
362static bool vbox_mode_fixup(struct drm_encoder *encoder,
363 const struct drm_display_mode *mode,
364 struct drm_display_mode *adjusted_mode)
365{
366 return true;
367}
368
369static void vbox_encoder_mode_set(struct drm_encoder *encoder,
370 struct drm_display_mode *mode,
371 struct drm_display_mode *adjusted_mode)
372{
373}
374
375static void vbox_encoder_prepare(struct drm_encoder *encoder)
376{
377
378}
379
380static void vbox_encoder_commit(struct drm_encoder *encoder)
381{
382
383}
384
385
386static const struct drm_encoder_helper_funcs vbox_enc_helper_funcs =
387{
388 .dpms = vbox_encoder_dpms,
389 .mode_fixup = vbox_mode_fixup,
390 .prepare = vbox_encoder_prepare,
391 .commit = vbox_encoder_commit,
392 .mode_set = vbox_encoder_mode_set,
393};
394
395struct drm_encoder *vbox_encoder_init(struct drm_device *dev, unsigned i)
396{
397 struct vbox_encoder *vbox_encoder;
398
399 LogFunc(("vboxvideo: %d: dev=%d\n", __LINE__));
400 vbox_encoder = kzalloc(sizeof(struct vbox_encoder), GFP_KERNEL);
401 if (!vbox_encoder)
402 return NULL;
403
404 drm_encoder_init(dev, &vbox_encoder->base, &vbox_enc_funcs,
405 DRM_MODE_ENCODER_DAC);
406 drm_encoder_helper_add(&vbox_encoder->base, &vbox_enc_helper_funcs);
407
408 vbox_encoder->base.possible_crtcs = 1 << i;
409 LogFunc(("vboxvideo: %d: vbox_encoder=%p\n", __LINE__, vbox_encoder));
410 return &vbox_encoder->base;
411}
412
413static void vboxUpdateHints(struct vbox_connector *pVBoxConnector)
414{
415 struct vbox_private *pVBox;
416 int rc;
417
418 LogFunc(("vboxvideo: %d: pVBoxConnector=%p\n", __LINE__, pVBoxConnector));
419 pVBox = pVBoxConnector->base.dev->dev_private;
420 rc = VBoxHGSMIGetModeHints(&pVBox->Ctx, pVBox->cCrtcs, pVBox->paVBVAModeHints);
421 AssertMsgRCReturnVoid(rc, ("VBoxHGSMIGetModeHints failed, rc=%Rrc.\n", rc));
422 if (pVBox->paVBVAModeHints[pVBoxConnector->iCrtc].magic == VBVAMODEHINT_MAGIC)
423 {
424 pVBoxConnector->modeHint.cX = pVBox->paVBVAModeHints[pVBoxConnector->iCrtc].cx & 0x8fff;
425 pVBoxConnector->modeHint.cY = pVBox->paVBVAModeHints[pVBoxConnector->iCrtc].cy & 0x8fff;
426 pVBoxConnector->modeHint.fDisconnected = !(pVBox->paVBVAModeHints[pVBoxConnector->iCrtc].fEnabled);
427 LogFunc(("vboxvideo: %d: cX=%u, cY=%u, fDisconnected=%RTbool\n", __LINE__,
428 (unsigned)pVBoxConnector->modeHint.cX, (unsigned)pVBoxConnector->modeHint.cY,
429 pVBoxConnector->modeHint.fDisconnected));
430 }
431}
432
433static int vbox_get_modes(struct drm_connector *pConnector)
434{
435 struct vbox_connector *pVBoxConnector = NULL;
436 struct drm_display_mode *pMode = NULL;
437 unsigned cModes = 0;
438 int cxPreferred, cyPreferred;
439
440 LogFunc(("vboxvideo: %d: pConnector=%p\n", __LINE__, pConnector));
441 pVBoxConnector = to_vbox_connector(pConnector);
442 vboxUpdateHints(pVBoxConnector);
443 cModes = drm_add_modes_noedid(pConnector, 2560, 1600);
444 cxPreferred = pVBoxConnector->modeHint.cX ? pVBoxConnector->modeHint.cX : 1024;
445 cyPreferred = pVBoxConnector->modeHint.cY ? pVBoxConnector->modeHint.cY : 768;
446 pMode = drm_cvt_mode(pConnector->dev, cxPreferred, cyPreferred, 60, false,
447 false, false);
448 if (pMode)
449 {
450 pMode->type |= DRM_MODE_TYPE_PREFERRED;
451 drm_mode_probed_add(pConnector, pMode);
452 ++cModes;
453 }
454 return cModes;
455}
456
457static int vbox_mode_valid(struct drm_connector *connector,
458 struct drm_display_mode *mode)
459{
460 return MODE_OK;
461}
462
463static void vbox_connector_destroy(struct drm_connector *pConnector)
464{
465 struct vbox_connector *pVBoxConnector = NULL;
466
467 LogFunc(("vboxvideo: %d: connector=%p\n", __LINE__, pConnector));
468 pVBoxConnector = to_vbox_connector(pConnector);
469 device_remove_file(pConnector->dev->dev, &pVBoxConnector->deviceAttribute);
470#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0)
471 drm_sysfs_connector_remove(pConnector);
472#else
473 drm_connector_unregister(pConnector);
474#endif
475 drm_connector_cleanup(pConnector);
476 kfree(pConnector);
477}
478
479static enum drm_connector_status
480vbox_connector_detect(struct drm_connector *pConnector, bool fForce)
481{
482 struct vbox_connector *pVBoxConnector = NULL;
483
484 (void) fForce;
485 LogFunc(("vboxvideo: %d: connector=%p\n", __LINE__, pConnector));
486 pVBoxConnector = to_vbox_connector(pConnector);
487 vboxUpdateHints(pVBoxConnector);
488 return !pVBoxConnector->modeHint.fDisconnected;
489}
490
491static int vbox_fill_modes(struct drm_connector *pConnector, uint32_t xMax, uint32_t yMax)
492{
493 struct vbox_connector *pVBoxConnector;
494 struct drm_device *pDrmDev;
495 struct drm_display_mode *pMode, *pIter;
496
497 LogFunc(("vboxvideo: %d: pConnector=%p, xMax=%lu, yMax = %lu\n", __LINE__,
498 pConnector, (unsigned long)xMax, (unsigned long)yMax));
499 pVBoxConnector = to_vbox_connector(pConnector);
500 pDrmDev = pVBoxConnector->base.dev;
501 list_for_each_entry_safe(pMode, pIter, &pConnector->modes, head)
502 {
503 list_del(&pMode->head);
504 drm_mode_destroy(pDrmDev, pMode);
505 }
506 return drm_helper_probe_single_connector_modes(pConnector, xMax, yMax);
507}
508
509static const struct drm_connector_helper_funcs vbox_connector_helper_funcs =
510{
511 .mode_valid = vbox_mode_valid,
512 .get_modes = vbox_get_modes,
513 .best_encoder = vbox_best_single_encoder,
514};
515
516static const struct drm_connector_funcs vbox_connector_funcs =
517{
518 .dpms = drm_helper_connector_dpms,
519 .detect = vbox_connector_detect,
520 .fill_modes = vbox_fill_modes,
521 .destroy = vbox_connector_destroy,
522};
523
524ssize_t vbox_connector_write_sysfs(struct device *pDev,
525 struct device_attribute *pAttr,
526 const char *psz, size_t cch)
527{
528 struct vbox_connector *pVBoxConnector;
529 struct vbox_private *pVBox;
530
531 LogFunc(("vboxvideo: %d: pDev=%p, pAttr=%p, psz=%s, cch=%llu\n", __LINE__,
532 pDev, pAttr, psz, (unsigned long long)cch));
533 pVBoxConnector = container_of(pAttr, struct vbox_connector,
534 deviceAttribute);
535 pVBox = pVBoxConnector->base.dev->dev_private;
536 drm_kms_helper_hotplug_event(pVBoxConnector->base.dev);
537 if (pVBox->fbdev)
538 drm_fb_helper_hotplug_event(&pVBox->fbdev->helper);
539 return cch;
540}
541
542int vbox_connector_init(struct drm_device *pDev, unsigned cScreen,
543 struct drm_encoder *pEncoder)
544{
545 struct vbox_connector *pVBoxConnector;
546 struct drm_connector *pConnector;
547 int rc;
548
549 LogFunc(("vboxvideo: %d: pDev=%p, pEncoder=%p\n", __LINE__, pDev,
550 pEncoder));
551 pVBoxConnector = kzalloc(sizeof(struct vbox_connector), GFP_KERNEL);
552 if (!pVBoxConnector)
553 return -ENOMEM;
554
555 pConnector = &pVBoxConnector->base;
556 pVBoxConnector->iCrtc = cScreen;
557
558 /*
559 * Set up the sysfs file we use for getting video mode hints from user
560 * space.
561 */
562 snprintf(pVBoxConnector->szName, sizeof(pVBoxConnector->szName),
563 "vbox_screen_%u", cScreen);
564 pVBoxConnector->deviceAttribute.attr.name = pVBoxConnector->szName;
565 pVBoxConnector->deviceAttribute.attr.mode = S_IWUSR;
566 pVBoxConnector->deviceAttribute.show = NULL;
567 pVBoxConnector->deviceAttribute.store = vbox_connector_write_sysfs;
568 rc = device_create_file(pDev->dev, &pVBoxConnector->deviceAttribute);
569 if (rc < 0)
570 {
571 kfree(pVBoxConnector);
572 return rc;
573 }
574 drm_connector_init(pDev, pConnector, &vbox_connector_funcs,
575 DRM_MODE_CONNECTOR_VGA);
576 drm_connector_helper_add(pConnector, &vbox_connector_helper_funcs);
577
578 pConnector->interlace_allowed = 0;
579 pConnector->doublescan_allowed = 0;
580
581#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0)
582 drm_sysfs_connector_add(pConnector);
583#else
584 drm_connector_register(pConnector);
585#endif
586
587 drm_mode_connector_attach_encoder(pConnector, pEncoder);
588
589 LogFunc(("vboxvideo: %d: pConnector=%p\n", __LINE__, pConnector));
590 return 0;
591}
592
593#if 0
594/* allocate cursor cache and pin at start of VRAM */
595int vbox_cursor_init(struct drm_device *dev)
596{
597 struct vbox_private *vbox = dev->dev_private;
598 int size;
599 int ret;
600 struct drm_gem_object *obj;
601 struct vbox_bo *bo;
602 uint64_t gpu_addr;
603
604 size = (AST_HWC_SIZE + AST_HWC_SIGNATURE_SIZE) * AST_DEFAULT_HWC_NUM;
605
606 ret = vbox_gem_create(dev, size, true, &obj);
607 if (ret)
608 return ret;
609 bo = gem_to_vbox_bo(obj);
610 ret = vbox_bo_reserve(bo, false);
611 if (unlikely(ret != 0))
612 goto fail;
613
614 ret = vbox_bo_pin(bo, TTM_PL_FLAG_VRAM, &gpu_addr);
615 vbox_bo_unreserve(bo);
616 if (ret)
617 goto fail;
618
619 /* kmap the object */
620 ret = ttm_bo_kmap(&bo->bo, 0, bo->bo.num_pages, &vbox->cache_kmap);
621 if (ret)
622 goto fail;
623
624 vbox->cursor_cache = obj;
625 vbox->cursor_cache_gpu_addr = gpu_addr;
626 DRM_DEBUG_KMS("pinned cursor cache at %llx\n", vbox->cursor_cache_gpu_addr);
627 return 0;
628fail:
629 return ret;
630}
631
632void vbox_cursor_fini(struct drm_device *dev)
633{
634 struct vbox_private *vbox = dev->dev_private;
635 ttm_bo_kunmap(&vbox->cache_kmap);
636 drm_gem_object_unreference_unlocked(vbox->cursor_cache);
637}
638#endif
639
640int vbox_mode_init(struct drm_device *pDev)
641{
642 struct vbox_private *pVBox = pDev->dev_private;
643 struct drm_encoder *pEncoder;
644 unsigned i;
645 /* vbox_cursor_init(dev); */
646 LogFunc(("vboxvideo: %d: pDev=%p\n", __LINE__, pDev));
647 for (i = 0; i < pVBox->cCrtcs; ++i)
648 {
649 vbox_crtc_init(pDev, i);
650 pEncoder = vbox_encoder_init(pDev, i);
651 if (pEncoder)
652 vbox_connector_init(pDev, i, pEncoder);
653 }
654 return 0;
655}
656
657void vbox_mode_fini(struct drm_device *dev)
658{
659 /* vbox_cursor_fini(dev); */
660}
661
662
663void VBoxRefreshModes(struct drm_device *pDev)
664{
665 struct vbox_private *vbox = pDev->dev_private;
666 struct drm_crtc *crtci;
667 unsigned long flags;
668
669 LogFunc(("vboxvideo: %d\n", __LINE__));
670 spin_lock_irqsave(&vbox->dev_lock, flags);
671 list_for_each_entry(crtci, &pDev->mode_config.crtc_list, head)
672 vbox_do_modeset(crtci, &crtci->hwmode);
673 spin_unlock_irqrestore(&vbox->dev_lock, flags);
674 LogFunc(("vboxvideo: %d\n", __LINE__));
675}
676
677
678/** Copy the ARGB image and generate the mask, which is needed in case the host
679 * does not support ARGB cursors. The mask is a 1BPP bitmap with the bit set
680 * if the corresponding alpha value in the ARGB image is greater than 0xF0. */
681static void copy_cursor_image(u8 *src, u8 *dst, int width, int height,
682 size_t cbMask)
683{
684 unsigned i, j;
685 size_t cbLine = (width + 7) / 8;
686
687 memcpy(dst + cbMask, src, width * height * 4);
688 for (i = 0; i < height; ++i)
689 for (j = 0; j < width; ++j)
690 if (((uint32_t *)src)[i * width + j] > 0xf0000000)
691 dst[i * cbLine + j / 8] |= (0x80 >> (j % 8));
692}
693
694static int vbox_cursor_set2(struct drm_crtc *crtc, struct drm_file *file_priv,
695 uint32_t handle, uint32_t width, uint32_t height,
696 int32_t hot_x, int32_t hot_y)
697{
698 struct vbox_private *vbox = crtc->dev->dev_private;
699 struct vbox_crtc *vbox_crtc = to_vbox_crtc(crtc);
700 struct drm_gem_object *obj;
701 struct vbox_bo *bo;
702 int ret, rc;
703 struct ttm_bo_kmap_obj uobj_map;
704 u8 *src;
705 u8 *dst = NULL;
706 size_t cbData, cbMask;
707 bool src_isiomem;
708
709 if (!handle) {
710 /* Hide cursor. */
711 VBoxHGSMIUpdatePointerShape(&vbox->Ctx, 0, 0, 0, 0, 0, NULL, 0);
712 return 0;
713 }
714 if ( width > VBOX_MAX_CURSOR_WIDTH || height > VBOX_MAX_CURSOR_HEIGHT
715 || width == 0 || hot_x > width || height == 0 || hot_y > height)
716 return -EINVAL;
717
718 obj = drm_gem_object_lookup(crtc->dev, file_priv, handle);
719 if (obj)
720 {
721 bo = gem_to_vbox_bo(obj);
722 ret = vbox_bo_reserve(bo, false);
723 if (!ret)
724 {
725 /* The mask must be calculated based on the alpha channel, one bit
726 * per ARGB word, and must be 32-bit padded. */
727 cbMask = ((width + 7) / 8 * height + 3) & ~3;
728 cbData = width * height * 4 + cbMask;
729 dst = kmalloc(cbData, GFP_KERNEL);
730 if (dst)
731 {
732 ret = ttm_bo_kmap(&bo->bo, 0, bo->bo.num_pages, &uobj_map);
733 if (!ret)
734 {
735 src = ttm_kmap_obj_virtual(&uobj_map, &src_isiomem);
736 if (!src_isiomem)
737 {
738 uint32_t fFlags = VBOX_MOUSE_POINTER_VISIBLE
739 | VBOX_MOUSE_POINTER_SHAPE
740 | VBOX_MOUSE_POINTER_ALPHA;
741 copy_cursor_image(src, dst, width, height, cbMask);
742 rc = VBoxHGSMIUpdatePointerShape(&vbox->Ctx, fFlags,
743 hot_x, hot_y, width,
744 height, dst, cbData);
745 ret = RTErrConvertToErrno(rc);
746 }
747 else
748 DRM_ERROR("src cursor bo should be in main memory\n");
749 ttm_bo_kunmap(&uobj_map);
750 }
751 kfree(dst);
752 }
753 vbox_bo_unreserve(bo);
754 }
755 drm_gem_object_unreference_unlocked(obj);
756 }
757 else
758 {
759 DRM_ERROR("Cannot find cursor object %x for crtc\n", handle);
760 ret = -ENOENT;
761 }
762 return ret;
763}
764
765static int vbox_cursor_move(struct drm_crtc *crtc,
766 int x, int y)
767{
768 return 0;
769}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette