2 * Maru overlay device for VGA
4 * Copyright (C) 2011 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
7 * JinHyung Jo <jinhyung.jo@samsung.com>
8 * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
35 #include "maru_device_ids.h"
36 #include "maru_overlay.h"
39 MULTI_DEBUG_CHANNEL(qemu, maru_overlay);
41 #define QEMU_DEV_NAME "MARU_OVERLAY"
43 #define OVERLAY_MEM_SIZE (8192 * 1024) /* 4MB(overlay0) + 4MB(overlay1) */
44 #define OVERLAY_REG_SIZE 256
45 #define OVERLAY1_REG_OFFSET (OVERLAY_REG_SIZE / 2)
50 OVERLAY_POSITION = 0x04, /* left top position */
51 OVERLAY_SIZE = 0x08, /* width and height */
56 uint8_t overlay0_power;
57 uint16_t overlay0_left;
58 uint16_t overlay0_top;
59 uint16_t overlay0_width;
60 uint16_t overlay0_height;
62 uint8_t overlay1_power;
63 uint16_t overlay1_left;
64 uint16_t overlay1_top;
65 uint16_t overlay1_width;
66 uint16_t overlay1_height;
68 typedef struct OverlayState {
71 MemoryRegion mem_addr;
72 MemoryRegion mmio_addr;
76 static uint64_t overlay_reg_read(void *opaque,
77 target_phys_addr_t addr,
82 TRACE("GET => overlay0 power status(%d)\n", overlay0_power);
83 return overlay0_power;
85 case OVERLAY_POSITION:
86 TRACE("GET => overlay0 position, left(%d):top(%d)\n",
87 overlay0_left, overlay0_top);
88 return overlay0_left | overlay0_top << 16;
91 TRACE("GET => overlay0 size, width(%d):height(%d)\n",
92 overlay0_width, overlay0_height);
93 return overlay0_width | overlay0_height << 16;
95 case OVERLAY1_REG_OFFSET + OVERLAY_POWER:
96 TRACE("GET => overlay1 power status(%d)\n", overlay1_power);
97 return overlay1_power;
99 case OVERLAY1_REG_OFFSET + OVERLAY_POSITION:
100 TRACE("GET => overlay1 position, left(%d):top(%d)\n",
101 overlay1_left, overlay1_top);
102 return overlay1_left | overlay1_top << 16;
104 case OVERLAY1_REG_OFFSET + OVERLAY_SIZE:
105 TRACE("GET => overlay1 size, width(%d):height(%d)\n",
106 overlay1_width, overlay1_height);
107 return overlay1_width | overlay1_height << 16;
110 ERR("wrong overlay register read - addr : %d\n", (int)addr);
117 static void overlay_reg_write(void *opaque,
118 target_phys_addr_t addr,
124 overlay0_power = val;
125 TRACE("SET => overlay0 power status(%d)\n", overlay0_power);
126 if (!overlay0_power) {
127 /* clear the last overlay area. */
128 memset(overlay_ptr, 0x00, (OVERLAY_MEM_SIZE / 2));
129 overlay0_left = overlay0_top = overlay0_width = overlay0_height = 0;
130 TRACE("clear the last overlay0 area\n");
133 case OVERLAY_POSITION:
134 overlay0_left = val & 0xFFFF;
135 overlay0_top = val >> 16;
136 TRACE("SET => overlay0 position, left(%d):top(%d)\n",
137 overlay0_left, overlay0_top);
140 overlay0_width = val & 0xFFFF;
141 overlay0_height = val >> 16;
142 TRACE("SET => overlay0 size, width(%d):height(%d)\n",
143 overlay0_width, overlay0_height);
145 case OVERLAY1_REG_OFFSET + OVERLAY_POWER:
146 overlay1_power = val;
147 TRACE("SET => overlay1 power status(%d)\n", overlay1_power);
148 if (!overlay1_power) {
149 /* clear the last overlay area. */
150 memset(overlay_ptr + OVERLAY1_REG_OFFSET,
151 0x00, (OVERLAY_MEM_SIZE / 2));
152 overlay1_left = overlay1_top = overlay1_width = overlay1_height = 0;
153 TRACE("clear the last overlay1 area\n");
156 case OVERLAY1_REG_OFFSET + OVERLAY_POSITION:
157 overlay1_left = val & 0xFFFF;
158 overlay1_top = val >> 16;
159 TRACE("SET => overlay1 position, left(%d):top(%d)\n",
160 overlay1_left, overlay1_top);
162 case OVERLAY1_REG_OFFSET + OVERLAY_SIZE:
163 overlay1_width = val & 0xFFFF;
164 overlay1_height = val >> 16;
165 TRACE("SET => overlay1 size, width(%d):height(%d)\n",
166 overlay1_width, overlay1_height);
169 ERR("wrong overlay register write - addr : %d\n", (int)addr);
174 static const MemoryRegionOps overlay_mmio_ops = {
175 .read = overlay_reg_read,
176 .write = overlay_reg_write,
177 .endianness = DEVICE_LITTLE_ENDIAN,
180 static int overlay_initfn(PCIDevice *dev)
182 OverlayState *s = DO_UPCAST(OverlayState, dev, dev);
183 uint8_t *pci_conf = s->dev.config;
185 pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_TIZEN);
186 pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_VIRTUAL_OVERLAY);
187 pci_config_set_class(pci_conf, PCI_CLASS_DISPLAY_OTHER);
189 memory_region_init_ram(&s->mem_addr, "maru_overlay.ram", OVERLAY_MEM_SIZE);
190 overlay_ptr = memory_region_get_ram_ptr(&s->mem_addr);
192 memory_region_init_io(&s->mmio_addr, &overlay_mmio_ops,
197 /* setup memory space */
198 /* memory #0 device memory (overlay surface) */
199 /* memory #1 memory-mapped I/O */
200 pci_register_bar(&s->dev, 0, PCI_BASE_ADDRESS_MEM_PREFETCH, &s->mem_addr);
201 pci_register_bar(&s->dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->mmio_addr);
206 DeviceState *pci_maru_overlay_init(PCIBus *bus)
208 INFO("Maru overlay was initailized!\n");
209 return &pci_create_simple(bus, -1, QEMU_DEV_NAME)->qdev;
212 static void overlay_classinit(ObjectClass *klass, void *data)
214 PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
217 k->init = overlay_initfn;
220 static TypeInfo overlay_info = {
221 .name = QEMU_DEV_NAME,
222 .parent = TYPE_PCI_DEVICE,
223 .instance_size = sizeof(OverlayState),
224 .class_init = overlay_classinit,
227 static void overlay_register_types(void)
229 type_register_static(&overlay_info);
232 type_init(overlay_register_types);