bm_csi_hw.c 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  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 "bm_printk.h"
  31. #include "bm_csi_ioctl.h"
  32. #include "bm_csi_hw.h"
  33. #include "dw-dphy-rx.h"
  34. #include "bm_csi_dphy.h"
  35. #define check_retval(x)\
  36. do {\
  37. if ((x))\
  38. return -EIO;\
  39. } while (0)
  40. struct csi_format_context {
  41. uint32_t format;
  42. uint32_t width;
  43. uint32_t height;
  44. };
  45. int bm_csi_write_reg(struct bm_csi_drvdata *drvdata, void *__user args)
  46. {
  47. struct bm_csi_reg_t reg;
  48. check_retval(copy_from_user(&reg, args, sizeof(reg)));
  49. writel(reg.value, drvdata->base + reg.offset);
  50. bm_info("%s addr 0x%08x val 0x%08x\n", __func__, reg.offset, reg.value);
  51. return 0;
  52. }
  53. int bm_csi_read_reg(struct bm_csi_drvdata *drvdata, void *__user args)
  54. {
  55. struct bm_csi_reg_t reg;
  56. check_retval(copy_from_user(&reg, args, sizeof(reg)));
  57. reg.value = readl(drvdata->base + reg.offset);
  58. check_retval(copy_to_user(args, &reg, sizeof(reg)));
  59. bm_info("%s addr 0x%08x val 0x%08x\n", __func__, reg.offset, reg.value);
  60. return 0;
  61. }
  62. int bm_csi_reset(struct bm_csi_drvdata *drvdata, void *__user args)
  63. {
  64. bm_info("%s: csi reset success\n", __func__);
  65. dw_csi_soc_reset();
  66. dw_mipi_csi_reset(&drvdata->csi_dev);
  67. dw_dphy_reset(drvdata->dphy->phy);
  68. return 0;
  69. }
  70. static uint32_t csi_power_on_sta = 0;
  71. int bm_csi_en_power(struct bm_csi_drvdata *drvdata)
  72. {
  73. bm_info("%s: csi set power\n", __func__);
  74. csi_power_on_sta = 1;
  75. dw_mipi_csi_s_power(&drvdata->csi_dev, csi_power_on_sta);
  76. return 0;
  77. }
  78. int bm_csi_dis_power(struct bm_csi_drvdata *drvdata)
  79. {
  80. bm_info("%s: csi set power\n", __func__);
  81. csi_power_on_sta = 0;
  82. dw_mipi_csi_s_power(&drvdata->csi_dev, csi_power_on_sta);
  83. return 0;
  84. }
  85. int bm_csi_set_power(struct bm_csi_drvdata *drvdata, void *__user args)
  86. {
  87. bm_info("%s: csi set power\n", __func__);
  88. check_retval(copy_from_user(&csi_power_on_sta, args, sizeof(csi_power_on_sta)));
  89. dw_mipi_csi_s_power(&drvdata->csi_dev, csi_power_on_sta);
  90. return 0;
  91. }
  92. int bm_csi_get_power(struct bm_csi_drvdata *drvdata, void *__user args)
  93. {
  94. bm_info("%s: csi get power\n", __func__);
  95. check_retval(copy_to_user(args, &csi_power_on_sta, sizeof(csi_power_on_sta)));
  96. return 0;
  97. }
  98. int bm_csi_set_clock(struct bm_csi_drvdata *drvdata, void *__user args)
  99. {
  100. struct dw_dphy_rx *dphy = drvdata->dphy;
  101. bm_info("%s: \n", __func__);
  102. check_retval(copy_from_user(&dphy->dphy_freq, args, sizeof(dphy->dphy_freq)));
  103. return 0;
  104. }
  105. int bm_csi_get_clock(struct bm_csi_drvdata *drvdata, void *__user args)
  106. {
  107. struct dw_dphy_rx *dphy = drvdata->dphy;
  108. bm_info("%s: \n", __func__);
  109. check_retval(copy_to_user(args, &dphy->dphy_freq, sizeof(dphy->dphy_freq)));
  110. return 0;
  111. }
  112. int bm_csi_set_pixclk(struct bm_csi_drvdata *drvdata, void *__user args)
  113. {
  114. uint32_t freq_hz = 0;
  115. bm_info("%s: \n", __func__);
  116. check_retval(copy_from_user(&freq_hz, args, sizeof(freq_hz)));
  117. return dw_csi_set_pixclk(freq_hz);
  118. }
  119. int bm_csi_get_pixclk(struct bm_csi_drvdata *drvdata, void *__user args)
  120. {
  121. uint32_t freq_hz = 0;
  122. bm_info("%s: \n", __func__);
  123. dw_csi_get_pixclk(&freq_hz);
  124. check_retval(copy_to_user(args, &freq_hz, sizeof(freq_hz)));
  125. return 0;
  126. }
  127. int bm_csi_set_stream(struct bm_csi_drvdata *drvdata, void *__user args)
  128. {
  129. bm_info("%s: \n", __func__);
  130. return 0;
  131. }
  132. int bm_csi_get_stream(struct bm_csi_drvdata *drvdata, void *__user args)
  133. {
  134. bm_info("%s: \n", __func__);
  135. check_retval(copy_to_user(args, &csi_power_on_sta, sizeof(csi_power_on_sta)));
  136. return 0;
  137. }
  138. int bm_csi_set_fmt(struct bm_csi_drvdata *drvdata, void *__user args)
  139. {
  140. struct dw_csi *csi_dev = &drvdata->csi_dev;
  141. u8 dt = 0;
  142. //struct csi_format_context fmt;
  143. bm_info("%s: \n", __func__);
  144. check_retval(copy_from_user(&dt, args, sizeof(dt)));
  145. /*
  146. csi_dev->fmt->mbus_code = fmt.format;
  147. csi_dev->fmt->width = fmt.width;
  148. csi_dev->fmt->height = fmt.height;
  149. */
  150. csi_dev->ipi_dt = dt;
  151. dw_mipi_csi_set_ipi_fmt(csi_dev);
  152. /*
  153. if(fmt.height > 0 && fmt.width > 0) {
  154. csi_dev->hw.ipi_color_mode = COLOR16;
  155. csi_dev->hw.ipi_auto_flush = 1;
  156. csi_dev->hw.ipi_adv_features = LINE_EVENT_SELECTION(EVSELAUTO);
  157. csi_dev->hw.htotal = fmt.width + csi_dev->hw.hsa + csi_dev->hw.hbp + csi_dev->hw.hsd;
  158. csi_dev->hw.vactive = fmt.height;
  159. csi_dev->hw.output = 0;
  160. }
  161. */
  162. return 0;
  163. }
  164. int bm_csi_get_fmt(struct bm_csi_drvdata *drvdata, void *__user args)
  165. {
  166. struct dw_csi *csi_dev = &drvdata->csi_dev;
  167. struct csi_format_context fmt;
  168. bm_info("%s: \n", __func__);
  169. fmt.format = csi_dev->fmt->mbus_code;
  170. fmt.height = csi_dev->fmt->height;
  171. fmt.width = csi_dev->fmt->width;
  172. check_retval(copy_to_user(args, &fmt, sizeof(fmt)));
  173. return 0;
  174. }
  175. int bm_csi_set_vc_select(struct bm_csi_drvdata *drvdata, void *__user args)
  176. {
  177. struct csi_vc_select_context vc;
  178. struct dw_csi *csi_dev = &drvdata->csi_dev;
  179. bm_info("%s: \n", __func__);
  180. check_retval(copy_from_user(&vc, args, sizeof(vc)));
  181. if (vc.ipi_idx == 1) {
  182. csi_dev->hw.ipi1_en = true;
  183. csi_dev->hw.virtual_ch = vc.vc_ch;
  184. } else if (vc.ipi_idx == 2) {
  185. csi_dev->hw.ipi2_en = true;
  186. csi_dev->hw.ipi2_virtual_ch = vc.vc_ch;
  187. } else if (vc.ipi_idx == 3) {
  188. csi_dev->hw.ipi3_en = true;
  189. csi_dev->hw.ipi3_virtual_ch = vc.vc_ch;
  190. }
  191. return 0;
  192. }
  193. int bm_csi_ipi_enable(struct bm_csi_drvdata *drvdata, void *__user args)
  194. {
  195. int ipi_idx;
  196. struct dw_csi *csi_dev = &drvdata->csi_dev;
  197. bm_info("%s: \n", __func__);
  198. check_retval(copy_from_user(&ipi_idx, args, sizeof(ipi_idx)));
  199. if (ipi_idx == 1) {
  200. csi_dev->hw.ipi1_en = true;
  201. } else if (ipi_idx == 2) {
  202. csi_dev->hw.ipi2_en = true;
  203. } else if (ipi_idx == 3) {
  204. csi_dev->hw.ipi3_en = true;
  205. }
  206. dw_mipi_csi_start(csi_dev);
  207. return 0;
  208. }
  209. int bm_csi_ipi_disable(struct bm_csi_drvdata *drvdata, void *__user args)
  210. {
  211. int ipi_idx;
  212. struct dw_csi *csi_dev = &drvdata->csi_dev;
  213. bm_info("%s: \n", __func__);
  214. check_retval(copy_from_user(&ipi_idx, args, sizeof(ipi_idx)));
  215. if (ipi_idx == 1) {
  216. csi_dev->hw.ipi1_en = 0;
  217. } else if (ipi_idx == 2) {
  218. csi_dev->hw.ipi2_en = 0;
  219. } else if (ipi_idx == 3) {
  220. csi_dev->hw.ipi3_en = 0;
  221. }
  222. dw_mipi_csi_stop(csi_dev);
  223. return 0;
  224. }
  225. int bm_csi_get_vc_select(struct bm_csi_drvdata *drvdata, void *__user args)
  226. {
  227. struct csi_vc_select_context vc;
  228. struct dw_csi *csi_dev = &drvdata->csi_dev;
  229. bm_info("%s: \n", __func__);
  230. if (vc.ipi_idx == 1) {
  231. vc.vc_ch = csi_dev->hw.virtual_ch;
  232. } else if (vc.ipi_idx == 2) {
  233. vc.vc_ch = csi_dev->hw.ipi2_virtual_ch;
  234. } else if (vc.ipi_idx == 3) {
  235. vc.vc_ch = csi_dev->hw.ipi3_virtual_ch;
  236. }
  237. check_retval(copy_to_user(args, &vc, sizeof(vc)));
  238. return 0;
  239. }
  240. int bm_csi_set_lane_cfg(struct bm_csi_drvdata *drvdata, void *__user args)
  241. {
  242. struct dw_csi *csi_dev = &drvdata->csi_dev;
  243. bm_info("%s: \n", __func__);
  244. check_retval(copy_from_user(&csi_dev->hw.num_lanes, args, sizeof(csi_dev->hw.num_lanes)));
  245. return 0;
  246. }
  247. typedef struct {
  248. int ipi_idx;
  249. int val;
  250. } dw_csi_hsx_cfg_t;
  251. int bm_csi_set_hsa(struct bm_csi_drvdata *drvdata, void *__user args)
  252. {
  253. struct dw_csi *csi_dev = &drvdata->csi_dev;
  254. dw_csi_hsx_cfg_t cfg;
  255. bm_info("%s: \n", __func__);
  256. check_retval(copy_from_user(&cfg, args, sizeof(cfg)));
  257. if (cfg.ipi_idx == 1) {
  258. csi_dev->hw.hsa = cfg.val;
  259. } else if(cfg.ipi_idx == 2) {
  260. csi_dev->hw.ipi2_hsa = cfg.val;
  261. } else if(cfg.ipi_idx == 3) {
  262. csi_dev->hw.ipi3_hsa = cfg.val;
  263. } else {
  264. return -1;
  265. }
  266. return 0;
  267. }
  268. int bm_csi_set_hbp(struct bm_csi_drvdata *drvdata, void *__user args)
  269. {
  270. struct dw_csi *csi_dev = &drvdata->csi_dev;
  271. dw_csi_hsx_cfg_t cfg;
  272. bm_info("%s: \n", __func__);
  273. check_retval(copy_from_user(&cfg, args, sizeof(cfg)));
  274. if (cfg.ipi_idx == 1) {
  275. csi_dev->hw.hbp = cfg.val;
  276. } else if(cfg.ipi_idx == 2) {
  277. csi_dev->hw.ipi2_hbp = cfg.val;
  278. } else if(cfg.ipi_idx == 3) {
  279. csi_dev->hw.ipi3_hbp = cfg.val;
  280. } else {
  281. return -1;
  282. }
  283. return 0;
  284. }
  285. int bm_csi_set_hsd(struct bm_csi_drvdata *drvdata, void *__user args)
  286. {
  287. struct dw_csi *csi_dev = &drvdata->csi_dev;
  288. dw_csi_hsx_cfg_t cfg;
  289. bm_info("%s: \n", __func__);
  290. check_retval(copy_from_user(&cfg, args, sizeof(cfg)));
  291. if (cfg.ipi_idx == 1) {
  292. csi_dev->hw.hsd = cfg.val;
  293. } else if(cfg.ipi_idx == 2) {
  294. csi_dev->hw.ipi2_hsd = cfg.val;
  295. } else if(cfg.ipi_idx == 3) {
  296. csi_dev->hw.ipi3_hsd = cfg.val;
  297. } else {
  298. return -1;
  299. }
  300. return 0;
  301. }