43194b4233f0502631e56d289b6d3422a630c213
[sdk/emulator/qemu.git] / tizen / src / hw / maru_overlay.c
1 /* 
2  * Maru overlay device for VGA
3  *
4  * Copyright (C) 2011 - 2012 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: 
7  * SeokYeon Hwang <syeon.hwang@samsung.com>
8  * SangJin Kim <sangjin3.kim@samsung.com>
9  * MunKyu Im <munkyu.im@samsung.com>
10  * KiTae Kim <kt920.kim@samsung.com>
11  * JinHyung Jo <jinhyung.jo@samsung.com>
12  * SungMin Ha <sungmin82.ha@samsung.com>
13  * JiHye Kim <jihye1128.kim@samsung.com>
14  * GiWoong Kim <giwoong.kim@samsung.com>
15  * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
16  * DongKyun Yun
17  * DoHyung Hong
18  * Hyunjun Son
19  *
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.
24  *
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.
29  *
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.
33  *
34  * Contributors:
35  * - S-Core Co., Ltd
36  *
37  */
38 #include "pc.h"
39 #include "pci.h"
40 #include "maru_device_ids.h"
41 #include "maru_overlay.h"
42 #include "debug_ch.h"
43
44 MULTI_DEBUG_CHANNEL(qemu, maru_overlay);
45
46 #define QEMU_DEV_NAME           "MARU_OVERLAY"
47
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)
51
52
53 enum {
54         OVERLAY_POWER    = 0x00,
55         OVERLAY_POSITION = 0x04,        // left top position
56         OVERLAY_SIZE     = 0x08,        // width and height
57 };
58
59 uint8_t* overlay_ptr;
60
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;
66
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;
72
73 typedef struct OverlayState {
74     PCIDevice       dev;
75
76     MemoryRegion    mem_addr;
77     MemoryRegion    mmio_addr;
78
79 } OverlayState;
80
81
82 static uint64_t overlay_reg_read(void *opaque, target_phys_addr_t addr, unsigned size)
83 {
84     switch (addr) {
85     case OVERLAY_POWER:
86         TRACE("GET => overlay0 power status(%d)\n", overlay0_power);
87         return overlay0_power;
88         break;
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;
93         break;
94     case OVERLAY_SIZE:
95         TRACE("GET => overlay0 size, width(%d):height(%d)\n",
96               overlay0_width, overlay0_height);
97         return overlay0_width | overlay0_height << 16;
98         break;
99     case OVERLAY1_REG_OFFSET + OVERLAY_POWER:
100         TRACE("GET => overlay1 power status(%d)\n", overlay1_power);
101         return overlay1_power;
102         break;
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;
107         break;
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;
112         break;
113     default:
114         ERR("wrong overlay register read - addr : %d\n", (int)addr);
115         break;
116     }
117
118     return 0;
119 }
120
121 static void overlay_reg_write(void *opaque, target_phys_addr_t addr, uint64_t val, unsigned size)
122 {
123     switch (addr) {
124     case OVERLAY_POWER:
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");
132         }
133         break;
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);
139         break;
140     case OVERLAY_SIZE:
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);
145         break;
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");
155         }
156         break;
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);
162         break;
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);
168         break;
169     default:
170         ERR("wrong overlay register write - addr : %d\n", (int)addr);
171         break;
172     }
173 }
174
175 static const MemoryRegionOps overlay_mmio_ops = {
176     .read = overlay_reg_read,
177     .write = overlay_reg_write,
178     .endianness = DEVICE_LITTLE_ENDIAN,
179 };
180
181 static int overlay_initfn(PCIDevice *dev)
182 {
183     OverlayState *s = DO_UPCAST(OverlayState, dev, dev);
184     uint8_t *pci_conf = s->dev.config;
185
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);
189
190     memory_region_init_ram(&s->mem_addr, "maru_overlay.ram", OVERLAY_MEM_SIZE);
191     overlay_ptr = memory_region_get_ram_ptr(&s->mem_addr);
192
193     memory_region_init_io (&s->mmio_addr, &overlay_mmio_ops, s, "maru_overlay_mmio", OVERLAY_REG_SIZE);
194
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);
200
201     return 0;
202 }
203
204 DeviceState *pci_maru_overlay_init(PCIBus *bus)
205 {
206     INFO("Maru overlay was initailized!\n");
207     return &pci_create_simple(bus, -1, QEMU_DEV_NAME)->qdev;
208 }
209
210 static void overlay_classinit(ObjectClass *klass, void *data)
211 {
212     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
213
214     k->no_hotplug = 1;
215     k->init = overlay_initfn;
216 }
217
218 static TypeInfo overlay_info = {
219     .name          = QEMU_DEV_NAME,
220     .parent        = TYPE_PCI_DEVICE,
221     .instance_size = sizeof(OverlayState),
222     .class_init    = overlay_classinit,
223 };
224
225 static void overlay_register_types(void)
226 {
227     type_register_static(&overlay_info);
228 }
229
230 type_init(overlay_register_types);