fimc-reg.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788
  1. /*
  2. * Register interface file for Samsung Camera Interface (FIMC) driver
  3. *
  4. * Copyright (C) 2010 - 2012 Samsung Electronics Co., Ltd.
  5. * 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/io.h>
  12. #include <linux/delay.h>
  13. #include <media/s5p_fimc.h>
  14. #include "fimc-reg.h"
  15. #include "fimc-core.h"
  16. void fimc_hw_reset(struct fimc_dev *dev)
  17. {
  18. u32 cfg;
  19. cfg = readl(dev->regs + FIMC_REG_CISRCFMT);
  20. cfg |= FIMC_REG_CISRCFMT_ITU601_8BIT;
  21. writel(cfg, dev->regs + FIMC_REG_CISRCFMT);
  22. /* Software reset. */
  23. cfg = readl(dev->regs + FIMC_REG_CIGCTRL);
  24. cfg |= (FIMC_REG_CIGCTRL_SWRST | FIMC_REG_CIGCTRL_IRQ_LEVEL);
  25. writel(cfg, dev->regs + FIMC_REG_CIGCTRL);
  26. udelay(10);
  27. cfg = readl(dev->regs + FIMC_REG_CIGCTRL);
  28. cfg &= ~FIMC_REG_CIGCTRL_SWRST;
  29. writel(cfg, dev->regs + FIMC_REG_CIGCTRL);
  30. if (dev->variant->out_buf_count > 4)
  31. fimc_hw_set_dma_seq(dev, 0xF);
  32. }
  33. static u32 fimc_hw_get_in_flip(struct fimc_ctx *ctx)
  34. {
  35. u32 flip = FIMC_REG_MSCTRL_FLIP_NORMAL;
  36. if (ctx->hflip)
  37. flip = FIMC_REG_MSCTRL_FLIP_X_MIRROR;
  38. if (ctx->vflip)
  39. flip = FIMC_REG_MSCTRL_FLIP_Y_MIRROR;
  40. if (ctx->rotation <= 90)
  41. return flip;
  42. return (flip ^ FIMC_REG_MSCTRL_FLIP_180) & FIMC_REG_MSCTRL_FLIP_180;
  43. }
  44. static u32 fimc_hw_get_target_flip(struct fimc_ctx *ctx)
  45. {
  46. u32 flip = FIMC_REG_CITRGFMT_FLIP_NORMAL;
  47. if (ctx->hflip)
  48. flip |= FIMC_REG_CITRGFMT_FLIP_X_MIRROR;
  49. if (ctx->vflip)
  50. flip |= FIMC_REG_CITRGFMT_FLIP_Y_MIRROR;
  51. if (ctx->rotation <= 90)
  52. return flip;
  53. return (flip ^ FIMC_REG_CITRGFMT_FLIP_180) & FIMC_REG_CITRGFMT_FLIP_180;
  54. }
  55. void fimc_hw_set_rotation(struct fimc_ctx *ctx)
  56. {
  57. u32 cfg, flip;
  58. struct fimc_dev *dev = ctx->fimc_dev;
  59. cfg = readl(dev->regs + FIMC_REG_CITRGFMT);
  60. cfg &= ~(FIMC_REG_CITRGFMT_INROT90 | FIMC_REG_CITRGFMT_OUTROT90 |
  61. FIMC_REG_CITRGFMT_FLIP_180);
  62. /*
  63. * The input and output rotator cannot work simultaneously.
  64. * Use the output rotator in output DMA mode or the input rotator
  65. * in direct fifo output mode.
  66. */
  67. if (ctx->rotation == 90 || ctx->rotation == 270) {
  68. if (ctx->out_path == FIMC_IO_LCDFIFO)
  69. cfg |= FIMC_REG_CITRGFMT_INROT90;
  70. else
  71. cfg |= FIMC_REG_CITRGFMT_OUTROT90;
  72. }
  73. if (ctx->out_path == FIMC_IO_DMA) {
  74. cfg |= fimc_hw_get_target_flip(ctx);
  75. writel(cfg, dev->regs + FIMC_REG_CITRGFMT);
  76. } else {
  77. /* LCD FIFO path */
  78. flip = readl(dev->regs + FIMC_REG_MSCTRL);
  79. flip &= ~FIMC_REG_MSCTRL_FLIP_MASK;
  80. flip |= fimc_hw_get_in_flip(ctx);
  81. writel(flip, dev->regs + FIMC_REG_MSCTRL);
  82. }
  83. }
  84. void fimc_hw_set_target_format(struct fimc_ctx *ctx)
  85. {
  86. u32 cfg;
  87. struct fimc_dev *dev = ctx->fimc_dev;
  88. struct fimc_frame *frame = &ctx->d_frame;
  89. dbg("w= %d, h= %d color: %d", frame->width,
  90. frame->height, frame->fmt->color);
  91. cfg = readl(dev->regs + FIMC_REG_CITRGFMT);
  92. cfg &= ~(FIMC_REG_CITRGFMT_FMT_MASK | FIMC_REG_CITRGFMT_HSIZE_MASK |
  93. FIMC_REG_CITRGFMT_VSIZE_MASK);
  94. switch (frame->fmt->color) {
  95. case FIMC_FMT_RGB444...FIMC_FMT_RGB888:
  96. cfg |= FIMC_REG_CITRGFMT_RGB;
  97. break;
  98. case FIMC_FMT_YCBCR420:
  99. cfg |= FIMC_REG_CITRGFMT_YCBCR420;
  100. break;
  101. case FIMC_FMT_YCBYCR422...FIMC_FMT_CRYCBY422:
  102. if (frame->fmt->colplanes == 1)
  103. cfg |= FIMC_REG_CITRGFMT_YCBCR422_1P;
  104. else
  105. cfg |= FIMC_REG_CITRGFMT_YCBCR422;
  106. break;
  107. default:
  108. break;
  109. }
  110. if (ctx->rotation == 90 || ctx->rotation == 270)
  111. cfg |= (frame->height << 16) | frame->width;
  112. else
  113. cfg |= (frame->width << 16) | frame->height;
  114. writel(cfg, dev->regs + FIMC_REG_CITRGFMT);
  115. cfg = readl(dev->regs + FIMC_REG_CITAREA);
  116. cfg &= ~FIMC_REG_CITAREA_MASK;
  117. cfg |= (frame->width * frame->height);
  118. writel(cfg, dev->regs + FIMC_REG_CITAREA);
  119. }
  120. static void fimc_hw_set_out_dma_size(struct fimc_ctx *ctx)
  121. {
  122. struct fimc_dev *dev = ctx->fimc_dev;
  123. struct fimc_frame *frame = &ctx->d_frame;
  124. u32 cfg;
  125. cfg = (frame->f_height << 16) | frame->f_width;
  126. writel(cfg, dev->regs + FIMC_REG_ORGOSIZE);
  127. /* Select color space conversion equation (HD/SD size).*/
  128. cfg = readl(dev->regs + FIMC_REG_CIGCTRL);
  129. if (frame->f_width >= 1280) /* HD */
  130. cfg |= FIMC_REG_CIGCTRL_CSC_ITU601_709;
  131. else /* SD */
  132. cfg &= ~FIMC_REG_CIGCTRL_CSC_ITU601_709;
  133. writel(cfg, dev->regs + FIMC_REG_CIGCTRL);
  134. }
  135. void fimc_hw_set_out_dma(struct fimc_ctx *ctx)
  136. {
  137. struct fimc_dev *dev = ctx->fimc_dev;
  138. struct fimc_frame *frame = &ctx->d_frame;
  139. struct fimc_dma_offset *offset = &frame->dma_offset;
  140. struct fimc_fmt *fmt = frame->fmt;
  141. u32 cfg;
  142. /* Set the input dma offsets. */
  143. cfg = (offset->y_v << 16) | offset->y_h;
  144. writel(cfg, dev->regs + FIMC_REG_CIOYOFF);
  145. cfg = (offset->cb_v << 16) | offset->cb_h;
  146. writel(cfg, dev->regs + FIMC_REG_CIOCBOFF);
  147. cfg = (offset->cr_v << 16) | offset->cr_h;
  148. writel(cfg, dev->regs + FIMC_REG_CIOCROFF);
  149. fimc_hw_set_out_dma_size(ctx);
  150. /* Configure chroma components order. */
  151. cfg = readl(dev->regs + FIMC_REG_CIOCTRL);
  152. cfg &= ~(FIMC_REG_CIOCTRL_ORDER2P_MASK |
  153. FIMC_REG_CIOCTRL_ORDER422_MASK |
  154. FIMC_REG_CIOCTRL_YCBCR_PLANE_MASK |
  155. FIMC_REG_CIOCTRL_RGB16FMT_MASK);
  156. if (fmt->colplanes == 1)
  157. cfg |= ctx->out_order_1p;
  158. else if (fmt->colplanes == 2)
  159. cfg |= ctx->out_order_2p | FIMC_REG_CIOCTRL_YCBCR_2PLANE;
  160. else if (fmt->colplanes == 3)
  161. cfg |= FIMC_REG_CIOCTRL_YCBCR_3PLANE;
  162. if (fmt->color == FIMC_FMT_RGB565)
  163. cfg |= FIMC_REG_CIOCTRL_RGB565;
  164. else if (fmt->color == FIMC_FMT_RGB555)
  165. cfg |= FIMC_REG_CIOCTRL_ARGB1555;
  166. else if (fmt->color == FIMC_FMT_RGB444)
  167. cfg |= FIMC_REG_CIOCTRL_ARGB4444;
  168. writel(cfg, dev->regs + FIMC_REG_CIOCTRL);
  169. }
  170. static void fimc_hw_en_autoload(struct fimc_dev *dev, int enable)
  171. {
  172. u32 cfg = readl(dev->regs + FIMC_REG_ORGISIZE);
  173. if (enable)
  174. cfg |= FIMC_REG_CIREAL_ISIZE_AUTOLOAD_EN;
  175. else
  176. cfg &= ~FIMC_REG_CIREAL_ISIZE_AUTOLOAD_EN;
  177. writel(cfg, dev->regs + FIMC_REG_ORGISIZE);
  178. }
  179. void fimc_hw_en_lastirq(struct fimc_dev *dev, int enable)
  180. {
  181. u32 cfg = readl(dev->regs + FIMC_REG_CIOCTRL);
  182. if (enable)
  183. cfg |= FIMC_REG_CIOCTRL_LASTIRQ_ENABLE;
  184. else
  185. cfg &= ~FIMC_REG_CIOCTRL_LASTIRQ_ENABLE;
  186. writel(cfg, dev->regs + FIMC_REG_CIOCTRL);
  187. }
  188. void fimc_hw_set_prescaler(struct fimc_ctx *ctx)
  189. {
  190. struct fimc_dev *dev = ctx->fimc_dev;
  191. struct fimc_scaler *sc = &ctx->scaler;
  192. u32 cfg, shfactor;
  193. shfactor = 10 - (sc->hfactor + sc->vfactor);
  194. cfg = shfactor << 28;
  195. cfg |= (sc->pre_hratio << 16) | sc->pre_vratio;
  196. writel(cfg, dev->regs + FIMC_REG_CISCPRERATIO);
  197. cfg = (sc->pre_dst_width << 16) | sc->pre_dst_height;
  198. writel(cfg, dev->regs + FIMC_REG_CISCPREDST);
  199. }
  200. static void fimc_hw_set_scaler(struct fimc_ctx *ctx)
  201. {
  202. struct fimc_dev *dev = ctx->fimc_dev;
  203. struct fimc_scaler *sc = &ctx->scaler;
  204. struct fimc_frame *src_frame = &ctx->s_frame;
  205. struct fimc_frame *dst_frame = &ctx->d_frame;
  206. u32 cfg = readl(dev->regs + FIMC_REG_CISCCTRL);
  207. cfg &= ~(FIMC_REG_CISCCTRL_CSCR2Y_WIDE | FIMC_REG_CISCCTRL_CSCY2R_WIDE |
  208. FIMC_REG_CISCCTRL_SCALEUP_H | FIMC_REG_CISCCTRL_SCALEUP_V |
  209. FIMC_REG_CISCCTRL_SCALERBYPASS | FIMC_REG_CISCCTRL_ONE2ONE |
  210. FIMC_REG_CISCCTRL_INRGB_FMT_MASK | FIMC_REG_CISCCTRL_OUTRGB_FMT_MASK |
  211. FIMC_REG_CISCCTRL_INTERLACE | FIMC_REG_CISCCTRL_RGB_EXT);
  212. if (!(ctx->flags & FIMC_COLOR_RANGE_NARROW))
  213. cfg |= (FIMC_REG_CISCCTRL_CSCR2Y_WIDE |
  214. FIMC_REG_CISCCTRL_CSCY2R_WIDE);
  215. if (!sc->enabled)
  216. cfg |= FIMC_REG_CISCCTRL_SCALERBYPASS;
  217. if (sc->scaleup_h)
  218. cfg |= FIMC_REG_CISCCTRL_SCALEUP_H;
  219. if (sc->scaleup_v)
  220. cfg |= FIMC_REG_CISCCTRL_SCALEUP_V;
  221. if (sc->copy_mode)
  222. cfg |= FIMC_REG_CISCCTRL_ONE2ONE;
  223. if (ctx->in_path == FIMC_IO_DMA) {
  224. switch (src_frame->fmt->color) {
  225. case FIMC_FMT_RGB565:
  226. cfg |= FIMC_REG_CISCCTRL_INRGB_FMT_RGB565;
  227. break;
  228. case FIMC_FMT_RGB666:
  229. cfg |= FIMC_REG_CISCCTRL_INRGB_FMT_RGB666;
  230. break;
  231. case FIMC_FMT_RGB888:
  232. cfg |= FIMC_REG_CISCCTRL_INRGB_FMT_RGB888;
  233. break;
  234. }
  235. }
  236. if (ctx->out_path == FIMC_IO_DMA) {
  237. u32 color = dst_frame->fmt->color;
  238. if (color >= FIMC_FMT_RGB444 && color <= FIMC_FMT_RGB565)
  239. cfg |= FIMC_REG_CISCCTRL_OUTRGB_FMT_RGB565;
  240. else if (color == FIMC_FMT_RGB666)
  241. cfg |= FIMC_REG_CISCCTRL_OUTRGB_FMT_RGB666;
  242. else if (color == FIMC_FMT_RGB888)
  243. cfg |= FIMC_REG_CISCCTRL_OUTRGB_FMT_RGB888;
  244. } else {
  245. cfg |= FIMC_REG_CISCCTRL_OUTRGB_FMT_RGB888;
  246. if (ctx->flags & FIMC_SCAN_MODE_INTERLACED)
  247. cfg |= FIMC_REG_CISCCTRL_INTERLACE;
  248. }
  249. writel(cfg, dev->regs + FIMC_REG_CISCCTRL);
  250. }
  251. void fimc_hw_set_mainscaler(struct fimc_ctx *ctx)
  252. {
  253. struct fimc_dev *dev = ctx->fimc_dev;
  254. struct fimc_variant *variant = dev->variant;
  255. struct fimc_scaler *sc = &ctx->scaler;
  256. u32 cfg;
  257. dbg("main_hratio= 0x%X main_vratio= 0x%X",
  258. sc->main_hratio, sc->main_vratio);
  259. fimc_hw_set_scaler(ctx);
  260. cfg = readl(dev->regs + FIMC_REG_CISCCTRL);
  261. cfg &= ~(FIMC_REG_CISCCTRL_MHRATIO_MASK |
  262. FIMC_REG_CISCCTRL_MVRATIO_MASK);
  263. if (variant->has_mainscaler_ext) {
  264. cfg |= FIMC_REG_CISCCTRL_MHRATIO_EXT(sc->main_hratio);
  265. cfg |= FIMC_REG_CISCCTRL_MVRATIO_EXT(sc->main_vratio);
  266. writel(cfg, dev->regs + FIMC_REG_CISCCTRL);
  267. cfg = readl(dev->regs + FIMC_REG_CIEXTEN);
  268. cfg &= ~(FIMC_REG_CIEXTEN_MVRATIO_EXT_MASK |
  269. FIMC_REG_CIEXTEN_MHRATIO_EXT_MASK);
  270. cfg |= FIMC_REG_CIEXTEN_MHRATIO_EXT(sc->main_hratio);
  271. cfg |= FIMC_REG_CIEXTEN_MVRATIO_EXT(sc->main_vratio);
  272. writel(cfg, dev->regs + FIMC_REG_CIEXTEN);
  273. } else {
  274. cfg |= FIMC_REG_CISCCTRL_MHRATIO(sc->main_hratio);
  275. cfg |= FIMC_REG_CISCCTRL_MVRATIO(sc->main_vratio);
  276. writel(cfg, dev->regs + FIMC_REG_CISCCTRL);
  277. }
  278. }
  279. void fimc_hw_en_capture(struct fimc_ctx *ctx)
  280. {
  281. struct fimc_dev *dev = ctx->fimc_dev;
  282. u32 cfg = readl(dev->regs + FIMC_REG_CIIMGCPT);
  283. if (ctx->out_path == FIMC_IO_DMA) {
  284. /* one shot mode */
  285. cfg |= FIMC_REG_CIIMGCPT_CPT_FREN_ENABLE |
  286. FIMC_REG_CIIMGCPT_IMGCPTEN;
  287. } else {
  288. /* Continuous frame capture mode (freerun). */
  289. cfg &= ~(FIMC_REG_CIIMGCPT_CPT_FREN_ENABLE |
  290. FIMC_REG_CIIMGCPT_CPT_FRMOD_CNT);
  291. cfg |= FIMC_REG_CIIMGCPT_IMGCPTEN;
  292. }
  293. if (ctx->scaler.enabled)
  294. cfg |= FIMC_REG_CIIMGCPT_IMGCPTEN_SC;
  295. cfg |= FIMC_REG_CIIMGCPT_IMGCPTEN;
  296. writel(cfg, dev->regs + FIMC_REG_CIIMGCPT);
  297. }
  298. void fimc_hw_set_effect(struct fimc_ctx *ctx)
  299. {
  300. struct fimc_dev *dev = ctx->fimc_dev;
  301. struct fimc_effect *effect = &ctx->effect;
  302. u32 cfg = 0;
  303. if (effect->type != FIMC_REG_CIIMGEFF_FIN_BYPASS) {
  304. cfg |= FIMC_REG_CIIMGEFF_IE_SC_AFTER |
  305. FIMC_REG_CIIMGEFF_IE_ENABLE;
  306. cfg |= effect->type;
  307. if (effect->type == FIMC_REG_CIIMGEFF_FIN_ARBITRARY)
  308. cfg |= (effect->pat_cb << 13) | effect->pat_cr;
  309. }
  310. writel(cfg, dev->regs + FIMC_REG_CIIMGEFF);
  311. }
  312. void fimc_hw_set_rgb_alpha(struct fimc_ctx *ctx)
  313. {
  314. struct fimc_dev *dev = ctx->fimc_dev;
  315. struct fimc_frame *frame = &ctx->d_frame;
  316. u32 cfg;
  317. if (!(frame->fmt->flags & FMT_HAS_ALPHA))
  318. return;
  319. cfg = readl(dev->regs + FIMC_REG_CIOCTRL);
  320. cfg &= ~FIMC_REG_CIOCTRL_ALPHA_OUT_MASK;
  321. cfg |= (frame->alpha << 4);
  322. writel(cfg, dev->regs + FIMC_REG_CIOCTRL);
  323. }
  324. static void fimc_hw_set_in_dma_size(struct fimc_ctx *ctx)
  325. {
  326. struct fimc_dev *dev = ctx->fimc_dev;
  327. struct fimc_frame *frame = &ctx->s_frame;
  328. u32 cfg_o = 0;
  329. u32 cfg_r = 0;
  330. if (FIMC_IO_LCDFIFO == ctx->out_path)
  331. cfg_r |= FIMC_REG_CIREAL_ISIZE_AUTOLOAD_EN;
  332. cfg_o |= (frame->f_height << 16) | frame->f_width;
  333. cfg_r |= (frame->height << 16) | frame->width;
  334. writel(cfg_o, dev->regs + FIMC_REG_ORGISIZE);
  335. writel(cfg_r, dev->regs + FIMC_REG_CIREAL_ISIZE);
  336. }
  337. void fimc_hw_set_in_dma(struct fimc_ctx *ctx)
  338. {
  339. struct fimc_dev *dev = ctx->fimc_dev;
  340. struct fimc_frame *frame = &ctx->s_frame;
  341. struct fimc_dma_offset *offset = &frame->dma_offset;
  342. u32 cfg;
  343. /* Set the pixel offsets. */
  344. cfg = (offset->y_v << 16) | offset->y_h;
  345. writel(cfg, dev->regs + FIMC_REG_CIIYOFF);
  346. cfg = (offset->cb_v << 16) | offset->cb_h;
  347. writel(cfg, dev->regs + FIMC_REG_CIICBOFF);
  348. cfg = (offset->cr_v << 16) | offset->cr_h;
  349. writel(cfg, dev->regs + FIMC_REG_CIICROFF);
  350. /* Input original and real size. */
  351. fimc_hw_set_in_dma_size(ctx);
  352. /* Use DMA autoload only in FIFO mode. */
  353. fimc_hw_en_autoload(dev, ctx->out_path == FIMC_IO_LCDFIFO);
  354. /* Set the input DMA to process single frame only. */
  355. cfg = readl(dev->regs + FIMC_REG_MSCTRL);
  356. cfg &= ~(FIMC_REG_MSCTRL_INFORMAT_MASK
  357. | FIMC_REG_MSCTRL_IN_BURST_COUNT_MASK
  358. | FIMC_REG_MSCTRL_INPUT_MASK
  359. | FIMC_REG_MSCTRL_C_INT_IN_MASK
  360. | FIMC_REG_MSCTRL_2P_IN_ORDER_MASK);
  361. cfg |= (FIMC_REG_MSCTRL_IN_BURST_COUNT(4)
  362. | FIMC_REG_MSCTRL_INPUT_MEMORY
  363. | FIMC_REG_MSCTRL_FIFO_CTRL_FULL);
  364. switch (frame->fmt->color) {
  365. case FIMC_FMT_RGB565...FIMC_FMT_RGB888:
  366. cfg |= FIMC_REG_MSCTRL_INFORMAT_RGB;
  367. break;
  368. case FIMC_FMT_YCBCR420:
  369. cfg |= FIMC_REG_MSCTRL_INFORMAT_YCBCR420;
  370. if (frame->fmt->colplanes == 2)
  371. cfg |= ctx->in_order_2p | FIMC_REG_MSCTRL_C_INT_IN_2PLANE;
  372. else
  373. cfg |= FIMC_REG_MSCTRL_C_INT_IN_3PLANE;
  374. break;
  375. case FIMC_FMT_YCBYCR422...FIMC_FMT_CRYCBY422:
  376. if (frame->fmt->colplanes == 1) {
  377. cfg |= ctx->in_order_1p
  378. | FIMC_REG_MSCTRL_INFORMAT_YCBCR422_1P;
  379. } else {
  380. cfg |= FIMC_REG_MSCTRL_INFORMAT_YCBCR422;
  381. if (frame->fmt->colplanes == 2)
  382. cfg |= ctx->in_order_2p
  383. | FIMC_REG_MSCTRL_C_INT_IN_2PLANE;
  384. else
  385. cfg |= FIMC_REG_MSCTRL_C_INT_IN_3PLANE;
  386. }
  387. break;
  388. default:
  389. break;
  390. }
  391. writel(cfg, dev->regs + FIMC_REG_MSCTRL);
  392. /* Input/output DMA linear/tiled mode. */
  393. cfg = readl(dev->regs + FIMC_REG_CIDMAPARAM);
  394. cfg &= ~FIMC_REG_CIDMAPARAM_TILE_MASK;
  395. if (tiled_fmt(ctx->s_frame.fmt))
  396. cfg |= FIMC_REG_CIDMAPARAM_R_64X32;
  397. if (tiled_fmt(ctx->d_frame.fmt))
  398. cfg |= FIMC_REG_CIDMAPARAM_W_64X32;
  399. writel(cfg, dev->regs + FIMC_REG_CIDMAPARAM);
  400. }
  401. void fimc_hw_set_input_path(struct fimc_ctx *ctx)
  402. {
  403. struct fimc_dev *dev = ctx->fimc_dev;
  404. u32 cfg = readl(dev->regs + FIMC_REG_MSCTRL);
  405. cfg &= ~FIMC_REG_MSCTRL_INPUT_MASK;
  406. if (ctx->in_path == FIMC_IO_DMA)
  407. cfg |= FIMC_REG_MSCTRL_INPUT_MEMORY;
  408. else
  409. cfg |= FIMC_REG_MSCTRL_INPUT_EXTCAM;
  410. writel(cfg, dev->regs + FIMC_REG_MSCTRL);
  411. }
  412. void fimc_hw_set_output_path(struct fimc_ctx *ctx)
  413. {
  414. struct fimc_dev *dev = ctx->fimc_dev;
  415. u32 cfg = readl(dev->regs + FIMC_REG_CISCCTRL);
  416. cfg &= ~FIMC_REG_CISCCTRL_LCDPATHEN_FIFO;
  417. if (ctx->out_path == FIMC_IO_LCDFIFO)
  418. cfg |= FIMC_REG_CISCCTRL_LCDPATHEN_FIFO;
  419. writel(cfg, dev->regs + FIMC_REG_CISCCTRL);
  420. }
  421. void fimc_hw_set_input_addr(struct fimc_dev *dev, struct fimc_addr *paddr)
  422. {
  423. u32 cfg = readl(dev->regs + FIMC_REG_CIREAL_ISIZE);
  424. cfg |= FIMC_REG_CIREAL_ISIZE_ADDR_CH_DIS;
  425. writel(cfg, dev->regs + FIMC_REG_CIREAL_ISIZE);
  426. writel(paddr->y, dev->regs + FIMC_REG_CIIYSA(0));
  427. writel(paddr->cb, dev->regs + FIMC_REG_CIICBSA(0));
  428. writel(paddr->cr, dev->regs + FIMC_REG_CIICRSA(0));
  429. cfg &= ~FIMC_REG_CIREAL_ISIZE_ADDR_CH_DIS;
  430. writel(cfg, dev->regs + FIMC_REG_CIREAL_ISIZE);
  431. }
  432. void fimc_hw_set_output_addr(struct fimc_dev *dev,
  433. struct fimc_addr *paddr, int index)
  434. {
  435. int i = (index == -1) ? 0 : index;
  436. do {
  437. writel(paddr->y, dev->regs + FIMC_REG_CIOYSA(i));
  438. writel(paddr->cb, dev->regs + FIMC_REG_CIOCBSA(i));
  439. writel(paddr->cr, dev->regs + FIMC_REG_CIOCRSA(i));
  440. dbg("dst_buf[%d]: 0x%X, cb: 0x%X, cr: 0x%X",
  441. i, paddr->y, paddr->cb, paddr->cr);
  442. } while (index == -1 && ++i < FIMC_MAX_OUT_BUFS);
  443. }
  444. int fimc_hw_set_camera_polarity(struct fimc_dev *fimc,
  445. struct s5p_fimc_isp_info *cam)
  446. {
  447. u32 cfg = readl(fimc->regs + FIMC_REG_CIGCTRL);
  448. cfg &= ~(FIMC_REG_CIGCTRL_INVPOLPCLK | FIMC_REG_CIGCTRL_INVPOLVSYNC |
  449. FIMC_REG_CIGCTRL_INVPOLHREF | FIMC_REG_CIGCTRL_INVPOLHSYNC |
  450. FIMC_REG_CIGCTRL_INVPOLFIELD);
  451. if (cam->flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)
  452. cfg |= FIMC_REG_CIGCTRL_INVPOLPCLK;
  453. if (cam->flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)
  454. cfg |= FIMC_REG_CIGCTRL_INVPOLVSYNC;
  455. if (cam->flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)
  456. cfg |= FIMC_REG_CIGCTRL_INVPOLHREF;
  457. if (cam->flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)
  458. cfg |= FIMC_REG_CIGCTRL_INVPOLHSYNC;
  459. if (cam->flags & V4L2_MBUS_FIELD_EVEN_LOW)
  460. cfg |= FIMC_REG_CIGCTRL_INVPOLFIELD;
  461. writel(cfg, fimc->regs + FIMC_REG_CIGCTRL);
  462. return 0;
  463. }
  464. struct mbus_pixfmt_desc {
  465. u32 pixelcode;
  466. u32 cisrcfmt;
  467. u16 bus_width;
  468. };
  469. static const struct mbus_pixfmt_desc pix_desc[] = {
  470. { V4L2_MBUS_FMT_YUYV8_2X8, FIMC_REG_CISRCFMT_ORDER422_YCBYCR, 8 },
  471. { V4L2_MBUS_FMT_YVYU8_2X8, FIMC_REG_CISRCFMT_ORDER422_YCRYCB, 8 },
  472. { V4L2_MBUS_FMT_VYUY8_2X8, FIMC_REG_CISRCFMT_ORDER422_CRYCBY, 8 },
  473. { V4L2_MBUS_FMT_UYVY8_2X8, FIMC_REG_CISRCFMT_ORDER422_CBYCRY, 8 },
  474. };
  475. int fimc_hw_set_camera_source(struct fimc_dev *fimc,
  476. struct s5p_fimc_isp_info *cam)
  477. {
  478. struct fimc_frame *f = &fimc->vid_cap.ctx->s_frame;
  479. u32 cfg = 0;
  480. u32 bus_width;
  481. int i;
  482. if (cam->bus_type == FIMC_ITU_601 || cam->bus_type == FIMC_ITU_656) {
  483. for (i = 0; i < ARRAY_SIZE(pix_desc); i++) {
  484. if (fimc->vid_cap.mf.code == pix_desc[i].pixelcode) {
  485. cfg = pix_desc[i].cisrcfmt;
  486. bus_width = pix_desc[i].bus_width;
  487. break;
  488. }
  489. }
  490. if (i == ARRAY_SIZE(pix_desc)) {
  491. v4l2_err(&fimc->vid_cap.vfd,
  492. "Camera color format not supported: %d\n",
  493. fimc->vid_cap.mf.code);
  494. return -EINVAL;
  495. }
  496. if (cam->bus_type == FIMC_ITU_601) {
  497. if (bus_width == 8)
  498. cfg |= FIMC_REG_CISRCFMT_ITU601_8BIT;
  499. else if (bus_width == 16)
  500. cfg |= FIMC_REG_CISRCFMT_ITU601_16BIT;
  501. } /* else defaults to ITU-R BT.656 8-bit */
  502. } else if (cam->bus_type == FIMC_MIPI_CSI2) {
  503. if (fimc_fmt_is_user_defined(f->fmt->color))
  504. cfg |= FIMC_REG_CISRCFMT_ITU601_8BIT;
  505. }
  506. cfg |= (f->o_width << 16) | f->o_height;
  507. writel(cfg, fimc->regs + FIMC_REG_CISRCFMT);
  508. return 0;
  509. }
  510. void fimc_hw_set_camera_offset(struct fimc_dev *fimc, struct fimc_frame *f)
  511. {
  512. u32 hoff2, voff2;
  513. u32 cfg = readl(fimc->regs + FIMC_REG_CIWDOFST);
  514. cfg &= ~(FIMC_REG_CIWDOFST_HOROFF_MASK | FIMC_REG_CIWDOFST_VEROFF_MASK);
  515. cfg |= FIMC_REG_CIWDOFST_OFF_EN |
  516. (f->offs_h << 16) | f->offs_v;
  517. writel(cfg, fimc->regs + FIMC_REG_CIWDOFST);
  518. /* See CIWDOFSTn register description in the datasheet for details. */
  519. hoff2 = f->o_width - f->width - f->offs_h;
  520. voff2 = f->o_height - f->height - f->offs_v;
  521. cfg = (hoff2 << 16) | voff2;
  522. writel(cfg, fimc->regs + FIMC_REG_CIWDOFST2);
  523. }
  524. int fimc_hw_set_camera_type(struct fimc_dev *fimc,
  525. struct s5p_fimc_isp_info *cam)
  526. {
  527. u32 cfg, tmp;
  528. struct fimc_vid_cap *vid_cap = &fimc->vid_cap;
  529. u32 csis_data_alignment = 32;
  530. cfg = readl(fimc->regs + FIMC_REG_CIGCTRL);
  531. /* Select ITU B interface, disable Writeback path and test pattern. */
  532. cfg &= ~(FIMC_REG_CIGCTRL_TESTPAT_MASK | FIMC_REG_CIGCTRL_SELCAM_ITU_A |
  533. FIMC_REG_CIGCTRL_SELCAM_MIPI | FIMC_REG_CIGCTRL_CAMIF_SELWB |
  534. FIMC_REG_CIGCTRL_SELCAM_MIPI_A | FIMC_REG_CIGCTRL_CAM_JPEG);
  535. switch (cam->bus_type) {
  536. case FIMC_MIPI_CSI2:
  537. cfg |= FIMC_REG_CIGCTRL_SELCAM_MIPI;
  538. if (cam->mux_id == 0)
  539. cfg |= FIMC_REG_CIGCTRL_SELCAM_MIPI_A;
  540. /* TODO: add remaining supported formats. */
  541. switch (vid_cap->mf.code) {
  542. case V4L2_MBUS_FMT_VYUY8_2X8:
  543. tmp = FIMC_REG_CSIIMGFMT_YCBCR422_8BIT;
  544. break;
  545. case V4L2_MBUS_FMT_JPEG_1X8:
  546. case V4L2_MBUS_FMT_S5C_UYVY_JPEG_1X8:
  547. tmp = FIMC_REG_CSIIMGFMT_USER(1);
  548. cfg |= FIMC_REG_CIGCTRL_CAM_JPEG;
  549. break;
  550. default:
  551. v4l2_err(&vid_cap->vfd,
  552. "Not supported camera pixel format: %#x\n",
  553. vid_cap->mf.code);
  554. return -EINVAL;
  555. }
  556. tmp |= (csis_data_alignment == 32) << 8;
  557. writel(tmp, fimc->regs + FIMC_REG_CSIIMGFMT);
  558. break;
  559. case FIMC_ITU_601...FIMC_ITU_656:
  560. if (cam->mux_id == 0) /* ITU-A, ITU-B: 0, 1 */
  561. cfg |= FIMC_REG_CIGCTRL_SELCAM_ITU_A;
  562. break;
  563. case FIMC_LCD_WB:
  564. cfg |= FIMC_REG_CIGCTRL_CAMIF_SELWB;
  565. break;
  566. default:
  567. v4l2_err(&vid_cap->vfd, "Invalid camera bus type selected\n");
  568. return -EINVAL;
  569. }
  570. writel(cfg, fimc->regs + FIMC_REG_CIGCTRL);
  571. return 0;
  572. }
  573. void fimc_hw_clear_irq(struct fimc_dev *dev)
  574. {
  575. u32 cfg = readl(dev->regs + FIMC_REG_CIGCTRL);
  576. cfg |= FIMC_REG_CIGCTRL_IRQ_CLR;
  577. writel(cfg, dev->regs + FIMC_REG_CIGCTRL);
  578. }
  579. void fimc_hw_enable_scaler(struct fimc_dev *dev, bool on)
  580. {
  581. u32 cfg = readl(dev->regs + FIMC_REG_CISCCTRL);
  582. if (on)
  583. cfg |= FIMC_REG_CISCCTRL_SCALERSTART;
  584. else
  585. cfg &= ~FIMC_REG_CISCCTRL_SCALERSTART;
  586. writel(cfg, dev->regs + FIMC_REG_CISCCTRL);
  587. }
  588. void fimc_hw_activate_input_dma(struct fimc_dev *dev, bool on)
  589. {
  590. u32 cfg = readl(dev->regs + FIMC_REG_MSCTRL);
  591. if (on)
  592. cfg |= FIMC_REG_MSCTRL_ENVID;
  593. else
  594. cfg &= ~FIMC_REG_MSCTRL_ENVID;
  595. writel(cfg, dev->regs + FIMC_REG_MSCTRL);
  596. }
  597. void fimc_hw_dis_capture(struct fimc_dev *dev)
  598. {
  599. u32 cfg = readl(dev->regs + FIMC_REG_CIIMGCPT);
  600. cfg &= ~(FIMC_REG_CIIMGCPT_IMGCPTEN | FIMC_REG_CIIMGCPT_IMGCPTEN_SC);
  601. writel(cfg, dev->regs + FIMC_REG_CIIMGCPT);
  602. }
  603. /* Return an index to the buffer actually being written. */
  604. s32 fimc_hw_get_frame_index(struct fimc_dev *dev)
  605. {
  606. s32 reg;
  607. if (dev->variant->has_cistatus2) {
  608. reg = readl(dev->regs + FIMC_REG_CISTATUS2) & 0x3f;
  609. return reg - 1;
  610. }
  611. reg = readl(dev->regs + FIMC_REG_CISTATUS);
  612. return (reg & FIMC_REG_CISTATUS_FRAMECNT_MASK) >>
  613. FIMC_REG_CISTATUS_FRAMECNT_SHIFT;
  614. }
  615. /* Return an index to the buffer being written previously. */
  616. s32 fimc_hw_get_prev_frame_index(struct fimc_dev *dev)
  617. {
  618. s32 reg;
  619. if (!dev->variant->has_cistatus2)
  620. return -1;
  621. reg = readl(dev->regs + FIMC_REG_CISTATUS2);
  622. return ((reg >> 7) & 0x3f) - 1;
  623. }
  624. /* Locking: the caller holds fimc->slock */
  625. void fimc_activate_capture(struct fimc_ctx *ctx)
  626. {
  627. fimc_hw_enable_scaler(ctx->fimc_dev, ctx->scaler.enabled);
  628. fimc_hw_en_capture(ctx);
  629. }
  630. void fimc_deactivate_capture(struct fimc_dev *fimc)
  631. {
  632. fimc_hw_en_lastirq(fimc, true);
  633. fimc_hw_dis_capture(fimc);
  634. fimc_hw_enable_scaler(fimc, false);
  635. fimc_hw_en_lastirq(fimc, false);
  636. }