drv_ccap.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488
  1. /**************************************************************************//**
  2. *
  3. * @copyright (C) 2019 Nuvoton Technology Corp. All rights reserved.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0
  6. *
  7. * Change Logs:
  8. * Date Author Notes
  9. * 2022-8-16 Wayne First version
  10. *
  11. ******************************************************************************/
  12. #include <rtconfig.h>
  13. #if defined(BSP_USING_CCAP)
  14. #include <rthw.h>
  15. #include "NuMicro.h"
  16. #include "ccap_sensor.h"
  17. #include "drv_ccap.h"
  18. #define LOG_TAG "drv.ccap"
  19. #define DBG_ENABLE
  20. #define DBG_SECTION_NAME LOG_TAG
  21. #define DBG_LEVEL LOG_LVL_INFO
  22. #define DBG_COLOR
  23. #include <rtdbg.h>
  24. /* Private Typedef --------------------------------------------------------------*/
  25. enum
  26. {
  27. CCAP_START = -1,
  28. #if defined(BSP_USING_CCAP0)
  29. CCAP0_IDX,
  30. #endif
  31. CCAP_CNT
  32. };
  33. struct nu_ccap
  34. {
  35. struct rt_device device;
  36. char *name;
  37. CCAP_T *base;
  38. uint32_t rstidx;
  39. uint32_t modid_ccap;
  40. uint32_t modid_sensor;
  41. IRQn_Type irqn;
  42. ccap_config sConfig;
  43. };
  44. typedef struct nu_ccap *nu_ccap_t;
  45. static struct nu_ccap nu_ccap_arr [] =
  46. {
  47. #if defined(BSP_USING_CCAP0)
  48. {
  49. .name = "ccap0",
  50. .base = CCAP,
  51. .rstidx = CCAP_RST,
  52. .modid_ccap = CCAP_MODULE,
  53. .modid_sensor = SEN_MODULE,
  54. .irqn = CCAP_IRQn,
  55. },
  56. #endif
  57. };
  58. static void nu_ccap_isr(nu_ccap_t ccap)
  59. {
  60. CCAP_T *base = ccap->base;
  61. uint32_t u32CapInt, u32EvtMsk;
  62. u32CapInt = base->INT;
  63. u32EvtMsk = 0;
  64. if ((u32CapInt & (CCAP_INT_VIEN_Msk | CCAP_INT_VINTF_Msk)) == (CCAP_INT_VIEN_Msk | CCAP_INT_VINTF_Msk))
  65. {
  66. base->INT |= CCAP_INT_VINTF_Msk; /* Clear Frame end interrupt */
  67. u32EvtMsk |= NU_CCAP_FRAME_END;
  68. }
  69. if ((u32CapInt & (CCAP_INT_ADDRMIEN_Msk | CCAP_INT_ADDRMINTF_Msk)) == (CCAP_INT_ADDRMIEN_Msk | CCAP_INT_ADDRMINTF_Msk))
  70. {
  71. base->INT |= CCAP_INT_ADDRMINTF_Msk; /* Clear Address match interrupt */
  72. u32EvtMsk |= NU_CCAP_ADDRESS_MATCH;
  73. }
  74. if ((u32CapInt & (CCAP_INT_MEIEN_Msk | CCAP_INT_MEINTF_Msk)) == (CCAP_INT_MEIEN_Msk | CCAP_INT_MEINTF_Msk))
  75. {
  76. base->INT |= CCAP_INT_MEINTF_Msk; /* Clear Memory error interrupt */
  77. u32EvtMsk |= NU_CCAP_MEMORY_ERROR;
  78. }
  79. /* Invoke callback */
  80. if (ccap->device.rx_indicate != RT_NULL)
  81. ccap->device.rx_indicate(&ccap->device, 1);
  82. if (ccap->sConfig.pfnEvHndler && u32EvtMsk)
  83. ccap->sConfig.pfnEvHndler(ccap->sConfig.pvData, u32EvtMsk);
  84. base->CTL = base->CTL | CCAP_CTL_UPDATE;
  85. }
  86. #if defined(BSP_USING_CCAP0)
  87. /* CCAP interrupt entry */
  88. void CCAP_IRQHandler(void)
  89. {
  90. /* enter interrupt */
  91. rt_interrupt_enter();
  92. nu_ccap_isr(&nu_ccap_arr[CCAP0_IDX]);
  93. /* leave interrupt */
  94. rt_interrupt_leave();
  95. }
  96. #endif
  97. /* common device interface */
  98. static rt_err_t ccap_init(rt_device_t dev)
  99. {
  100. return RT_EOK;
  101. }
  102. static void ccap_sensor_setfreq(nu_ccap_t psNuCcap, uint32_t u32SensorFreq)
  103. {
  104. uint32_t u32RegLockLevel = SYS_IsRegLocked();
  105. /* Unlock protected registers */
  106. if (u32RegLockLevel)
  107. SYS_UnlockReg();
  108. if (u32SensorFreq > 0)
  109. {
  110. int32_t i32Div;
  111. /* Specified sensor clock */
  112. i32Div = CLK_GetHCLKFreq() / u32SensorFreq;
  113. if (i32Div == 0)
  114. i32Div = 1;
  115. CLK_EnableModuleClock(psNuCcap->modid_ccap);
  116. CLK_SetModuleClock(psNuCcap->modid_ccap, CLK_CLKSEL0_CCAPSEL_HCLK, MODULE_NoMsk);
  117. CLK_EnableModuleClock(psNuCcap->modid_sensor);
  118. CLK_SetModuleClock(psNuCcap->modid_sensor, MODULE_NoMsk, CLK_CLKDIV3_VSENSE(i32Div));
  119. LOG_I("CCAP Engine clock:%d", CLK_GetHCLKFreq());
  120. LOG_I("CCAP Sensor preferred clock %d, divider:%d", u32SensorFreq, i32Div);
  121. LOG_I("CCAP Sensor actully clock:%d", CLK_GetHCLKFreq() / i32Div);
  122. }
  123. else
  124. {
  125. CLK_DisableModuleClock(psNuCcap->modid_ccap);
  126. CLK_DisableModuleClock(psNuCcap->modid_sensor);
  127. }
  128. /* Lock protected registers */
  129. if (u32RegLockLevel)
  130. SYS_LockReg();
  131. }
  132. static rt_err_t ccap_pipe_configure(nu_ccap_t psNuCcap, ccap_view_info_t psViewInfo)
  133. {
  134. sensor_mode_info_t psSensorModeInfo = (sensor_mode_info_t)psViewInfo;
  135. ccap_config_t psCcapConf = &psNuCcap->sConfig;
  136. uint32_t u32PipeEnabling = 0;
  137. struct rt_device_rect_info *psRectCropping = &psCcapConf->sRectCropping;
  138. /* Set Cropping Window Vertical/Horizontal Starting Address and Cropping Window Size */
  139. CCAP_SetCroppingWindow(psNuCcap->base, psRectCropping->y, psRectCropping->x, psRectCropping->height, psRectCropping->width);
  140. if (psCcapConf->sPipeInfo_Packet.pu8FarmAddr)
  141. {
  142. uint32_t u32WM, u32WN, u32HM, u32HN;
  143. /* Set System Memory Packet Base Address Register */
  144. CCAP_SetPacketBuf(psNuCcap->base, (uint32_t)psCcapConf->sPipeInfo_Packet.pu8FarmAddr);
  145. u32WM = u32WN = u32HM = u32HN = 0;
  146. /* Set Packet Scaling Vertical/Horizontal Factor Register */
  147. if (psCcapConf->sPipeInfo_Packet.u32Height < psRectCropping->height)
  148. {
  149. u32HN = psCcapConf->sPipeInfo_Packet.u32Height;
  150. u32HM = psRectCropping->height;
  151. }
  152. if (psCcapConf->sPipeInfo_Packet.u32Width < psRectCropping->width)
  153. {
  154. u32WN = psCcapConf->sPipeInfo_Packet.u32Width;
  155. u32WM = psRectCropping->width;
  156. }
  157. CCAP_SetPacketScaling(psNuCcap->base,
  158. u32HN,
  159. u32HM,
  160. u32WN,
  161. u32WM);
  162. /* Set Packet Frame Output Pixel Stride Width */
  163. CCAP_SetPacketStride(psNuCcap->base, psCcapConf->u32Stride_Packet);
  164. u32PipeEnabling |= CCAP_CTL_PKTEN;
  165. }
  166. if (psCcapConf->sPipeInfo_Planar.pu8FarmAddr)
  167. {
  168. uint32_t u32Offset = 0;
  169. uint32_t u32WM, u32WN, u32HM, u32HN;
  170. uint32_t u32Div = 0;
  171. if (psCcapConf->sPipeInfo_Planar.u32PixFmt == CCAP_PAR_PLNFMT_YUV422)
  172. {
  173. /* U/V farm size equals Y/2 farm size */
  174. u32Div = 2;
  175. }
  176. else if (psCcapConf->sPipeInfo_Planar.u32PixFmt == CCAP_PAR_PLNFMT_YUV420)
  177. {
  178. /* U/V farm size equals Y/4 farm size */
  179. u32Div = 4;
  180. }
  181. else
  182. {
  183. goto fail_ccap_pipe_configure;
  184. }
  185. /* Set System Memory Planar Y Base Address Register */
  186. CCAP_SetPlanarYBuf(psNuCcap->base, (uint32_t)psCcapConf->sPipeInfo_Planar.pu8FarmAddr + u32Offset);
  187. u32Offset = psCcapConf->sPipeInfo_Planar.u32Height * psCcapConf->sPipeInfo_Planar.u32Width;
  188. /* Set System Memory Planar U Base Address Register */
  189. CCAP_SetPlanarUBuf(psNuCcap->base, (uint32_t)psCcapConf->sPipeInfo_Planar.pu8FarmAddr + u32Offset);
  190. u32Offset += ((psCcapConf->sPipeInfo_Planar.u32Height * psCcapConf->sPipeInfo_Planar.u32Width) / u32Div);
  191. /* Set System Memory Planar V Base Address Register */
  192. CCAP_SetPlanarVBuf(psNuCcap->base, (uint32_t)psCcapConf->sPipeInfo_Planar.pu8FarmAddr + u32Offset);
  193. u32WM = u32WN = u32HM = u32HN = 0;
  194. /* Set Planar Scaling Vertical/Horizontal Factor Register */
  195. if (psCcapConf->sPipeInfo_Planar.u32Height < psRectCropping->height)
  196. {
  197. u32HN = psCcapConf->sPipeInfo_Planar.u32Height;
  198. u32HM = psRectCropping->height;
  199. }
  200. if (psCcapConf->sPipeInfo_Planar.u32Width < psRectCropping->width)
  201. {
  202. u32WN = psCcapConf->sPipeInfo_Planar.u32Width;
  203. u32WM = psRectCropping->width;
  204. }
  205. /* Set Planar Scaling Vertical/Horizontal Factor Register */
  206. CCAP_SetPlanarScaling(psNuCcap->base,
  207. u32HN,
  208. u32HM,
  209. u32WN,
  210. u32WM);
  211. /* Set Planar Frame Output Pixel Stride Width */
  212. CCAP_SetPlanarStride(psNuCcap->base, psCcapConf->u32Stride_Planar);
  213. u32PipeEnabling |= CCAP_CTL_PLNEN;
  214. }
  215. /* Set Vsync polarity, Hsync polarity, pixel clock polarity, Sensor Format and Order */
  216. CCAP_Open(psNuCcap->base,
  217. psSensorModeInfo->u32Polarity |
  218. psViewInfo->u32PixFmt |
  219. psCcapConf->sPipeInfo_Packet.u32PixFmt |
  220. psCcapConf->sPipeInfo_Planar.u32PixFmt,
  221. u32PipeEnabling);
  222. return RT_EOK;
  223. fail_ccap_pipe_configure:
  224. return -RT_ERROR;
  225. }
  226. static rt_err_t ccap_open(rt_device_t dev, rt_uint16_t oflag)
  227. {
  228. nu_ccap_t psNuCcap = (nu_ccap_t)dev;
  229. uint32_t u32RegLockLevel = SYS_IsRegLocked();
  230. /* Unlock protected registers */
  231. if (u32RegLockLevel)
  232. SYS_UnlockReg();
  233. /* Enable clock */
  234. ccap_sensor_setfreq(psNuCcap, 24000000);
  235. /* Reset IP */
  236. SYS_ResetModule(psNuCcap->rstidx);
  237. /* Lock protected registers */
  238. if (u32RegLockLevel)
  239. SYS_LockReg();
  240. /* Unmask External CCAP Interrupt */
  241. NVIC_EnableIRQ(psNuCcap->irqn);
  242. return RT_EOK;
  243. }
  244. static rt_err_t ccap_close(rt_device_t dev)
  245. {
  246. nu_ccap_t psNuCcap = (nu_ccap_t)dev;
  247. /* Stop capture engine */
  248. CCAP_Stop(psNuCcap->base, FALSE);
  249. /* Disable CCAP Interrupt */
  250. CCAP_DisableInt(psNuCcap->base, CCAP_INT_VIEN_Msk);
  251. /* Mask External CCAP Interrupt */
  252. NVIC_DisableIRQ(psNuCcap->irqn);
  253. /* Disable clock */
  254. ccap_sensor_setfreq(psNuCcap, 0);
  255. return RT_EOK;
  256. }
  257. static rt_err_t ccap_control(rt_device_t dev, int cmd, void *args)
  258. {
  259. nu_ccap_t psNuCcap = (nu_ccap_t)dev;
  260. rt_err_t ret = -RT_ERROR;
  261. if (psNuCcap == RT_NULL)
  262. goto exit_ccap_control;
  263. switch (cmd)
  264. {
  265. case CCAP_CMD_CONFIG:
  266. {
  267. ccap_config *psCcapConf = (ccap_config *)args;
  268. if (args == RT_NULL)
  269. goto exit_ccap_control;
  270. rt_memcpy(&psNuCcap->sConfig, psCcapConf, sizeof(ccap_config));
  271. }
  272. break;
  273. case CCAP_CMD_START_CAPTURE:
  274. /* Enable CCAP Interrupt */
  275. CCAP_EnableInt(psNuCcap->base, CCAP_INT_VIEN_Msk);
  276. /* Start capture engine */
  277. CCAP_Start(psNuCcap->base);
  278. break;
  279. case CCAP_CMD_STOP_CAPTURE:
  280. /* Disable CCAP Interrupt */
  281. CCAP_DisableInt(psNuCcap->base, CCAP_INT_VIEN_Msk);
  282. /* Stop capture engine */
  283. CCAP_Stop(psNuCcap->base, FALSE);
  284. break;
  285. case CCAP_CMD_SET_SENCLK:
  286. {
  287. rt_uint32_t u32SenClk;
  288. RT_ASSERT(args);
  289. u32SenClk = *((rt_uint32_t *)args);
  290. if (u32SenClk > 0)
  291. ccap_sensor_setfreq(psNuCcap, u32SenClk);
  292. }
  293. break;
  294. case CCAP_CMD_SET_PIPES:
  295. {
  296. ccap_view_info_t psViewInfo;
  297. RT_ASSERT(args);
  298. psViewInfo = (ccap_view_info_t)args;
  299. ret = ccap_pipe_configure(psNuCcap, psViewInfo);
  300. }
  301. break;
  302. case CCAP_CMD_SET_OPMODE:
  303. {
  304. RT_ASSERT(args);
  305. int i32IsOneSutterMode = *((int *)args);
  306. /* Set shutter or continuous mode */
  307. CCAP_SET_CTL(psNuCcap->base, (i32IsOneSutterMode > 0) ? CCAP_CTL_SHUTTER_Msk : 0);
  308. }
  309. break;
  310. case CCAP_CMD_SET_BASEADDR:
  311. {
  312. uint32_t u32Offset = 0;
  313. ccap_config_t psCcapConf;
  314. RT_ASSERT(args);
  315. psCcapConf = (ccap_config_t)args;
  316. /* Set System Memory Packet Base Address Register */
  317. CCAP_SetPacketBuf(psNuCcap->base, (uint32_t)psCcapConf->sPipeInfo_Packet.pu8FarmAddr);
  318. /* Set System Memory Planar Y Base Address Register */
  319. CCAP_SetPlanarYBuf(psNuCcap->base, (uint32_t)psCcapConf->sPipeInfo_Planar.pu8FarmAddr + u32Offset);
  320. u32Offset = psCcapConf->sPipeInfo_Planar.u32Height * psCcapConf->sPipeInfo_Planar.u32Width;
  321. /* Set System Memory Planar U Base Address Register */
  322. CCAP_SetPlanarUBuf(psNuCcap->base, (uint32_t)psCcapConf->sPipeInfo_Planar.pu8FarmAddr + u32Offset);
  323. u32Offset += ((psCcapConf->sPipeInfo_Planar.u32Height * psCcapConf->sPipeInfo_Planar.u32Width) / 2);
  324. /* Set System Memory Planar V Base Address Register */
  325. CCAP_SetPlanarVBuf(psNuCcap->base, (uint32_t)psCcapConf->sPipeInfo_Planar.pu8FarmAddr + u32Offset);
  326. }
  327. break;
  328. default:
  329. return -RT_ENOSYS;
  330. }
  331. ret = RT_EOK;
  332. exit_ccap_control:
  333. return ret;
  334. }
  335. #ifdef RT_USING_DEVICE_OPS
  336. static struct rt_device_ops ccap_ops =
  337. {
  338. .init = ccap_init,
  339. .open = ccap_open,
  340. .close = ccap_close,
  341. .read = RT_NULL,
  342. .write = RT_NULL,
  343. .control = ccap_control,
  344. };
  345. #endif
  346. static rt_err_t ccap_register(struct rt_device *device, const char *name, void *user_data)
  347. {
  348. RT_ASSERT(device);
  349. device->type = RT_Device_Class_Miscellaneous;
  350. device->rx_indicate = RT_NULL;
  351. device->tx_complete = RT_NULL;
  352. #ifdef RT_USING_DEVICE_OPS
  353. device->ops = &inputcapture_ops;
  354. #else
  355. device->init = ccap_init;
  356. device->open = ccap_open;
  357. device->close = ccap_close;
  358. device->read = RT_NULL;
  359. device->write = RT_NULL;
  360. device->control = ccap_control;
  361. #endif
  362. device->user_data = user_data;
  363. return rt_device_register(device, name, RT_DEVICE_FLAG_RDONLY | RT_DEVICE_FLAG_STANDALONE);
  364. }
  365. /**
  366. * Hardware CCAP Initialization
  367. */
  368. int rt_hw_ccap_init(void)
  369. {
  370. int i;
  371. rt_err_t ret = RT_EOK;
  372. for (i = (CCAP_START + 1); i < CCAP_CNT; i++)
  373. {
  374. rt_memset(&nu_ccap_arr[i].sConfig, 0, sizeof(ccap_config));
  375. ret = ccap_register(&nu_ccap_arr[i].device, nu_ccap_arr[i].name, NULL);
  376. RT_ASSERT(ret == RT_EOK);
  377. }
  378. return ret;
  379. }
  380. INIT_DEVICE_EXPORT(rt_hw_ccap_init);
  381. #endif