bm_csi_hw.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412
  1. /*
  2. * Copyright (C) 2021 Alibaba Group Holding Limited
  3. * Author: liuyitong <yitong.lyt@alibaba-inc.com>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License version 2 as
  7. * published by the Free Software Foundation.
  8. */
  9. #include <asm/io.h>
  10. #include <linux/cdev.h>
  11. #include <linux/module.h>
  12. #include <linux/platform_device.h>
  13. #include <linux/delay.h>
  14. #include <linux/clk.h>
  15. #include <linux/io.h>
  16. #include <linux/mm.h>
  17. #include <linux/timer.h>
  18. #include <linux/kernel.h>
  19. #include <linux/init.h>
  20. #include <linux/ioctl.h>
  21. #include <linux/poll.h>
  22. #include <linux/workqueue.h>
  23. #include <linux/slab.h>
  24. #include <linux/proc_fs.h>
  25. #include <linux/debugfs.h>
  26. #include <linux/miscdevice.h>
  27. #include <linux/uaccess.h>
  28. #include <linux/interrupt.h>
  29. #include <linux/of.h>
  30. #include <linux/regmap.h>
  31. #include "bm_printk.h"
  32. #include "bm_csi_ioctl.h"
  33. #include "bm_csi_hw.h"
  34. #include "dw-dphy-rx.h"
  35. #include "bm_csi_dphy.h"
  36. #define check_retval(x)\
  37. do {\
  38. if ((x))\
  39. return -EIO;\
  40. } while (0)
  41. struct csi_format_context {
  42. uint32_t format;
  43. uint32_t width;
  44. uint32_t height;
  45. };
  46. int bm_csi_write_reg(struct bm_csi_drvdata *drvdata, void *__user args)
  47. {
  48. struct bm_csi_reg_t reg;
  49. check_retval(copy_from_user(&reg, args, sizeof(reg)));
  50. writel(reg.value, drvdata->base + reg.offset);
  51. bm_info("%s addr 0x%08x val 0x%08x\n", __func__, reg.offset, reg.value);
  52. return 0;
  53. }
  54. int bm_csi_read_reg(struct bm_csi_drvdata *drvdata, void *__user args)
  55. {
  56. struct bm_csi_reg_t reg;
  57. check_retval(copy_from_user(&reg, args, sizeof(reg)));
  58. reg.value = readl(drvdata->base + reg.offset);
  59. check_retval(copy_to_user(args, &reg, sizeof(reg)));
  60. bm_info("%s addr 0x%08x val 0x%08x\n", __func__, reg.offset, reg.value);
  61. return 0;
  62. }
  63. int bm_csi_read_array(struct bm_csi_drvdata *drvdata, void *__user args)
  64. {
  65. int index = 0;
  66. int cnt = 0;
  67. uint32_t value = 0;
  68. struct bm_csi_reg_arry_t array;
  69. check_retval(copy_from_user(&array, args, sizeof(struct bm_csi_reg_arry_t)));
  70. cnt = array.words;
  71. for (index = 0; index < cnt; index++) {
  72. value = readl(drvdata->base + array.start_addr + index * 4);
  73. check_retval(copy_to_user(&(array.buf[index]), &value, sizeof(value)));
  74. }
  75. return 0;
  76. }
  77. int bm_csi_reset(struct bm_csi_drvdata *drvdata, void *__user args)
  78. {
  79. bm_info("%s: csi reset success\n", __func__);
  80. dw_csi_soc_reset();
  81. dw_mipi_csi_reset(&drvdata->csi_dev);
  82. dw_dphy_reset(drvdata->dphy->phy);
  83. return 0;
  84. }
  85. int bm_csi_en_power(struct bm_csi_drvdata *drvdata)
  86. {
  87. bm_info("%s: csi set power\n", __func__);
  88. drvdata->csi_power_on_sta = 1;
  89. dw_mipi_csi_s_power(&drvdata->csi_dev, drvdata->csi_power_on_sta);
  90. return 0;
  91. }
  92. int bm_csi_dis_power(struct bm_csi_drvdata *drvdata)
  93. {
  94. bm_info("%s: csi set power\n", __func__);
  95. drvdata->csi_power_on_sta = 0;
  96. dw_mipi_csi_s_power(&drvdata->csi_dev, drvdata->csi_power_on_sta);
  97. return 0;
  98. }
  99. static int bm_csi_can_enable(struct bm_csi_drvdata *drvdata)
  100. {
  101. return 1;
  102. u32 csia_pixclk = 0;
  103. u32 csia_rst = 0;
  104. u32 csia_shutdown = 0;
  105. if (drvdata->csia_reg == NULL || drvdata->visys_clk_reg == NULL) {
  106. return 1;
  107. }
  108. regmap_read(drvdata->visys_clk_reg, 0xa0, &csia_pixclk);
  109. regmap_read(drvdata->csia_reg, 0x40 + R_CSI2_DPHY_RSTZ, &csia_rst);
  110. regmap_read(drvdata->csia_reg, 0x40 + R_CSI2_DPHY_SHUTDOWNZ, &csia_shutdown);
  111. if (csia_pixclk & (1 << 9) && (csia_rst | csia_shutdown)) {
  112. return 0;
  113. }
  114. return 1;
  115. }
  116. int bm_csi_set_power(struct bm_csi_drvdata *drvdata, void *__user args)
  117. {
  118. bm_info("%s: csi set power\n", __func__);
  119. check_retval(copy_from_user(&drvdata->csi_power_on_sta, args, sizeof(drvdata->csi_power_on_sta)));
  120. if (!bm_csi_can_enable(drvdata)) {
  121. printk("can't enable csi power!!!!!!!!!!!!!\n");
  122. return -1;
  123. }
  124. dw_mipi_csi_s_power(&drvdata->csi_dev, drvdata->csi_power_on_sta);
  125. return 0;
  126. }
  127. int bm_csi_get_power(struct bm_csi_drvdata *drvdata, void *__user args)
  128. {
  129. bm_info("%s: csi get power\n", __func__);
  130. check_retval(copy_to_user(args, &drvdata->csi_power_on_sta, sizeof(drvdata->csi_power_on_sta)));
  131. return 0;
  132. }
  133. int bm_csi_set_clock(struct bm_csi_drvdata *drvdata, void *__user args)
  134. {
  135. struct dw_dphy_rx *dphy = drvdata->dphy;
  136. bm_info("%s: \n", __func__);
  137. check_retval(copy_from_user(&dphy->dphy_freq, args, sizeof(dphy->dphy_freq)));
  138. return 0;
  139. }
  140. int bm_csi_get_clock(struct bm_csi_drvdata *drvdata, void *__user args)
  141. {
  142. struct dw_dphy_rx *dphy = drvdata->dphy;
  143. bm_info("%s: \n", __func__);
  144. check_retval(copy_to_user(args, &dphy->dphy_freq, sizeof(dphy->dphy_freq)));
  145. return 0;
  146. }
  147. int bm_csi_set_pixclk(struct bm_csi_drvdata *drvdata, void *__user args)
  148. {
  149. uint32_t freq_hz = 0;
  150. bm_info("%s: \n", __func__);
  151. check_retval(copy_from_user(&freq_hz, args, sizeof(freq_hz)));
  152. return dw_csi_set_pixclk(freq_hz);
  153. }
  154. int bm_csi_get_pixclk(struct bm_csi_drvdata *drvdata, void *__user args)
  155. {
  156. uint32_t freq_hz = 0;
  157. bm_info("%s: \n", __func__);
  158. dw_csi_get_pixclk(&freq_hz);
  159. check_retval(copy_to_user(args, &freq_hz, sizeof(freq_hz)));
  160. return 0;
  161. }
  162. int bm_csi_get_error(struct bm_csi_drvdata *drvdata, void *__user args)
  163. {
  164. bm_info("%s: \n", __func__);
  165. struct dw_csi_err_mask *error_mask = &drvdata->csi_dev.error_mask;
  166. check_retval(copy_to_user(args, error_mask, sizeof(struct dw_csi_err_mask)));
  167. return 0;
  168. }
  169. int bm_csi_set_stream(struct bm_csi_drvdata *drvdata, void *__user args)
  170. {
  171. bm_info("%s: \n", __func__);
  172. return 0;
  173. }
  174. int bm_csi_get_stream(struct bm_csi_drvdata *drvdata, void *__user args)
  175. {
  176. bm_info("%s: \n", __func__);
  177. check_retval(copy_to_user(args, &drvdata->csi_power_on_sta, sizeof(drvdata->csi_power_on_sta)));
  178. return 0;
  179. }
  180. int bm_csi_set_fmt(struct bm_csi_drvdata *drvdata, void *__user args)
  181. {
  182. struct dw_csi *csi_dev = &drvdata->csi_dev;
  183. u8 dt = 0;
  184. //struct csi_format_context fmt;
  185. bm_info("%s: \n", __func__);
  186. check_retval(copy_from_user(&dt, args, sizeof(dt)));
  187. /*
  188. csi_dev->fmt->mbus_code = fmt.format;
  189. csi_dev->fmt->width = fmt.width;
  190. csi_dev->fmt->height = fmt.height;
  191. */
  192. csi_dev->ipi_dt = dt;
  193. dw_mipi_csi_set_ipi_fmt(csi_dev);
  194. /*
  195. if(fmt.height > 0 && fmt.width > 0) {
  196. csi_dev->hw.ipi_color_mode = COLOR16;
  197. csi_dev->hw.ipi_auto_flush = 1;
  198. csi_dev->hw.ipi_adv_features = LINE_EVENT_SELECTION(EVSELAUTO);
  199. csi_dev->hw.htotal = fmt.width + csi_dev->hw.hsa + csi_dev->hw.hbp + csi_dev->hw.hsd;
  200. csi_dev->hw.vactive = fmt.height;
  201. csi_dev->hw.output = 0;
  202. }
  203. */
  204. return 0;
  205. }
  206. int bm_csi_get_fmt(struct bm_csi_drvdata *drvdata, void *__user args)
  207. {
  208. struct dw_csi *csi_dev = &drvdata->csi_dev;
  209. struct csi_format_context fmt;
  210. bm_info("%s: \n", __func__);
  211. fmt.format = csi_dev->fmt->mbus_code;
  212. fmt.height = csi_dev->fmt->height;
  213. fmt.width = csi_dev->fmt->width;
  214. check_retval(copy_to_user(args, &fmt, sizeof(fmt)));
  215. return 0;
  216. }
  217. int bm_csi_set_vc_select(struct bm_csi_drvdata *drvdata, void *__user args)
  218. {
  219. struct csi_vc_select_context vc;
  220. struct dw_csi *csi_dev = &drvdata->csi_dev;
  221. bm_info("%s: \n", __func__);
  222. check_retval(copy_from_user(&vc, args, sizeof(vc)));
  223. if (vc.ipi_idx == 1) {
  224. csi_dev->hw.virtual_ch = vc.vc_ch;
  225. } else if (vc.ipi_idx == 2) {
  226. csi_dev->hw.ipi2_virtual_ch = vc.vc_ch;
  227. } else if (vc.ipi_idx == 3) {
  228. csi_dev->hw.ipi3_virtual_ch = vc.vc_ch;
  229. }
  230. return 0;
  231. }
  232. int bm_csi_ipi_enable(struct bm_csi_drvdata *drvdata, void *__user args)
  233. {
  234. int ipi_idx;
  235. struct dw_csi *csi_dev = &drvdata->csi_dev;
  236. bm_info("%s: \n", __func__);
  237. if (!bm_csi_can_enable(drvdata)) {
  238. printk("can't enable csi ipi!!!!!!!!!!!!!\n");
  239. return -1;
  240. }
  241. check_retval(copy_from_user(&ipi_idx, args, sizeof(ipi_idx)));
  242. if (ipi_idx == 1) {
  243. csi_dev->hw.ipi1_en = true;
  244. } else if (ipi_idx == 2) {
  245. csi_dev->hw.ipi2_en = true;
  246. } else if (ipi_idx == 3) {
  247. csi_dev->hw.ipi3_en = true;
  248. }
  249. dw_mipi_csi_start(csi_dev);
  250. return 0;
  251. }
  252. int bm_csi_ipi_disable(struct bm_csi_drvdata *drvdata, void *__user args)
  253. {
  254. int ipi_idx;
  255. struct dw_csi *csi_dev = &drvdata->csi_dev;
  256. bm_info("%s: \n", __func__);
  257. check_retval(copy_from_user(&ipi_idx, args, sizeof(ipi_idx)));
  258. if (ipi_idx == 1) {
  259. csi_dev->hw.ipi1_en = 0;
  260. } else if (ipi_idx == 2) {
  261. csi_dev->hw.ipi2_en = 0;
  262. } else if (ipi_idx == 3) {
  263. csi_dev->hw.ipi3_en = 0;
  264. }
  265. dw_mipi_csi_stop(csi_dev);
  266. return 0;
  267. }
  268. int bm_csi_get_vc_select(struct bm_csi_drvdata *drvdata, void *__user args)
  269. {
  270. struct csi_vc_select_context vc;
  271. struct dw_csi *csi_dev = &drvdata->csi_dev;
  272. bm_info("%s: \n", __func__);
  273. if (vc.ipi_idx == 1) {
  274. vc.vc_ch = csi_dev->hw.virtual_ch;
  275. } else if (vc.ipi_idx == 2) {
  276. vc.vc_ch = csi_dev->hw.ipi2_virtual_ch;
  277. } else if (vc.ipi_idx == 3) {
  278. vc.vc_ch = csi_dev->hw.ipi3_virtual_ch;
  279. }
  280. check_retval(copy_to_user(args, &vc, sizeof(vc)));
  281. return 0;
  282. }
  283. int bm_csi_set_lane_cfg(struct bm_csi_drvdata *drvdata, void *__user args)
  284. {
  285. struct dw_csi *csi_dev = &drvdata->csi_dev;
  286. bm_info("%s: \n", __func__);
  287. check_retval(copy_from_user(&csi_dev->hw.num_lanes, args, sizeof(csi_dev->hw.num_lanes)));
  288. return 0;
  289. }
  290. typedef struct {
  291. int ipi_idx;
  292. int val;
  293. } dw_csi_hsx_cfg_t;
  294. int bm_csi_set_hsa(struct bm_csi_drvdata *drvdata, void *__user args)
  295. {
  296. struct dw_csi *csi_dev = &drvdata->csi_dev;
  297. dw_csi_hsx_cfg_t cfg;
  298. bm_info("%s: \n", __func__);
  299. check_retval(copy_from_user(&cfg, args, sizeof(cfg)));
  300. if (cfg.ipi_idx == 1) {
  301. csi_dev->hw.hsa = cfg.val;
  302. } else if(cfg.ipi_idx == 2) {
  303. csi_dev->hw.ipi2_hsa = cfg.val;
  304. } else if(cfg.ipi_idx == 3) {
  305. csi_dev->hw.ipi3_hsa = cfg.val;
  306. } else {
  307. return -1;
  308. }
  309. return 0;
  310. }
  311. int bm_csi_set_hbp(struct bm_csi_drvdata *drvdata, void *__user args)
  312. {
  313. struct dw_csi *csi_dev = &drvdata->csi_dev;
  314. dw_csi_hsx_cfg_t cfg;
  315. bm_info("%s: \n", __func__);
  316. check_retval(copy_from_user(&cfg, args, sizeof(cfg)));
  317. if (cfg.ipi_idx == 1) {
  318. csi_dev->hw.hbp = cfg.val;
  319. } else if(cfg.ipi_idx == 2) {
  320. csi_dev->hw.ipi2_hbp = cfg.val;
  321. } else if(cfg.ipi_idx == 3) {
  322. csi_dev->hw.ipi3_hbp = cfg.val;
  323. } else {
  324. return -1;
  325. }
  326. return 0;
  327. }
  328. int bm_csi_set_hsd(struct bm_csi_drvdata *drvdata, void *__user args)
  329. {
  330. struct dw_csi *csi_dev = &drvdata->csi_dev;
  331. dw_csi_hsx_cfg_t cfg;
  332. bm_info("%s: \n", __func__);
  333. check_retval(copy_from_user(&cfg, args, sizeof(cfg)));
  334. if (cfg.ipi_idx == 1) {
  335. csi_dev->hw.hsd = cfg.val;
  336. } else if(cfg.ipi_idx == 2) {
  337. csi_dev->hw.ipi2_hsd = cfg.val;
  338. } else if(cfg.ipi_idx == 3) {
  339. csi_dev->hw.ipi3_hsd = cfg.val;
  340. } else {
  341. return -1;
  342. }
  343. return 0;
  344. }