update source for tizen_2.1
[sdk/emulator/qemu.git] / tizen / src / hw / maru_camera_common_pci.c
1 /*
2  * Common implementation of MARU Virtual Camera device by PCI bus.
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  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
23  * MA  02110-1301, USA.
24  *
25  * Contributors:
26  * - S-Core Co., Ltd
27  *
28  */
29
30
31 #include <stdarg.h>
32 #include <stdlib.h>
33 #include <stdio.h>
34 #include <string.h>
35 #include <inttypes.h>
36 #include <signal.h>
37
38 #include "qemu-common.h"
39 #include "cpu-common.h"
40
41 #include "pci.h"
42 #include "pci_ids.h"
43 #include "maru_device_ids.h"
44
45 #include "maru_camera_common.h"
46 #include "tizen/src/debug_ch.h"
47
48 MULTI_DEBUG_CHANNEL(tizen, camera_pci);
49
50 #define MARU_PCI_CAMERA_DEVICE_NAME     "maru_camera_pci"
51
52 #define MARUCAM_MEM_SIZE    (4 * 1024 * 1024)   /* 4MB */
53 #define MARUCAM_REG_SIZE    (256)               /* 64 * 4Byte */
54
55 /*
56  *  I/O functions
57  */
58 static inline uint32_t
59 marucam_mmio_read(void *opaque, target_phys_addr_t offset)
60 {
61     uint32_t ret = 0;
62     MaruCamState *state = (MaruCamState *)opaque;
63
64     switch (offset & 0xFF) {
65     case MARUCAM_CMD_ISR:
66         qemu_mutex_lock(&state->thread_mutex);
67         ret = state->isr;
68         if (ret != 0) {
69             qemu_irq_lower(state->dev.irq[2]);
70             state->isr = 0;
71         }
72         qemu_mutex_unlock(&state->thread_mutex);
73         break;
74     case MARUCAM_CMD_G_DATA:
75         ret = state->param->stack[state->param->top++];
76         break;
77     case MARUCAM_CMD_OPEN:
78     case MARUCAM_CMD_CLOSE:
79     case MARUCAM_CMD_START_PREVIEW:
80     case MARUCAM_CMD_STOP_PREVIEW:
81     case MARUCAM_CMD_S_PARAM:
82     case MARUCAM_CMD_G_PARAM:
83     case MARUCAM_CMD_ENUM_FMT:
84     case MARUCAM_CMD_TRY_FMT:
85     case MARUCAM_CMD_S_FMT:
86     case MARUCAM_CMD_G_FMT:
87     case MARUCAM_CMD_QCTRL:
88     case MARUCAM_CMD_S_CTRL:
89     case MARUCAM_CMD_G_CTRL:
90     case MARUCAM_CMD_ENUM_FSIZES:
91     case MARUCAM_CMD_ENUM_FINTV:
92         ret = state->param->errCode;
93         state->param->errCode = 0;
94         break;
95     default:
96         ERR("Not supported command: 0x%x\n", offset);
97         ret = EINVAL;
98         break;
99     }
100     return ret;
101 }
102
103 static inline void
104 marucam_mmio_write(void *opaque, target_phys_addr_t offset, uint32_t value)
105 {
106     MaruCamState *state = (MaruCamState *)opaque;
107
108     switch (offset & 0xFF) {
109     case MARUCAM_CMD_OPEN:
110         marucam_device_open(state);
111         break;
112     case MARUCAM_CMD_CLOSE:
113         marucam_device_close(state);
114         break;
115     case MARUCAM_CMD_START_PREVIEW:
116         marucam_device_start_preview(state);
117         break;
118     case MARUCAM_CMD_STOP_PREVIEW:
119         marucam_device_stop_preview(state);
120         memset(state->vaddr, 0, MARUCAM_MEM_SIZE);
121         break;
122     case MARUCAM_CMD_S_PARAM:
123         marucam_device_s_param(state);
124         break;
125     case MARUCAM_CMD_G_PARAM:
126         marucam_device_g_param(state);
127         break;
128     case MARUCAM_CMD_ENUM_FMT:
129         marucam_device_enum_fmt(state);
130         break;
131     case MARUCAM_CMD_TRY_FMT:
132         marucam_device_try_fmt(state);
133         break;
134     case MARUCAM_CMD_S_FMT:
135         marucam_device_s_fmt(state);
136         break;
137     case MARUCAM_CMD_G_FMT:
138         marucam_device_g_fmt(state);
139         break;
140     case MARUCAM_CMD_QCTRL:
141         marucam_device_qctrl(state);
142         break;
143     case MARUCAM_CMD_S_CTRL:
144         marucam_device_s_ctrl(state);
145         break;
146     case MARUCAM_CMD_G_CTRL:
147         marucam_device_g_ctrl(state);
148         break;
149     case MARUCAM_CMD_ENUM_FSIZES:
150         marucam_device_enum_fsizes(state);
151         break;
152     case MARUCAM_CMD_ENUM_FINTV:
153         marucam_device_enum_fintv(state);
154         break;
155     case MARUCAM_CMD_S_DATA:
156         state->param->stack[state->param->top++] = value;
157         break;
158     case MARUCAM_CMD_DATACLR:
159         memset(state->param, 0, sizeof(MaruCamParam));
160         break;
161     case MARUCAM_CMD_REQFRAME:
162         qemu_mutex_lock(&state->thread_mutex);
163         state->req_frame = value + 1;
164         qemu_mutex_unlock(&state->thread_mutex);
165         break;
166     default:
167         ERR("Not supported command: 0x%x\n", offset);
168         break;
169     }
170 }
171
172 static const MemoryRegionOps maru_camera_mmio_ops = {
173     .old_mmio = {
174         .read = {
175             marucam_mmio_read,
176             marucam_mmio_read,
177             marucam_mmio_read,
178         },
179         .write = {
180             marucam_mmio_write,
181             marucam_mmio_write,
182             marucam_mmio_write,
183         },
184     },
185     .endianness = DEVICE_LITTLE_ENDIAN,
186 };
187
188 /*
189  *  QEMU bottom half funtion
190  */
191 static void marucam_tx_bh(void *opaque)
192 {
193     MaruCamState *state = (MaruCamState *)opaque;
194
195     qemu_mutex_lock(&state->thread_mutex);
196     if (state->isr) {
197         qemu_irq_raise(state->dev.irq[2]);
198     }
199     qemu_mutex_unlock(&state->thread_mutex);
200 }
201
202 /*
203  *  Initialization function
204  */
205 static int marucam_initfn(PCIDevice *dev)
206 {
207     MaruCamState *s = DO_UPCAST(MaruCamState, dev, dev);
208     uint8_t *pci_conf = s->dev.config;
209
210     pci_config_set_interrupt_pin(pci_conf, 0x03);
211
212     memory_region_init_ram(&s->vram, "marucamera.ram", MARUCAM_MEM_SIZE);
213     s->vaddr = memory_region_get_ram_ptr(&s->vram);
214     memset(s->vaddr, 0, MARUCAM_MEM_SIZE);
215
216     memory_region_init_io(&s->mmio,
217                           &maru_camera_mmio_ops,
218                           s,
219                           "maru-camera-mmio",
220                           MARUCAM_REG_SIZE);
221
222     pci_register_bar(&s->dev, 0, PCI_BASE_ADDRESS_MEM_PREFETCH, &s->vram);
223     pci_register_bar(&s->dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->mmio);
224
225     /* for worker thread */
226     s->param = (MaruCamParam *)g_malloc0(sizeof(MaruCamParam));
227     qemu_cond_init(&s->thread_cond);
228     qemu_mutex_init(&s->thread_mutex);
229
230     marucam_device_init(s);
231
232     s->tx_bh = qemu_bh_new(marucam_tx_bh, s);
233     INFO("[%s] camera device was initialized.\n", __func__);
234
235     return 0;
236 }
237
238 /*
239  *  Termination function
240  */
241 static void marucam_exitfn(PCIDevice *pci_dev)
242 {
243     MaruCamState *s =
244         OBJECT_CHECK(MaruCamState, pci_dev, MARU_PCI_CAMERA_DEVICE_NAME);
245
246     marucam_device_exit(s);
247     g_free(s->param);
248     qemu_cond_destroy(&s->thread_cond);
249     qemu_mutex_destroy(&s->thread_mutex);
250
251     memory_region_destroy(&s->vram);
252     memory_region_destroy(&s->mmio);
253
254
255     INFO("[%s] camera device was released.\n", __func__);
256 }
257
258 int maru_camera_pci_init(PCIBus *bus)
259 {
260     INFO("[%s] camera device was initialized.\n", __func__);
261     pci_create_simple(bus, -1, MARU_PCI_CAMERA_DEVICE_NAME);
262     return 0;
263 }
264
265 static void maru_camera_pci_class_init(ObjectClass *klass, void *data)
266 {
267     DeviceClass *dc = DEVICE_CLASS(klass);
268     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
269
270     k->no_hotplug = 1;
271     k->init = marucam_initfn;
272     k->exit = marucam_exitfn;
273     k->vendor_id = PCI_VENDOR_ID_TIZEN;
274     k->device_id = PCI_DEVICE_ID_VIRTUAL_CAMERA;
275     k->class_id = PCI_CLASS_OTHERS;
276     dc->desc = "MARU Virtual Camera device for Tizen emulator";
277 }
278
279 static TypeInfo maru_camera_info = {
280     .name          = MARU_PCI_CAMERA_DEVICE_NAME,
281     .parent        = TYPE_PCI_DEVICE,
282     .instance_size = sizeof(MaruCamState),
283     .class_init    = maru_camera_pci_class_init,
284 };
285
286 static void maru_camera_pci_register_types(void)
287 {
288     type_register_static(&maru_camera_info);
289 }
290
291 type_init(maru_camera_pci_register_types)