1d514b0f3Smrg/*
2d514b0f3Smrg * Copyright 2011 Red Hat, Inc.
3d514b0f3Smrg *
4d514b0f3Smrg * Permission is hereby granted, free of charge, to any person obtaining a
5d514b0f3Smrg * copy of this software and associated documentation files (the "Software"),
6d514b0f3Smrg * to deal in the Software without restriction, including without limitation
7d514b0f3Smrg * on the rights to use, copy, modify, merge, publish, distribute, sub
8d514b0f3Smrg * license, and/or sell copies of the Software, and to permit persons to whom
9d514b0f3Smrg * the Software is furnished to do so, subject to the following conditions:
10d514b0f3Smrg *
11d514b0f3Smrg * The above copyright notice and this permission notice (including the next
12d514b0f3Smrg * paragraph) shall be included in all copies or substantial portions of the
13d514b0f3Smrg * Software.
14d514b0f3Smrg *
15d514b0f3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16d514b0f3Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17d514b0f3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
18d514b0f3Smrg * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19d514b0f3Smrg * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20d514b0f3Smrg * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21d514b0f3Smrg */
22d514b0f3Smrg
23d514b0f3Smrg/** \file spiceqxl_driver.c
24d514b0f3Smrg * \author Alon Levy <alevy@redhat.com>
25d514b0f3Smrg *
26d514b0f3Smrg * most of the code is still in qxl_driver.c, but for clarity parts are moved
27d514b0f3Smrg * here, and only used / compiled if XSPICE is defined
28d514b0f3Smrg */
29d514b0f3Smrg#ifdef HAVE_CONFIG_H
30d514b0f3Smrg#include "config.h"
31d514b0f3Smrg#endif
32d514b0f3Smrg
33d514b0f3Smrg#include "qxl.h"
34d514b0f3Smrg#include "spiceqxl_driver.h"
35d514b0f3Smrg
36d514b0f3Smrg#define SPICE_ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
37d514b0f3Smrg
38d514b0f3Smrg#define QXL_MODE_EX(x_res, y_res)                 \
39d514b0f3Smrg    QXL_MODE_16_32(x_res, y_res, 0),              \
40d514b0f3Smrg    QXL_MODE_16_32(y_res, x_res, 1),              \
41d514b0f3Smrg    QXL_MODE_16_32(x_res, y_res, 2),              \
42d514b0f3Smrg    QXL_MODE_16_32(y_res, x_res, 3)
43d514b0f3Smrg
44d514b0f3Smrg#define QXL_MODE_16_32(x_res, y_res, orientation) \
45d514b0f3Smrg    QXL_MODE(x_res, y_res, 16, orientation),      \
46d514b0f3Smrg    QXL_MODE(x_res, y_res, 32, orientation)
47d514b0f3Smrg
48d514b0f3Smrg#define QXL_MODE(_x, _y, _b, _o)                  \
49d514b0f3Smrg    {   .x_res = _x,                              \
50d514b0f3Smrg        .y_res = _y,                              \
51d514b0f3Smrg        .bits  = _b,                              \
52d514b0f3Smrg        .stride = (_x) * (_b) / 8,                \
53d514b0f3Smrg        .x_mili = PIXEL_SIZE * (_x),              \
54d514b0f3Smrg        .y_mili = PIXEL_SIZE * (_y),              \
55d514b0f3Smrg        .orientation = _o,                        \
56d514b0f3Smrg    }
57d514b0f3Smrg
58d514b0f3Smrg#define PIXEL_SIZE 0.2936875 //1280x1024 is 14.8" x 11.9"
59d514b0f3Smrg
60d514b0f3Smrg#define ALIGN(x, y) (((x)+(y)-1) & ~((y)-1))
61d514b0f3Smrg
62d514b0f3Smrgstatic QXLMode qxl_modes[] = {
63d514b0f3Smrg    QXL_MODE_EX(640, 480),
64d514b0f3Smrg    QXL_MODE_EX(800, 480),
65d514b0f3Smrg    QXL_MODE_EX(800, 600),
66d514b0f3Smrg    QXL_MODE_EX(832, 624),
67d514b0f3Smrg    QXL_MODE_EX(960, 640),
68d514b0f3Smrg    QXL_MODE_EX(1024, 600),
69d514b0f3Smrg    QXL_MODE_EX(1024, 768),
70d514b0f3Smrg    QXL_MODE_EX(1152, 864),
71d514b0f3Smrg    QXL_MODE_EX(1152, 870),
72d514b0f3Smrg    QXL_MODE_EX(1280, 720),
73d514b0f3Smrg    QXL_MODE_EX(1280, 760),
74d514b0f3Smrg    QXL_MODE_EX(1280, 768),
75d514b0f3Smrg    QXL_MODE_EX(1280, 800),
76d514b0f3Smrg    QXL_MODE_EX(1280, 960),
77d514b0f3Smrg    QXL_MODE_EX(1280, 1024),
78d514b0f3Smrg    QXL_MODE_EX(1360, 768),
79d514b0f3Smrg    QXL_MODE_EX(1366, 768),
80d514b0f3Smrg    QXL_MODE_EX(1400, 1050),
81d514b0f3Smrg    QXL_MODE_EX(1440, 900),
82d514b0f3Smrg    QXL_MODE_EX(1600, 900),
83d514b0f3Smrg    QXL_MODE_EX(1600, 1200),
84d514b0f3Smrg    QXL_MODE_EX(1680, 1050),
85d514b0f3Smrg    QXL_MODE_EX(1920, 1080),
86d514b0f3Smrg    QXL_MODE_EX(1920, 1200),
87d514b0f3Smrg    QXL_MODE_EX(1920, 1440),
88d514b0f3Smrg    QXL_MODE_EX(2048, 1536),
89d514b0f3Smrg    QXL_MODE_EX(2560, 1440),
90d514b0f3Smrg    QXL_MODE_EX(2560, 1600),
91d514b0f3Smrg    QXL_MODE_EX(3840, 1080),
92d514b0f3Smrg    QXL_MODE_EX(2560, 2048),
93d514b0f3Smrg    QXL_MODE_EX(2800, 2100),
94d514b0f3Smrg    QXL_MODE_EX(3200, 2400),
95d514b0f3Smrg    QXL_MODE_EX(5760, 1080),
96d514b0f3Smrg    QXL_MODE_EX(7680, 1080),
97d514b0f3Smrg
98d514b0f3Smrg};
99d514b0f3Smrg
100d514b0f3Smrg
101d514b0f3Smrg// TODO - reuse code from qxl.c?
102d514b0f3Smrgvoid init_qxl_rom(qxl_screen_t* qxl, uint32_t rom_size)
103d514b0f3Smrg{
104d514b0f3Smrg    QXLRom *rom = qxl->rom;
105d514b0f3Smrg    struct QXLModes *modes = (struct QXLModes *)(rom + 1);
106d514b0f3Smrg    uint32_t ram_header_size;
107d514b0f3Smrg    uint32_t num_pages;
108d514b0f3Smrg    uint32_t fb;
109d514b0f3Smrg    int i, m;
110d514b0f3Smrg
111d514b0f3Smrg    memset(rom, 0, rom_size);
112d514b0f3Smrg
113d514b0f3Smrg    rom->magic         = QXL_ROM_MAGIC;
114d514b0f3Smrg    rom->id            = 0; // TODO - multihead?
115d514b0f3Smrg    rom->log_level     = 3;
116d514b0f3Smrg    rom->modes_offset  = (sizeof(QXLRom));
117d514b0f3Smrg
118d514b0f3Smrg    rom->slot_gen_bits = MEMSLOT_GENERATION_BITS;
119d514b0f3Smrg    rom->slot_id_bits  = MEMSLOT_SLOT_BITS;
120d514b0f3Smrg    rom->slots_start   = 0;
121d514b0f3Smrg    rom->slots_end     = 1;
122d514b0f3Smrg    rom->n_surfaces    = (NUM_SURFACES);
123d514b0f3Smrg
124d514b0f3Smrg    for (i = 0, m = 0; i < (SPICE_ARRAY_SIZE(qxl_modes)); i++) {
125d514b0f3Smrg        fb = qxl_modes[i].y_res * qxl_modes[i].stride;
126d514b0f3Smrg        if (fb > qxl->surface0_size)
127d514b0f3Smrg            continue;
128d514b0f3Smrg
129d514b0f3Smrg        modes->modes[m].id          = m;
130d514b0f3Smrg        modes->modes[m].x_res       = qxl_modes[i].x_res;
131d514b0f3Smrg        modes->modes[m].y_res       = qxl_modes[i].y_res;
132d514b0f3Smrg        modes->modes[m].bits        = qxl_modes[i].bits;
133d514b0f3Smrg        modes->modes[m].stride      = qxl_modes[i].stride;
134d514b0f3Smrg        modes->modes[m].x_mili      = qxl_modes[i].x_mili;
135d514b0f3Smrg        modes->modes[m].y_mili      = qxl_modes[i].y_mili;
136d514b0f3Smrg        modes->modes[m].orientation = qxl_modes[i].orientation;
137d514b0f3Smrg
138d514b0f3Smrg        m++;
139d514b0f3Smrg    }
140d514b0f3Smrg    modes->n_modes     = m;
141d514b0f3Smrg
142d514b0f3Smrg    ram_header_size    = ALIGN(sizeof(struct QXLRam), 4096);
143d514b0f3Smrg    num_pages          = qxl->vram_size;
144d514b0f3Smrg    num_pages         -= ram_header_size;
145d514b0f3Smrg    num_pages         -= qxl->surface0_size;
146d514b0f3Smrg    num_pages          = num_pages / TARGET_PAGE_SIZE;
147d514b0f3Smrg
148d514b0f3Smrg    rom->draw_area_offset   = 0;
149d514b0f3Smrg    rom->surface0_area_size = qxl->surface0_size;
150d514b0f3Smrg    rom->pages_offset       = rom->surface0_area_size;
151d514b0f3Smrg    rom->num_pages          = num_pages;
152d514b0f3Smrg    rom->ram_header_offset  = qxl->vram_size - ram_header_size;
153d514b0f3Smrg
154d514b0f3Smrg    qxl->shadow_rom = *qxl->rom;         // TODO - do we need this?
155d514b0f3Smrg}
156