2 * Common implementation of MARU Virtual Camera device by PCI bus.
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>
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.
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.
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,
38 #include "qemu-common.h"
39 #include "cpu-common.h"
43 #include "maru_device_ids.h"
45 #include "maru_camera_common.h"
46 #include "tizen/src/debug_ch.h"
48 MULTI_DEBUG_CHANNEL(tizen, camera_pci);
50 #define MARU_PCI_CAMERA_DEVICE_NAME "maru_camera_pci"
52 #define MARUCAM_MEM_SIZE (4 * 1024 * 1024) /* 4MB */
53 #define MARUCAM_REG_SIZE (256) /* 64 * 4Byte */
58 static inline uint32_t
59 marucam_mmio_read(void *opaque, target_phys_addr_t offset)
62 MaruCamState *state = (MaruCamState *)opaque;
64 switch (offset & 0xFF) {
66 qemu_mutex_lock(&state->thread_mutex);
69 qemu_irq_lower(state->dev.irq[2]);
72 qemu_mutex_unlock(&state->thread_mutex);
74 case MARUCAM_CMD_G_DATA:
75 ret = state->param->stack[state->param->top++];
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;
96 ERR("Not supported command: 0x%x\n", offset);
104 marucam_mmio_write(void *opaque, target_phys_addr_t offset, uint32_t value)
106 MaruCamState *state = (MaruCamState *)opaque;
108 switch (offset & 0xFF) {
109 case MARUCAM_CMD_OPEN:
110 marucam_device_open(state);
112 case MARUCAM_CMD_CLOSE:
113 marucam_device_close(state);
115 case MARUCAM_CMD_START_PREVIEW:
116 marucam_device_start_preview(state);
118 case MARUCAM_CMD_STOP_PREVIEW:
119 marucam_device_stop_preview(state);
120 memset(state->vaddr, 0, MARUCAM_MEM_SIZE);
122 case MARUCAM_CMD_S_PARAM:
123 marucam_device_s_param(state);
125 case MARUCAM_CMD_G_PARAM:
126 marucam_device_g_param(state);
128 case MARUCAM_CMD_ENUM_FMT:
129 marucam_device_enum_fmt(state);
131 case MARUCAM_CMD_TRY_FMT:
132 marucam_device_try_fmt(state);
134 case MARUCAM_CMD_S_FMT:
135 marucam_device_s_fmt(state);
137 case MARUCAM_CMD_G_FMT:
138 marucam_device_g_fmt(state);
140 case MARUCAM_CMD_QCTRL:
141 marucam_device_qctrl(state);
143 case MARUCAM_CMD_S_CTRL:
144 marucam_device_s_ctrl(state);
146 case MARUCAM_CMD_G_CTRL:
147 marucam_device_g_ctrl(state);
149 case MARUCAM_CMD_ENUM_FSIZES:
150 marucam_device_enum_fsizes(state);
152 case MARUCAM_CMD_ENUM_FINTV:
153 marucam_device_enum_fintv(state);
155 case MARUCAM_CMD_S_DATA:
156 state->param->stack[state->param->top++] = value;
158 case MARUCAM_CMD_DATACLR:
159 memset(state->param, 0, sizeof(MaruCamParam));
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);
167 ERR("Not supported command: 0x%x\n", offset);
172 static const MemoryRegionOps maru_camera_mmio_ops = {
185 .endianness = DEVICE_LITTLE_ENDIAN,
189 * QEMU bottom half funtion
191 static void marucam_tx_bh(void *opaque)
193 MaruCamState *state = (MaruCamState *)opaque;
195 qemu_mutex_lock(&state->thread_mutex);
197 qemu_irq_raise(state->dev.irq[2]);
199 qemu_mutex_unlock(&state->thread_mutex);
203 * Initialization function
205 static int marucam_initfn(PCIDevice *dev)
207 MaruCamState *s = DO_UPCAST(MaruCamState, dev, dev);
208 uint8_t *pci_conf = s->dev.config;
210 pci_config_set_interrupt_pin(pci_conf, 0x03);
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);
216 memory_region_init_io(&s->mmio,
217 &maru_camera_mmio_ops,
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);
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);
230 marucam_device_init(s);
232 s->tx_bh = qemu_bh_new(marucam_tx_bh, s);
233 INFO("[%s] camera device was initialized.\n", __func__);
239 * Termination function
241 static void marucam_exitfn(PCIDevice *pci_dev)
244 OBJECT_CHECK(MaruCamState, pci_dev, MARU_PCI_CAMERA_DEVICE_NAME);
246 marucam_device_exit(s);
248 qemu_cond_destroy(&s->thread_cond);
249 qemu_mutex_destroy(&s->thread_mutex);
251 memory_region_destroy(&s->vram);
252 memory_region_destroy(&s->mmio);
255 INFO("[%s] camera device was released.\n", __func__);
258 int maru_camera_pci_init(PCIBus *bus)
260 INFO("[%s] camera device was initialized.\n", __func__);
261 pci_create_simple(bus, -1, MARU_PCI_CAMERA_DEVICE_NAME);
265 static void maru_camera_pci_class_init(ObjectClass *klass, void *data)
267 DeviceClass *dc = DEVICE_CLASS(klass);
268 PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
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";
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,
286 static void maru_camera_pci_register_types(void)
288 type_register_static(&maru_camera_info);
291 type_init(maru_camera_pci_register_types)