fimc-reg.c 21 KB

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