fimc-reg.c 22 KB

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