gsc-regs.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430
  1. /*
  2. * Copyright (c) 2011 - 2012 Samsung Electronics Co., Ltd.
  3. * http://www.samsung.com
  4. *
  5. * Samsung EXYNOS5 SoC series G-Scaler driver
  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 as published
  9. * by the Free Software Foundation, either version 2 of the License,
  10. * or (at your option) any later version.
  11. */
  12. #include <linux/io.h>
  13. #include <linux/delay.h>
  14. #include "gsc-core.h"
  15. void gsc_hw_set_sw_reset(struct gsc_dev *dev)
  16. {
  17. writel(GSC_SW_RESET_SRESET, dev->regs + GSC_SW_RESET);
  18. }
  19. int gsc_wait_reset(struct gsc_dev *dev)
  20. {
  21. unsigned long end = jiffies + msecs_to_jiffies(50);
  22. u32 cfg;
  23. while (time_before(jiffies, end)) {
  24. cfg = readl(dev->regs + GSC_SW_RESET);
  25. if (!cfg)
  26. return 0;
  27. usleep_range(10, 20);
  28. }
  29. return -EBUSY;
  30. }
  31. void gsc_hw_set_frm_done_irq_mask(struct gsc_dev *dev, bool mask)
  32. {
  33. u32 cfg;
  34. cfg = readl(dev->regs + GSC_IRQ);
  35. if (mask)
  36. cfg |= GSC_IRQ_FRMDONE_MASK;
  37. else
  38. cfg &= ~GSC_IRQ_FRMDONE_MASK;
  39. writel(cfg, dev->regs + GSC_IRQ);
  40. }
  41. void gsc_hw_set_gsc_irq_enable(struct gsc_dev *dev, bool mask)
  42. {
  43. u32 cfg;
  44. cfg = readl(dev->regs + GSC_IRQ);
  45. if (mask)
  46. cfg |= GSC_IRQ_ENABLE;
  47. else
  48. cfg &= ~GSC_IRQ_ENABLE;
  49. writel(cfg, dev->regs + GSC_IRQ);
  50. }
  51. void gsc_hw_set_input_buf_masking(struct gsc_dev *dev, u32 shift,
  52. bool enable)
  53. {
  54. u32 cfg = readl(dev->regs + GSC_IN_BASE_ADDR_Y_MASK);
  55. u32 mask = 1 << shift;
  56. cfg &= ~mask;
  57. cfg |= enable << shift;
  58. writel(cfg, dev->regs + GSC_IN_BASE_ADDR_Y_MASK);
  59. writel(cfg, dev->regs + GSC_IN_BASE_ADDR_CB_MASK);
  60. writel(cfg, dev->regs + GSC_IN_BASE_ADDR_CR_MASK);
  61. }
  62. void gsc_hw_set_output_buf_masking(struct gsc_dev *dev, u32 shift,
  63. bool enable)
  64. {
  65. u32 cfg = readl(dev->regs + GSC_OUT_BASE_ADDR_Y_MASK);
  66. u32 mask = 1 << shift;
  67. cfg &= ~mask;
  68. cfg |= enable << shift;
  69. writel(cfg, dev->regs + GSC_OUT_BASE_ADDR_Y_MASK);
  70. writel(cfg, dev->regs + GSC_OUT_BASE_ADDR_CB_MASK);
  71. writel(cfg, dev->regs + GSC_OUT_BASE_ADDR_CR_MASK);
  72. }
  73. void gsc_hw_set_input_addr(struct gsc_dev *dev, struct gsc_addr *addr,
  74. int index)
  75. {
  76. pr_debug("src_buf[%d]: %pad, cb: %pad, cr: %pad", index,
  77. &addr->y, &addr->cb, &addr->cr);
  78. writel(addr->y, dev->regs + GSC_IN_BASE_ADDR_Y(index));
  79. writel(addr->cb, dev->regs + GSC_IN_BASE_ADDR_CB(index));
  80. writel(addr->cr, dev->regs + GSC_IN_BASE_ADDR_CR(index));
  81. }
  82. void gsc_hw_set_output_addr(struct gsc_dev *dev,
  83. struct gsc_addr *addr, int index)
  84. {
  85. pr_debug("dst_buf[%d]: %pad, cb: %pad, cr: %pad",
  86. index, &addr->y, &addr->cb, &addr->cr);
  87. writel(addr->y, dev->regs + GSC_OUT_BASE_ADDR_Y(index));
  88. writel(addr->cb, dev->regs + GSC_OUT_BASE_ADDR_CB(index));
  89. writel(addr->cr, dev->regs + GSC_OUT_BASE_ADDR_CR(index));
  90. }
  91. void gsc_hw_set_input_path(struct gsc_ctx *ctx)
  92. {
  93. struct gsc_dev *dev = ctx->gsc_dev;
  94. u32 cfg = readl(dev->regs + GSC_IN_CON);
  95. cfg &= ~(GSC_IN_PATH_MASK | GSC_IN_LOCAL_SEL_MASK);
  96. if (ctx->in_path == GSC_DMA)
  97. cfg |= GSC_IN_PATH_MEMORY;
  98. writel(cfg, dev->regs + GSC_IN_CON);
  99. }
  100. void gsc_hw_set_in_size(struct gsc_ctx *ctx)
  101. {
  102. struct gsc_dev *dev = ctx->gsc_dev;
  103. struct gsc_frame *frame = &ctx->s_frame;
  104. u32 cfg;
  105. /* Set input pixel offset */
  106. cfg = GSC_SRCIMG_OFFSET_X(frame->crop.left);
  107. cfg |= GSC_SRCIMG_OFFSET_Y(frame->crop.top);
  108. writel(cfg, dev->regs + GSC_SRCIMG_OFFSET);
  109. /* Set input original size */
  110. cfg = GSC_SRCIMG_WIDTH(frame->f_width);
  111. cfg |= GSC_SRCIMG_HEIGHT(frame->f_height);
  112. writel(cfg, dev->regs + GSC_SRCIMG_SIZE);
  113. /* Set input cropped size */
  114. cfg = GSC_CROPPED_WIDTH(frame->crop.width);
  115. cfg |= GSC_CROPPED_HEIGHT(frame->crop.height);
  116. writel(cfg, dev->regs + GSC_CROPPED_SIZE);
  117. }
  118. void gsc_hw_set_in_image_rgb(struct gsc_ctx *ctx)
  119. {
  120. struct gsc_dev *dev = ctx->gsc_dev;
  121. struct gsc_frame *frame = &ctx->s_frame;
  122. u32 cfg;
  123. cfg = readl(dev->regs + GSC_IN_CON);
  124. if (frame->colorspace == V4L2_COLORSPACE_REC709)
  125. cfg |= GSC_IN_RGB_HD_WIDE;
  126. else
  127. cfg |= GSC_IN_RGB_SD_WIDE;
  128. if (frame->fmt->pixelformat == V4L2_PIX_FMT_RGB565X)
  129. cfg |= GSC_IN_RGB565;
  130. else if (frame->fmt->pixelformat == V4L2_PIX_FMT_RGB32)
  131. cfg |= GSC_IN_XRGB8888;
  132. writel(cfg, dev->regs + GSC_IN_CON);
  133. }
  134. void gsc_hw_set_in_image_format(struct gsc_ctx *ctx)
  135. {
  136. struct gsc_dev *dev = ctx->gsc_dev;
  137. struct gsc_frame *frame = &ctx->s_frame;
  138. u32 i, depth = 0;
  139. u32 cfg;
  140. cfg = readl(dev->regs + GSC_IN_CON);
  141. cfg &= ~(GSC_IN_RGB_TYPE_MASK | GSC_IN_YUV422_1P_ORDER_MASK |
  142. GSC_IN_CHROMA_ORDER_MASK | GSC_IN_FORMAT_MASK |
  143. GSC_IN_TILE_TYPE_MASK | GSC_IN_TILE_MODE);
  144. writel(cfg, dev->regs + GSC_IN_CON);
  145. if (is_rgb(frame->fmt->color)) {
  146. gsc_hw_set_in_image_rgb(ctx);
  147. return;
  148. }
  149. for (i = 0; i < frame->fmt->num_planes; i++)
  150. depth += frame->fmt->depth[i];
  151. switch (frame->fmt->num_comp) {
  152. case 1:
  153. cfg |= GSC_IN_YUV422_1P;
  154. if (frame->fmt->yorder == GSC_LSB_Y)
  155. cfg |= GSC_IN_YUV422_1P_ORDER_LSB_Y;
  156. else
  157. cfg |= GSC_IN_YUV422_1P_OEDER_LSB_C;
  158. if (frame->fmt->corder == GSC_CBCR)
  159. cfg |= GSC_IN_CHROMA_ORDER_CBCR;
  160. else
  161. cfg |= GSC_IN_CHROMA_ORDER_CRCB;
  162. break;
  163. case 2:
  164. if (depth == 12)
  165. cfg |= GSC_IN_YUV420_2P;
  166. else
  167. cfg |= GSC_IN_YUV422_2P;
  168. if (frame->fmt->corder == GSC_CBCR)
  169. cfg |= GSC_IN_CHROMA_ORDER_CBCR;
  170. else
  171. cfg |= GSC_IN_CHROMA_ORDER_CRCB;
  172. break;
  173. case 3:
  174. if (depth == 12)
  175. cfg |= GSC_IN_YUV420_3P;
  176. else
  177. cfg |= GSC_IN_YUV422_3P;
  178. break;
  179. }
  180. if (is_tiled(frame->fmt))
  181. cfg |= GSC_IN_TILE_C_16x8 | GSC_IN_TILE_MODE;
  182. writel(cfg, dev->regs + GSC_IN_CON);
  183. }
  184. void gsc_hw_set_output_path(struct gsc_ctx *ctx)
  185. {
  186. struct gsc_dev *dev = ctx->gsc_dev;
  187. u32 cfg = readl(dev->regs + GSC_OUT_CON);
  188. cfg &= ~GSC_OUT_PATH_MASK;
  189. if (ctx->out_path == GSC_DMA)
  190. cfg |= GSC_OUT_PATH_MEMORY;
  191. else
  192. cfg |= GSC_OUT_PATH_LOCAL;
  193. writel(cfg, dev->regs + GSC_OUT_CON);
  194. }
  195. void gsc_hw_set_out_size(struct gsc_ctx *ctx)
  196. {
  197. struct gsc_dev *dev = ctx->gsc_dev;
  198. struct gsc_frame *frame = &ctx->d_frame;
  199. u32 cfg;
  200. /* Set output original size */
  201. if (ctx->out_path == GSC_DMA) {
  202. cfg = GSC_DSTIMG_OFFSET_X(frame->crop.left);
  203. cfg |= GSC_DSTIMG_OFFSET_Y(frame->crop.top);
  204. writel(cfg, dev->regs + GSC_DSTIMG_OFFSET);
  205. cfg = GSC_DSTIMG_WIDTH(frame->f_width);
  206. cfg |= GSC_DSTIMG_HEIGHT(frame->f_height);
  207. writel(cfg, dev->regs + GSC_DSTIMG_SIZE);
  208. }
  209. /* Set output scaled size */
  210. if (ctx->gsc_ctrls.rotate->val == 90 ||
  211. ctx->gsc_ctrls.rotate->val == 270) {
  212. cfg = GSC_SCALED_WIDTH(frame->crop.height);
  213. cfg |= GSC_SCALED_HEIGHT(frame->crop.width);
  214. } else {
  215. cfg = GSC_SCALED_WIDTH(frame->crop.width);
  216. cfg |= GSC_SCALED_HEIGHT(frame->crop.height);
  217. }
  218. writel(cfg, dev->regs + GSC_SCALED_SIZE);
  219. }
  220. void gsc_hw_set_out_image_rgb(struct gsc_ctx *ctx)
  221. {
  222. struct gsc_dev *dev = ctx->gsc_dev;
  223. struct gsc_frame *frame = &ctx->d_frame;
  224. u32 cfg;
  225. cfg = readl(dev->regs + GSC_OUT_CON);
  226. if (frame->colorspace == V4L2_COLORSPACE_REC709)
  227. cfg |= GSC_OUT_RGB_HD_WIDE;
  228. else
  229. cfg |= GSC_OUT_RGB_SD_WIDE;
  230. if (frame->fmt->pixelformat == V4L2_PIX_FMT_RGB565X)
  231. cfg |= GSC_OUT_RGB565;
  232. else if (frame->fmt->pixelformat == V4L2_PIX_FMT_RGB32)
  233. cfg |= GSC_OUT_XRGB8888;
  234. writel(cfg, dev->regs + GSC_OUT_CON);
  235. }
  236. void gsc_hw_set_out_image_format(struct gsc_ctx *ctx)
  237. {
  238. struct gsc_dev *dev = ctx->gsc_dev;
  239. struct gsc_frame *frame = &ctx->d_frame;
  240. u32 i, depth = 0;
  241. u32 cfg;
  242. cfg = readl(dev->regs + GSC_OUT_CON);
  243. cfg &= ~(GSC_OUT_RGB_TYPE_MASK | GSC_OUT_YUV422_1P_ORDER_MASK |
  244. GSC_OUT_CHROMA_ORDER_MASK | GSC_OUT_FORMAT_MASK |
  245. GSC_OUT_TILE_TYPE_MASK | GSC_OUT_TILE_MODE);
  246. writel(cfg, dev->regs + GSC_OUT_CON);
  247. if (is_rgb(frame->fmt->color)) {
  248. gsc_hw_set_out_image_rgb(ctx);
  249. return;
  250. }
  251. if (ctx->out_path != GSC_DMA) {
  252. cfg |= GSC_OUT_YUV444;
  253. goto end_set;
  254. }
  255. for (i = 0; i < frame->fmt->num_planes; i++)
  256. depth += frame->fmt->depth[i];
  257. switch (frame->fmt->num_comp) {
  258. case 1:
  259. cfg |= GSC_OUT_YUV422_1P;
  260. if (frame->fmt->yorder == GSC_LSB_Y)
  261. cfg |= GSC_OUT_YUV422_1P_ORDER_LSB_Y;
  262. else
  263. cfg |= GSC_OUT_YUV422_1P_OEDER_LSB_C;
  264. if (frame->fmt->corder == GSC_CBCR)
  265. cfg |= GSC_OUT_CHROMA_ORDER_CBCR;
  266. else
  267. cfg |= GSC_OUT_CHROMA_ORDER_CRCB;
  268. break;
  269. case 2:
  270. if (depth == 12)
  271. cfg |= GSC_OUT_YUV420_2P;
  272. else
  273. cfg |= GSC_OUT_YUV422_2P;
  274. if (frame->fmt->corder == GSC_CBCR)
  275. cfg |= GSC_OUT_CHROMA_ORDER_CBCR;
  276. else
  277. cfg |= GSC_OUT_CHROMA_ORDER_CRCB;
  278. break;
  279. case 3:
  280. cfg |= GSC_OUT_YUV420_3P;
  281. break;
  282. }
  283. if (is_tiled(frame->fmt))
  284. cfg |= GSC_OUT_TILE_C_16x8 | GSC_OUT_TILE_MODE;
  285. end_set:
  286. writel(cfg, dev->regs + GSC_OUT_CON);
  287. }
  288. void gsc_hw_set_prescaler(struct gsc_ctx *ctx)
  289. {
  290. struct gsc_dev *dev = ctx->gsc_dev;
  291. struct gsc_scaler *sc = &ctx->scaler;
  292. u32 cfg;
  293. cfg = GSC_PRESC_SHFACTOR(sc->pre_shfactor);
  294. cfg |= GSC_PRESC_H_RATIO(sc->pre_hratio);
  295. cfg |= GSC_PRESC_V_RATIO(sc->pre_vratio);
  296. writel(cfg, dev->regs + GSC_PRE_SCALE_RATIO);
  297. }
  298. void gsc_hw_set_mainscaler(struct gsc_ctx *ctx)
  299. {
  300. struct gsc_dev *dev = ctx->gsc_dev;
  301. struct gsc_scaler *sc = &ctx->scaler;
  302. u32 cfg;
  303. cfg = GSC_MAIN_H_RATIO_VALUE(sc->main_hratio);
  304. writel(cfg, dev->regs + GSC_MAIN_H_RATIO);
  305. cfg = GSC_MAIN_V_RATIO_VALUE(sc->main_vratio);
  306. writel(cfg, dev->regs + GSC_MAIN_V_RATIO);
  307. }
  308. void gsc_hw_set_rotation(struct gsc_ctx *ctx)
  309. {
  310. struct gsc_dev *dev = ctx->gsc_dev;
  311. u32 cfg;
  312. cfg = readl(dev->regs + GSC_IN_CON);
  313. cfg &= ~GSC_IN_ROT_MASK;
  314. switch (ctx->gsc_ctrls.rotate->val) {
  315. case 270:
  316. cfg |= GSC_IN_ROT_270;
  317. break;
  318. case 180:
  319. cfg |= GSC_IN_ROT_180;
  320. break;
  321. case 90:
  322. if (ctx->gsc_ctrls.hflip->val)
  323. cfg |= GSC_IN_ROT_90_XFLIP;
  324. else if (ctx->gsc_ctrls.vflip->val)
  325. cfg |= GSC_IN_ROT_90_YFLIP;
  326. else
  327. cfg |= GSC_IN_ROT_90;
  328. break;
  329. case 0:
  330. if (ctx->gsc_ctrls.hflip->val)
  331. cfg |= GSC_IN_ROT_XFLIP;
  332. else if (ctx->gsc_ctrls.vflip->val)
  333. cfg |= GSC_IN_ROT_YFLIP;
  334. }
  335. writel(cfg, dev->regs + GSC_IN_CON);
  336. }
  337. void gsc_hw_set_global_alpha(struct gsc_ctx *ctx)
  338. {
  339. struct gsc_dev *dev = ctx->gsc_dev;
  340. struct gsc_frame *frame = &ctx->d_frame;
  341. u32 cfg;
  342. if (!is_rgb(frame->fmt->color)) {
  343. pr_debug("Not a RGB format");
  344. return;
  345. }
  346. cfg = readl(dev->regs + GSC_OUT_CON);
  347. cfg &= ~GSC_OUT_GLOBAL_ALPHA_MASK;
  348. cfg |= GSC_OUT_GLOBAL_ALPHA(ctx->gsc_ctrls.global_alpha->val);
  349. writel(cfg, dev->regs + GSC_OUT_CON);
  350. }
  351. void gsc_hw_set_sfr_update(struct gsc_ctx *ctx)
  352. {
  353. struct gsc_dev *dev = ctx->gsc_dev;
  354. u32 cfg;
  355. cfg = readl(dev->regs + GSC_ENABLE);
  356. cfg |= GSC_ENABLE_SFR_UPDATE;
  357. writel(cfg, dev->regs + GSC_ENABLE);
  358. }