fimc-lite-reg.c 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Register interface file for EXYNOS FIMC-LITE (camera interface) driver
  4. *
  5. * Copyright (C) 2012 Samsung Electronics Co., Ltd.
  6. * Author: Sylwester Nawrocki <s.nawrocki@samsung.com>
  7. */
  8. #include <linux/bitops.h>
  9. #include <linux/delay.h>
  10. #include <linux/io.h>
  11. #include <media/drv-intf/exynos-fimc.h>
  12. #include "fimc-lite-reg.h"
  13. #include "fimc-lite.h"
  14. #include "fimc-core.h"
  15. #define FLITE_RESET_TIMEOUT 50 /* in ms */
  16. void flite_hw_reset(struct fimc_lite *dev)
  17. {
  18. unsigned long end = jiffies + msecs_to_jiffies(FLITE_RESET_TIMEOUT);
  19. u32 cfg;
  20. cfg = readl(dev->regs + FLITE_REG_CIGCTRL);
  21. cfg |= FLITE_REG_CIGCTRL_SWRST_REQ;
  22. writel(cfg, dev->regs + FLITE_REG_CIGCTRL);
  23. while (time_is_after_jiffies(end)) {
  24. cfg = readl(dev->regs + FLITE_REG_CIGCTRL);
  25. if (cfg & FLITE_REG_CIGCTRL_SWRST_RDY)
  26. break;
  27. usleep_range(1000, 5000);
  28. }
  29. cfg |= FLITE_REG_CIGCTRL_SWRST;
  30. writel(cfg, dev->regs + FLITE_REG_CIGCTRL);
  31. }
  32. void flite_hw_clear_pending_irq(struct fimc_lite *dev)
  33. {
  34. u32 cfg = readl(dev->regs + FLITE_REG_CISTATUS);
  35. cfg &= ~FLITE_REG_CISTATUS_IRQ_CAM;
  36. writel(cfg, dev->regs + FLITE_REG_CISTATUS);
  37. }
  38. u32 flite_hw_get_interrupt_source(struct fimc_lite *dev)
  39. {
  40. u32 intsrc = readl(dev->regs + FLITE_REG_CISTATUS);
  41. return intsrc & FLITE_REG_CISTATUS_IRQ_MASK;
  42. }
  43. void flite_hw_clear_last_capture_end(struct fimc_lite *dev)
  44. {
  45. u32 cfg = readl(dev->regs + FLITE_REG_CISTATUS2);
  46. cfg &= ~FLITE_REG_CISTATUS2_LASTCAPEND;
  47. writel(cfg, dev->regs + FLITE_REG_CISTATUS2);
  48. }
  49. void flite_hw_set_interrupt_mask(struct fimc_lite *dev)
  50. {
  51. u32 cfg, intsrc;
  52. /* Select interrupts to be enabled for each output mode */
  53. if (atomic_read(&dev->out_path) == FIMC_IO_DMA) {
  54. intsrc = FLITE_REG_CIGCTRL_IRQ_OVFEN |
  55. FLITE_REG_CIGCTRL_IRQ_LASTEN |
  56. FLITE_REG_CIGCTRL_IRQ_STARTEN |
  57. FLITE_REG_CIGCTRL_IRQ_ENDEN;
  58. } else {
  59. /* An output to the FIMC-IS */
  60. intsrc = FLITE_REG_CIGCTRL_IRQ_OVFEN |
  61. FLITE_REG_CIGCTRL_IRQ_LASTEN;
  62. }
  63. cfg = readl(dev->regs + FLITE_REG_CIGCTRL);
  64. cfg |= FLITE_REG_CIGCTRL_IRQ_DISABLE_MASK;
  65. cfg &= ~intsrc;
  66. writel(cfg, dev->regs + FLITE_REG_CIGCTRL);
  67. }
  68. void flite_hw_capture_start(struct fimc_lite *dev)
  69. {
  70. u32 cfg = readl(dev->regs + FLITE_REG_CIIMGCPT);
  71. cfg |= FLITE_REG_CIIMGCPT_IMGCPTEN;
  72. writel(cfg, dev->regs + FLITE_REG_CIIMGCPT);
  73. }
  74. void flite_hw_capture_stop(struct fimc_lite *dev)
  75. {
  76. u32 cfg = readl(dev->regs + FLITE_REG_CIIMGCPT);
  77. cfg &= ~FLITE_REG_CIIMGCPT_IMGCPTEN;
  78. writel(cfg, dev->regs + FLITE_REG_CIIMGCPT);
  79. }
  80. /*
  81. * Test pattern (color bars) enable/disable. External sensor
  82. * pixel clock must be active for the test pattern to work.
  83. */
  84. void flite_hw_set_test_pattern(struct fimc_lite *dev, bool on)
  85. {
  86. u32 cfg = readl(dev->regs + FLITE_REG_CIGCTRL);
  87. if (on)
  88. cfg |= FLITE_REG_CIGCTRL_TEST_PATTERN_COLORBAR;
  89. else
  90. cfg &= ~FLITE_REG_CIGCTRL_TEST_PATTERN_COLORBAR;
  91. writel(cfg, dev->regs + FLITE_REG_CIGCTRL);
  92. }
  93. static const u32 src_pixfmt_map[8][3] = {
  94. { MEDIA_BUS_FMT_YUYV8_2X8, FLITE_REG_CISRCSIZE_ORDER422_IN_YCBYCR,
  95. FLITE_REG_CIGCTRL_YUV422_1P },
  96. { MEDIA_BUS_FMT_YVYU8_2X8, FLITE_REG_CISRCSIZE_ORDER422_IN_YCRYCB,
  97. FLITE_REG_CIGCTRL_YUV422_1P },
  98. { MEDIA_BUS_FMT_UYVY8_2X8, FLITE_REG_CISRCSIZE_ORDER422_IN_CBYCRY,
  99. FLITE_REG_CIGCTRL_YUV422_1P },
  100. { MEDIA_BUS_FMT_VYUY8_2X8, FLITE_REG_CISRCSIZE_ORDER422_IN_CRYCBY,
  101. FLITE_REG_CIGCTRL_YUV422_1P },
  102. { MEDIA_BUS_FMT_SGRBG8_1X8, 0, FLITE_REG_CIGCTRL_RAW8 },
  103. { MEDIA_BUS_FMT_SGRBG10_1X10, 0, FLITE_REG_CIGCTRL_RAW10 },
  104. { MEDIA_BUS_FMT_SGRBG12_1X12, 0, FLITE_REG_CIGCTRL_RAW12 },
  105. { MEDIA_BUS_FMT_JPEG_1X8, 0, FLITE_REG_CIGCTRL_USER(1) },
  106. };
  107. /* Set camera input pixel format and resolution */
  108. void flite_hw_set_source_format(struct fimc_lite *dev, struct flite_frame *f)
  109. {
  110. u32 pixelcode = f->fmt->mbus_code;
  111. int i = ARRAY_SIZE(src_pixfmt_map);
  112. u32 cfg;
  113. while (--i) {
  114. if (src_pixfmt_map[i][0] == pixelcode)
  115. break;
  116. }
  117. if (i == 0 && src_pixfmt_map[i][0] != pixelcode) {
  118. v4l2_err(&dev->ve.vdev,
  119. "Unsupported pixel code, falling back to %#08x\n",
  120. src_pixfmt_map[i][0]);
  121. }
  122. cfg = readl(dev->regs + FLITE_REG_CIGCTRL);
  123. cfg &= ~FLITE_REG_CIGCTRL_FMT_MASK;
  124. cfg |= src_pixfmt_map[i][2];
  125. writel(cfg, dev->regs + FLITE_REG_CIGCTRL);
  126. cfg = readl(dev->regs + FLITE_REG_CISRCSIZE);
  127. cfg &= ~(FLITE_REG_CISRCSIZE_ORDER422_MASK |
  128. FLITE_REG_CISRCSIZE_SIZE_CAM_MASK);
  129. cfg |= (f->f_width << 16) | f->f_height;
  130. cfg |= src_pixfmt_map[i][1];
  131. writel(cfg, dev->regs + FLITE_REG_CISRCSIZE);
  132. }
  133. /* Set the camera host input window offsets (cropping) */
  134. void flite_hw_set_window_offset(struct fimc_lite *dev, struct flite_frame *f)
  135. {
  136. u32 hoff2, voff2;
  137. u32 cfg;
  138. cfg = readl(dev->regs + FLITE_REG_CIWDOFST);
  139. cfg &= ~FLITE_REG_CIWDOFST_OFST_MASK;
  140. cfg |= (f->rect.left << 16) | f->rect.top;
  141. cfg |= FLITE_REG_CIWDOFST_WINOFSEN;
  142. writel(cfg, dev->regs + FLITE_REG_CIWDOFST);
  143. hoff2 = f->f_width - f->rect.width - f->rect.left;
  144. voff2 = f->f_height - f->rect.height - f->rect.top;
  145. cfg = (hoff2 << 16) | voff2;
  146. writel(cfg, dev->regs + FLITE_REG_CIWDOFST2);
  147. }
  148. /* Select camera port (A, B) */
  149. static void flite_hw_set_camera_port(struct fimc_lite *dev, int id)
  150. {
  151. u32 cfg = readl(dev->regs + FLITE_REG_CIGENERAL);
  152. if (id == 0)
  153. cfg &= ~FLITE_REG_CIGENERAL_CAM_B;
  154. else
  155. cfg |= FLITE_REG_CIGENERAL_CAM_B;
  156. writel(cfg, dev->regs + FLITE_REG_CIGENERAL);
  157. }
  158. /* Select serial or parallel bus, camera port (A,B) and set signals polarity */
  159. void flite_hw_set_camera_bus(struct fimc_lite *dev,
  160. struct fimc_source_info *si)
  161. {
  162. u32 cfg = readl(dev->regs + FLITE_REG_CIGCTRL);
  163. unsigned int flags = si->flags;
  164. if (si->sensor_bus_type != FIMC_BUS_TYPE_MIPI_CSI2) {
  165. cfg &= ~(FLITE_REG_CIGCTRL_SELCAM_MIPI |
  166. FLITE_REG_CIGCTRL_INVPOLPCLK |
  167. FLITE_REG_CIGCTRL_INVPOLVSYNC |
  168. FLITE_REG_CIGCTRL_INVPOLHREF);
  169. if (flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)
  170. cfg |= FLITE_REG_CIGCTRL_INVPOLPCLK;
  171. if (flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)
  172. cfg |= FLITE_REG_CIGCTRL_INVPOLVSYNC;
  173. if (flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)
  174. cfg |= FLITE_REG_CIGCTRL_INVPOLHREF;
  175. } else {
  176. cfg |= FLITE_REG_CIGCTRL_SELCAM_MIPI;
  177. }
  178. writel(cfg, dev->regs + FLITE_REG_CIGCTRL);
  179. flite_hw_set_camera_port(dev, si->mux_id);
  180. }
  181. static void flite_hw_set_pack12(struct fimc_lite *dev, int on)
  182. {
  183. u32 cfg = readl(dev->regs + FLITE_REG_CIODMAFMT);
  184. cfg &= ~FLITE_REG_CIODMAFMT_PACK12;
  185. if (on)
  186. cfg |= FLITE_REG_CIODMAFMT_PACK12;
  187. writel(cfg, dev->regs + FLITE_REG_CIODMAFMT);
  188. }
  189. static void flite_hw_set_out_order(struct fimc_lite *dev, struct flite_frame *f)
  190. {
  191. static const u32 pixcode[4][2] = {
  192. { MEDIA_BUS_FMT_YUYV8_2X8, FLITE_REG_CIODMAFMT_YCBYCR },
  193. { MEDIA_BUS_FMT_YVYU8_2X8, FLITE_REG_CIODMAFMT_YCRYCB },
  194. { MEDIA_BUS_FMT_UYVY8_2X8, FLITE_REG_CIODMAFMT_CBYCRY },
  195. { MEDIA_BUS_FMT_VYUY8_2X8, FLITE_REG_CIODMAFMT_CRYCBY },
  196. };
  197. u32 cfg = readl(dev->regs + FLITE_REG_CIODMAFMT);
  198. int i = ARRAY_SIZE(pixcode);
  199. while (--i)
  200. if (pixcode[i][0] == f->fmt->mbus_code)
  201. break;
  202. cfg &= ~FLITE_REG_CIODMAFMT_YCBCR_ORDER_MASK;
  203. writel(cfg | pixcode[i][1], dev->regs + FLITE_REG_CIODMAFMT);
  204. }
  205. void flite_hw_set_dma_window(struct fimc_lite *dev, struct flite_frame *f)
  206. {
  207. u32 cfg;
  208. /* Maximum output pixel size */
  209. cfg = readl(dev->regs + FLITE_REG_CIOCAN);
  210. cfg &= ~FLITE_REG_CIOCAN_MASK;
  211. cfg |= (f->f_height << 16) | f->f_width;
  212. writel(cfg, dev->regs + FLITE_REG_CIOCAN);
  213. /* DMA offsets */
  214. cfg = readl(dev->regs + FLITE_REG_CIOOFF);
  215. cfg &= ~FLITE_REG_CIOOFF_MASK;
  216. cfg |= (f->rect.top << 16) | f->rect.left;
  217. writel(cfg, dev->regs + FLITE_REG_CIOOFF);
  218. }
  219. void flite_hw_set_dma_buffer(struct fimc_lite *dev, struct flite_buffer *buf)
  220. {
  221. unsigned int index;
  222. u32 cfg;
  223. if (dev->dd->max_dma_bufs == 1)
  224. index = 0;
  225. else
  226. index = buf->index;
  227. if (index == 0)
  228. writel(buf->paddr, dev->regs + FLITE_REG_CIOSA);
  229. else
  230. writel(buf->paddr, dev->regs + FLITE_REG_CIOSAN(index - 1));
  231. cfg = readl(dev->regs + FLITE_REG_CIFCNTSEQ);
  232. cfg |= BIT(index);
  233. writel(cfg, dev->regs + FLITE_REG_CIFCNTSEQ);
  234. }
  235. void flite_hw_mask_dma_buffer(struct fimc_lite *dev, u32 index)
  236. {
  237. u32 cfg;
  238. if (dev->dd->max_dma_bufs == 1)
  239. index = 0;
  240. cfg = readl(dev->regs + FLITE_REG_CIFCNTSEQ);
  241. cfg &= ~BIT(index);
  242. writel(cfg, dev->regs + FLITE_REG_CIFCNTSEQ);
  243. }
  244. /* Enable/disable output DMA, set output pixel size and offsets (composition) */
  245. void flite_hw_set_output_dma(struct fimc_lite *dev, struct flite_frame *f,
  246. bool enable)
  247. {
  248. u32 cfg = readl(dev->regs + FLITE_REG_CIGCTRL);
  249. if (!enable) {
  250. cfg |= FLITE_REG_CIGCTRL_ODMA_DISABLE;
  251. writel(cfg, dev->regs + FLITE_REG_CIGCTRL);
  252. return;
  253. }
  254. cfg &= ~FLITE_REG_CIGCTRL_ODMA_DISABLE;
  255. writel(cfg, dev->regs + FLITE_REG_CIGCTRL);
  256. flite_hw_set_out_order(dev, f);
  257. flite_hw_set_dma_window(dev, f);
  258. flite_hw_set_pack12(dev, 0);
  259. }
  260. void flite_hw_dump_regs(struct fimc_lite *dev, const char *label)
  261. {
  262. struct {
  263. u32 offset;
  264. const char * const name;
  265. } registers[] = {
  266. { 0x00, "CISRCSIZE" },
  267. { 0x04, "CIGCTRL" },
  268. { 0x08, "CIIMGCPT" },
  269. { 0x0c, "CICPTSEQ" },
  270. { 0x10, "CIWDOFST" },
  271. { 0x14, "CIWDOFST2" },
  272. { 0x18, "CIODMAFMT" },
  273. { 0x20, "CIOCAN" },
  274. { 0x24, "CIOOFF" },
  275. { 0x30, "CIOSA" },
  276. { 0x40, "CISTATUS" },
  277. { 0x44, "CISTATUS2" },
  278. { 0xf0, "CITHOLD" },
  279. { 0xfc, "CIGENERAL" },
  280. };
  281. u32 i;
  282. v4l2_info(&dev->subdev, "--- %s ---\n", label);
  283. for (i = 0; i < ARRAY_SIZE(registers); i++) {
  284. u32 cfg = readl(dev->regs + registers[i].offset);
  285. v4l2_info(&dev->subdev, "%9s: 0x%08x\n",
  286. registers[i].name, cfg);
  287. }
  288. }