isp_miv1.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626
  1. /****************************************************************************
  2. *
  3. * The MIT License (MIT)
  4. *
  5. * Copyright (c) 2020 VeriSilicon Holdings Co., Ltd.
  6. *
  7. * Permission is hereby granted, free of charge, to any person obtaining a
  8. * copy of this software and associated documentation files (the "Software"),
  9. * to deal in the Software without restriction, including without limitation
  10. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  11. * and/or sell copies of the Software, and to permit persons to whom the
  12. * Software is furnished to do so, subject to the following conditions:
  13. *
  14. * The above copyright notice and this permission notice shall be included in
  15. * all copies or substantial portions of the Software.
  16. *
  17. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  20. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  22. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  23. * DEALINGS IN THE SOFTWARE.
  24. *
  25. *****************************************************************************
  26. *
  27. * The GPL License (GPL)
  28. *
  29. * Copyright (c) 2020 VeriSilicon Holdings Co., Ltd.
  30. *
  31. * This program is free software; you can redistribute it and/or
  32. * modify it under the terms of the GNU General Public License
  33. * as published by the Free Software Foundation; either version 2
  34. * of the License, or (at your option) any later version.
  35. *
  36. * This program is distributed in the hope that it will be useful,
  37. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  38. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  39. * GNU General Public License for more details.
  40. *
  41. * You should have received a copy of the GNU General Public License
  42. * along with this program;
  43. *
  44. *****************************************************************************
  45. *
  46. * Note: This software is released under dual MIT and GPL licenses. A
  47. * recipient may use this file under the terms of either the MIT license or
  48. * GPL License. If you wish to use only one license not the other, you can
  49. * indicate your decision by deleting one of the above license notices in your
  50. * version of this file.
  51. *
  52. *****************************************************************************/
  53. #include "mrv_all_bits.h"
  54. #include "isp_ioctl.h"
  55. #include "isp_types.h"
  56. #ifdef ISP_MIV1
  57. extern MrvAllRegister_t *all_regs;
  58. static int getRawBit(u32 type, u32 *bit, u32 *len)
  59. {
  60. *len = 16;
  61. switch (type) {
  62. case ISP_PICBUF_TYPE_RAW8:
  63. *bit = 0;
  64. *len = 8;
  65. break;
  66. #if 0 /* normal process, need pass type from engine. */
  67. case ISP_PICBUF_TYPE_RAW10:
  68. *bit = 1;
  69. break;
  70. case ISP_PICBUF_TYPE_RAW12:
  71. *bit = 2;
  72. break;
  73. case ISP_PICBUF_TYPE_RAW14:
  74. *bit = 3;
  75. break;
  76. case ISP_PICBUF_TYPE_RAW16:
  77. *bit = 4;
  78. break;
  79. #else /* WA */
  80. case ISP_PICBUF_TYPE_RAW10:
  81. case ISP_PICBUF_TYPE_RAW12:
  82. case ISP_PICBUF_TYPE_RAW14:
  83. case ISP_PICBUF_TYPE_RAW16:
  84. *bit = 4;
  85. break;
  86. #endif
  87. default:
  88. pr_err("unsupport raw formt: %d\n", type);
  89. return -1;
  90. }
  91. return 0;
  92. }
  93. int isp_ioc_cfg_dma(struct isp_ic_dev *dev, void __user *args)
  94. {
  95. return 0;
  96. }
  97. int isp_ioc_start_dma_read(struct isp_ic_dev *dev, void __user *args)
  98. {
  99. struct isp_dma_context dma;
  100. u32 mi_dma_ctrl = isp_read_reg(dev, REG_ADDR(mi_dma_ctrl));
  101. u32 llength = 0, mcm_rd_fmt_bit = 0;
  102. u32 mi_imsc = 0, mcm_fmt = 0;
  103. pr_info("enter %s\n", __func__);
  104. viv_check_retval(copy_from_user(&dma, args, sizeof(dma)));
  105. REG_SET_SLICE(mi_dma_ctrl, MRV_MI_DMA_BURST_LEN_LUM, dma.burst_y);
  106. REG_SET_SLICE(mi_dma_ctrl, MRV_MI_DMA_BURST_LEN_CHROM, dma.burst_c);
  107. isp_write_reg(dev, REG_ADDR(mi_dma_y_pic_start_ad),
  108. (MRV_MI_DMA_Y_PIC_START_AD_MASK & dma.base));
  109. getRawBit(dma.type, &mcm_rd_fmt_bit, &llength);
  110. llength = dma.width * llength / 8;
  111. REG_SET_SLICE(mcm_fmt, MCM_RD_RAW_BIT, mcm_rd_fmt_bit);
  112. isp_write_reg(dev, REG_ADDR(mi_dma_y_pic_width),
  113. (MRV_MI_DMA_Y_PIC_WIDTH_MASK & dma.width));
  114. isp_write_reg(dev, REG_ADDR(mi_dma_y_llength),
  115. (MRV_MI_DMA_Y_LLENGTH_MASK & llength));
  116. isp_write_reg(dev, REG_ADDR(mi_dma_y_pic_size),
  117. (MRV_MI_DMA_Y_PIC_SIZE_MASK & (llength * dma.height)));
  118. isp_write_reg(dev, REG_ADDR(mi_dma_cb_pic_start_ad), 0);
  119. isp_write_reg(dev, REG_ADDR(mi_dma_cr_pic_start_ad), 0);
  120. isp_write_reg(dev, REG_ADDR(mi_dma_ctrl), mi_dma_ctrl);
  121. isp_write_reg(dev, REG_ADDR(mi_dma_status), 0);
  122. isp_write_reg(dev, REG_ADDR(mi_dma_y_raw_fmt), mcm_fmt);
  123. isp_write_reg(dev, REG_ADDR(mi_dma_y_raw_lval),
  124. (MRV_MI_DMA_Y_LLENGTH_MASK & llength));
  125. mi_imsc = isp_read_reg(dev, REG_ADDR(mi_imsc));
  126. mi_imsc |= MRV_MI_DMA_READY_MASK;
  127. isp_write_reg(dev, REG_ADDR(mi_imsc), mi_imsc);
  128. isp_write_reg(dev, REG_ADDR(mi_dma_start), MRV_MI_DMA_START_MASK);
  129. return 0;
  130. }
  131. u32 getScaleFactor(u32 src, u32 dst)
  132. {
  133. if (dst > src) {
  134. return ((65536 * (src - 1)) / (dst - 1));
  135. } else if (dst < src) {
  136. return ((65536 * (dst - 1)) / (src - 1)) + 1;
  137. }
  138. return 65536;
  139. }
  140. int set_scaling(int id, struct isp_ic_dev *dev, bool stabilization)
  141. {
  142. u32 addr, ctrl;
  143. u32 iw, ih, ow, oh;
  144. u32 inputWidth, inputHeight, outputWidth, outputHeight;
  145. u32 scale_hy, scale_hcb, scale_hcr, scale_vy, scale_vc;
  146. struct isp_mi_data_path_context *path = &dev->mi.path[id];
  147. if (id == IC_MI_PATH_MAIN) { /* mp */
  148. addr = REG_ADDR(mrsz_ctrl);
  149. } else if (id == IC_MI_PATH_SELF) { /* sp */
  150. addr = REG_ADDR(srsz_ctrl);
  151. } else {
  152. return -EINVAL;
  153. }
  154. inputWidth = path->in_width;
  155. inputHeight = path->in_height;
  156. outputWidth = path->out_width;
  157. outputHeight = path->out_height;
  158. if (stabilization) { /* enabled image stabilization. */
  159. inputWidth = isp_read_reg(dev, REG_ADDR(isp_is_h_size));
  160. inputHeight = isp_read_reg(dev, REG_ADDR(isp_is_v_size));
  161. }
  162. ctrl = isp_read_reg(dev, addr);
  163. iw = inputWidth / 2;
  164. ih = inputHeight;
  165. ow = outputWidth / 2;
  166. oh = outputHeight;
  167. switch (path->in_mode) {
  168. case IC_MI_DATAMODE_YUV422:
  169. oh = outputHeight;
  170. break;
  171. case IC_MI_DATAMODE_YUV420:
  172. oh = outputHeight / 2; /* scale cbcr */
  173. break;
  174. default:
  175. return -EFAULT;
  176. }
  177. REG_SET_SLICE(ctrl, MRV_MRSZ_SCALE_HY_ENABLE,
  178. inputWidth != outputWidth);
  179. REG_SET_SLICE(ctrl, MRV_MRSZ_SCALE_VY_ENABLE,
  180. inputHeight != outputHeight);
  181. REG_SET_SLICE(ctrl, MRV_MRSZ_SCALE_HY_UP, inputWidth < outputWidth);
  182. REG_SET_SLICE(ctrl, MRV_MRSZ_SCALE_VY_UP, inputHeight < outputHeight);
  183. scale_hy = getScaleFactor(inputWidth, outputWidth);
  184. scale_vy = getScaleFactor(inputHeight, outputHeight);
  185. REG_SET_SLICE(ctrl, MRV_MRSZ_SCALE_HC_ENABLE, iw != ow);
  186. REG_SET_SLICE(ctrl, MRV_MRSZ_SCALE_VC_ENABLE, ih != oh);
  187. REG_SET_SLICE(ctrl, MRV_MRSZ_SCALE_HC_UP, iw < ow);
  188. REG_SET_SLICE(ctrl, MRV_MRSZ_SCALE_VC_UP, ih < oh);
  189. scale_hcr = getScaleFactor(iw, ow);
  190. scale_hcb = getScaleFactor(iw, ow);
  191. scale_vc = getScaleFactor(ih, oh);
  192. REG_SET_SLICE(ctrl, MRV_MRSZ_AUTO_UPD, 1);
  193. if (id == IC_MI_PATH_MAIN) {
  194. isp_write_reg(dev, REG_ADDR(mrsz_scale_vc), scale_vc);
  195. isp_write_reg(dev, REG_ADDR(mrsz_scale_vy), scale_vy);
  196. isp_write_reg(dev, REG_ADDR(mrsz_scale_hcr), scale_hcr);
  197. isp_write_reg(dev, REG_ADDR(mrsz_scale_hcb), scale_hcb);
  198. isp_write_reg(dev, REG_ADDR(mrsz_scale_hy), scale_hy);
  199. isp_write_reg(dev, REG_ADDR(mrsz_ctrl),
  200. ctrl | MRV_MRSZ_CFG_UPD_MASK);
  201. } else if (id == IC_MI_PATH_SELF) {
  202. isp_write_reg(dev, REG_ADDR(srsz_scale_vc), scale_vc);
  203. isp_write_reg(dev, REG_ADDR(srsz_scale_vy), scale_vy);
  204. isp_write_reg(dev, REG_ADDR(srsz_scale_hcr), scale_hcr);
  205. isp_write_reg(dev, REG_ADDR(srsz_scale_hcb), scale_hcb);
  206. isp_write_reg(dev, REG_ADDR(srsz_scale_hy), scale_hy);
  207. isp_write_reg(dev, REG_ADDR(srsz_ctrl),
  208. ctrl | MRV_MRSZ_CFG_UPD_MASK);
  209. }
  210. return 0;
  211. }
  212. #ifdef ISP_MI_BP
  213. int isp_bppath_start(struct isp_ic_dev *dev)
  214. {
  215. struct isp_mi_context mi = *(&dev->mi);
  216. u32 bp_ctrl = 0, lval = 0;
  217. struct isp_mi_data_path_context *path = &mi.path[2];
  218. u32 mi_imsc = isp_read_reg(dev, REG_ADDR(mi_imsc));
  219. int i;
  220. pr_info("enter %s\n", __func__);
  221. bp_ctrl = 0;
  222. lval = path->out_width;
  223. if (mi.path[2].enable) {
  224. bp_ctrl &= ~MRV_MI_BP_WRITE_RAWBIT_MASK;
  225. if (path->data_alignMode == ISP_MI_DATA_ALIGN_16BIT_MODE) {
  226. if ((path->out_mode == IC_MI_DATAMODE_RAW10) ||
  227. (path->out_mode == IC_MI_DATAMODE_RAW12) ||
  228. (path->out_mode == IC_MI_DATAMODE_RAW14)) {
  229. lval = (path->out_width + 3) / 4;
  230. }
  231. } else if (path->data_alignMode ==
  232. ISP_MI_DATA_ALIGN_128BIT_MODE) {
  233. if ((path->out_mode == IC_MI_DATAMODE_RAW10)
  234. || (path->out_mode == IC_MI_DATAMODE_RAW12)
  235. || (path->out_mode == IC_MI_DATAMODE_RAW14)) {
  236. lval = (path->out_width * 2 + 126) / 128;
  237. }
  238. } else {
  239. if (path->out_mode == IC_MI_DATAMODE_RAW10) {
  240. lval = (path->out_width * 10 + 63) / 64;
  241. } else if (path->out_mode == IC_MI_DATAMODE_RAW12) {
  242. lval = (path->out_width * 12 + 63) / 64;
  243. } else if (path->out_mode == IC_MI_DATAMODE_RAW14) {
  244. lval = (path->out_width * 14 + 63) / 64;
  245. } else if (path->out_mode == IC_MI_DATAMODE_RAW16) {
  246. lval = (path->out_width * 16 + 63) / 64;
  247. } else {
  248. lval = (path->out_width * 8 + 63) / 64;
  249. }
  250. }
  251. lval <<= 3;
  252. REG_SET_SLICE(bp_ctrl, BP_WR_RAW_ALIGNED, path->data_alignMode);
  253. switch (mi.path[2].out_mode) {
  254. case (IC_MI_DATAMODE_RAW8):
  255. REG_SET_SLICE(bp_ctrl, MRV_MI_BP_WRITE_RAWBIT,
  256. MRV_MI_BP_WRITE_RAWBIT_RAW_8);
  257. REG_SET_SLICE(bp_ctrl, MRV_MI_BP_WRITE_FORMAT,
  258. MRV_MI_BP_WRITE_INTERLEAVE_FORMAT);
  259. break;
  260. case (IC_MI_DATAMODE_RAW12):
  261. REG_SET_SLICE(bp_ctrl, BP_WR_BYTE_SWAP, 1);
  262. REG_SET_SLICE(bp_ctrl, MRV_MI_BP_WRITE_RAWBIT,
  263. MRV_MI_BP_WRITE_RAWBIT_RAW_12);
  264. REG_SET_SLICE(bp_ctrl, MRV_MI_BP_WRITE_FORMAT,
  265. MRV_MI_BP_WRITE_INTERLEAVE_FORMAT);
  266. break;
  267. case (IC_MI_DATAMODE_RAW10):
  268. REG_SET_SLICE(bp_ctrl, BP_WR_BYTE_SWAP, 1);
  269. REG_SET_SLICE(bp_ctrl, MRV_MI_BP_WRITE_RAWBIT,
  270. MRV_MI_BP_WRITE_RAWBIT_RAW_10);
  271. REG_SET_SLICE(bp_ctrl, MRV_MI_BP_WRITE_FORMAT,
  272. MRV_MI_BP_WRITE_INTERLEAVE_FORMAT);
  273. break;
  274. default:
  275. break;
  276. }
  277. isp_write_reg(dev, REG_ADDR(mi_bp_wr_size_init),
  278. lval * mi.path[2].out_height);
  279. isp_write_reg(dev, REG_ADDR(mi_bp_pic_width),
  280. mi.path[2].out_width);
  281. isp_write_reg(dev, REG_ADDR(mi_bp_wr_llength), lval);
  282. isp_write_reg(dev, REG_ADDR(mi_bp_pic_height),
  283. mi.path[2].out_height);
  284. isp_write_reg(dev, REG_ADDR(mi_bp_pic_size),
  285. lval * mi.path[2].out_height);
  286. /* enable frame end irq for bp path */
  287. mi_imsc |=
  288. MRV_MI_BP_FRAME_END_MASK | MRV_MI_BP_WRAP_R_MASK |
  289. MRV_MI_BP_WRAP_GR_MASK | MRV_MI_BP_WRAP_GB_MASK |
  290. MRV_MI_BP_WRAP_B_MASK;
  291. }
  292. if (!dev->rawis.enable) {
  293. isp_write_reg(dev, REG_ADDR(isp_raw_is_h_size),
  294. mi.path[2].out_width);
  295. isp_write_reg(dev, REG_ADDR(isp_raw_is_v_size),
  296. mi.path[2].out_height);
  297. isp_write_reg(dev, REG_ADDR(isp_raw_is_ctrl), 0);
  298. }
  299. bp_ctrl |= MRV_MI_BP_PATH_ENABLE_MASK;
  300. isp_write_reg(dev, REG_ADDR(mi_bp_ctrl), bp_ctrl);
  301. isp_write_reg(dev, REG_ADDR(mi_imsc), mi_imsc);
  302. return 0;
  303. }
  304. #endif
  305. int isp_mi_start(struct isp_ic_dev *dev)
  306. {
  307. struct isp_mi_context mi = *(&dev->mi);
  308. u32 mi_init, mi_ctrl, mi_imsc;
  309. u32 out_stride;
  310. int i;
  311. u8 retry = 3;
  312. pr_info("enter %s\n", __func__);
  313. isp_write_reg(dev, REG_ADDR(mrsz_ctrl), 0);
  314. isp_write_reg(dev, REG_ADDR(mrsz_ctrl_shd), 0);
  315. for (i = 0; i < 2; i++) {
  316. if (mi.path[i].hscale || mi.path[i].vscale) {
  317. set_scaling(i, dev, dev->is.enable);
  318. }
  319. }
  320. mi_init = 0;
  321. mi_ctrl = 0;
  322. mi_imsc = 0;
  323. if (mi.path[0].enable) {
  324. /* remove update enable bits for offset and base registers */
  325. mi_init &= ~MRV_MI_MP_OUTPUT_FORMAT_MASK;
  326. mi_ctrl &= ~MRV_MI_MP_WRITE_FORMAT_MASK;
  327. /* config mi_init output format for yuv format */
  328. if (mi.path[0].out_mode <= IC_MI_DATAMODE_YUV400)
  329. REG_SET_SLICE(mi_init, MRV_MI_MP_OUTPUT_FORMAT,
  330. IC_MI_DATAMODE_YUV400 -
  331. mi.path[0].out_mode);
  332. switch (mi.path[0].out_mode) {
  333. case (IC_MI_DATAMODE_RAW8):
  334. REG_SET_SLICE(mi_ctrl, MRV_MI_MP_WRITE_FORMAT,
  335. MRV_MI_MP_WRITE_FORMAT_RAW_8);
  336. REG_SET_SLICE(mi_ctrl, MRV_MI_RAW_ENABLE, 1);
  337. REG_SET_SLICE(mi_init, MRV_MI_MP_OUTPUT_FORMAT,
  338. MRV_MI_MP_OUTPUT_FORMAT_RAW8);
  339. break;
  340. case (IC_MI_DATAMODE_RAW12):
  341. REG_SET_SLICE(mi_ctrl, MRV_MI_MP_WRITE_FORMAT,
  342. MRV_MI_MP_WRITE_FORMAT_RAW_12);
  343. REG_SET_SLICE(mi_ctrl, MRV_MI_RAW_ENABLE, 1);
  344. REG_SET_SLICE(mi_init, MRV_MI_MP_OUTPUT_FORMAT,
  345. MRV_MI_MP_OUTPUT_FORMAT_RAW12);
  346. isp_write_reg(dev, REG_ADDR(mi_output_align_format), 1);
  347. break;
  348. case (IC_MI_DATAMODE_RAW10):
  349. REG_SET_SLICE(mi_ctrl, MRV_MI_MP_WRITE_FORMAT,
  350. MRV_MI_MP_WRITE_FORMAT_RAW_12);
  351. REG_SET_SLICE(mi_ctrl, MRV_MI_RAW_ENABLE, 1);
  352. REG_SET_SLICE(mi_init, MRV_MI_MP_OUTPUT_FORMAT,
  353. MRV_MI_MP_OUTPUT_FORMAT_RAW10);
  354. isp_write_reg(dev, REG_ADDR(mi_output_align_format), 1);
  355. break;
  356. case (IC_MI_DATAMODE_JPEG):
  357. REG_SET_SLICE(mi_ctrl, MRV_MI_MP_WRITE_FORMAT,
  358. MRV_MI_MP_WRITE_FORMAT_PLANAR);
  359. REG_SET_SLICE(mi_ctrl, MRV_MI_JPEG_ENABLE, 1);
  360. break;
  361. case (IC_MI_DATAMODE_YUV444):
  362. case (IC_MI_DATAMODE_YUV422):
  363. case (IC_MI_DATAMODE_YUV420):
  364. case (IC_MI_DATAMODE_YUV400):
  365. if (mi.path[0].data_layout == IC_MI_DATASTORAGE_PLANAR) {
  366. REG_SET_SLICE(mi_ctrl, MRV_MI_MP_WRITE_FORMAT,
  367. MRV_MI_MP_WRITE_FORMAT_PLANAR);
  368. } else if (mi.path[0].data_layout ==
  369. IC_MI_DATASTORAGE_SEMIPLANAR) {
  370. REG_SET_SLICE(mi_ctrl, MRV_MI_MP_WRITE_FORMAT,
  371. MRV_MI_MP_WRITE_FORMAT_SEMIPLANAR);
  372. } else if (mi.path[0].data_layout ==
  373. IC_MI_DATASTORAGE_INTERLEAVED) {
  374. REG_SET_SLICE(mi_ctrl, MRV_MI_MP_WRITE_FORMAT,
  375. MRV_MI_MP_WRITE_FORMAT_INTERLEAVED);
  376. } else {
  377. break;
  378. }
  379. REG_SET_SLICE(mi_ctrl, MRV_MI_MP_ENABLE, 1);
  380. break;
  381. default:
  382. break;
  383. }
  384. out_stride = mi.path[0].data_layout ==
  385. IC_MI_DATASTORAGE_INTERLEAVED ?
  386. (mi.path[0].out_width * 2) : (mi.path[0].out_width);
  387. isp_write_reg(dev, REG_ADDR(mi_mp_y_pic_width), out_stride);
  388. isp_write_reg(dev, REG_ADDR(mi_mp_y_llength), out_stride);
  389. isp_write_reg(dev, REG_ADDR(mi_mp_y_pic_height),
  390. mi.path[0].out_height);
  391. isp_write_reg(dev, REG_ADDR(mi_mp_y_pic_size),
  392. out_stride * mi.path[0].out_height);
  393. /* workaround to resolve the problem that the mi_mp_y_pic_width can't be written */
  394. for(i = 0; i < retry; i++) {
  395. if(isp_read_reg(dev, REG_ADDR(mi_mp_y_pic_width)) != out_stride) {
  396. isp_write_reg(dev, REG_ADDR(mi_mp_y_pic_width), out_stride);
  397. } else {
  398. break;
  399. }
  400. }
  401. if(retry == i) {
  402. pr_info("%s: update mi_mp_y_pic_width error!\n", __func__);
  403. }
  404. /* enable frame end irq for main path */
  405. mi_imsc |=
  406. (MRV_MI_MP_FRAME_END_MASK | MRV_MI_WRAP_MP_Y_MASK |
  407. MRV_MI_WRAP_MP_CB_MASK | MRV_MI_WRAP_MP_CR_MASK);
  408. }
  409. if (mi.path[1].enable) {
  410. /* setup mi for self-path */
  411. mi_ctrl &= ~(MRV_MI_SP_WRITE_FORMAT_MASK);
  412. REG_SET_SLICE(mi_ctrl, MRV_MI_SP_INPUT_FORMAT,
  413. mi.path[1].in_mode - 1);
  414. REG_SET_SLICE(mi_ctrl, MRV_MI_SP_OUTPUT_FORMAT,
  415. mi.path[1].out_mode - 1);
  416. switch (mi.path[1].out_mode) {
  417. case (IC_MI_DATAMODE_RGB888):
  418. case (IC_MI_DATAMODE_RGB666):
  419. case (IC_MI_DATAMODE_RGB565):
  420. REG_SET_SLICE(mi_ctrl, MRV_MI_SP_WRITE_FORMAT,
  421. MRV_MI_SP_WRITE_FORMAT_RGB_INTERLEAVED);
  422. break;
  423. case (IC_MI_DATAMODE_YUV444):
  424. case (IC_MI_DATAMODE_YUV400):
  425. if (mi.path[1].data_layout == IC_MI_DATASTORAGE_PLANAR) {
  426. REG_SET_SLICE(mi_ctrl, MRV_MI_SP_WRITE_FORMAT,
  427. MRV_MI_SP_WRITE_FORMAT_PLANAR);
  428. }
  429. break;
  430. case (IC_MI_DATAMODE_YUV422):
  431. switch (mi.path[1].data_layout) {
  432. case (IC_MI_DATASTORAGE_PLANAR):
  433. REG_SET_SLICE(mi_ctrl, MRV_MI_SP_WRITE_FORMAT,
  434. MRV_MI_SP_WRITE_FORMAT_PLANAR);
  435. break;
  436. case (IC_MI_DATASTORAGE_SEMIPLANAR):
  437. REG_SET_SLICE(mi_ctrl, MRV_MI_SP_WRITE_FORMAT,
  438. MRV_MI_SP_WRITE_FORMAT_SEMIPLANAR);
  439. break;
  440. case (IC_MI_DATASTORAGE_INTERLEAVED):
  441. REG_SET_SLICE(mi_ctrl, MRV_MI_SP_WRITE_FORMAT,
  442. MRV_MI_SP_WRITE_FORMAT_INTERLEAVED);
  443. break;
  444. default:
  445. break;
  446. }
  447. break;
  448. case (IC_MI_DATAMODE_YUV420):
  449. switch (mi.path[1].data_layout) {
  450. case (IC_MI_DATASTORAGE_PLANAR):
  451. REG_SET_SLICE(mi_ctrl, MRV_MI_SP_WRITE_FORMAT,
  452. MRV_MI_SP_WRITE_FORMAT_PLANAR);
  453. break;
  454. case (IC_MI_DATASTORAGE_SEMIPLANAR):
  455. REG_SET_SLICE(mi_ctrl, MRV_MI_SP_WRITE_FORMAT,
  456. MRV_MI_SP_WRITE_FORMAT_SEMIPLANAR);
  457. break;
  458. default:
  459. break;
  460. }
  461. break;
  462. default:
  463. break;
  464. }
  465. out_stride = mi.path[1].data_layout ==
  466. IC_MI_DATASTORAGE_INTERLEAVED ?
  467. mi.path[1].out_width * 2 : mi.path[1].out_width;
  468. REG_SET_SLICE(mi_ctrl, MRV_MI_SP_ENABLE, 1);
  469. isp_write_reg(dev, REG_ADDR(mi_sp_y_pic_width), out_stride);
  470. isp_write_reg(dev, REG_ADDR(mi_sp_y_llength), out_stride);
  471. isp_write_reg(dev, REG_ADDR(mi_sp_y_pic_height),
  472. mi.path[1].out_height);
  473. isp_write_reg(dev, REG_ADDR(mi_sp_y_pic_size),
  474. out_stride * mi.path[1].out_height);
  475. /* enable frame end interrupt on self path */
  476. mi_imsc |=
  477. (MRV_MI_SP_FRAME_END_MASK | MRV_MI_WRAP_SP_Y_MASK |
  478. MRV_MI_WRAP_SP_CB_MASK | MRV_MI_WRAP_SP_CR_MASK);
  479. }
  480. #if defined(__KERNEL__) && defined(ENABLE_IRQ)
  481. for (i = 0; i < MI_PATH_NUM; ++i) {
  482. dev->mi_buf[i] = NULL;
  483. dev->mi_buf_shd[i] = NULL;
  484. }
  485. if (dev->state)
  486. *dev->state |= STATE_DRIVER_STARTED;
  487. #endif
  488. mi_ctrl |= (MRV_MI_INIT_BASE_EN_MASK | MRV_MI_INIT_OFFSET_EN_MASK);
  489. REG_SET_SLICE(mi_ctrl, MRV_MI_BURST_LEN_CHROM, mi.burst_len);
  490. REG_SET_SLICE(mi_ctrl, MRV_MI_BURST_LEN_LUM, mi.burst_len);
  491. isp_write_reg(dev, REG_ADDR(mi_ctrl), mi_ctrl | 0x2000);
  492. REG_SET_SLICE(mi_init, MRV_MI_MI_CFG_UPD, 1);
  493. isp_write_reg(dev, REG_ADDR(mi_imsc), mi_imsc);
  494. #ifdef ISP_MI_BP
  495. isp_bppath_start(dev);
  496. #endif
  497. isp_write_reg(dev, REG_ADDR(mi_init), mi_init);
  498. return 0;
  499. }
  500. int isp_mi_stop(struct isp_ic_dev *dev)
  501. {
  502. u32 mi_ctrl = 0, mi_init = 0;
  503. pr_info("enter %s\n", __func__);
  504. isp_write_reg(dev, REG_ADDR(mi_imsc), 0);
  505. /* disable mi path */
  506. mi_ctrl = isp_read_reg(dev, REG_ADDR(mi_ctrl));
  507. REG_SET_SLICE(mi_ctrl, MRV_MI_MP_ENABLE, 0);
  508. REG_SET_SLICE(mi_ctrl, MRV_MI_SP_ENABLE, 0);
  509. REG_SET_SLICE(mi_ctrl, MRV_MI_JPEG_ENABLE, 0);
  510. REG_SET_SLICE(mi_ctrl, MRV_MI_RAW_ENABLE, 0);
  511. isp_write_reg(dev, REG_ADDR(mi_ctrl), mi_ctrl);
  512. mi_init = isp_read_reg(dev, REG_ADDR(mi_init));
  513. REG_SET_SLICE(mi_init, MRV_MI_MI_CFG_UPD, 1);
  514. isp_write_reg(dev, REG_ADDR(mi_init), mi_init);
  515. #if defined(__KERNEL__) && defined(ENABLE_IRQ)
  516. if (dev->state)
  517. *dev->state &= ~STATE_DRIVER_STARTED;
  518. clean_dma_buffer(dev);
  519. #endif
  520. return 0;
  521. }
  522. int isp_set_buffer(struct isp_ic_dev *dev, struct isp_buffer_context *buf)
  523. {
  524. u32 addr;
  525. if (!dev || !buf) {
  526. pr_err("NULL pointer %s\n", __func__);
  527. return -EINVAL;
  528. }
  529. addr = buf->path == 0 ?
  530. REG_ADDR(mi_mp_y_base_ad_init) : REG_ADDR(mi_sp_y_base_ad_init);
  531. isp_write_reg(dev, addr, (buf->addr_y & MRV_MI_MP_Y_BASE_AD_INIT_MASK));
  532. isp_write_reg(dev, addr + 1 * 4,
  533. (buf->size_y & MRV_MI_MP_Y_SIZE_INIT_MASK));
  534. isp_write_reg(dev, addr + 2 * 4, 0);
  535. isp_write_reg(dev, addr + 5 * 4,
  536. (buf->addr_cb & MRV_MI_MP_CB_BASE_AD_INIT_MASK));
  537. isp_write_reg(dev, addr + 6 * 4,
  538. (buf->size_cb & MRV_MI_MP_CB_SIZE_INIT_MASK));
  539. isp_write_reg(dev, addr + 7 * 4, 0);
  540. isp_write_reg(dev, addr + 9 * 4,
  541. (buf->addr_cr & MRV_MI_MP_CR_BASE_AD_INIT_MASK));
  542. isp_write_reg(dev, addr + 10 * 4,
  543. (buf->size_cr & MRV_MI_MP_CR_SIZE_INIT_MASK));
  544. isp_write_reg(dev, addr + 11 * 4, 0);
  545. return 0;
  546. }
  547. int isp_set_bp_buffer(struct isp_ic_dev *dev, struct isp_bp_buffer_context *buf)
  548. {
  549. #ifndef ISP_MI_BP
  550. pr_err("unsupported function: %s", __func__);
  551. return -EINVAL;
  552. #else
  553. isp_write_reg(dev, REG_ADDR(mi_bp_r_base_ad_init),
  554. (buf->addr_r & BP_R_BASE_AD_INIT_MASK));
  555. isp_write_reg(dev, REG_ADDR(mi_bp_gr_base_ad_init),
  556. (buf->addr_gr & BP_GR_BASE_AD_INIT_MASK));
  557. isp_write_reg(dev, REG_ADDR(mi_bp_gb_base_ad_init),
  558. (buf->addr_gb & BP_GB_BASE_AD_INIT_MASK));
  559. isp_write_reg(dev, REG_ADDR(mi_bp_b_base_ad_init),
  560. (buf->addr_b & BP_B_BASE_AD_INIT_MASK));
  561. return 0;
  562. #endif
  563. }
  564. u32 isp_read_mi_irq(struct isp_ic_dev * dev)
  565. {
  566. return isp_read_reg(dev, REG_ADDR(mi_mis));
  567. }
  568. void isp_reset_mi_irq(struct isp_ic_dev *dev, u32 icr)
  569. {
  570. isp_write_reg(dev, REG_ADDR(mi_icr), icr);
  571. }
  572. #endif