1 /*
2  * Copyright 2021 QuickLogic
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  * SPDX-License-Identifier: Apache-2.0
17  */
18 #include "rtconfig.h"
19 #ifdef PKG_USING_FREERTOS_WRAPPER
20 #include "FreeRTOS.h"
21 #include <camera.h>
22 #include <string.h>
23 #include <stdint.h>
24 #include <stdbool.h>
25 #include "semphr.h"
26 #include "core-v-mcu-config.h"
27 #include "hal_fc_event.h"
28 #include "hal_udma_ctrl_reg_defs.h"
29 #include "hal_udma_cam_reg_defs.h"
30 #include <udma_cam_driver.h>
31 #include <udma_i2cm_driver.h>
32 #include "himax.h"
33 #include "camera.h"
34 
35 reg_cfg_t himaxRegInit[] = {
36     {BLC_TGT, 0x08},            //  BLC target :8  at 8 bit mode
37     {BLC2_TGT, 0x08},           //  BLI target :8  at 8 bit mode
38     {0x3044, 0x0A},             //  Increase CDS time for settling
39     {0x3045, 0x00},             //  Make symetric for cds_tg and rst_tg
40     {0x3047, 0x0A},             //  Increase CDS time for settling
41     {0x3050, 0xC0},             //  Make negative offset up to 4x
42     {0x3051, 0x42},
43     {0x3052, 0x50},
44     {0x3053, 0x00},
45     {0x3054, 0x03},             //  tuning sf sig clamping as lowest
46     {0x3055, 0xF7},             //  tuning dsun
47     {0x3056, 0xF8},             //  increase adc nonoverlap clk
48     {0x3057, 0x29},             //  increase adc pwr for missing code
49     {0x3058, 0x1F},             //  turn on dsun
50     {0x3059, 0x1E},
51     {0x3064, 0x00},
52     {0x3065, 0x04},             //  pad pull 0
53 
54     {BLC_CFG, 0x43},            //  BLC_on, IIR
55 
56     {0x1001, 0x43},             //  BLC dithering en
57     {0x1002, 0x43},             //  blc_darkpixel_thd
58     {0x0350, 0x00},             //  Dgain Control
59     {BLI_EN, 0x01},             //  BLI enable
60     {0x1003, 0x00},             //  BLI Target [Def: 0x20]
61 
62     {DPC_CTRL, 0x01},           //  DPC option 0: DPC off   1 : mono   3 : bayer1   5 : bayer2
63     {0x1009, 0xA0},             //  cluster hot pixel th
64     {0x100A, 0x60},             //  cluster cold pixel th
65     {SINGLE_THR_HOT, 0x90},     //  single hot pixel th
66     {SINGLE_THR_COLD, 0x40},    //  single cold pixel th
67     {0x1012, 0x00},             //  Sync. shift disable
68     {0x2000, 0x07},
69     {0x2003, 0x00},
70     {0x2004, 0x1C},
71     {0x2007, 0x00},
72     {0x2008, 0x58},
73     {0x200B, 0x00},
74     {0x200C, 0x7A},
75     {0x200F, 0x00},
76     {0x2010, 0xB8},
77     {0x2013, 0x00},
78     {0x2014, 0x58},
79     {0x2017, 0x00},
80     {0x2018, 0x9B},
81 
82     {AE_CTRL,        0x01},      //Automatic Exposure Gain Control
83     {AE_TARGET_MEAN, 0x3C},      //AE target mean [Def: 0x3C]
84     {AE_MIN_MEAN,    0x0A},      //AE min target mean [Def: 0x0A]
85 
86     {INTEGRATION_H,  0x00},      //Integration H [Def: 0x01]
87     {INTEGRATION_L,  0x60},      //Integration L [Def: 0x08]
88     {ANALOG_GAIN,    0x00},      //Analog Global Gain
89     {DAMPING_FACTOR, 0x20},      //Damping Factor [Def: 0x20]
90     {DIGITAL_GAIN_H, 0x01},      //Digital Gain High [Def: 0x01]
91     {DIGITAL_GAIN_L, 0x00},      //Digital Gain Low [Def: 0x00]
92 
93     {0x2103, 0x03},
94 
95     {0x2104, 0x05},
96     {0x2105, 0x01},
97 
98     {0x2106, 0x54},
99 
100     {0x2108, 0x03},
101     {0x2109, 0x04},
102 
103     {0x210B, 0xC0},
104     {0x210E, 0x00}, //Flicker Control
105     {0x210F, 0x00},
106     {0x2110, 0x3C},
107     {0x2111, 0x00},
108     {0x2112, 0x32},
109 
110     {0x2150, 0x30},
111     {0x0340, 0x02},
112     {0x0341, 0x16},
113     {0x0342, 0x01},
114     {0x0343, 0x78},
115     {0x3010, 0x01},
116     {0x0383, 0x01},
117     {0x0387, 0x01},
118     {0x0390, 0x00},
119     {0x3011, 0x70},
120     {0x3059, 0x02},
121     {0x3060, 0x01},
122 //    {0x3060, 0x25}, //Clock gating and clock divisors
123     {0x3068, 0x20}, //PCLK0 polarity
124     {IMG_ORIENTATION, 0x01}, // change the orientation
125     {0x0104, 0x01},
126     {0x0100, 0x01},
127 	//{0x0601, 0x11}	//Test pattern walking ones
128 	//{0x0601, 0x01}	//Test pattern colour bar
129 };
130 
131 SemaphoreHandle_t  cam_semaphore_rx;
132 static uint8_t cam;
camISR()133 static void camISR() {
134 
135 }
cam_open(uint8_t cam_id)136 void cam_open (uint8_t cam_id)
137 {
138 	int i = 0;
139 	volatile UdmaCtrl_t*		pudma_ctrl = (UdmaCtrl_t*)UDMA_CH_ADDR_CTRL;
140 
141 	/* Enable reset and enable uart clock */
142 	pudma_ctrl->reg_rst |= (UDMA_CTRL_CAM0_CLKEN << cam_id);
143 	pudma_ctrl->reg_rst &= ~(UDMA_CTRL_CAM0_CLKEN << cam_id);
144 	pudma_ctrl->reg_cg |= (UDMA_CTRL_CAM0_CLKEN << cam_id);
145 
146 	//psdio_regs->clk_div_b.clk_div = 5;
147 	//psdio_regs->clk_div_b.valid = 1;
148 	hal_setpinmux(21, 0);
149 	hal_setpinmux(22, 0);
150 	hal_setpinmux(25, 0);
151 	for(i=0; i<8; i++ )
152 	{
153 		//set pin muxes to sdio functionality
154 		 hal_setpinmux(29+i, 0);
155 	}
156 
157 	/* See if already initialized */
158 	if (cam_semaphore_rx != NULL ){
159 		return;
160 	}
161 
162 	/* Set semaphore */
163 	SemaphoreHandle_t shSemaphoreHandle;		// FreeRTOS.h has a define for xSemaphoreHandle, so can't use that
164 	shSemaphoreHandle = xSemaphoreCreateBinary();
165 	configASSERT(shSemaphoreHandle);
166 	xSemaphoreGive(shSemaphoreHandle);
167 	cam_semaphore_rx = shSemaphoreHandle;
168 
169 
170 	/* Set handlers. */
171 	pi_fc_event_handler_set(SOC_EVENT_UDMA_CAM_RX(cam_id), camISR, cam_semaphore_rx);
172 	/* Enable SOC events propagation to FC. */
173 	hal_soc_eu_set_fc_mask(SOC_EVENT_UDMA_CAM_RX(cam_id));
174 
175 	/* configure */
176 	cam = 0x48; // Himax address
177 	udma_cam_control(kCamReset, NULL);
178 
179 	return;
180 }
udma_cam_control(udma_cam_control_type_t control_type,void * pparam)181 uint16_t udma_cam_control(udma_cam_control_type_t control_type, void* pparam) {
182 	short retval = 0;
183 	uint16_t i;
184 	SemaphoreHandle_t shSemaphoreHandle;
185 	camera_struct_t *camera;
186 	//camera = (camera_struct_t *)0x1A102300;  // Peripheral 5?
187 	camera = (camera_struct_t *)(UDMA_CH_ADDR_CAM + 0 * UDMA_CH_SIZE);
188 	shSemaphoreHandle = cam_semaphore_rx;
189 
190 	switch (control_type) {
191 	case kCamReset:
192 		_himaxRegWrite(SW_RESET, HIMAX_RESET);
193 		break;
194 	case kCamID:
195 		udma_i2cm_16read8(0, cam, MODEL_ID_H, 2, &retval, 0);
196 		retval = (retval >> 8) & 0xff | (retval <<8);
197 		break;
198 	case kCamInit:
199 	    for(i=0; i<(sizeof(himaxRegInit)/sizeof(reg_cfg_t)); i++){
200 	        _himaxRegWrite(himaxRegInit[i].addr, himaxRegInit[i].data);
201 	    }
202 	    camera->cfg_ll = 0<<16 | 0;
203 	    	camera->cfg_ur = 323<<16 | 243; // 320 x 240 ?
204 	    	camera->cfg_filter = (1 << 16) | (1 << 8) | 1;
205 	    	camera->cfg_size = 324;
206 	    	camera->vsync_pol = 1;
207 	    	camera->cfg_glob = (0 << 0) | //  framedrop disabled
208 	    			(000000 << 1) | // number of frames to drop
209 	    			(0 << 7) | // Frame slice disabled
210 	    			(004 << 8) | // Format binary 100 = ByPass little endian
211 	    			(0000 << 11);  // Shift value ignored in bypass
212 
213 	    break;
214 	case kCamFrame:
215 		configASSERT( xSemaphoreTake( shSemaphoreHandle, 1000000 ) == pdTRUE );
216 		camera->rx_saddr = pparam;
217 		camera->rx_size = (244*324);
218 		camera->rx_cfg = 0x12;  // start 16-bit transfers
219     	camera->cfg_glob = camera->cfg_glob |
220     			(1 << 31) ; // enable 1 == go
221 
222 		configASSERT( xSemaphoreTake( shSemaphoreHandle, 1000000 ) == pdTRUE );
223     	camera->cfg_glob = camera->cfg_glob &
224     			(0x7fffffff) ; // enable 1 == go
225 		configASSERT( xSemaphoreGive( shSemaphoreHandle ) == pdTRUE );
226 	}
227 	return retval;
228 }
229 
_himaxRegWrite(unsigned int addr,unsigned char value)230 void _himaxRegWrite(unsigned int addr, unsigned char value){
231 	uint8_t naddr;
232 	uint16_t data;
233 	naddr = (addr>>8) & 0xff;
234 	data = (value << 8) | (addr & 0xff);
235 	udma_i2cm_write (0, cam, naddr, 2, &data, 0);
236    //     i2c_16write8(cam,addr,value);
237 }
238 #endif
239