Home | History | Annotate | Line # | Download | only in src
      1 /*
      2  * Copyright 2008 Red Hat, Inc.
      3  *
      4  * Permission is hereby granted, free of charge, to any person obtaining a
      5  * copy of this software and associated documentation files (the "Software"),
      6  * to deal in the Software without restriction, including without limitation
      7  * on the rights to use, copy, modify, merge, publish, distribute, sub
      8  * license, and/or sell copies of the Software, and to permit persons to whom
      9  * the Software is furnished to do so, subject to the following conditions:
     10  *
     11  * The above copyright notice and this permission notice (including the next
     12  * paragraph) shall be included in all copies or substantial portions of the
     13  * Software.
     14  *
     15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     17  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
     18  * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
     19  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
     20  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     21  */
     22 
     23 /* code to handle UMS modesetting */
     24 
     25 #ifdef HAVE_CONFIG_H
     26 #include <config.h>
     27 #endif
     28 #include "qxl.h"
     29 
     30 /* These constants govern which modes are reported to X as preferred */
     31 #define DEFAULT_WIDTH       1024
     32 #define DEFAULT_HEIGHT       768
     33 
     34 static void qxl_update_monitors_config (qxl_screen_t *qxl);
     35 
     36 static DisplayModePtr
     37 screen_create_mode (ScrnInfoPtr pScrn, int width, int height, int type)
     38 {
     39     DisplayModePtr mode;
     40 
     41     mode = xnfcalloc (1, sizeof (DisplayModeRec));
     42 
     43     mode->status = MODE_OK;
     44     mode->type = type;
     45     mode->HDisplay   = width;
     46     mode->HSyncStart = (width * 105 / 100 + 7) & ~7;
     47     mode->HSyncEnd   = (width * 115 / 100 + 7) & ~7;
     48     mode->HTotal     = (width * 130 / 100 + 7) & ~7;
     49     mode->VDisplay   = height;
     50     mode->VSyncStart = height + 1;
     51     mode->VSyncEnd   = height + 4;
     52     mode->VTotal     = height * 1035 / 1000;
     53     mode->Clock = mode->HTotal * mode->VTotal * 60 / 1000;
     54     mode->Flags = V_NHSYNC | V_PVSYNC;
     55 
     56     xf86SetModeDefaultName (mode);
     57     xf86SetModeCrtc (mode, pScrn->adjustFlags); /* needed? xf86-video-modesetting does this */
     58 
     59     return mode;
     60 }
     61 
     62 static DisplayModePtr
     63 qxl_add_mode (qxl_screen_t *qxl, ScrnInfoPtr pScrn, int width, int height, int type)
     64 {
     65     DisplayModePtr mode;
     66 
     67     mode = screen_create_mode (pScrn, width, height, type);
     68     pScrn->modes = qxl->x_modes = xf86ModesAdd (qxl->x_modes, mode);
     69 
     70     return mode;
     71 }
     72 
     73 static int
     74 check_crtc (qxl_screen_t *qxl)
     75 {
     76     int i, count = 0;
     77     xf86CrtcPtr crtc;
     78 
     79     if (qxl->crtcs == NULL) {
     80         return 0;
     81     }
     82 
     83     for (i = 0 ; i < qxl->num_heads; ++i)
     84     {
     85 	crtc = qxl->crtcs[i];
     86 
     87 	if (!crtc->enabled || crtc->mode.CrtcHDisplay == 0 ||
     88 	    crtc->mode.CrtcVDisplay == 0)
     89 	{
     90 	    continue;
     91 	}
     92 	count++;
     93     }
     94 
     95 #if 0
     96     if (count == 0)
     97     {
     98 	ErrorF ("check crtc failed, count == 0!!\n");
     99 	BREAKPOINT ();
    100     }
    101 #endif
    102 
    103     return count;
    104 }
    105 
    106 static void
    107 qxl_update_monitors_config (qxl_screen_t *qxl)
    108 {
    109     int i;
    110     QXLHead *head;
    111     xf86CrtcPtr crtc;
    112     qxl_output_private *qxl_output;
    113     QXLRam * ram = get_ram_header (qxl);
    114 
    115     if (check_crtc (qxl) == 0)
    116         return;
    117 
    118     qxl->monitors_config->count = 0;
    119     qxl->monitors_config->max_allowed = qxl->num_heads;
    120     for (i = 0 ; i < qxl->num_heads; ++i)
    121     {
    122 	head = &qxl->monitors_config->heads[qxl->monitors_config->count];
    123 	crtc = qxl->crtcs[i];
    124 	qxl_output = qxl->outputs[i]->driver_private;
    125 	head->id = i;
    126 	head->surface_id = 0;
    127 	head->flags = 0;
    128 
    129 	if (!crtc->enabled || crtc->mode.CrtcHDisplay == 0 ||
    130 	    crtc->mode.CrtcVDisplay == 0)
    131 	{
    132 	    head->width = head->height = head->x = head->y = 0;
    133 	    qxl_output->status = XF86OutputStatusDisconnected;
    134 	}
    135 	else
    136 	{
    137 	    head->width = crtc->mode.CrtcHDisplay;
    138 	    head->height = crtc->mode.CrtcVDisplay;
    139 	    head->x = crtc->x;
    140 	    head->y = crtc->y;
    141 	    qxl->monitors_config->count++;
    142 	    qxl_output->status = XF86OutputStatusConnected;
    143 	}
    144     }
    145     /* initialize when actually used, memslots should be initialized by now */
    146     if (ram->monitors_config == 0)
    147     {
    148 	ram->monitors_config = physical_address (qxl, qxl->monitors_config,
    149 	                                         qxl->main_mem_slot);
    150     }
    151 
    152     qxl_io_monitors_config_async (qxl);
    153 }
    154 
    155 static Bool
    156 crtc_set_mode_major (xf86CrtcPtr crtc, DisplayModePtr mode,
    157                      Rotation rotation, int x, int y)
    158 {
    159     qxl_crtc_private *crtc_private = crtc->driver_private;
    160     qxl_screen_t *    qxl = crtc_private->qxl;
    161 
    162     if (crtc == qxl->crtcs[0] && mode == NULL)
    163     {
    164 	/* disallow disabling of monitor 0 mode */
    165 	ErrorF ("%s: not allowing crtc 0 disablement\n", __func__);
    166 	return FALSE;
    167     }
    168 
    169     crtc->mode = *mode;
    170     crtc->x = x;
    171     crtc->y = y;
    172     crtc->rotation = rotation;
    173 #if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC (1, 5, 99, 0, 0)
    174     crtc->transformPresent = FALSE;
    175 #endif
    176     /* TODO set EDID here */
    177     return TRUE;
    178 }
    179 
    180 Bool
    181 qxl_create_desired_modes (qxl_screen_t *qxl)
    182 {
    183     int i;
    184     xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR (qxl->pScrn);
    185 
    186     CHECK_POINT ();
    187 
    188     for (i = 0 ; i < config->num_crtc; ++i)
    189     {
    190 	xf86CrtcPtr crtc = config->crtc[i];
    191 	if (!crtc->enabled)
    192 	    continue;
    193 
    194 	if (!crtc_set_mode_major (
    195 		crtc, &crtc->desiredMode, crtc->desiredRotation,
    196 		crtc->desiredX, crtc->desiredY))
    197 	{
    198 	    return FALSE;
    199 	}
    200     }
    201 
    202     qxl_update_monitors_config(qxl);
    203     return TRUE;
    204 }
    205 
    206 void
    207 qxl_update_edid (qxl_screen_t *qxl)
    208 {
    209     xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR (qxl->pScrn);
    210     int i;
    211 
    212     for (i = 0; i < config->num_crtc; ++i)
    213     {
    214 	xf86CrtcPtr crtc = config->crtc[i];
    215 
    216 	if (!crtc->enabled)
    217 	    continue;
    218 
    219 	/* TODO set EDID here */
    220     }
    221 }
    222 
    223 
    224 static DisplayModePtr
    225 qxl_output_get_modes (xf86OutputPtr output)
    226 {
    227     qxl_output_private *qxl_output = output->driver_private;
    228     DisplayModePtr      modes = xf86DuplicateModes (qxl_output->qxl->pScrn, qxl_output->qxl->x_modes);
    229 
    230     /* xf86ProbeOutputModes owns this memory */
    231     return modes;
    232 }
    233 
    234 static void
    235 qxl_output_destroy (xf86OutputPtr output)
    236 {
    237     qxl_output_private *qxl_output = output->driver_private;
    238 
    239     xf86DrvMsg (qxl_output->qxl->pScrn->scrnIndex, X_INFO,
    240                 "%s", __func__);
    241 }
    242 
    243 static void
    244 qxl_output_dpms (xf86OutputPtr output, int mode)
    245 {
    246 }
    247 
    248 static void
    249 qxl_output_create_resources (xf86OutputPtr output)
    250 {
    251 }
    252 
    253 static Bool
    254 qxl_output_set_property (xf86OutputPtr output, Atom property,
    255                          RRPropertyValuePtr value)
    256 {
    257     /* EDID data is stored in the "EDID" atom property, we must return
    258      * TRUE here for that. No penalty to say ok to everything else. */
    259     return TRUE;
    260 }
    261 
    262 static Bool
    263 qxl_output_get_property (xf86OutputPtr output, Atom property)
    264 {
    265     return TRUE;
    266 }
    267 
    268 static xf86OutputStatus
    269 qxl_output_detect (xf86OutputPtr output)
    270 {
    271     qxl_output_private *qxl_output = output->driver_private;
    272 
    273     return qxl_output->status;
    274 }
    275 
    276 static Bool
    277 qxl_output_mode_valid (xf86OutputPtr output, DisplayModePtr pModes)
    278 {
    279     return MODE_OK;
    280 }
    281 
    282 static const xf86OutputFuncsRec qxl_output_funcs = {
    283     .dpms = qxl_output_dpms,
    284     .create_resources = qxl_output_create_resources,
    285 #ifdef RANDR_12_INTERFACE
    286     .set_property = qxl_output_set_property,
    287     .get_property = qxl_output_get_property,
    288 #endif
    289     .detect = qxl_output_detect,
    290     .mode_valid = qxl_output_mode_valid,
    291 
    292     .get_modes = qxl_output_get_modes,
    293     .destroy = qxl_output_destroy
    294 };
    295 
    296 
    297 static void
    298 qxl_crtc_dpms (xf86CrtcPtr crtc, int mode)
    299 {
    300 }
    301 
    302 static Bool
    303 qxl_crtc_set_mode_major (xf86CrtcPtr crtc, DisplayModePtr mode,
    304                          Rotation rotation, int x, int y)
    305 {
    306     qxl_crtc_private *crtc_private = crtc->driver_private;
    307     qxl_screen_t *    qxl = crtc_private->qxl;
    308 
    309     CHECK_POINT ();
    310 
    311     if (!crtc_set_mode_major (crtc, mode, rotation, x, y))
    312 	return FALSE;
    313 
    314     qxl_update_monitors_config (qxl);
    315 
    316     return TRUE;
    317 }
    318 
    319 static void
    320 qxl_crtc_set_cursor_colors (xf86CrtcPtr crtc, int bg, int fg)
    321 {
    322 }
    323 
    324 static void
    325 qxl_crtc_set_cursor_position (xf86CrtcPtr crtc, int x, int y)
    326 {
    327 }
    328 
    329 static void
    330 qxl_crtc_load_cursor_argb (xf86CrtcPtr crtc, CARD32 *image)
    331 {
    332 }
    333 
    334 static void
    335 qxl_crtc_hide_cursor (xf86CrtcPtr crtc)
    336 {
    337 }
    338 
    339 static void
    340 qxl_crtc_show_cursor (xf86CrtcPtr crtc)
    341 {
    342 }
    343 
    344 static void
    345 qxl_crtc_gamma_set (xf86CrtcPtr crtc, uint16_t *red, uint16_t *green,
    346                     uint16_t *blue, int size)
    347 {
    348 }
    349 
    350 static void
    351 qxl_crtc_destroy (xf86CrtcPtr crtc)
    352 {
    353     qxl_crtc_private *crtc_private = crtc->driver_private;
    354     qxl_screen_t *    qxl = crtc_private->qxl;
    355 
    356     xf86DrvMsg (qxl->pScrn->scrnIndex, X_INFO, "%s\n", __func__);
    357 }
    358 
    359 static Bool
    360 qxl_crtc_lock (xf86CrtcPtr crtc)
    361 {
    362     qxl_crtc_private *crtc_private = crtc->driver_private;
    363     qxl_screen_t *    qxl = crtc_private->qxl;
    364 
    365     xf86DrvMsg (qxl->pScrn->scrnIndex, X_INFO, "%s\n", __func__);
    366     return TRUE;
    367 }
    368 
    369 static void
    370 qxl_crtc_unlock (xf86CrtcPtr crtc)
    371 {
    372     qxl_crtc_private *crtc_private = crtc->driver_private;
    373     qxl_screen_t *    qxl = crtc_private->qxl;
    374 
    375     xf86DrvMsg (qxl->pScrn->scrnIndex, X_INFO, "%s\n", __func__);
    376     qxl_update_monitors_config (qxl);
    377 }
    378 
    379 static const xf86CrtcFuncsRec qxl_crtc_funcs = {
    380     .dpms = qxl_crtc_dpms,
    381     .set_mode_major = qxl_crtc_set_mode_major,
    382     .set_cursor_colors = qxl_crtc_set_cursor_colors,
    383     .set_cursor_position = qxl_crtc_set_cursor_position,
    384     .show_cursor = qxl_crtc_show_cursor,
    385     .hide_cursor = qxl_crtc_hide_cursor,
    386     .load_cursor_argb = qxl_crtc_load_cursor_argb,
    387     .lock = qxl_crtc_lock,
    388     .unlock = qxl_crtc_unlock,
    389 
    390     .gamma_set = qxl_crtc_gamma_set,
    391     .destroy = qxl_crtc_destroy,
    392 };
    393 
    394 
    395 static Bool
    396 qxl_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height)
    397 {
    398     qxl_screen_t *qxl = scrn->driverPrivate;
    399 
    400     xf86DrvMsg (scrn->scrnIndex, X_INFO, "%s: Placeholder resize %dx%d\n",
    401                 __func__, width, height);
    402     if (!qxl_resize_primary (qxl, width, height))
    403 	return FALSE;
    404 
    405     scrn->virtualX = width;
    406     scrn->virtualY = height;
    407 
    408     // when starting, no monitor is enabled, and count == 0
    409     // we want to avoid server/client freaking out with temporary config
    410     qxl_update_monitors_config (qxl);
    411 
    412     return TRUE;
    413 }
    414 
    415 static const xf86CrtcConfigFuncsRec qxl_xf86crtc_config_funcs = {
    416     qxl_xf86crtc_resize
    417 };
    418 
    419 void
    420 qxl_initialize_x_modes (qxl_screen_t *qxl, ScrnInfoPtr pScrn,
    421                         unsigned int *max_x, unsigned int *max_y)
    422 {
    423     int i;
    424     int size;
    425     int preferred_flag;
    426 
    427     *max_x = *max_y = 0;
    428     /* Create a list of modes used by the qxl_output_get_modes */
    429     for (i = 0; i < qxl->num_modes; i++)
    430     {
    431 	if (qxl->modes[i].orientation == 0)
    432 	{
    433 	    size = qxl->modes[i].y_res * qxl->modes[i].stride;
    434 	    if (size > qxl->surface0_size)
    435 	    {
    436 		ErrorF ("skipping mode %dx%d not fitting in surface0\n",
    437 		        qxl->modes[i].x_res, qxl->modes[i].y_res);
    438 		continue;
    439 	    }
    440 
    441             if (qxl->modes[i].x_res == DEFAULT_WIDTH && qxl->modes[i].y_res == DEFAULT_HEIGHT)
    442                 preferred_flag = M_T_PREFERRED;
    443             else
    444                 preferred_flag = 0;
    445 
    446 	    qxl_add_mode (qxl, pScrn, qxl->modes[i].x_res, qxl->modes[i].y_res,
    447 	                  M_T_DRIVER | preferred_flag);
    448 
    449 	    if (qxl->modes[i].x_res > *max_x)
    450 		*max_x = qxl->modes[i].x_res;
    451 	    if (qxl->modes[i].y_res > *max_y)
    452 		*max_y = qxl->modes[i].y_res;
    453 	}
    454     }
    455 }
    456 
    457 void
    458 qxl_init_randr (ScrnInfoPtr pScrn, qxl_screen_t *qxl)
    459 {
    460     char                name[32];
    461     qxl_output_private *qxl_output;
    462     qxl_crtc_private *  qxl_crtc;
    463     int                 i;
    464     xf86OutputPtr       output;
    465 
    466     xf86CrtcConfigInit (pScrn, &qxl_xf86crtc_config_funcs);
    467 
    468     /* CHECKME: This is actually redundant, it's overwritten by a later call via
    469      * xf86InitialConfiguration */
    470     xf86CrtcSetSizeRange (pScrn, 320, 200, 8192, 8192);
    471 
    472     qxl->crtcs = xnfcalloc (sizeof (xf86CrtcPtr), qxl->num_heads);
    473     qxl->outputs = xnfcalloc (sizeof (xf86OutputPtr), qxl->num_heads);
    474 
    475     for (i = 0 ; i < qxl->num_heads; ++i)
    476     {
    477 	qxl->crtcs[i] = xf86CrtcCreate (pScrn, &qxl_crtc_funcs);
    478 	if (!qxl->crtcs[i])
    479 	    xf86DrvMsg (pScrn->scrnIndex, X_ERROR, "failed to create Crtc %d", i);
    480 
    481 	qxl_crtc = xnfcalloc (sizeof (qxl_crtc_private), 1);
    482 	qxl->crtcs[i]->driver_private = qxl_crtc;
    483 	qxl_crtc->head = i;
    484 	qxl_crtc->qxl = qxl;
    485 	snprintf (name, sizeof (name), "qxl-%d", i);
    486 	qxl->outputs[i] = output = xf86OutputCreate (pScrn, &qxl_output_funcs, name);
    487 	if (!output)
    488 	    xf86DrvMsg (pScrn->scrnIndex, X_ERROR, "failed to create Output %d", i);
    489 
    490 	output->possible_crtcs = (1 << i); /* bitrange of allowed outputs - do a 1:1 */
    491 	output->possible_clones = 0; /* TODO: not? */
    492 	qxl_output = xnfcalloc (sizeof (qxl_output_private), 1);
    493 	output->driver_private = qxl_output;
    494 	qxl_output->head = i;
    495 	qxl_output->qxl = qxl;
    496 	qxl_output->status = i ? XF86OutputStatusDisconnected : XF86OutputStatusConnected;
    497 	qxl_crtc->output = output;
    498     }
    499 
    500     xf86InitialConfiguration (pScrn, TRUE);
    501 
    502     qxl->virtual_x = pScrn->virtualX;
    503     qxl->virtual_y = pScrn->virtualY;
    504     /* all crtcs are enabled here, but their mode is 0,
    505        resulting monitor config empty atm */
    506 }
    507