fimc-lite-reg.c 9.4 KB

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