camif-regs.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606
  1. /*
  2. * Samsung s3c24xx/s3c64xx SoC CAMIF driver
  3. *
  4. * Copyright (C) 2012 Sylwester Nawrocki <sylvester.nawrocki@gmail.com>
  5. * Copyright (C) 2012 Tomasz Figa <tomasz.figa@gmail.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. #define pr_fmt(fmt) "%s:%d " fmt, __func__, __LINE__
  12. #include <linux/delay.h>
  13. #include "camif-regs.h"
  14. #define camif_write(_camif, _off, _val) writel(_val, (_camif)->io_base + (_off))
  15. #define camif_read(_camif, _off) readl((_camif)->io_base + (_off))
  16. void camif_hw_reset(struct camif_dev *camif)
  17. {
  18. u32 cfg;
  19. cfg = camif_read(camif, S3C_CAMIF_REG_CISRCFMT);
  20. cfg |= CISRCFMT_ITU601_8BIT;
  21. camif_write(camif, S3C_CAMIF_REG_CISRCFMT, cfg);
  22. /* S/W reset */
  23. cfg = camif_read(camif, S3C_CAMIF_REG_CIGCTRL);
  24. cfg |= CIGCTRL_SWRST;
  25. if (camif->variant->ip_revision == S3C6410_CAMIF_IP_REV)
  26. cfg |= CIGCTRL_IRQ_LEVEL;
  27. camif_write(camif, S3C_CAMIF_REG_CIGCTRL, cfg);
  28. udelay(10);
  29. cfg = camif_read(camif, S3C_CAMIF_REG_CIGCTRL);
  30. cfg &= ~CIGCTRL_SWRST;
  31. camif_write(camif, S3C_CAMIF_REG_CIGCTRL, cfg);
  32. udelay(10);
  33. }
  34. void camif_hw_clear_pending_irq(struct camif_vp *vp)
  35. {
  36. u32 cfg = camif_read(vp->camif, S3C_CAMIF_REG_CIGCTRL);
  37. cfg |= CIGCTRL_IRQ_CLR(vp->id);
  38. camif_write(vp->camif, S3C_CAMIF_REG_CIGCTRL, cfg);
  39. }
  40. /*
  41. * Sets video test pattern (off, color bar, horizontal or vertical gradient).
  42. * External sensor pixel clock must be active for the test pattern to work.
  43. */
  44. void camif_hw_set_test_pattern(struct camif_dev *camif, unsigned int pattern)
  45. {
  46. u32 cfg = camif_read(camif, S3C_CAMIF_REG_CIGCTRL);
  47. cfg &= ~CIGCTRL_TESTPATTERN_MASK;
  48. cfg |= (pattern << 27);
  49. camif_write(camif, S3C_CAMIF_REG_CIGCTRL, cfg);
  50. }
  51. void camif_hw_set_effect(struct camif_dev *camif, unsigned int effect,
  52. unsigned int cr, unsigned int cb)
  53. {
  54. static const struct v4l2_control colorfx[] = {
  55. { V4L2_COLORFX_NONE, CIIMGEFF_FIN_BYPASS },
  56. { V4L2_COLORFX_BW, CIIMGEFF_FIN_ARBITRARY },
  57. { V4L2_COLORFX_SEPIA, CIIMGEFF_FIN_ARBITRARY },
  58. { V4L2_COLORFX_NEGATIVE, CIIMGEFF_FIN_NEGATIVE },
  59. { V4L2_COLORFX_ART_FREEZE, CIIMGEFF_FIN_ARTFREEZE },
  60. { V4L2_COLORFX_EMBOSS, CIIMGEFF_FIN_EMBOSSING },
  61. { V4L2_COLORFX_SILHOUETTE, CIIMGEFF_FIN_SILHOUETTE },
  62. { V4L2_COLORFX_SET_CBCR, CIIMGEFF_FIN_ARBITRARY },
  63. };
  64. unsigned int i, cfg;
  65. for (i = 0; i < ARRAY_SIZE(colorfx); i++)
  66. if (colorfx[i].id == effect)
  67. break;
  68. if (i == ARRAY_SIZE(colorfx))
  69. return;
  70. cfg = camif_read(camif, S3C_CAMIF_REG_CIIMGEFF(camif->vp->offset));
  71. /* Set effect */
  72. cfg &= ~CIIMGEFF_FIN_MASK;
  73. cfg |= colorfx[i].value;
  74. /* Set both paths */
  75. if (camif->variant->ip_revision >= S3C6400_CAMIF_IP_REV) {
  76. if (effect == V4L2_COLORFX_NONE)
  77. cfg &= ~CIIMGEFF_IE_ENABLE_MASK;
  78. else
  79. cfg |= CIIMGEFF_IE_ENABLE_MASK;
  80. }
  81. cfg &= ~CIIMGEFF_PAT_CBCR_MASK;
  82. cfg |= cr | (cb << 13);
  83. camif_write(camif, S3C_CAMIF_REG_CIIMGEFF(camif->vp->offset), cfg);
  84. }
  85. static const u32 src_pixfmt_map[8][2] = {
  86. { V4L2_MBUS_FMT_YUYV8_2X8, CISRCFMT_ORDER422_YCBYCR },
  87. { V4L2_MBUS_FMT_YVYU8_2X8, CISRCFMT_ORDER422_YCRYCB },
  88. { V4L2_MBUS_FMT_UYVY8_2X8, CISRCFMT_ORDER422_CBYCRY },
  89. { V4L2_MBUS_FMT_VYUY8_2X8, CISRCFMT_ORDER422_CRYCBY },
  90. };
  91. /* Set camera input pixel format and resolution */
  92. void camif_hw_set_source_format(struct camif_dev *camif)
  93. {
  94. struct v4l2_mbus_framefmt *mf = &camif->mbus_fmt;
  95. unsigned int i = ARRAY_SIZE(src_pixfmt_map);
  96. u32 cfg;
  97. while (i-- >= 0) {
  98. if (src_pixfmt_map[i][0] == mf->code)
  99. break;
  100. }
  101. if (i == 0 && src_pixfmt_map[i][0] != mf->code) {
  102. dev_err(camif->dev,
  103. "Unsupported pixel code, falling back to %#08x\n",
  104. src_pixfmt_map[i][0]);
  105. }
  106. cfg = camif_read(camif, S3C_CAMIF_REG_CISRCFMT);
  107. cfg &= ~(CISRCFMT_ORDER422_MASK | CISRCFMT_SIZE_CAM_MASK);
  108. cfg |= (mf->width << 16) | mf->height;
  109. cfg |= src_pixfmt_map[i][1];
  110. camif_write(camif, S3C_CAMIF_REG_CISRCFMT, cfg);
  111. }
  112. /* Set the camera host input window offsets (cropping) */
  113. void camif_hw_set_camera_crop(struct camif_dev *camif)
  114. {
  115. struct v4l2_mbus_framefmt *mf = &camif->mbus_fmt;
  116. struct v4l2_rect *crop = &camif->camif_crop;
  117. u32 hoff2, voff2;
  118. u32 cfg;
  119. /* Note: s3c244x requirement: left = f_width - rect.width / 2 */
  120. cfg = camif_read(camif, S3C_CAMIF_REG_CIWDOFST);
  121. cfg &= ~(CIWDOFST_OFST_MASK | CIWDOFST_WINOFSEN);
  122. cfg |= (crop->left << 16) | crop->top;
  123. if (crop->left != 0 || crop->top != 0)
  124. cfg |= CIWDOFST_WINOFSEN;
  125. camif_write(camif, S3C_CAMIF_REG_CIWDOFST, cfg);
  126. if (camif->variant->ip_revision == S3C6410_CAMIF_IP_REV) {
  127. hoff2 = mf->width - crop->width - crop->left;
  128. voff2 = mf->height - crop->height - crop->top;
  129. cfg = (hoff2 << 16) | voff2;
  130. camif_write(camif, S3C_CAMIF_REG_CIWDOFST2, cfg);
  131. }
  132. }
  133. void camif_hw_clear_fifo_overflow(struct camif_vp *vp)
  134. {
  135. struct camif_dev *camif = vp->camif;
  136. u32 cfg;
  137. cfg = camif_read(camif, S3C_CAMIF_REG_CIWDOFST);
  138. if (vp->id == 0)
  139. cfg |= (CIWDOFST_CLROVCOFIY | CIWDOFST_CLROVCOFICB |
  140. CIWDOFST_CLROVCOFICR);
  141. else
  142. cfg |= (/* CIWDOFST_CLROVPRFIY | */ CIWDOFST_CLROVPRFICB |
  143. CIWDOFST_CLROVPRFICR);
  144. camif_write(camif, S3C_CAMIF_REG_CIWDOFST, cfg);
  145. }
  146. /* Set video bus signals polarity */
  147. void camif_hw_set_camera_bus(struct camif_dev *camif)
  148. {
  149. unsigned int flags = camif->pdata.sensor.flags;
  150. u32 cfg = camif_read(camif, S3C_CAMIF_REG_CIGCTRL);
  151. cfg &= ~(CIGCTRL_INVPOLPCLK | CIGCTRL_INVPOLVSYNC |
  152. CIGCTRL_INVPOLHREF | CIGCTRL_INVPOLFIELD);
  153. if (flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)
  154. cfg |= CIGCTRL_INVPOLPCLK;
  155. if (flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)
  156. cfg |= CIGCTRL_INVPOLVSYNC;
  157. /*
  158. * HREF is normally high during frame active data
  159. * transmission and low during horizontal synchronization
  160. * period. Thus HREF active high means HSYNC active low.
  161. */
  162. if (flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH)
  163. cfg |= CIGCTRL_INVPOLHREF; /* HREF active low */
  164. if (camif->variant->ip_revision == S3C6410_CAMIF_IP_REV) {
  165. if (flags & V4L2_MBUS_FIELD_EVEN_LOW)
  166. cfg |= CIGCTRL_INVPOLFIELD;
  167. cfg |= CIGCTRL_FIELDMODE;
  168. }
  169. pr_debug("Setting CIGCTRL to: %#x\n", cfg);
  170. camif_write(camif, S3C_CAMIF_REG_CIGCTRL, cfg);
  171. }
  172. void camif_hw_set_output_addr(struct camif_vp *vp,
  173. struct camif_addr *paddr, int i)
  174. {
  175. struct camif_dev *camif = vp->camif;
  176. camif_write(camif, S3C_CAMIF_REG_CIYSA(vp->id, i), paddr->y);
  177. if (camif->variant->ip_revision == S3C6410_CAMIF_IP_REV
  178. || vp->id == VP_CODEC) {
  179. camif_write(camif, S3C_CAMIF_REG_CICBSA(vp->id, i),
  180. paddr->cb);
  181. camif_write(camif, S3C_CAMIF_REG_CICRSA(vp->id, i),
  182. paddr->cr);
  183. }
  184. pr_debug("dst_buf[%d]: %#X, cb: %#X, cr: %#X\n",
  185. i, paddr->y, paddr->cb, paddr->cr);
  186. }
  187. static void camif_hw_set_out_dma_size(struct camif_vp *vp)
  188. {
  189. struct camif_frame *frame = &vp->out_frame;
  190. u32 cfg;
  191. cfg = camif_read(vp->camif, S3C_CAMIF_REG_CITRGFMT(vp->id, vp->offset));
  192. cfg &= ~CITRGFMT_TARGETSIZE_MASK;
  193. cfg |= (frame->f_width << 16) | frame->f_height;
  194. camif_write(vp->camif, S3C_CAMIF_REG_CITRGFMT(vp->id, vp->offset), cfg);
  195. }
  196. static void camif_get_dma_burst(u32 width, u32 ybpp, u32 *mburst, u32 *rburst)
  197. {
  198. unsigned int nwords = width * ybpp / 4;
  199. unsigned int div, rem;
  200. if (WARN_ON(width < 8 || (width * ybpp) & 7))
  201. return;
  202. for (div = 16; div >= 2; div /= 2) {
  203. if (nwords < div)
  204. continue;
  205. rem = nwords & (div - 1);
  206. if (rem == 0) {
  207. *mburst = div;
  208. *rburst = div;
  209. break;
  210. }
  211. if (rem == div / 2 || rem == div / 4) {
  212. *mburst = div;
  213. *rburst = rem;
  214. break;
  215. }
  216. }
  217. }
  218. void camif_hw_set_output_dma(struct camif_vp *vp)
  219. {
  220. struct camif_dev *camif = vp->camif;
  221. struct camif_frame *frame = &vp->out_frame;
  222. const struct camif_fmt *fmt = vp->out_fmt;
  223. unsigned int ymburst = 0, yrburst = 0;
  224. u32 cfg;
  225. camif_hw_set_out_dma_size(vp);
  226. if (camif->variant->ip_revision == S3C6410_CAMIF_IP_REV) {
  227. struct camif_dma_offset *offset = &frame->dma_offset;
  228. /* Set the input dma offsets. */
  229. cfg = S3C_CISS_OFFS_INITIAL(offset->initial);
  230. cfg |= S3C_CISS_OFFS_LINE(offset->line);
  231. camif_write(camif, S3C_CAMIF_REG_CISSY(vp->id), cfg);
  232. camif_write(camif, S3C_CAMIF_REG_CISSCB(vp->id), cfg);
  233. camif_write(camif, S3C_CAMIF_REG_CISSCR(vp->id), cfg);
  234. }
  235. /* Configure DMA burst values */
  236. camif_get_dma_burst(frame->rect.width, fmt->ybpp, &ymburst, &yrburst);
  237. cfg = camif_read(camif, S3C_CAMIF_REG_CICTRL(vp->id, vp->offset));
  238. cfg &= ~CICTRL_BURST_MASK;
  239. cfg |= CICTRL_YBURST1(ymburst) | CICTRL_YBURST2(yrburst);
  240. cfg |= CICTRL_CBURST1(ymburst / 2) | CICTRL_CBURST2(yrburst / 2);
  241. camif_write(camif, S3C_CAMIF_REG_CICTRL(vp->id, vp->offset), cfg);
  242. pr_debug("ymburst: %u, yrburst: %u\n", ymburst, yrburst);
  243. }
  244. void camif_hw_set_input_path(struct camif_vp *vp)
  245. {
  246. u32 cfg = camif_read(vp->camif, S3C_CAMIF_REG_MSCTRL(vp->id));
  247. cfg &= ~MSCTRL_SEL_DMA_CAM;
  248. camif_write(vp->camif, S3C_CAMIF_REG_MSCTRL(vp->id), cfg);
  249. }
  250. void camif_hw_set_target_format(struct camif_vp *vp)
  251. {
  252. struct camif_dev *camif = vp->camif;
  253. struct camif_frame *frame = &vp->out_frame;
  254. u32 cfg;
  255. pr_debug("fw: %d, fh: %d color: %d\n", frame->f_width,
  256. frame->f_height, vp->out_fmt->color);
  257. cfg = camif_read(camif, S3C_CAMIF_REG_CITRGFMT(vp->id, vp->offset));
  258. cfg &= ~CITRGFMT_TARGETSIZE_MASK;
  259. if (camif->variant->ip_revision == S3C244X_CAMIF_IP_REV) {
  260. /* We currently support only YCbCr 4:2:2 at the camera input */
  261. cfg |= CITRGFMT_IN422;
  262. cfg &= ~CITRGFMT_OUT422;
  263. if (vp->out_fmt->color == IMG_FMT_YCBCR422P)
  264. cfg |= CITRGFMT_OUT422;
  265. } else {
  266. cfg &= ~CITRGFMT_OUTFORMAT_MASK;
  267. switch (vp->out_fmt->color) {
  268. case IMG_FMT_RGB565...IMG_FMT_XRGB8888:
  269. cfg |= CITRGFMT_OUTFORMAT_RGB;
  270. break;
  271. case IMG_FMT_YCBCR420...IMG_FMT_YCRCB420:
  272. cfg |= CITRGFMT_OUTFORMAT_YCBCR420;
  273. break;
  274. case IMG_FMT_YCBCR422P:
  275. cfg |= CITRGFMT_OUTFORMAT_YCBCR422;
  276. break;
  277. case IMG_FMT_YCBYCR422...IMG_FMT_CRYCBY422:
  278. cfg |= CITRGFMT_OUTFORMAT_YCBCR422I;
  279. break;
  280. }
  281. }
  282. /* Rotation is only supported by s3c64xx */
  283. if (vp->rotation == 90 || vp->rotation == 270)
  284. cfg |= (frame->f_height << 16) | frame->f_width;
  285. else
  286. cfg |= (frame->f_width << 16) | frame->f_height;
  287. camif_write(camif, S3C_CAMIF_REG_CITRGFMT(vp->id, vp->offset), cfg);
  288. /* Target area, output pixel width * height */
  289. cfg = camif_read(camif, S3C_CAMIF_REG_CITAREA(vp->id, vp->offset));
  290. cfg &= ~CITAREA_MASK;
  291. cfg |= (frame->f_width * frame->f_height);
  292. camif_write(camif, S3C_CAMIF_REG_CITAREA(vp->id, vp->offset), cfg);
  293. }
  294. void camif_hw_set_flip(struct camif_vp *vp)
  295. {
  296. u32 cfg = camif_read(vp->camif,
  297. S3C_CAMIF_REG_CITRGFMT(vp->id, vp->offset));
  298. cfg &= ~CITRGFMT_FLIP_MASK;
  299. if (vp->hflip)
  300. cfg |= CITRGFMT_FLIP_Y_MIRROR;
  301. if (vp->vflip)
  302. cfg |= CITRGFMT_FLIP_X_MIRROR;
  303. camif_write(vp->camif, S3C_CAMIF_REG_CITRGFMT(vp->id, vp->offset), cfg);
  304. }
  305. static void camif_hw_set_prescaler(struct camif_vp *vp)
  306. {
  307. struct camif_dev *camif = vp->camif;
  308. struct camif_scaler *sc = &vp->scaler;
  309. u32 cfg, shfactor, addr;
  310. addr = S3C_CAMIF_REG_CISCPRERATIO(vp->id, vp->offset);
  311. shfactor = 10 - (sc->h_shift + sc->v_shift);
  312. cfg = shfactor << 28;
  313. cfg |= (sc->pre_h_ratio << 16) | sc->pre_v_ratio;
  314. camif_write(camif, addr, cfg);
  315. cfg = (sc->pre_dst_width << 16) | sc->pre_dst_height;
  316. camif_write(camif, S3C_CAMIF_REG_CISCPREDST(vp->id, vp->offset), cfg);
  317. }
  318. void camif_s3c244x_hw_set_scaler(struct camif_vp *vp)
  319. {
  320. struct camif_dev *camif = vp->camif;
  321. struct camif_scaler *scaler = &vp->scaler;
  322. unsigned int color = vp->out_fmt->color;
  323. u32 cfg;
  324. camif_hw_set_prescaler(vp);
  325. cfg = camif_read(camif, S3C_CAMIF_REG_CISCCTRL(vp->id, vp->offset));
  326. cfg &= ~(CISCCTRL_SCALEUP_MASK | CISCCTRL_SCALERBYPASS |
  327. CISCCTRL_MAIN_RATIO_MASK | CIPRSCCTRL_RGB_FORMAT_24BIT);
  328. if (scaler->enable) {
  329. if (scaler->scaleup_h) {
  330. if (vp->id == VP_CODEC)
  331. cfg |= CISCCTRL_SCALEUP_H;
  332. else
  333. cfg |= CIPRSCCTRL_SCALEUP_H;
  334. }
  335. if (scaler->scaleup_v) {
  336. if (vp->id == VP_CODEC)
  337. cfg |= CISCCTRL_SCALEUP_V;
  338. else
  339. cfg |= CIPRSCCTRL_SCALEUP_V;
  340. }
  341. } else {
  342. if (vp->id == VP_CODEC)
  343. cfg |= CISCCTRL_SCALERBYPASS;
  344. }
  345. cfg |= ((scaler->main_h_ratio & 0x1ff) << 16);
  346. cfg |= scaler->main_v_ratio & 0x1ff;
  347. if (vp->id == VP_PREVIEW) {
  348. if (color == IMG_FMT_XRGB8888)
  349. cfg |= CIPRSCCTRL_RGB_FORMAT_24BIT;
  350. cfg |= CIPRSCCTRL_SAMPLE;
  351. }
  352. camif_write(camif, S3C_CAMIF_REG_CISCCTRL(vp->id, vp->offset), cfg);
  353. pr_debug("main: h_ratio: %#x, v_ratio: %#x",
  354. scaler->main_h_ratio, scaler->main_v_ratio);
  355. }
  356. void camif_s3c64xx_hw_set_scaler(struct camif_vp *vp)
  357. {
  358. struct camif_dev *camif = vp->camif;
  359. struct camif_scaler *scaler = &vp->scaler;
  360. unsigned int color = vp->out_fmt->color;
  361. u32 cfg;
  362. camif_hw_set_prescaler(vp);
  363. cfg = camif_read(camif, S3C_CAMIF_REG_CISCCTRL(vp->id, vp->offset));
  364. cfg &= ~(CISCCTRL_CSCR2Y_WIDE | CISCCTRL_CSCY2R_WIDE
  365. | CISCCTRL_SCALEUP_H | CISCCTRL_SCALEUP_V
  366. | CISCCTRL_SCALERBYPASS | CISCCTRL_ONE2ONE
  367. | CISCCTRL_INRGB_FMT_MASK | CISCCTRL_OUTRGB_FMT_MASK
  368. | CISCCTRL_INTERLACE | CISCCTRL_EXTRGB_EXTENSION
  369. | CISCCTRL_MAIN_RATIO_MASK);
  370. cfg |= (CISCCTRL_CSCR2Y_WIDE | CISCCTRL_CSCY2R_WIDE);
  371. if (!scaler->enable) {
  372. cfg |= CISCCTRL_SCALERBYPASS;
  373. } else {
  374. if (scaler->scaleup_h)
  375. cfg |= CISCCTRL_SCALEUP_H;
  376. if (scaler->scaleup_v)
  377. cfg |= CISCCTRL_SCALEUP_V;
  378. if (scaler->copy)
  379. cfg |= CISCCTRL_ONE2ONE;
  380. }
  381. switch (color) {
  382. case IMG_FMT_RGB666:
  383. cfg |= CISCCTRL_OUTRGB_FMT_RGB666;
  384. break;
  385. case IMG_FMT_XRGB8888:
  386. cfg |= CISCCTRL_OUTRGB_FMT_RGB888;
  387. break;
  388. }
  389. cfg |= (scaler->main_h_ratio & 0x1ff) << 16;
  390. cfg |= scaler->main_v_ratio & 0x1ff;
  391. camif_write(camif, S3C_CAMIF_REG_CISCCTRL(vp->id, vp->offset), cfg);
  392. pr_debug("main: h_ratio: %#x, v_ratio: %#x",
  393. scaler->main_h_ratio, scaler->main_v_ratio);
  394. }
  395. void camif_hw_set_scaler(struct camif_vp *vp)
  396. {
  397. unsigned int ip_rev = vp->camif->variant->ip_revision;
  398. if (ip_rev == S3C244X_CAMIF_IP_REV)
  399. camif_s3c244x_hw_set_scaler(vp);
  400. else
  401. camif_s3c64xx_hw_set_scaler(vp);
  402. }
  403. void camif_hw_enable_scaler(struct camif_vp *vp, bool on)
  404. {
  405. u32 addr = S3C_CAMIF_REG_CISCCTRL(vp->id, vp->offset);
  406. u32 cfg;
  407. cfg = camif_read(vp->camif, addr);
  408. if (on)
  409. cfg |= CISCCTRL_SCALERSTART;
  410. else
  411. cfg &= ~CISCCTRL_SCALERSTART;
  412. camif_write(vp->camif, addr, cfg);
  413. }
  414. void camif_hw_set_lastirq(struct camif_vp *vp, int enable)
  415. {
  416. u32 addr = S3C_CAMIF_REG_CICTRL(vp->id, vp->offset);
  417. u32 cfg;
  418. cfg = camif_read(vp->camif, addr);
  419. if (enable)
  420. cfg |= CICTRL_LASTIRQ_ENABLE;
  421. else
  422. cfg &= ~CICTRL_LASTIRQ_ENABLE;
  423. camif_write(vp->camif, addr, cfg);
  424. }
  425. void camif_hw_enable_capture(struct camif_vp *vp)
  426. {
  427. struct camif_dev *camif = vp->camif;
  428. u32 cfg;
  429. cfg = camif_read(camif, S3C_CAMIF_REG_CIIMGCPT(vp->offset));
  430. camif->stream_count++;
  431. if (camif->variant->ip_revision == S3C6410_CAMIF_IP_REV)
  432. cfg |= CIIMGCPT_CPT_FREN_ENABLE(vp->id);
  433. if (vp->scaler.enable)
  434. cfg |= CIIMGCPT_IMGCPTEN_SC(vp->id);
  435. if (camif->stream_count == 1)
  436. cfg |= CIIMGCPT_IMGCPTEN;
  437. camif_write(camif, S3C_CAMIF_REG_CIIMGCPT(vp->offset), cfg);
  438. pr_debug("CIIMGCPT: %#x, camif->stream_count: %d\n",
  439. cfg, camif->stream_count);
  440. }
  441. void camif_hw_disable_capture(struct camif_vp *vp)
  442. {
  443. struct camif_dev *camif = vp->camif;
  444. u32 cfg;
  445. cfg = camif_read(camif, S3C_CAMIF_REG_CIIMGCPT(vp->offset));
  446. cfg &= ~CIIMGCPT_IMGCPTEN_SC(vp->id);
  447. if (WARN_ON(--(camif->stream_count) < 0))
  448. camif->stream_count = 0;
  449. if (camif->stream_count == 0)
  450. cfg &= ~CIIMGCPT_IMGCPTEN;
  451. pr_debug("CIIMGCPT: %#x, camif->stream_count: %d\n",
  452. cfg, camif->stream_count);
  453. camif_write(camif, S3C_CAMIF_REG_CIIMGCPT(vp->offset), cfg);
  454. }
  455. void camif_hw_dump_regs(struct camif_dev *camif, const char *label)
  456. {
  457. struct {
  458. u32 offset;
  459. const char * const name;
  460. } registers[] = {
  461. { S3C_CAMIF_REG_CISRCFMT, "CISRCFMT" },
  462. { S3C_CAMIF_REG_CIWDOFST, "CIWDOFST" },
  463. { S3C_CAMIF_REG_CIGCTRL, "CIGCTRL" },
  464. { S3C_CAMIF_REG_CIWDOFST2, "CIWDOFST2" },
  465. { S3C_CAMIF_REG_CIYSA(0, 0), "CICOYSA0" },
  466. { S3C_CAMIF_REG_CICBSA(0, 0), "CICOCBSA0" },
  467. { S3C_CAMIF_REG_CICRSA(0, 0), "CICOCRSA0" },
  468. { S3C_CAMIF_REG_CIYSA(0, 1), "CICOYSA1" },
  469. { S3C_CAMIF_REG_CICBSA(0, 1), "CICOCBSA1" },
  470. { S3C_CAMIF_REG_CICRSA(0, 1), "CICOCRSA1" },
  471. { S3C_CAMIF_REG_CIYSA(0, 2), "CICOYSA2" },
  472. { S3C_CAMIF_REG_CICBSA(0, 2), "CICOCBSA2" },
  473. { S3C_CAMIF_REG_CICRSA(0, 2), "CICOCRSA2" },
  474. { S3C_CAMIF_REG_CIYSA(0, 3), "CICOYSA3" },
  475. { S3C_CAMIF_REG_CICBSA(0, 3), "CICOCBSA3" },
  476. { S3C_CAMIF_REG_CICRSA(0, 3), "CICOCRSA3" },
  477. { S3C_CAMIF_REG_CIYSA(1, 0), "CIPRYSA0" },
  478. { S3C_CAMIF_REG_CIYSA(1, 1), "CIPRYSA1" },
  479. { S3C_CAMIF_REG_CIYSA(1, 2), "CIPRYSA2" },
  480. { S3C_CAMIF_REG_CIYSA(1, 3), "CIPRYSA3" },
  481. { S3C_CAMIF_REG_CITRGFMT(0, 0), "CICOTRGFMT" },
  482. { S3C_CAMIF_REG_CITRGFMT(1, 0), "CIPRTRGFMT" },
  483. { S3C_CAMIF_REG_CICTRL(0, 0), "CICOCTRL" },
  484. { S3C_CAMIF_REG_CICTRL(1, 0), "CIPRCTRL" },
  485. { S3C_CAMIF_REG_CISCPREDST(0, 0), "CICOSCPREDST" },
  486. { S3C_CAMIF_REG_CISCPREDST(1, 0), "CIPRSCPREDST" },
  487. { S3C_CAMIF_REG_CISCPRERATIO(0, 0), "CICOSCPRERATIO" },
  488. { S3C_CAMIF_REG_CISCPRERATIO(1, 0), "CIPRSCPRERATIO" },
  489. { S3C_CAMIF_REG_CISCCTRL(0, 0), "CICOSCCTRL" },
  490. { S3C_CAMIF_REG_CISCCTRL(1, 0), "CIPRSCCTRL" },
  491. { S3C_CAMIF_REG_CITAREA(0, 0), "CICOTAREA" },
  492. { S3C_CAMIF_REG_CITAREA(1, 0), "CIPRTAREA" },
  493. { S3C_CAMIF_REG_CISTATUS(0, 0), "CICOSTATUS" },
  494. { S3C_CAMIF_REG_CISTATUS(1, 0), "CIPRSTATUS" },
  495. { S3C_CAMIF_REG_CIIMGCPT(0), "CIIMGCPT" },
  496. };
  497. u32 i;
  498. pr_info("--- %s ---\n", label);
  499. for (i = 0; i < ARRAY_SIZE(registers); i++) {
  500. u32 cfg = readl(camif->io_base + registers[i].offset);
  501. printk(KERN_INFO "%s:\t0x%08x\n", registers[i].name, cfg);
  502. }
  503. }