2 * Maru overlay device for VGA
4 * Copyright (C) 2011 - 2012 Samsung Electronics Co., Ltd. All rights reserved.
7 * DoHyung Hong <don.hong@samsung.com>
8 * SeokYeon Hwang <syeon.hwang@samsung.com>
9 * Hyunjun Son <hj79.son@samsung.com>
10 * SangJin Kim <sangjin3.kim@samsung.com>
11 * MunKyu Im <munkyu.im@samsung.com>
12 * KiTae Kim <kt920.kim@samsung.com>
13 * JinHyung Jo <jinhyung.jo@samsung.com>
14 * SungMin Ha <sungmin82.ha@samsung.com>
15 * JiHye Kim <jihye1128.kim@samsung.com>
16 * GiWoong Kim <giwoong.kim@samsung.com>
17 * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
18 * DongKyun Yun <dk77.yun@samsung.com>
20 * This program is free software; you can redistribute it and/or
21 * modify it under the terms of the GNU General Public License
22 * as published by the Free Software Foundation; either version 2
23 * of the License, or (at your option) any later version.
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
30 * You should have received a copy of the GNU General Public License
31 * along with this program; if not, write to the Free Software
32 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
40 #include "maru_device_ids.h"
41 #include "maru_overlay.h"
44 MULTI_DEBUG_CHANNEL(qemu, maru_overlay);
46 #define QEMU_DEV_NAME "MARU_OVERLAY"
48 #define OVERLAY_MEM_SIZE (8192 * 1024) // 4MB(overlay0) + 4MB(overlay1)
49 #define OVERLAY_REG_SIZE 256
50 #define OVERLAY1_REG_OFFSET (OVERLAY_REG_SIZE / 2)
55 OVERLAY_POSITION = 0x04, // left top position
56 OVERLAY_SIZE = 0x08, // width and height
61 uint8_t overlay0_power;
62 uint16_t overlay0_left;
63 uint16_t overlay0_top;
64 uint16_t overlay0_width;
65 uint16_t overlay0_height;
67 uint8_t overlay1_power;
68 uint16_t overlay1_left;
69 uint16_t overlay1_top;
70 uint16_t overlay1_width;
71 uint16_t overlay1_height;
73 typedef struct OverlayState {
76 MemoryRegion mem_addr;
77 MemoryRegion mmio_addr;
82 static uint64_t overlay_reg_read(void *opaque, target_phys_addr_t addr, unsigned size)
86 TRACE("GET => overlay0 power status(%d)\n", overlay0_power);
87 return overlay0_power;
89 case OVERLAY_POSITION:
90 TRACE("GET => overlay0 position, left(%d):top(%d)\n",
91 overlay0_left, overlay0_top);
92 return overlay0_left | overlay0_top << 16;
95 TRACE("GET => overlay0 size, width(%d):height(%d)\n",
96 overlay0_width, overlay0_height);
97 return overlay0_width | overlay0_height << 16;
99 case OVERLAY1_REG_OFFSET + OVERLAY_POWER:
100 TRACE("GET => overlay1 power status(%d)\n", overlay1_power);
101 return overlay1_power;
103 case OVERLAY1_REG_OFFSET + OVERLAY_POSITION:
104 TRACE("GET => overlay1 position, left(%d):top(%d)\n",
105 overlay1_left, overlay1_top);
106 return overlay1_left | overlay1_top << 16;
108 case OVERLAY1_REG_OFFSET + OVERLAY_SIZE:
109 TRACE("GET => overlay1 size, width(%d):height(%d)\n",
110 overlay1_width, overlay1_height);
111 return overlay1_width | overlay1_height << 16;
114 ERR("wrong overlay register read - addr : %d\n", (int)addr);
121 static void overlay_reg_write(void *opaque, target_phys_addr_t addr, uint64_t val, unsigned size)
125 overlay0_power = val;
126 TRACE("SET => overlay0 power status(%d)\n", overlay0_power);
127 if (!overlay0_power) {
128 /* clear the last overlay area. */
129 memset(overlay_ptr, 0x00, (OVERLAY_MEM_SIZE / 2));
130 overlay0_left = overlay0_top = overlay0_width = overlay0_height = 0;
131 TRACE("clear the last overlay0 area\n");
134 case OVERLAY_POSITION:
135 overlay0_left = val & 0xFFFF;
136 overlay0_top = val >> 16;
137 TRACE("SET => overlay0 position, left(%d):top(%d)\n",
138 overlay0_left, overlay0_top);
141 overlay0_width = val & 0xFFFF;
142 overlay0_height = val >> 16;
143 TRACE("SET => overlay0 size, width(%d):height(%d)\n",
144 overlay0_width, overlay0_height);
146 case OVERLAY1_REG_OFFSET + OVERLAY_POWER:
147 overlay1_power = val;
148 TRACE("SET => overlay1 power status(%d)\n", overlay1_power);
149 if (!overlay1_power) {
150 /* clear the last overlay area. */
151 memset(overlay_ptr + OVERLAY1_REG_OFFSET,
152 0x00, (OVERLAY_MEM_SIZE / 2));
153 overlay1_left = overlay1_top = overlay1_width = overlay1_height = 0;
154 TRACE("clear the last overlay1 area\n");
157 case OVERLAY1_REG_OFFSET + OVERLAY_POSITION:
158 overlay1_left = val & 0xFFFF;
159 overlay1_top = val >> 16;
160 TRACE("SET => overlay1 position, left(%d):top(%d)\n",
161 overlay1_left, overlay1_top);
163 case OVERLAY1_REG_OFFSET + OVERLAY_SIZE:
164 overlay1_width = val & 0xFFFF;
165 overlay1_height = val >> 16;
166 TRACE("SET => overlay1 size, width(%d):height(%d)\n",
167 overlay1_width, overlay1_height);
170 ERR("wrong overlay register write - addr : %d\n", (int)addr);
175 static const MemoryRegionOps overlay_mmio_ops = {
176 .read = overlay_reg_read,
177 .write = overlay_reg_write,
178 .endianness = DEVICE_LITTLE_ENDIAN,
181 static int overlay_initfn(PCIDevice *dev)
183 OverlayState *s = DO_UPCAST(OverlayState, dev, dev);
184 uint8_t *pci_conf = s->dev.config;
186 pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_TIZEN);
187 pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_VIRTUAL_OVERLAY);
188 pci_config_set_class(pci_conf, PCI_CLASS_DISPLAY_OTHER);
190 memory_region_init_ram(&s->mem_addr, NULL, "maru_overlay.ram", OVERLAY_MEM_SIZE);
191 overlay_ptr = memory_region_get_ram_ptr(&s->mem_addr);
193 memory_region_init_io (&s->mmio_addr, &overlay_mmio_ops, s, "maru_overlay_mmio", OVERLAY_REG_SIZE);
195 /* setup memory space */
196 /* memory #0 device memory (overlay surface) */
197 /* memory #1 memory-mapped I/O */
198 pci_register_bar(&s->dev, 0, PCI_BASE_ADDRESS_MEM_PREFETCH, &s->mem_addr);
199 pci_register_bar(&s->dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->mmio_addr);
204 int pci_maru_overlay_init(PCIBus *bus)
206 INFO("Maru overlay was initailized!\n");
207 pci_create_simple(bus, -1, QEMU_DEV_NAME);
211 static PCIDeviceInfo overlay_info = {
212 .qdev.name = QEMU_DEV_NAME,
213 .qdev.size = sizeof(OverlayState),
215 .init = overlay_initfn,
218 static void overlay_register(void)
220 pci_qdev_register(&overlay_info);
223 device_init(overlay_register);