aboutsummaryrefslogtreecommitdiff
path: root/lib/chibios-contrib/ext/mcux-sdk/components/video/camera/device/mt9m114/fsl_mt9m114.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/chibios-contrib/ext/mcux-sdk/components/video/camera/device/mt9m114/fsl_mt9m114.c')
-rw-r--r--lib/chibios-contrib/ext/mcux-sdk/components/video/camera/device/mt9m114/fsl_mt9m114.c397
1 files changed, 397 insertions, 0 deletions
diff --git a/lib/chibios-contrib/ext/mcux-sdk/components/video/camera/device/mt9m114/fsl_mt9m114.c b/lib/chibios-contrib/ext/mcux-sdk/components/video/camera/device/mt9m114/fsl_mt9m114.c
new file mode 100644
index 000000000..c843aff38
--- /dev/null
+++ b/lib/chibios-contrib/ext/mcux-sdk/components/video/camera/device/mt9m114/fsl_mt9m114.c
@@ -0,0 +1,397 @@
1/*
2 * Copyright 2017-2018 NXP
3 * All rights reserved.
4 *
5 *
6 * SPDX-License-Identifier: BSD-3-Clause
7 */
8
9#include "fsl_video_common.h"
10#include "fsl_camera.h"
11#include "fsl_camera_device.h"
12#include "fsl_mt9m114.h"
13
14/*******************************************************************************
15 * Definitions
16 ******************************************************************************/
17
18#define MT9M114_DelayMs(ms) VIDEO_DelayMs(ms)
19#define MT9M114_Write(handle, reg, size, value) \
20 VIDEO_I2C_WriteReg(MT9M114_I2C_ADDR, kVIDEO_RegAddr16Bit, (reg), (video_reg_width_t)(size), (value), \
21 ((mt9m114_resource_t *)((handle)->resource))->i2cSendFunc)
22#define MT9M114_Read(handle, reg, size, value) \
23 VIDEO_I2C_ReadReg(MT9M114_I2C_ADDR, kVIDEO_RegAddr16Bit, (reg), (video_reg_width_t)(size), (value), \
24 ((mt9m114_resource_t *)((handle)->resource))->i2cReceiveFunc)
25#define MT9M114_Modify(handle, reg, size, clrMask, value) \
26 VIDEO_I2C_ModifyReg(MT9M114_I2C_ADDR, kVIDEO_RegAddr16Bit, (reg), (video_reg_width_t)(size), (clrMask), (value), \
27 ((mt9m114_resource_t *)((handle)->resource))->i2cReceiveFunc, \
28 ((mt9m114_resource_t *)((handle)->resource))->i2cSendFunc)
29
30typedef struct _mt9m114_reg
31{
32 uint16_t reg;
33 uint8_t size;
34 uint32_t value;
35} mt9m114_reg_t;
36
37/*******************************************************************************
38 * Prototypes
39 ******************************************************************************/
40status_t MT9M114_Init(camera_device_handle_t *handle, const camera_config_t *config);
41status_t MT9M114_Deinit(camera_device_handle_t *handle);
42status_t MT9M114_Start(camera_device_handle_t *handle);
43status_t MT9M114_Stop(camera_device_handle_t *handle);
44status_t MT9M114_Control(camera_device_handle_t *handle, camera_device_cmd_t cmd, int32_t arg);
45status_t MT9M114_InitExt(camera_device_handle_t *handle, const camera_config_t *config, const void *specialConfig);
46
47/*******************************************************************************
48 * Variables
49 ******************************************************************************/
50const camera_device_operations_t mt9m114_ops = {
51 .init = MT9M114_Init,
52 .deinit = MT9M114_Deinit,
53 .start = MT9M114_Start,
54 .stop = MT9M114_Stop,
55 .control = MT9M114_Control,
56 .init_ext = MT9M114_InitExt,
57};
58
59static const mt9m114_reg_t mt9m114_720p[] = {
60 {MT9M114_VAR_CAM_SENSOR_CFG_Y_ADDR_START, 2, 0x007C}, /* cam_sensor_cfg_y_addr_start = 124 */
61 {MT9M114_VAR_CAM_SENSOR_CFG_X_ADDR_START, 2, 0x0004}, /* cam_sensor_cfg_x_addr_start = 4 */
62 {MT9M114_VAR_CAM_SENSOR_CFG_Y_ADDR_END, 2, 0x0353}, /* cam_sensor_cfg_y_addr_end = 851 */
63 {MT9M114_VAR_CAM_SENSOR_CFG_X_ADDR_END, 2, 0x050B}, /* cam_sensor_cfg_x_addr_end = 1291 */
64 {MT9M114_VAR_CAM_SENSOR_CFG_CPIPE_LAST_ROW, 2, 0x02D3}, /* cam_sensor_cfg_cpipe_last_row = 723 */
65 {MT9M114_VAR_CAM_CROP_WINDOW_WIDTH, 2, 0x0500}, /* cam_crop_window_width = 1280 */
66 {MT9M114_VAR_CAM_CROP_WINDOW_HEIGHT, 2, 0x02D0}, /* cam_crop_window_height = 720 */
67 {MT9M114_VAR_CAM_OUTPUT_WIDTH, 2, 0x0500}, /* cam_output_width = 1280 */
68 {MT9M114_VAR_CAM_OUTPUT_HEIGHT, 2, 0x02D0}, /* cam_output_height = 720 */
69 {MT9M114_VAR_CAM_STAT_AWB_CLIP_WINDOW_XEND, 2, 0x04FF}, /* cam_stat_awb_clip_window_xend = 1279 */
70 {MT9M114_VAR_CAM_STAT_AWB_CLIP_WINDOW_YEND, 2, 0x02CF}, /* cam_stat_awb_clip_window_yend = 719 */
71 {MT9M114_VAR_CAM_STAT_AE_INITIAL_WINDOW_XEND, 2, 0x00FF}, /* cam_stat_ae_initial_window_xend = 255 */
72 {MT9M114_VAR_CAM_STAT_AE_INITIAL_WINDOW_YEND, 2, 0x008F}, /* cam_stat_ae_initial_window_yend = 143 */
73};
74
75static const mt9m114_reg_t mt9m114_480_272[] = {
76 {MT9M114_VAR_CAM_SENSOR_CFG_Y_ADDR_START, 2, 0x00D4}, /* cam_sensor_cfg_y_addr_start = 212 */
77 {MT9M114_VAR_CAM_SENSOR_CFG_X_ADDR_START, 2, 0x00A4}, /* cam_sensor_cfg_x_addr_start = 164 */
78 {MT9M114_VAR_CAM_SENSOR_CFG_Y_ADDR_END, 2, 0x02FB}, /* cam_sensor_cfg_y_addr_end = 763 */
79 {MT9M114_VAR_CAM_SENSOR_CFG_X_ADDR_END, 2, 0x046B}, /* cam_sensor_cfg_x_addr_end = 1131 */
80 {MT9M114_VAR_CAM_SENSOR_CFG_CPIPE_LAST_ROW, 2, 0x0223}, /* cam_sensor_cfg_cpipe_last_row = 547 */
81 {MT9M114_VAR_CAM_CROP_WINDOW_WIDTH, 2, 0x03C0}, /* cam_crop_window_width = 960 */
82 {MT9M114_VAR_CAM_CROP_WINDOW_HEIGHT, 2, 0x0220}, /* cam_crop_window_height = 544 */
83 {MT9M114_VAR_CAM_OUTPUT_WIDTH, 2, 0x01E0}, /* cam_output_width = 480 */
84 {MT9M114_VAR_CAM_OUTPUT_HEIGHT, 2, 0x0110}, /* cam_output_height = 272 */
85 {MT9M114_VAR_CAM_STAT_AWB_CLIP_WINDOW_XEND, 2, 0x01DF}, /* cam_stat_awb_clip_window_xend = 479 */
86 {MT9M114_VAR_CAM_STAT_AWB_CLIP_WINDOW_YEND, 2, 0x010F}, /* cam_stat_awb_clip_window_yend = 271 */
87 {MT9M114_VAR_CAM_STAT_AE_INITIAL_WINDOW_XEND, 2, 0x005F}, /* cam_stat_ae_initial_window_xend = 95 */
88 {MT9M114_VAR_CAM_STAT_AE_INITIAL_WINDOW_YEND, 2, 0x0035}, /* cam_stat_ae_initial_window_yend = 53 */
89};
90
91static const mt9m114_reg_t mt9m114InitConfig[] = {
92 {MT9M114_REG_LOGICAL_ADDRESS_ACCESS, 2u, 0x1000},
93 /* PLL Fout = (Fin * 2 * m) / ((n + 1) * (p + 1)) */
94 {MT9M114_VAR_CAM_SYSCTL_PLL_ENABLE, 1u, 0x01}, /* cam_sysctl_pll_enable = 1 */
95 {MT9M114_VAR_CAM_SYSCTL_PLL_DIVIDER_M_N, 2u, 0x0120}, /* cam_sysctl_pll_divider_m_n = 288 */
96 {MT9M114_VAR_CAM_SYSCTL_PLL_DIVIDER_P, 2u, 0x0700}, /* cam_sysctl_pll_divider_p = 1792 */
97 {MT9M114_VAR_CAM_SENSOR_CFG_PIXCLK, 4u, 0x2DC6C00}, /* cam_sensor_cfg_pixclk = 48000000 */
98 {0x316A, 2, 0x8270}, /* auto txlo_row for hot pixel and linear full well optimization */
99 {0x316C, 2, 0x8270}, /* auto txlo for hot pixel and linear full well optimization */
100 {0x3ED0, 2, 0x2305}, /* eclipse setting, ecl range=1, ecl value=2, ivln=3 */
101 {0x3ED2, 2, 0x77CF}, /* TX_hi=12 */
102 {0x316E, 2, 0x8202}, /* auto ecl , threshold 2x, ecl=0 at high gain, ecl=2 for low gain */
103 {0x3180, 2, 0x87FF}, /* enable delta dark */
104 {0x30D4, 2, 0x6080}, /* disable column correction due to AE oscillation problem */
105 {0xA802, 2, 0x0008}, /* RESERVED_AE_TRACK_02 */
106 {0x3E14, 2, 0xFF39}, /* Enabling pixout clamping to VAA during ADC streaming to solve column band issue */
107 {MT9M114_VAR_CAM_SENSOR_CFG_ROW_SPEED, 2u, 0x0001}, /* cam_sensor_cfg_row_speed = 1 */
108 {MT9M114_VAR_CAM_SENSOR_CFG_FINE_INTEG_TIME_MIN, 2u, 0x00DB}, /* cam_sensor_cfg_fine_integ_time_min = 219 */
109 {MT9M114_VAR_CAM_SENSOR_CFG_FINE_INTEG_TIME_MAX, 2u, 0x07C2}, /* cam_sensor_cfg_fine_integ_time_max = 1986 */
110 {MT9M114_VAR_CAM_SENSOR_CFG_FRAME_LENGTH_LINES, 2u, 0x02FE}, /* cam_sensor_cfg_frame_length_lines = 766 */
111 {MT9M114_VAR_CAM_SENSOR_CFG_LINE_LENGTH_PCK, 2u, 0x0845}, /* cam_sensor_cfg_line_length_pck = 2117 */
112 {MT9M114_VAR_CAM_SENSOR_CFG_FINE_CORRECTION, 2u, 0x0060}, /* cam_sensor_cfg_fine_correction = 96 */
113 {MT9M114_VAR_CAM_SENSOR_CFG_REG_0_DATA, 2u, 0x0020}, /* cam_sensor_cfg_reg_0_data = 32 */
114 {MT9M114_VAR_CAM_SENSOR_CONTROL_READ_MODE, 2u, 0x0000}, /* cam_sensor_control_read_mode = 0 */
115 {MT9M114_VAR_CAM_CROP_WINDOW_XOFFSET, 2u, 0x0000}, /* cam_crop_window_xoffset = 0 */
116 {MT9M114_VAR_CAM_CROP_WINDOW_YOFFSET, 2u, 0x0000}, /* cam_crop_window_yoffset = 0 */
117 {MT9M114_VAR_CAM_CROP_CROPMODE, 1u, 0x03}, /* cam_crop_cropmode = 3 */
118 {MT9M114_VAR_CAM_AET_AEMODE, 1u, 0x00}, /* cam_aet_aemode = 0 */
119 {MT9M114_VAR_CAM_AET_MAX_FRAME_RATE, 2u, 0x1D9A}, /* cam_aet_max_frame_rate = 7578 */
120 {MT9M114_VAR_CAM_AET_MIN_FRAME_RATE, 2u, 0x1D9A}, /* cam_aet_min_frame_rate = 7578 */
121 {MT9M114_VAR_CAM_STAT_AWB_CLIP_WINDOW_XSTART, 2u, 0x0000}, /* cam_stat_awb_clip_window_xstart = 0 */
122 {MT9M114_VAR_CAM_STAT_AWB_CLIP_WINDOW_YSTART, 2u, 0x0000}, /* cam_stat_awb_clip_window_ystart = 0 */
123 {MT9M114_VAR_CAM_STAT_AE_INITIAL_WINDOW_XSTART, 2u, 0x0000}, /* cam_stat_ae_initial_window_xstart = 0 */
124 {MT9M114_VAR_CAM_STAT_AE_INITIAL_WINDOW_YSTART, 2u, 0x0000}, /* cam_stat_ae_initial_window_ystart = 0 */
125 {MT9M114_REG_PAD_SLEW, 2u, 0x0777}, /* Pad slew rate */
126 {MT9M114_VAR_CAM_OUTPUT_FORMAT_YUV, 2u, 0x0038}, /* Must set cam_output_format_yuv_clip for CSI */
127};
128
129/*******************************************************************************
130 * Code
131 ******************************************************************************/
132
133static status_t MT9M114_MultiWrite(camera_device_handle_t *handle, const mt9m114_reg_t regs[], uint32_t num)
134{
135 status_t status = kStatus_Success;
136
137 for (uint32_t i = 0; i < num; i++)
138 {
139 status = MT9M114_Write(handle, regs[i].reg, regs[i].size, regs[i].value);
140
141 if (kStatus_Success != status)
142 {
143 break;
144 }
145 }
146
147 return status;
148}
149
150static status_t MT9M114_SoftwareReset(camera_device_handle_t *handle)
151{
152 status_t status;
153
154 status = MT9M114_Modify(handle, MT9M114_REG_RESET_AND_MISC_CONTROL, 2u, 0x01, 0x01);
155 if (kStatus_Success != status)
156 {
157 return status;
158 }
159
160 MT9M114_DelayMs(1);
161
162 status = MT9M114_Modify(handle, MT9M114_REG_RESET_AND_MISC_CONTROL, 2u, 0x01, 0x00);
163 if (kStatus_Success != status)
164 {
165 return status;
166 }
167
168 MT9M114_DelayMs(45);
169
170 return kStatus_Success;
171}
172
173/*
174 * Set state, the parameter nextState could be
175 *
176 * MT9M114_SYS_STATE_ENTER_CONFIG_CHANGE
177 * MT9M114_SYS_STATE_START_STREAMING
178 * MT9M114_SYS_STATE_ENTER_SUSPEND
179 * MT9M114_SYS_STATE_ENTER_STANDBY
180 * MT9M114_SYS_STATE_LEAVE_STANDBY
181 */
182static status_t MT9M114_SetState(camera_device_handle_t *handle, uint16_t nextState)
183{
184 status_t status;
185 uint16_t value = 0U;
186
187 /* Set the desired next state. */
188 status = MT9M114_Write(handle, MT9M114_VAR_SYSMGR_NEXT_STATE, 1u, nextState);
189 if (kStatus_Success != status)
190 {
191 return status;
192 }
193
194 /* Check that the FW is ready to accept a new command. */
195 while (true)
196 {
197 status = MT9M114_Read(handle, MT9M114_REG_COMMAND_REGISTER, 2u, &value);
198 if (kStatus_Success != status)
199 {
200 return status;
201 }
202
203 if (0U == (value & MT9M114_COMMAND_SET_STATE))
204 {
205 break;
206 }
207 }
208
209 /* Issue the Set State command. */
210 status = MT9M114_Write(handle, MT9M114_REG_COMMAND_REGISTER, 2u, MT9M114_COMMAND_SET_STATE | MT9M114_COMMAND_OK);
211 if (kStatus_Success != status)
212 {
213 return status;
214 }
215
216 /* Wait for the FW to complete the command. */
217 while (true)
218 {
219 MT9M114_DelayMs(1);
220 status = MT9M114_Read(handle, MT9M114_REG_COMMAND_REGISTER, 2u, &value);
221 if (kStatus_Success != status)
222 {
223 return status;
224 }
225
226 if (0U == (value & MT9M114_COMMAND_SET_STATE))
227 {
228 break;
229 }
230 }
231
232 /* Check the 'OK' bit to see if the command was successful. */
233 status = MT9M114_Read(handle, MT9M114_REG_COMMAND_REGISTER, 2u, &value);
234 if (kStatus_Success != status)
235 {
236 return status;
237 }
238
239 if (0U == (value & MT9M114_COMMAND_OK))
240 {
241 return kStatus_Fail;
242 }
243
244 return kStatus_Success;
245}
246
247status_t MT9M114_Init(camera_device_handle_t *handle, const camera_config_t *config)
248{
249 status_t status;
250 uint16_t chip_id = 0;
251 uint16_t outputFormat = 0;
252
253 mt9m114_resource_t *resource = (mt9m114_resource_t *)(handle->resource);
254
255 if ((kCAMERA_InterfaceGatedClock != config->interface) && (kCAMERA_InterfaceNonGatedClock != config->interface) &&
256 (kCAMERA_InterfaceCCIR656 != config->interface))
257 {
258 return kStatus_InvalidArgument;
259 }
260
261 /* Only support 480 * 272 and 720P. */
262 if (((uint32_t)kVIDEO_Resolution720P != config->resolution) &&
263 (FSL_VIDEO_RESOLUTION(480, 272) != config->resolution))
264 {
265 return kStatus_InvalidArgument;
266 }
267
268 /* Only support 30 fps now. */
269 if (30U != config->framePerSec)
270 {
271 return kStatus_InvalidArgument;
272 }
273
274 /* Only support RGB565 and YUV422 */
275 if ((kVIDEO_PixelFormatRGB565 != config->pixelFormat) && (kVIDEO_PixelFormatYUYV != config->pixelFormat))
276 {
277 return kStatus_InvalidArgument;
278 }
279
280 /* The input clock (EXTCLK) must be 24MHz. */
281 if (24000000U != resource->inputClockFreq_Hz)
282 {
283 return kStatus_InvalidArgument;
284 }
285
286 /* Polarity check */
287 if (config->controlFlags !=
288 ((uint32_t)kCAMERA_HrefActiveHigh | (uint32_t)kCAMERA_DataLatchOnRisingEdge | (uint32_t)kCAMERA_VsyncActiveLow))
289 {
290 return kStatus_InvalidArgument;
291 }
292
293 resource->pullResetPin(false); /* Reset pin low. */
294 MT9M114_DelayMs(50); /* Delay at least 50 ms. */
295 resource->pullResetPin(true); /* Reset pin high. */
296 MT9M114_DelayMs(45); /* Delay typically 44.5 ms. */
297
298 /* Identify the device. */
299 status = MT9M114_Read(handle, MT9M114_REG_CHIP_ID, 2u, &chip_id);
300 if (kStatus_Success != status)
301 {
302 return status;
303 }
304 if (MT9M114_CHIP_ID != chip_id)
305 {
306 return kStatus_Fail;
307 }
308
309 /* SW reset. */
310 status = MT9M114_SoftwareReset(handle);
311 if (kStatus_Success != status)
312 {
313 return status;
314 }
315
316 status = MT9M114_MultiWrite(handle, mt9m114InitConfig, ARRAY_SIZE(mt9m114InitConfig));
317 if (kStatus_Success != status)
318 {
319 return status;
320 }
321
322 /* Pixel format. */
323 if (kVIDEO_PixelFormatRGB565 == config->pixelFormat)
324 {
325 outputFormat |= ((1U << 8U) | (1U << 1U));
326 }
327
328 if (kCAMERA_InterfaceCCIR656 == config->interface)
329 {
330 outputFormat |= (1U << 3U);
331 }
332
333 status = MT9M114_Write(handle, MT9M114_VAR_CAM_OUTPUT_FORMAT, 2, outputFormat);
334 if (kStatus_Success != status)
335 {
336 return status;
337 }
338
339 if (kCAMERA_InterfaceNonGatedClock == config->interface)
340 {
341 status = MT9M114_Write(handle, MT9M114_VAR_CAM_PORT_OUTPUT_CONTROL, 2, 0x8020);
342 }
343 else
344 {
345 status = MT9M114_Write(handle, MT9M114_VAR_CAM_PORT_OUTPUT_CONTROL, 2, 0x8000);
346 }
347
348 if (kStatus_Success != status)
349 {
350 return status;
351 }
352
353 /* Resolution */
354 if (config->resolution == FSL_VIDEO_RESOLUTION(480, 272))
355 {
356 status = MT9M114_MultiWrite(handle, mt9m114_480_272, ARRAY_SIZE(mt9m114_480_272));
357 }
358 else
359 {
360 status = MT9M114_MultiWrite(handle, mt9m114_720p, ARRAY_SIZE(mt9m114_720p));
361 }
362
363 if (kStatus_Success != status)
364 {
365 return status;
366 }
367
368 /* Execute Change-Config command. */
369 return MT9M114_SetState(handle, MT9M114_SYS_STATE_ENTER_CONFIG_CHANGE);
370}
371
372status_t MT9M114_Deinit(camera_device_handle_t *handle)
373{
374 ((mt9m114_resource_t *)(handle->resource))->pullResetPin(false);
375
376 return kStatus_Success;
377}
378
379status_t MT9M114_Start(camera_device_handle_t *handle)
380{
381 return MT9M114_SetState(handle, MT9M114_SYS_STATE_START_STREAMING);
382}
383
384status_t MT9M114_Stop(camera_device_handle_t *handle)
385{
386 return MT9M114_SetState(handle, MT9M114_SYS_STATE_ENTER_SUSPEND);
387}
388
389status_t MT9M114_Control(camera_device_handle_t *handle, camera_device_cmd_t cmd, int32_t arg)
390{
391 return kStatus_InvalidArgument;
392}
393
394status_t MT9M114_InitExt(camera_device_handle_t *handle, const camera_config_t *config, const void *specialConfig)
395{
396 return MT9M114_Init(handle, config);
397}