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 <timer.h>
30 #include <plat/inc/gpio.h>
31 #include <plat/inc/exti.h>
32 #include <plat/inc/syscfg.h>
33 #include <variant/inc/variant.h>
34 
35 #define VSYNC_APP_ID      APP_ID_MAKE(APP_ID_VENDOR_GOOGLE, 7)
36 #define VSYNC_APP_VERSION 1
37 
38 #ifndef VSYNC_PIN
39 #error "VSYNC_PIN is not defined; please define in variant.h"
40 #endif
41 
42 #ifndef VSYNC_IRQ
43 #error "VSYNC_IRQ is not defined; please define in variant.h"
44 #endif
45 
46 #define INFO_PRINT(fmt, ...) do { \
47         osLog(LOG_INFO, "%s " fmt, "[VSYNC]", ##__VA_ARGS__); \
48     } while (0);
49 
50 #define DEBUG_PRINT(fmt, ...) do { \
51         if (enable_debug) {  \
52             INFO_PRINT(fmt, ##__VA_ARGS__); \
53         } \
54     } while (0);
55 
56 static const bool enable_debug = 0;
57 
58 static struct SensorTask
59 {
60     struct Gpio *pin;
61     struct ChainedIsr isr;
62 
63     uint32_t id;
64     uint32_t sensorHandle;
65 
66     bool on;
67 } mTask;
68 
vsyncIsr(struct ChainedIsr * localIsr)69 static bool vsyncIsr(struct ChainedIsr *localIsr)
70 {
71     struct SensorTask *data = container_of(localIsr, struct SensorTask, isr);
72     union EmbeddedDataPoint sample;
73 
74     if (!extiIsPendingGpio(data->pin)) {
75         return false;
76     }
77 
78     if (data->on) {
79         sample.idata = 1;
80         osEnqueueEvt(sensorGetMyEventType(SENS_TYPE_VSYNC), sample.vptr, NULL);
81     }
82 
83     extiClearPendingGpio(data->pin);
84     return true;
85 }
86 
enableInterrupt(struct Gpio * pin,struct ChainedIsr * isr)87 static bool enableInterrupt(struct Gpio *pin, struct ChainedIsr *isr)
88 {
89     gpioConfigInput(pin, GPIO_SPEED_LOW, GPIO_PULL_NONE);
90     syscfgSetExtiPort(pin);
91     extiEnableIntGpio(pin, EXTI_TRIGGER_FALLING);
92     extiChainIsr(VSYNC_IRQ, isr);
93     return true;
94 }
95 
disableInterrupt(struct Gpio * pin,struct ChainedIsr * isr)96 static bool disableInterrupt(struct Gpio *pin, struct ChainedIsr *isr)
97 {
98     extiUnchainIsr(VSYNC_IRQ, isr);
99     extiDisableIntGpio(pin);
100     return true;
101 }
102 
103 static const struct SensorInfo mSensorInfo =
104 {
105     .sensorName = "Camera Vsync",
106     .sensorType = SENS_TYPE_VSYNC,
107     .numAxis = NUM_AXIS_EMBEDDED,
108     .interrupt = NANOHUB_INT_NONWAKEUP,
109     .minSamples = 20,
110 };
111 
vsyncPower(bool on,void * cookie)112 static bool vsyncPower(bool on, void *cookie)
113 {
114     INFO_PRINT("power %d\n", on);
115 
116     if (on) {
117         extiClearPendingGpio(mTask.pin);
118         enableInterrupt(mTask.pin, &mTask.isr);
119     } else {
120         disableInterrupt(mTask.pin, &mTask.isr);
121         extiClearPendingGpio(mTask.pin);
122     }
123 
124     mTask.on = on;
125     sensorSignalInternalEvt(mTask.sensorHandle, SENSOR_INTERNAL_EVT_POWER_STATE_CHG, on, 0);
126     return true;
127 }
128 
vsyncFirmwareUpload(void * cookie)129 static bool vsyncFirmwareUpload(void *cookie)
130 {
131     return sensorSignalInternalEvt(mTask.sensorHandle, SENSOR_INTERNAL_EVT_FW_STATE_CHG, 1, 0);
132 }
133 
vsyncSetRate(uint32_t rate,uint64_t latency,void * cookie)134 static bool vsyncSetRate(uint32_t rate, uint64_t latency, void *cookie)
135 {
136     INFO_PRINT("setRate\n");
137     return sensorSignalInternalEvt(mTask.sensorHandle, SENSOR_INTERNAL_EVT_RATE_CHG, rate, latency);
138 }
139 
vsyncFlush(void * cookie)140 static bool vsyncFlush(void *cookie)
141 {
142     INFO_PRINT("flush\n");
143     return osEnqueueEvt(sensorGetMyEventType(SENS_TYPE_VSYNC), SENSOR_DATA_EVENT_FLUSH, NULL);
144 }
145 
146 static const struct SensorOps mSensorOps =
147 {
148     .sensorPower = vsyncPower,
149     .sensorFirmwareUpload = vsyncFirmwareUpload,
150     .sensorSetRate = vsyncSetRate,
151     .sensorFlush = vsyncFlush,
152 };
153 
handleEvent(uint32_t evtType,const void * evtData)154 static void handleEvent(uint32_t evtType, const void* evtData)
155 {
156 }
157 
startTask(uint32_t taskId)158 static bool startTask(uint32_t taskId)
159 {
160     INFO_PRINT("task starting\n");
161 
162     mTask.id = taskId;
163     mTask.sensorHandle = sensorRegister(&mSensorInfo, &mSensorOps, NULL, true);
164     mTask.pin = gpioRequest(VSYNC_PIN);
165     mTask.isr.func = vsyncIsr;
166 
167     return true;
168 }
169 
endTask(void)170 static void endTask(void)
171 {
172     disableInterrupt(mTask.pin, &mTask.isr);
173     extiUnchainIsr(VSYNC_IRQ, &mTask.isr);
174     extiClearPendingGpio(mTask.pin);
175     gpioRelease(mTask.pin);
176     sensorUnregister(mTask.sensorHandle);
177 }
178 
179 INTERNAL_APP_INIT(VSYNC_APP_ID, VSYNC_APP_VERSION, startTask, endTask, handleEvent);
180