update source for tizen_2.1
[sdk/emulator/qemu.git] / tizen / src / hw / maru_brightness.c
1 /*
2  * Maru brightness device for VGA
3  *
4  * Copyright (C) 2011 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact:
7  * JinHyung Jo <jinhyung.jo@samsung.com>
8  * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
9  * DongKyun Yun
10  * DoHyung Hong
11  * Hyunjun Son
12  *
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.
17  *
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.
22  *
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,
26  * MA  02110-1301, USA.
27  *
28  * Contributors:
29  * - S-Core Co., Ltd
30  *
31  */
32
33
34 #include "pc.h"
35 #ifdef TARGET_ARM
36 #include "console.h"
37 #endif
38 #include "pci.h"
39 #include "maru_device_ids.h"
40 #include "maru_brightness.h"
41 #include "skin/maruskin_server.h"
42 #include "debug_ch.h"
43
44 MULTI_DEBUG_CHANNEL(qemu, maru_brightness);
45
46 #define QEMU_DEV_NAME           "MARU_BRIGHTNESS"
47
48 #define BRIGHTNESS_MEM_SIZE    (4 * 1024)    /* 4KB */
49 #define BRIGHTNESS_REG_SIZE    256
50
51 typedef struct BrightnessState {
52     PCIDevice       dev;
53     ram_addr_t      vram_offset;
54     MemoryRegion    mmio_addr;
55 } BrightnessState;
56
57 enum {
58     BRIGHTNESS_LEVEL = 0x00,
59     BRIGHTNESS_OFF = 0x04,
60 };
61
62 uint32_t brightness_level = BRIGHTNESS_MAX;
63 uint32_t brightness_off;
64
65 /* level : 1 ~ 100, interval : 1 or 2 */
66 /* skip 100 level, set to default alpha */
67 uint8_t brightness_tbl[] = {100, /* level 0 : for dimming */
68 /* level 01 ~ 10 */         106, 108, 109, 111, 112, 114, 115, 117, 118, 120,
69 /* level 11 ~ 20 */         121, 123, 124, 126, 127, 129, 130, 132, 133, 135,
70 /* level 21 ~ 30 */         136, 138, 139, 141, 142, 144, 145, 147, 148, 150,
71 /* level 31 ~ 40 */         151, 153, 154, 156, 157, 159, 160, 162, 163, 165,
72 /* level 41 ~ 50 */         166, 168, 169, 171, 172, 174, 175, 177, 178, 180,
73 /* level 51 ~ 60 */         181, 183, 184, 186, 187, 189, 190, 192, 193, 195,
74 /* level 61 ~ 70 */         196, 198, 199, 201, 202, 204, 205, 207, 208, 210,
75 /* level 71 ~ 80 */         211, 213, 214, 216, 217, 219, 220, 222, 223, 225,
76 /* level 81 ~ 90 */         226, 228, 229, 231, 232, 234, 235, 237, 238, 240,
77 /* level 91 ~ 99 */         241, 243, 244, 246, 247, 249, 250, 252, 253};
78
79 QEMUBH *bh;
80
81 static uint64_t brightness_reg_read(void *opaque,
82                                     target_phys_addr_t addr,
83                                     unsigned size)
84 {
85     switch (addr & 0xFF) {
86     case BRIGHTNESS_LEVEL:
87         INFO("brightness_reg_read: brightness_level = %d\n", brightness_level);
88         return brightness_level;
89     case BRIGHTNESS_OFF:
90         INFO("brightness_reg_read: brightness_off = %d\n", brightness_off);
91         return brightness_off;
92     default:
93         ERR("wrong brightness register read - addr : %d\n", (int)addr);
94         break;
95     }
96
97     return 0;
98 }
99
100 static void brightness_reg_write(void *opaque,
101                                  target_phys_addr_t addr,
102                                  uint64_t val,
103                                  unsigned size)
104 {
105     switch (addr & 0xFF) {
106     case BRIGHTNESS_LEVEL:
107 #if BRIGHTNESS_MIN > 0
108         if (val < BRIGHTNESS_MIN || val > BRIGHTNESS_MAX) {
109 #else
110         if (val > BRIGHTNESS_MAX) {
111 #endif
112             ERR("brightness_reg_write: Invalide brightness level.\n");
113         } else {
114             brightness_level = val;
115             INFO("brightness_level : %lld\n", val);
116 #ifdef TARGET_ARM
117             vga_hw_invalidate();
118 #endif
119         }
120         return;
121     case BRIGHTNESS_OFF:
122         INFO("brightness_off : %lld\n", val);
123         if (brightness_off == val) {
124             return;
125         }
126
127         brightness_off = val;
128
129 #ifdef TARGET_ARM
130         vga_hw_invalidate();
131 #endif
132
133         /* notify to skin process */
134         qemu_bh_schedule(bh);
135
136         return;
137     default:
138         ERR("wrong brightness register write - addr : %d\n", (int)addr);
139         break;
140     }
141 }
142
143 static const MemoryRegionOps brightness_mmio_ops = {
144     .read = brightness_reg_read,
145     .write = brightness_reg_write,
146     .endianness = DEVICE_LITTLE_ENDIAN,
147 };
148
149 static void brightness_exitfn(PCIDevice *dev)
150 {
151     if (bh) {
152         qemu_bh_delete(bh);
153     }
154 }
155
156 static void maru_brightness_bh(void *opaque)
157 {
158     if (brightness_off == 0) {
159         notify_brightness(TRUE);
160     } else {
161         notify_brightness(FALSE);
162     }
163 }
164
165 static int brightness_initfn(PCIDevice *dev)
166 {
167     BrightnessState *s = DO_UPCAST(BrightnessState, dev, dev);
168     uint8_t *pci_conf = s->dev.config;
169
170     pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_TIZEN);
171     pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_VIRTUAL_BRIGHTNESS);
172     pci_config_set_class(pci_conf, PCI_CLASS_DISPLAY_OTHER);
173
174     memory_region_init_io(&s->mmio_addr, &brightness_mmio_ops, s,
175                             "maru_brightness_mmio", BRIGHTNESS_REG_SIZE);
176     pci_register_bar(&s->dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->mmio_addr);
177
178     bh = qemu_bh_new(maru_brightness_bh, s);
179
180     return 0;
181 }
182
183 /* external interface */
184 DeviceState *pci_maru_brightness_init(PCIBus *bus)
185 {
186     return &pci_create_simple(bus, -1, QEMU_DEV_NAME)->qdev;
187 }
188
189 static void brightness_classinit(ObjectClass *klass, void *data)
190 {
191     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
192
193     k->no_hotplug = 1;
194     k->init = brightness_initfn;
195     k->exit = brightness_exitfn;
196 }
197
198 static TypeInfo brightness_info = {
199     .name = QEMU_DEV_NAME,
200     .parent = TYPE_PCI_DEVICE,
201     .instance_size = sizeof(BrightnessState),
202     .class_init = brightness_classinit,
203 };
204
205 static void brightness_register_types(void)
206 {
207     type_register_static(&brightness_info);
208 }
209
210 type_init(brightness_register_types);