1 /*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <stdlib.h>
18 #include <string.h>
19 #include <float.h>
20
21 #include <eventnums.h>
22 #include <gpio.h>
23 #include <heap.h>
24 #include <hostIntf.h>
25 #include <isr.h>
26 #include <nanohubPacket.h>
27 #include <sensors.h>
28 #include <seos.h>
29 #include <slab.h>
30 #include <timer.h>
31 #include <plat/gpio.h>
32 #include <plat/exti.h>
33 #include <plat/syscfg.h>
34 #include <variant/variant.h>
35
36 #define VSYNC_APP_ID APP_ID_MAKE(NANOHUB_VENDOR_GOOGLE, 7)
37 #define VSYNC_APP_VERSION 2
38
39 // This defines how many vsync events we could handle being backed up in the
40 // queue. Use this to size our slab
41 #define MAX_VSYNC_EVENTS 4
42 #define MAX_VSYNC_INT_LATENCY 1000 /* in ns */
43
44 #ifndef VSYNC_PIN
45 #error "VSYNC_PIN is not defined; please define in variant.h"
46 #endif
47
48 #ifndef VSYNC_IRQ
49 #error "VSYNC_IRQ is not defined; please define in variant.h"
50 #endif
51
52 #define INFO_PRINT(fmt, ...) do { \
53 osLog(LOG_INFO, "%s " fmt, "[VSYNC]", ##__VA_ARGS__); \
54 } while (0);
55
56 #define ERROR_PRINT(fmt, ...) INFO_PRINT("%s" fmt, "ERROR: ", ##__VA_ARGS__); \
57
58 #define DEBUG_PRINT(fmt, ...) do { \
59 if (enable_debug) { \
60 INFO_PRINT(fmt, ##__VA_ARGS__); \
61 } \
62 } while (0);
63
64 static const bool __attribute__((unused)) enable_debug = 0;
65
66 static struct SensorTask
67 {
68 struct Gpio *pin;
69 struct ChainedIsr isr;
70 struct SlabAllocator *evtSlab;
71
72
73 uint32_t id;
74 uint32_t sensorHandle;
75
76 bool on;
77 } mTask;
78
vsyncAllocateEvt(struct SingleAxisDataEvent ** evPtr,uint64_t time)79 static bool vsyncAllocateEvt(struct SingleAxisDataEvent **evPtr, uint64_t time)
80 {
81 struct SingleAxisDataEvent *ev;
82
83 *evPtr = slabAllocatorAlloc(mTask.evtSlab);
84
85 ev = *evPtr;
86 if (!ev) {
87 ERROR_PRINT("slabAllocatorAlloc() failed\n");
88 return false;
89 }
90
91 memset(&ev->samples[0].firstSample, 0x00, sizeof(struct SensorFirstSample));
92 ev->referenceTime = time;
93 ev->samples[0].firstSample.numSamples = 1;
94 ev->samples[0].idata = 1;
95
96 return true;
97 }
98
vsyncFreeEvt(void * ptr)99 static void vsyncFreeEvt(void *ptr)
100 {
101 slabAllocatorFree(mTask.evtSlab, ptr);
102 }
103
vsyncIsr(struct ChainedIsr * localIsr)104 static bool vsyncIsr(struct ChainedIsr *localIsr)
105 {
106 struct SensorTask *data = container_of(localIsr, struct SensorTask, isr);
107 struct SingleAxisDataEvent *ev;
108
109 if (!extiIsPendingGpio(data->pin)) {
110 return false;
111 }
112
113 if (data->on) {
114 if (vsyncAllocateEvt(&ev, sensorGetTime())) {
115 if (!osEnqueueEvtOrFree(sensorGetMyEventType(SENS_TYPE_VSYNC), ev, vsyncFreeEvt)) {
116 ERROR_PRINT("osEnqueueEvtOrFree() failed\n");
117 }
118 }
119 }
120
121 extiClearPendingGpio(data->pin);
122 return true;
123 }
124
enableInterrupt(struct Gpio * pin,struct ChainedIsr * isr)125 static bool enableInterrupt(struct Gpio *pin, struct ChainedIsr *isr)
126 {
127 gpioConfigInput(pin, GPIO_SPEED_LOW, GPIO_PULL_NONE);
128 syscfgSetExtiPort(pin);
129 extiEnableIntGpio(pin, EXTI_TRIGGER_FALLING);
130 extiChainIsr(VSYNC_IRQ, isr);
131 return true;
132 }
133
disableInterrupt(struct Gpio * pin,struct ChainedIsr * isr)134 static bool disableInterrupt(struct Gpio *pin, struct ChainedIsr *isr)
135 {
136 extiUnchainIsr(VSYNC_IRQ, isr);
137 extiDisableIntGpio(pin);
138 return true;
139 }
140
141 static const struct SensorInfo mSensorInfo =
142 {
143 .sensorName = "Camera Vsync",
144 .sensorType = SENS_TYPE_VSYNC,
145 .numAxis = NUM_AXIS_ONE,
146 .interrupt = NANOHUB_INT_NONWAKEUP,
147 .minSamples = 20,
148 };
149
vsyncPower(bool on,void * cookie)150 static bool vsyncPower(bool on, void *cookie)
151 {
152 INFO_PRINT("power %d\n", on);
153
154 if (on) {
155 extiClearPendingGpio(mTask.pin);
156 enableInterrupt(mTask.pin, &mTask.isr);
157 } else {
158 disableInterrupt(mTask.pin, &mTask.isr);
159 extiClearPendingGpio(mTask.pin);
160 }
161
162 mTask.on = on;
163 sensorSignalInternalEvt(mTask.sensorHandle, SENSOR_INTERNAL_EVT_POWER_STATE_CHG, on, 0);
164 return true;
165 }
166
vsyncFirmwareUpload(void * cookie)167 static bool vsyncFirmwareUpload(void *cookie)
168 {
169 return sensorSignalInternalEvt(mTask.sensorHandle, SENSOR_INTERNAL_EVT_FW_STATE_CHG, 1, 0);
170 }
171
vsyncSetRate(uint32_t rate,uint64_t latency,void * cookie)172 static bool vsyncSetRate(uint32_t rate, uint64_t latency, void *cookie)
173 {
174 INFO_PRINT("setRate\n");
175 return sensorSignalInternalEvt(mTask.sensorHandle, SENSOR_INTERNAL_EVT_RATE_CHG, rate, latency);
176 }
177
vsyncFlush(void * cookie)178 static bool vsyncFlush(void *cookie)
179 {
180 INFO_PRINT("flush\n");
181 return osEnqueueEvt(sensorGetMyEventType(SENS_TYPE_VSYNC), SENSOR_DATA_EVENT_FLUSH, NULL);
182 }
183
184 static const struct SensorOps mSensorOps =
185 {
186 .sensorPower = vsyncPower,
187 .sensorFirmwareUpload = vsyncFirmwareUpload,
188 .sensorSetRate = vsyncSetRate,
189 .sensorFlush = vsyncFlush,
190 };
191
handleEvent(uint32_t evtType,const void * evtData)192 static void handleEvent(uint32_t evtType, const void* evtData)
193 {
194 }
195
startTask(uint32_t taskId)196 static bool startTask(uint32_t taskId)
197 {
198 mTask.id = taskId;
199 mTask.sensorHandle = sensorRegister(&mSensorInfo, &mSensorOps, NULL, true);
200 mTask.pin = gpioRequest(VSYNC_PIN);
201 mTask.isr.func = vsyncIsr;
202 mTask.isr.maxLatencyNs = MAX_VSYNC_INT_LATENCY;
203
204 mTask.evtSlab = slabAllocatorNew(sizeof(struct SingleAxisDataEvent) + sizeof(struct SingleAxisDataPoint), 4, MAX_VSYNC_EVENTS);
205 if (!mTask.evtSlab) {
206 ERROR_PRINT("slabAllocatorNew() failed\n");
207 return false;
208 }
209
210 return true;
211 }
212
endTask(void)213 static void endTask(void)
214 {
215 disableInterrupt(mTask.pin, &mTask.isr);
216 extiUnchainIsr(VSYNC_IRQ, &mTask.isr);
217 extiClearPendingGpio(mTask.pin);
218 gpioRelease(mTask.pin);
219 sensorUnregister(mTask.sensorHandle);
220 }
221
222 INTERNAL_APP_INIT(VSYNC_APP_ID, VSYNC_APP_VERSION, startTask, endTask, handleEvent);
223