ddp_rdma_ex.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760
  1. #define LOG_TAG "RDMA"
  2. #include "ddp_log.h"
  3. #ifdef CONFIG_MTK_CLKMGR
  4. #include <mach/mt_clkmgr.h>
  5. #endif
  6. #include <linux/delay.h>
  7. #include "ddp_info.h"
  8. #include "ddp_reg.h"
  9. #include "ddp_matrix_para.h"
  10. #include "ddp_rdma.h"
  11. #include "ddp_rdma_ex.h"
  12. #include "ddp_dump.h"
  13. #include "lcm_drv.h"
  14. #include "primary_display.h"
  15. #include "m4u.h"
  16. #include "ddp_drv.h"
  17. #include "ddp_debug.h"
  18. #include "ddp_irq.h"
  19. static unsigned int rdma_fps[RDMA_INSTANCES] = { 60, 60 };
  20. static enum RDMA_INPUT_FORMAT rdma_input_format_convert(DpColorFormat fmt)
  21. {
  22. enum RDMA_INPUT_FORMAT rdma_fmt = RDMA_INPUT_FORMAT_RGB565;
  23. switch (fmt) {
  24. case eBGR565:
  25. rdma_fmt = RDMA_INPUT_FORMAT_BGR565;
  26. break;
  27. case eRGB888:
  28. rdma_fmt = RDMA_INPUT_FORMAT_RGB888;
  29. break;
  30. case eRGBA8888:
  31. rdma_fmt = RDMA_INPUT_FORMAT_RGBA8888;
  32. break;
  33. case eARGB8888:
  34. rdma_fmt = RDMA_INPUT_FORMAT_ARGB8888;
  35. break;
  36. case eVYUY:
  37. rdma_fmt = RDMA_INPUT_FORMAT_VYUY;
  38. break;
  39. case eYVYU:
  40. rdma_fmt = RDMA_INPUT_FORMAT_YVYU;
  41. break;
  42. case eRGB565:
  43. rdma_fmt = RDMA_INPUT_FORMAT_RGB565;
  44. break;
  45. case eBGR888:
  46. rdma_fmt = RDMA_INPUT_FORMAT_BGR888;
  47. break;
  48. case eBGRA8888:
  49. rdma_fmt = RDMA_INPUT_FORMAT_BGRA8888;
  50. break;
  51. case eABGR8888:
  52. rdma_fmt = RDMA_INPUT_FORMAT_ABGR8888;
  53. break;
  54. case eUYVY:
  55. rdma_fmt = RDMA_INPUT_FORMAT_UYVY;
  56. break;
  57. case eYUY2:
  58. rdma_fmt = RDMA_INPUT_FORMAT_YUYV;
  59. break;
  60. default:
  61. DDPERR("rdma_input_format_convert fmt=%d, rdma_fmt=%d\n", fmt, rdma_fmt);
  62. }
  63. return rdma_fmt;
  64. }
  65. static unsigned int rdma_input_format_byte_swap(enum RDMA_INPUT_FORMAT inputFormat)
  66. {
  67. int input_swap = 0;
  68. switch (inputFormat) {
  69. case RDMA_INPUT_FORMAT_BGR565:
  70. case RDMA_INPUT_FORMAT_RGB888:
  71. case RDMA_INPUT_FORMAT_RGBA8888:
  72. case RDMA_INPUT_FORMAT_ARGB8888:
  73. case RDMA_INPUT_FORMAT_VYUY:
  74. case RDMA_INPUT_FORMAT_YVYU:
  75. input_swap = 1;
  76. break;
  77. case RDMA_INPUT_FORMAT_RGB565:
  78. case RDMA_INPUT_FORMAT_BGR888:
  79. case RDMA_INPUT_FORMAT_BGRA8888:
  80. case RDMA_INPUT_FORMAT_ABGR8888:
  81. case RDMA_INPUT_FORMAT_UYVY:
  82. case RDMA_INPUT_FORMAT_YUYV:
  83. input_swap = 0;
  84. break;
  85. default:
  86. DDPERR("unknown RDMA input format is %d\n", inputFormat);
  87. ASSERT(0);
  88. }
  89. return input_swap;
  90. }
  91. static unsigned int rdma_input_format_bpp(enum RDMA_INPUT_FORMAT inputFormat)
  92. {
  93. int bpp = 0;
  94. switch (inputFormat) {
  95. case RDMA_INPUT_FORMAT_BGR565:
  96. case RDMA_INPUT_FORMAT_RGB565:
  97. case RDMA_INPUT_FORMAT_VYUY:
  98. case RDMA_INPUT_FORMAT_UYVY:
  99. case RDMA_INPUT_FORMAT_YVYU:
  100. case RDMA_INPUT_FORMAT_YUYV:
  101. bpp = 2;
  102. break;
  103. case RDMA_INPUT_FORMAT_RGB888:
  104. case RDMA_INPUT_FORMAT_BGR888:
  105. bpp = 3;
  106. break;
  107. case RDMA_INPUT_FORMAT_ARGB8888:
  108. case RDMA_INPUT_FORMAT_ABGR8888:
  109. case RDMA_INPUT_FORMAT_RGBA8888:
  110. case RDMA_INPUT_FORMAT_BGRA8888:
  111. bpp = 4;
  112. break;
  113. default:
  114. DDPERR("unknown RDMA input format = %d\n", inputFormat);
  115. ASSERT(0);
  116. }
  117. return bpp;
  118. }
  119. static unsigned int rdma_input_format_color_space(enum RDMA_INPUT_FORMAT inputFormat)
  120. {
  121. int space = 0;
  122. switch (inputFormat) {
  123. case RDMA_INPUT_FORMAT_BGR565:
  124. case RDMA_INPUT_FORMAT_RGB565:
  125. case RDMA_INPUT_FORMAT_RGB888:
  126. case RDMA_INPUT_FORMAT_BGR888:
  127. case RDMA_INPUT_FORMAT_RGBA8888:
  128. case RDMA_INPUT_FORMAT_BGRA8888:
  129. case RDMA_INPUT_FORMAT_ARGB8888:
  130. case RDMA_INPUT_FORMAT_ABGR8888:
  131. space = 0;
  132. break;
  133. case RDMA_INPUT_FORMAT_VYUY:
  134. case RDMA_INPUT_FORMAT_UYVY:
  135. case RDMA_INPUT_FORMAT_YVYU:
  136. case RDMA_INPUT_FORMAT_YUYV:
  137. space = 1;
  138. break;
  139. default:
  140. DDPERR("unknown RDMA input format = %d\n", inputFormat);
  141. ASSERT(0);
  142. }
  143. return space;
  144. }
  145. static unsigned int rdma_input_format_reg_value(enum RDMA_INPUT_FORMAT inputFormat)
  146. {
  147. int reg_value = 0;
  148. switch (inputFormat) {
  149. case RDMA_INPUT_FORMAT_BGR565:
  150. case RDMA_INPUT_FORMAT_RGB565:
  151. reg_value = 0x0;
  152. break;
  153. case RDMA_INPUT_FORMAT_RGB888:
  154. case RDMA_INPUT_FORMAT_BGR888:
  155. reg_value = 0x1;
  156. break;
  157. case RDMA_INPUT_FORMAT_RGBA8888:
  158. case RDMA_INPUT_FORMAT_BGRA8888:
  159. reg_value = 0x2;
  160. break;
  161. case RDMA_INPUT_FORMAT_ARGB8888:
  162. case RDMA_INPUT_FORMAT_ABGR8888:
  163. reg_value = 0x3;
  164. break;
  165. case RDMA_INPUT_FORMAT_VYUY:
  166. case RDMA_INPUT_FORMAT_UYVY:
  167. reg_value = 0x4;
  168. break;
  169. case RDMA_INPUT_FORMAT_YVYU:
  170. case RDMA_INPUT_FORMAT_YUYV:
  171. reg_value = 0x5;
  172. break;
  173. default:
  174. DDPERR("unknown RDMA input format is %d\n", inputFormat);
  175. ASSERT(0);
  176. }
  177. return reg_value;
  178. }
  179. static char *rdma_intput_format_name(enum RDMA_INPUT_FORMAT fmt, int swap)
  180. {
  181. switch (fmt) {
  182. case RDMA_INPUT_FORMAT_BGR565:
  183. return swap ? "eBGR565" : "eRGB565";
  184. case RDMA_INPUT_FORMAT_RGB565:
  185. return "eRGB565";
  186. case RDMA_INPUT_FORMAT_RGB888:
  187. return swap ? "eRGB888" : "eBGR888";
  188. case RDMA_INPUT_FORMAT_BGR888:
  189. return "eBGR888";
  190. case RDMA_INPUT_FORMAT_RGBA8888:
  191. return swap ? "eRGBA888" : "eBGRA888";
  192. case RDMA_INPUT_FORMAT_BGRA8888:
  193. return "eBGRA888";
  194. case RDMA_INPUT_FORMAT_ARGB8888:
  195. return swap ? "eARGB8888" : "eABGR8888";
  196. case RDMA_INPUT_FORMAT_ABGR8888:
  197. return "eABGR8888";
  198. case RDMA_INPUT_FORMAT_VYUY:
  199. return swap ? "eVYUY" : "eUYVY";
  200. case RDMA_INPUT_FORMAT_UYVY:
  201. return "eUYVY";
  202. case RDMA_INPUT_FORMAT_YVYU:
  203. return swap ? "eYVYU" : "eYUY2";
  204. case RDMA_INPUT_FORMAT_YUYV:
  205. return "eYUY2";
  206. default:
  207. DDPERR("rdma_intput_format_name unknown fmt=%d, swap=%d\n", fmt, swap);
  208. break;
  209. }
  210. return "unknown";
  211. }
  212. int rdma_enable_irq(DISP_MODULE_ENUM module, void *handle, DDP_IRQ_LEVEL irq_level)
  213. {
  214. unsigned int idx = rdma_index(module);
  215. switch (irq_level) {
  216. case DDP_IRQ_LEVEL_ALL:
  217. DISP_REG_SET(handle, idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_INT_ENABLE, 0x1E);
  218. break;
  219. case DDP_IRQ_LEVEL_ERROR:
  220. DISP_REG_SET(handle, idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_INT_ENABLE, 0x18);
  221. /* only enable underflow/abnormal irq */
  222. break;
  223. case DDP_IRQ_LEVEL_NONE:
  224. DISP_REG_SET(handle, idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_INT_ENABLE, 0x0);
  225. break;
  226. default:
  227. break;
  228. }
  229. return 0;
  230. }
  231. int rdma_start(DISP_MODULE_ENUM module, void *handle)
  232. {
  233. unsigned int idx = rdma_index(module);
  234. DISP_REG_SET(handle, idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_INT_ENABLE, 0x3E);
  235. DISP_REG_SET_FIELD(handle, GLOBAL_CON_FLD_ENGINE_EN,
  236. idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_GLOBAL_CON, 1);
  237. return 0;
  238. }
  239. int rdma_stop(DISP_MODULE_ENUM module, void *handle)
  240. {
  241. unsigned int idx = rdma_index(module);
  242. DISP_REG_SET_FIELD(handle, GLOBAL_CON_FLD_ENGINE_EN,
  243. idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_GLOBAL_CON, 0);
  244. DISP_REG_SET(handle, idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_INT_ENABLE, 0);
  245. DISP_REG_SET(handle, idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_INT_STATUS, 0);
  246. return 0;
  247. }
  248. int rdma_reset(DISP_MODULE_ENUM module, void *handle)
  249. {
  250. unsigned int delay_cnt = 0;
  251. int ret = 0;
  252. unsigned int idx = rdma_index(module);
  253. DISP_REG_SET_FIELD(handle, GLOBAL_CON_FLD_SOFT_RESET,
  254. idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_GLOBAL_CON, 1);
  255. while ((DISP_REG_GET(idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_GLOBAL_CON) & 0x700) == 0x100) {
  256. delay_cnt++;
  257. udelay(10);
  258. if (delay_cnt > 10000) {
  259. ret = -1;
  260. DDPERR("rdma%d_reset timeout, stage 1! DISP_REG_RDMA_GLOBAL_CON=0x%x\n",
  261. idx, DISP_REG_GET(idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_GLOBAL_CON));
  262. break;
  263. }
  264. }
  265. DISP_REG_SET_FIELD(handle, GLOBAL_CON_FLD_SOFT_RESET,
  266. idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_GLOBAL_CON, 0);
  267. delay_cnt = 0;
  268. while ((DISP_REG_GET(idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_GLOBAL_CON) & 0x700) != 0x100) {
  269. delay_cnt++;
  270. udelay(10);
  271. if (delay_cnt > 10000) {
  272. ret = -1;
  273. DDPERR("rdma%d_reset timeout, stage 2! DISP_REG_RDMA_GLOBAL_CON=0x%x\n",
  274. idx, DISP_REG_GET(idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_GLOBAL_CON));
  275. break;
  276. }
  277. }
  278. return ret;
  279. }
  280. /* set ultra registers */
  281. void rdma_set_ultra(unsigned int idx, unsigned int width, unsigned int height, unsigned int bpp,
  282. unsigned int frame_rate, void *handle)
  283. {
  284. /* constant */
  285. static const unsigned int blank_overhead = 115; /* it is 1.15, need to divide 100 later */
  286. static const unsigned int rdma_fifo_width = 16; /* in unit of byte */
  287. static const unsigned int ultra_low_time = 6; /* in unit of us */
  288. static const unsigned int pre_ultra_low_time = 8; /* in unit of us */
  289. static const unsigned int pre_ultra_high_time = 9; /* in unit of us */
  290. static const unsigned int fifo_valid_line_ratio = 125; /* valid size 1/8 line; */
  291. static const unsigned int fifo_min_size = 32;
  292. /* working variables */
  293. unsigned int consume_levels_per_sec;
  294. unsigned int ultra_low_level;
  295. unsigned int pre_ultra_low_level;
  296. unsigned int pre_ultra_high_level;
  297. unsigned int ultra_high_ofs;
  298. unsigned int pre_ultra_low_ofs;
  299. unsigned int pre_ultra_high_ofs;
  300. unsigned int fifo_valid_size = 16;
  301. /* compute fifo valid size */
  302. fifo_valid_size = (width * bpp * fifo_valid_line_ratio) / (rdma_fifo_width * 1000);
  303. fifo_valid_size = fifo_valid_size > fifo_min_size ? fifo_valid_size : fifo_min_size;
  304. /* consume_levels_per_sec = ((long long unsigned int)width * height * frame_rate * blank_overhead * bpp) /
  305. rdma_fifo_width / 100;
  306. */
  307. /* change calculation order to prevent overflow of unsigned int */
  308. consume_levels_per_sec = (width * height * frame_rate * bpp / rdma_fifo_width / 100) * blank_overhead;
  309. /* /1000000 for ultra_low_time in unit of us */
  310. ultra_low_level = (unsigned int)(ultra_low_time * consume_levels_per_sec / 1000000);
  311. pre_ultra_low_level = (unsigned int)(pre_ultra_low_time * consume_levels_per_sec / 1000000);
  312. pre_ultra_high_level = (unsigned int)(pre_ultra_high_time * consume_levels_per_sec / 1000000);
  313. pre_ultra_low_ofs = pre_ultra_low_level - ultra_low_level;
  314. ultra_high_ofs = 1;
  315. pre_ultra_high_ofs = pre_ultra_high_level - pre_ultra_low_level;
  316. if (gUltraEnable == 1) {
  317. ultra_low_level = 0x6b;
  318. pre_ultra_low_ofs = 0xa0;
  319. ultra_high_ofs = 1;
  320. pre_ultra_high_ofs = 1;
  321. }
  322. /* write ultra_low_level, ultra_high_ofs, pre_ultra_low_ofs,
  323. * pre_ultra_high_ofs into register DISP_RDMA_MEM_GMC_SETTING_0
  324. */
  325. DISP_REG_SET(handle, idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_MEM_GMC_SETTING_0,
  326. ultra_low_level | (pre_ultra_low_ofs << 8) | (ultra_high_ofs << 16) |
  327. (pre_ultra_high_ofs << 24));
  328. /* set rdma ultra/pre-ultra according to resolution */
  329. if (width > 540) {
  330. DISP_REG_SET(handle, idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_MEM_GMC_SETTING_0, 0x0C011832);
  331. DISP_REG_SET(handle, idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_MEM_GMC_SETTING_1, 0x000000A8);
  332. }
  333. else if (width > 480) {
  334. DISP_REG_SET(handle, idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_MEM_GMC_SETTING_0, 0x21010D1C);
  335. DISP_REG_SET(handle, idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_MEM_GMC_SETTING_1, 0x000000B4);
  336. }
  337. else {
  338. DISP_REG_SET(handle, idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_MEM_GMC_SETTING_0, 0x28010A16);
  339. DISP_REG_SET(handle, idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_MEM_GMC_SETTING_1, 0x000000B6);
  340. }
  341. if (gRDMAUltraSetting)
  342. DISP_REG_SET(handle, idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_MEM_GMC_SETTING_0,
  343. gRDMAUltraSetting);
  344. DISP_REG_SET_FIELD(handle, FIFO_CON_FLD_OUTPUT_VALID_FIFO_THRESHOLD,
  345. idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_FIFO_CON, fifo_valid_size);
  346. DDPDBG("FIFO_VALID_Size = 0x%03x = %d\n", fifo_valid_size, fifo_valid_size);
  347. DDPDBG("ultra_low_level = 0x%03x = %d\n", ultra_low_level, ultra_low_level);
  348. DDPDBG("pre_ultra_low_level = 0x%03x = %d\n", pre_ultra_low_level, pre_ultra_low_level);
  349. DDPDBG("pre_ultra_high_level = 0x%03x = %d\n", pre_ultra_high_level, pre_ultra_high_level);
  350. DDPDBG("ultra_high_ofs = 0x%03x = %d\n", ultra_high_ofs, ultra_high_ofs);
  351. DDPDBG("pre_ultra_low_ofs = 0x%03x = %d\n", pre_ultra_low_ofs, pre_ultra_low_ofs);
  352. DDPDBG("pre_ultra_high_ofs = 0x%03x = %d\n", pre_ultra_high_ofs, pre_ultra_high_ofs);
  353. }
  354. /* fixme: spec has no RDMA format, fix enum definition here */
  355. static int rdma_config(DISP_MODULE_ENUM module,
  356. enum RDMA_MODE mode,
  357. unsigned long address,
  358. DpColorFormat inFormat,
  359. unsigned pitch,
  360. unsigned width,
  361. unsigned height, unsigned ufoe_enable, DISP_BUFFER_TYPE sec, void *handle)
  362. {
  363. unsigned int output_is_yuv = 0;
  364. enum RDMA_INPUT_FORMAT inputFormat = rdma_input_format_convert(inFormat);
  365. unsigned int bpp = rdma_input_format_bpp(inputFormat);
  366. unsigned int input_is_yuv = rdma_input_format_color_space(inputFormat);
  367. unsigned int input_swap = rdma_input_format_byte_swap(inputFormat);
  368. unsigned int input_format_reg = rdma_input_format_reg_value(inputFormat);
  369. unsigned int color_matrix = 0x6; /* 0110 MTX_BT601_TO_RGB */
  370. unsigned int idx = rdma_index(module);
  371. unsigned int size_con_reg = 0;
  372. unsigned long size_con_handle = 0;
  373. #if defined(CONFIG_TRUSTONIC_TEE_SUPPORT) && defined(CONFIG_MTK_SEC_VIDEO_PATH_SUPPORT)
  374. DDPMSG
  375. ("RDMAConfig idx %d, mode %d, address 0x%lx, inputformat %s, pitch %u, width %u, height %u,sec%d\n",
  376. idx, mode, address, rdma_intput_format_name(inputFormat, input_swap), pitch, width,
  377. height, sec);
  378. #else
  379. DDPDBG
  380. ("RDMAConfig idx %d, mode %d, address 0x%lx, inputformat %s, pitch %u, width %u, height %u,sec%d\n",
  381. idx, mode, address, rdma_intput_format_name(inputFormat, input_swap), pitch, width,
  382. height, sec);
  383. #endif
  384. if ((width > RDMA_MAX_WIDTH) || (height > RDMA_MAX_HEIGHT))
  385. DDPERR("RDMA input overflow, w=%d, h=%d, max_w=%d, max_h=%d\n", width, height,
  386. RDMA_MAX_WIDTH, RDMA_MAX_HEIGHT);
  387. if (input_is_yuv == 1 && output_is_yuv == 0) {
  388. DISP_REG_SET_FIELD(size_con_handle, SIZE_CON_0_FLD_MATRIX_ENABLE, &size_con_reg, 1);
  389. DISP_REG_SET_FIELD(size_con_handle, SIZE_CON_0_FLD_MATRIX_INT_MTX_SEL,
  390. &size_con_reg, color_matrix);
  391. } else if (input_is_yuv == 0 && output_is_yuv == 1) {
  392. color_matrix = 0x2; /* 0x0010, RGB_TO_BT601 */
  393. DISP_REG_SET_FIELD(size_con_handle, SIZE_CON_0_FLD_MATRIX_ENABLE, &size_con_reg, 1);
  394. DISP_REG_SET_FIELD(size_con_handle, SIZE_CON_0_FLD_MATRIX_INT_MTX_SEL,
  395. &size_con_reg, color_matrix);
  396. } else {
  397. DISP_REG_SET_FIELD(size_con_handle, SIZE_CON_0_FLD_MATRIX_ENABLE, &size_con_reg, 0);
  398. DISP_REG_SET_FIELD(size_con_handle, SIZE_CON_0_FLD_MATRIX_INT_MTX_SEL,
  399. &size_con_reg, 0);
  400. }
  401. DISP_REG_SET_FIELD(handle, GLOBAL_CON_FLD_MODE_SEL,
  402. idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_GLOBAL_CON, mode);
  403. /* FORMAT & SWAP only works when RDMA memory mode, set both to 0 when RDMA direct link mode. */
  404. DISP_REG_SET_FIELD(handle, MEM_CON_FLD_MEM_MODE_INPUT_FORMAT,
  405. idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_MEM_CON,
  406. ((mode == RDMA_MODE_DIRECT_LINK) ? 0 : input_format_reg & 0xf));
  407. DISP_REG_SET_FIELD(handle, MEM_CON_FLD_MEM_MODE_INPUT_SWAP,
  408. idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_MEM_CON,
  409. ((mode == RDMA_MODE_DIRECT_LINK) ? 0 : input_swap));
  410. if (sec != DISP_SECURE_BUFFER) {
  411. DISP_REG_SET(handle, idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_MEM_START_ADDR, address);
  412. } else {
  413. int m4u_port;
  414. unsigned int size = pitch * height;
  415. m4u_port = M4U_PORT_DISP_RDMA0;
  416. /* for sec layer, addr variable stores sec handle */
  417. /* we need to pass this handle and offset to cmdq driver */
  418. /* cmdq sec driver will help to convert handle to correct address */
  419. cmdqRecWriteSecure(handle,
  420. disp_addr_convert(idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_MEM_START_ADDR),
  421. CMDQ_SAM_H_2_MVA, address, 0, size, m4u_port);
  422. /* DISP_REG_SET(handle, idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_MEM_START_ADDR,
  423. address-0xbc000000+0x8c00000);
  424. */
  425. }
  426. DISP_REG_SET(handle, idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_MEM_SRC_PITCH, pitch);
  427. /* DISP_REG_SET(handle,idx*DISP_RDMA_INDEX_OFFSET+ DISP_REG_RDMA_INT_ENABLE, 0x3F); */
  428. DISP_REG_SET_FIELD(size_con_handle, SIZE_CON_0_FLD_OUTPUT_FRAME_WIDTH, &size_con_reg, width);
  429. DISP_REG_SET(handle, idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_SIZE_CON_0, size_con_reg);
  430. DISP_REG_SET(handle, idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_SIZE_CON_1, height);
  431. rdma_set_ultra(idx, width, height, bpp, rdma_fps[idx], handle);
  432. #if 1
  433. if (ufoe_enable == 0) { /* UFOE bypassed, enable RDMA underflow intr, else disable RDMA underflow intr */
  434. DISP_REG_SET_FIELD(handle, FIFO_CON_FLD_FIFO_UNDERFLOW_EN,
  435. idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_FIFO_CON, 1);
  436. DISP_REG_SET_FIELD(handle, FIFO_CON_FLD_OUTPUT_VALID_FIFO_THRESHOLD,
  437. idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_FIFO_CON,
  438. gRDMAFIFOLen);
  439. } else {
  440. DISP_REG_SET_FIELD(handle, FIFO_CON_FLD_FIFO_UNDERFLOW_EN,
  441. idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_FIFO_CON, 1);
  442. DISP_REG_SET_FIELD(handle, FIFO_CON_FLD_OUTPUT_VALID_FIFO_THRESHOLD,
  443. idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_FIFO_CON,
  444. width * 3 * 3 / 16 / 2); /* FHD:304, HD:203, QHD:151 */
  445. }
  446. #endif
  447. return 0;
  448. }
  449. int rdma_clock_on(DISP_MODULE_ENUM module, void *handle)
  450. {
  451. unsigned int idx = rdma_index(module);
  452. #ifdef ENABLE_CLK_MGR
  453. if (idx == 0) {
  454. #ifdef CONFIG_MTK_CLKMGR
  455. enable_clock(MT_CG_DISP0_DISP_RDMA0, "RDMA0");
  456. #else
  457. ddp_clk_enable(DISP0_DISP_RDMA0);
  458. #endif
  459. } else {
  460. #ifdef CONFIG_MTK_CLKMGR
  461. enable_clock(MT_CG_DISP0_DISP_RDMA1, "RDMA1");
  462. #else
  463. ddp_clk_enable(DISP0_DISP_RDMA1);
  464. #endif
  465. }
  466. #endif
  467. DDPMSG("rdma_%d_clock_on CG 0x%x\n", idx, DISP_REG_GET(DISP_REG_CONFIG_MMSYS_CG_CON0));
  468. return 0;
  469. }
  470. int rdma_clock_off(DISP_MODULE_ENUM module, void *handle)
  471. {
  472. unsigned int idx = rdma_index(module);
  473. #ifdef ENABLE_CLK_MGR
  474. if (idx == 0) {
  475. #ifdef CONFIG_MTK_CLKMGR
  476. disable_clock(MT_CG_DISP0_DISP_RDMA0, "RDMA0");
  477. #else
  478. ddp_clk_disable(DISP0_DISP_RDMA0);
  479. #endif
  480. } else {
  481. #ifdef CONFIG_MTK_CLKMGR
  482. disable_clock(MT_CG_DISP0_DISP_RDMA1, "RDMA1");
  483. #else
  484. ddp_clk_disable(DISP0_DISP_RDMA1);
  485. #endif
  486. }
  487. #endif
  488. DDPMSG("rdma_%d_clock_off CG 0x%x\n", idx, DISP_REG_GET(DISP_REG_CONFIG_MMSYS_CG_CON0));
  489. return 0;
  490. }
  491. void rdma_dump_reg(DISP_MODULE_ENUM module)
  492. {
  493. unsigned int idx = rdma_index(module);
  494. DDPDUMP("== DISP RDMA%d REGS ==\n", idx);
  495. DDPDUMP("(0x000)R_INTEN =0x%x\n",
  496. DISP_REG_GET(DISP_REG_RDMA_INT_ENABLE + DISP_RDMA_INDEX_OFFSET * idx));
  497. DDPDUMP("(0x004)R_INTS =0x%x\n",
  498. DISP_REG_GET(DISP_REG_RDMA_INT_STATUS + DISP_RDMA_INDEX_OFFSET * idx));
  499. DDPDUMP("(0x010)R_CON =0x%x\n",
  500. DISP_REG_GET(DISP_REG_RDMA_GLOBAL_CON + DISP_RDMA_INDEX_OFFSET * idx));
  501. DDPDUMP("(0x014)R_SIZE0 =0x%x\n",
  502. DISP_REG_GET(DISP_REG_RDMA_SIZE_CON_0 + DISP_RDMA_INDEX_OFFSET * idx));
  503. DDPDUMP("(0x018)R_SIZE1 =0x%x\n",
  504. DISP_REG_GET(DISP_REG_RDMA_SIZE_CON_1 + DISP_RDMA_INDEX_OFFSET * idx));
  505. DDPDUMP("(0x01c)R_TAR_LINE =0x%x\n",
  506. DISP_REG_GET(DISP_REG_RDMA_TARGET_LINE + DISP_RDMA_INDEX_OFFSET * idx));
  507. DDPDUMP("(0x024)R_M_CON =0x%x\n",
  508. DISP_REG_GET(DISP_REG_RDMA_MEM_CON + DISP_RDMA_INDEX_OFFSET * idx));
  509. DDPDUMP("(0xf00)R_M_S_ADDR =0x%x\n",
  510. DISP_REG_GET(DISP_REG_RDMA_MEM_START_ADDR + DISP_RDMA_INDEX_OFFSET * idx));
  511. DDPDUMP("(0x02c)R_M_SRC_PITCH =0x%x\n",
  512. DISP_REG_GET(DISP_REG_RDMA_MEM_SRC_PITCH + DISP_RDMA_INDEX_OFFSET * idx));
  513. DDPDUMP("(0x030)R_M_GMC_SET0 =0x%x\n",
  514. DISP_REG_GET(DISP_REG_RDMA_MEM_GMC_SETTING_0 + DISP_RDMA_INDEX_OFFSET * idx));
  515. DDPDUMP("(0x034)R_M_SLOW_CON =0x%x\n",
  516. DISP_REG_GET(DISP_REG_RDMA_MEM_SLOW_CON + DISP_RDMA_INDEX_OFFSET * idx));
  517. DDPDUMP("(0x038)R_M_GMC_SET1 =0x%x\n",
  518. DISP_REG_GET(DISP_REG_RDMA_MEM_GMC_SETTING_1 + DISP_RDMA_INDEX_OFFSET * idx));
  519. DDPDUMP("(0x040)R_FIFO_CON =0x%x\n",
  520. DISP_REG_GET(DISP_REG_RDMA_FIFO_CON + DISP_RDMA_INDEX_OFFSET * idx));
  521. DDPDUMP("(0x044)R_FIFO_LOG =0x%x\n",
  522. DISP_REG_GET(DISP_REG_RDMA_FIFO_LOG + DISP_RDMA_INDEX_OFFSET * idx));
  523. DDPDUMP("(0x078)R_PRE_ADD0 =0x%x\n",
  524. DISP_REG_GET(DISP_REG_RDMA_PRE_ADD_0 + DISP_RDMA_INDEX_OFFSET * idx));
  525. DDPDUMP("(0x07c)R_PRE_ADD1 =0x%x\n",
  526. DISP_REG_GET(DISP_REG_RDMA_PRE_ADD_1 + DISP_RDMA_INDEX_OFFSET * idx));
  527. DDPDUMP("(0x080)R_PRE_ADD2 =0x%x\n",
  528. DISP_REG_GET(DISP_REG_RDMA_PRE_ADD_2 + DISP_RDMA_INDEX_OFFSET * idx));
  529. DDPDUMP("(0x084)R_POST_ADD0 =0x%x\n",
  530. DISP_REG_GET(DISP_REG_RDMA_POST_ADD_0 + DISP_RDMA_INDEX_OFFSET * idx));
  531. DDPDUMP("(0x088)R_POST_ADD1 =0x%x\n",
  532. DISP_REG_GET(DISP_REG_RDMA_POST_ADD_1 + DISP_RDMA_INDEX_OFFSET * idx));
  533. DDPDUMP("(0x08c)R_POST_ADD2 =0x%x\n",
  534. DISP_REG_GET(DISP_REG_RDMA_POST_ADD_2 + DISP_RDMA_INDEX_OFFSET * idx));
  535. DDPDUMP("(0x090)R_DUMMY =0x%x\n",
  536. DISP_REG_GET(DISP_REG_RDMA_DUMMY + DISP_RDMA_INDEX_OFFSET * idx));
  537. DDPDUMP("(0x094)R_OUT_SEL =0x%x\n",
  538. DISP_REG_GET(DISP_REG_RDMA_DEBUG_OUT_SEL + DISP_RDMA_INDEX_OFFSET * idx));
  539. DDPDUMP("(0x094)R_M_START =0x%x\n",
  540. DISP_REG_GET(DISP_REG_RDMA_MEM_START_ADDR + DISP_RDMA_INDEX_OFFSET * idx));
  541. DDPDUMP("(0x0f0)R_IN_PXL_CNT =0x%x\n",
  542. DISP_REG_GET(DISP_REG_RDMA_IN_P_CNT + DISP_RDMA_INDEX_OFFSET * idx));
  543. DDPDUMP("(0x0f4)R_IN_LINE_CNT =0x%x\n",
  544. DISP_REG_GET(DISP_REG_RDMA_IN_LINE_CNT + DISP_RDMA_INDEX_OFFSET * idx));
  545. DDPDUMP("(0x0f8)R_OUT_PXL_CNT =0x%x\n",
  546. DISP_REG_GET(DISP_REG_RDMA_OUT_P_CNT + DISP_RDMA_INDEX_OFFSET * idx));
  547. DDPDUMP("(0x0fc)R_OUT_LINE_CNT=0x%x\n",
  548. DISP_REG_GET(DISP_REG_RDMA_OUT_LINE_CNT + DISP_RDMA_INDEX_OFFSET * idx));
  549. }
  550. void rdma_dump_analysis(DISP_MODULE_ENUM module)
  551. {
  552. unsigned int idx = rdma_index(module);
  553. DDPDUMP("==DISP RDMA%d ANALYSIS==\n", idx);
  554. DDPDUMP("rdma%d: en=%d, memory mode=%d, w=%d, h=%d, pitch=%d, addr=0x%x, fmt=%s, fifo_min=%d,\n",
  555. idx, DISP_REG_GET(DISP_REG_RDMA_GLOBAL_CON + DISP_RDMA_INDEX_OFFSET * idx) & 0x1,
  556. (DISP_REG_GET(DISP_REG_RDMA_GLOBAL_CON + DISP_RDMA_INDEX_OFFSET * idx) & 0x2) ? 1 : 0,
  557. DISP_REG_GET(DISP_REG_RDMA_SIZE_CON_0 + DISP_RDMA_INDEX_OFFSET * idx) & 0xfff,
  558. DISP_REG_GET(DISP_REG_RDMA_SIZE_CON_1 + DISP_RDMA_INDEX_OFFSET * idx) & 0xfffff,
  559. DISP_REG_GET(DISP_REG_RDMA_MEM_SRC_PITCH + DISP_RDMA_INDEX_OFFSET * idx),
  560. DISP_REG_GET(DISP_REG_RDMA_MEM_START_ADDR + DISP_RDMA_INDEX_OFFSET * idx),
  561. rdma_intput_format_name((DISP_REG_GET(DISP_REG_RDMA_MEM_CON + DISP_RDMA_INDEX_OFFSET * idx) >> 4) & 0xf,
  562. (DISP_REG_GET(DISP_REG_RDMA_MEM_CON + DISP_RDMA_INDEX_OFFSET * idx) >> 8) & 0x1),
  563. DISP_REG_GET(DISP_REG_RDMA_FIFO_LOG + DISP_RDMA_INDEX_OFFSET * idx));
  564. DDPDUMP("in_p_cnt=%d, in_l_cnt=%d, out_p_cnt=%d, out_l_cnt=%d, rdma_start_time=%lld ns,rdma_end_time=%lld ns\n",
  565. DISP_REG_GET(DISP_REG_RDMA_IN_P_CNT + DISP_RDMA_INDEX_OFFSET * idx),
  566. DISP_REG_GET(DISP_REG_RDMA_IN_LINE_CNT + DISP_RDMA_INDEX_OFFSET * idx),
  567. DISP_REG_GET(DISP_REG_RDMA_OUT_P_CNT + DISP_RDMA_INDEX_OFFSET * idx),
  568. DISP_REG_GET(DISP_REG_RDMA_OUT_LINE_CNT + DISP_RDMA_INDEX_OFFSET * idx),
  569. rdma_start_time[idx], rdma_end_time[idx]);
  570. DDPDUMP("irq cnt: start=%d, end=%d, underflow=%d, targetline=%d\n",
  571. rdma_start_irq_cnt[idx], rdma_done_irq_cnt[idx], rdma_underflow_irq_cnt[idx],
  572. rdma_targetline_irq_cnt[idx]);
  573. }
  574. static int rdma_dump(DISP_MODULE_ENUM module, int level)
  575. {
  576. rdma_dump_analysis(module);
  577. rdma_dump_reg(module);
  578. return 0;
  579. }
  580. void rdma_get_info(int idx, RDMA_BASIC_STRUCT *info)
  581. {
  582. RDMA_BASIC_STRUCT *p = info;
  583. p->addr = DISP_REG_GET(DISP_REG_RDMA_MEM_START_ADDR + DISP_RDMA_INDEX_OFFSET * idx);
  584. p->src_w = DISP_REG_GET(DISP_REG_RDMA_SIZE_CON_0 + DISP_RDMA_INDEX_OFFSET * idx) & 0xfff;
  585. p->src_h = DISP_REG_GET(DISP_REG_RDMA_SIZE_CON_1 + DISP_RDMA_INDEX_OFFSET * idx) & 0xfffff;
  586. p->bpp = rdma_input_format_bpp((DISP_REG_GET(DISP_REG_RDMA_MEM_CON + DISP_RDMA_INDEX_OFFSET * idx) >> 4) &
  587. 0xf);
  588. }
  589. static inline enum RDMA_MODE rdma_config_mode(unsigned long address)
  590. {
  591. return address ? RDMA_MODE_MEMORY : RDMA_MODE_DIRECT_LINK;
  592. }
  593. static int do_rdma_config_l(DISP_MODULE_ENUM module, disp_ddp_path_config *pConfig, void *handle)
  594. {
  595. RDMA_CONFIG_STRUCT *r_config = &pConfig->rdma_config;
  596. enum RDMA_MODE mode = rdma_config_mode(r_config->address);
  597. LCM_PARAMS *lcm_param = &(pConfig->dispif_config);
  598. unsigned int width = pConfig->dst_dirty ? pConfig->dst_w : r_config->width;
  599. unsigned int height = pConfig->dst_dirty ? pConfig->dst_h : r_config->height;
  600. if (pConfig->fps)
  601. rdma_fps[rdma_index(module)] = pConfig->fps / 100;
  602. if (mode == RDMA_MODE_DIRECT_LINK && r_config->security != DISP_NORMAL_BUFFER)
  603. DDPERR("%s: rdma directlink BUT is sec ??!!\n", __func__);
  604. rdma_config(module, mode, (mode == RDMA_MODE_DIRECT_LINK) ? 0 : r_config->address, /* address */
  605. (mode == RDMA_MODE_DIRECT_LINK) ? eRGB888 : r_config->inputFormat, /* inputFormat */
  606. (mode == RDMA_MODE_DIRECT_LINK) ? 0 : r_config->pitch, /* pitch */
  607. width, height, lcm_param->dsi.ufoe_enable, r_config->security, handle);
  608. return 0;
  609. }
  610. static int setup_rdma_sec(DISP_MODULE_ENUM module, disp_ddp_path_config *pConfig, void *handle)
  611. {
  612. static int rdma_is_sec[RDMA_INSTANCES];
  613. CMDQ_ENG_ENUM cmdq_engine;
  614. int rdma_idx = rdma_index(module);
  615. DISP_BUFFER_TYPE security = pConfig->rdma_config.security;
  616. enum RDMA_MODE mode = rdma_config_mode(pConfig->rdma_config.address);
  617. cmdq_engine = rdma_idx == 0 ? CMDQ_ENG_DISP_RDMA0 : CMDQ_ENG_DISP_RDMA1;
  618. if (!handle) {
  619. DDPMSG("[SVP] bypass rdma sec setting sec=%d,handle=NULL\n", security);
  620. return 0;
  621. }
  622. /* sec setting make sence only in memory mode ! */
  623. if (mode == RDMA_MODE_MEMORY) {
  624. if (security == DISP_SECURE_BUFFER) {
  625. cmdqRecSetSecure(handle, 1);
  626. /* set engine as sec */
  627. cmdqRecSecureEnablePortSecurity(handle, (1LL << cmdq_engine));
  628. /* cmdqRecSecureEnableDAPC(handle, (1LL << cmdq_engine)); */
  629. if (rdma_is_sec[rdma_idx] == 0)
  630. DDPMSG("[SVP] switch rdma%d to sec\n", rdma_idx);
  631. rdma_is_sec[rdma_idx] = 1;
  632. } else {
  633. if (rdma_is_sec[rdma_idx]) {
  634. /* rdma is in sec stat, we need to switch it to nonsec */
  635. cmdqRecHandle nonsec_switch_handle;
  636. int ret;
  637. ret = cmdqRecCreate(CMDQ_SCENARIO_DISP_PRIMARY_DISABLE_SECURE_PATH,
  638. &(nonsec_switch_handle));
  639. if (ret)
  640. DDPAEE("[SVP]fail to create disable handle %s ret=%d\n",
  641. __func__, ret);
  642. cmdqRecReset(nonsec_switch_handle);
  643. _cmdq_insert_wait_frame_done_token_mira(nonsec_switch_handle);
  644. cmdqRecSetSecure(nonsec_switch_handle, 1);
  645. /*ugly work around by kzhang !!. will remove when cmdq delete disable scenario.
  646. * To avoid translation fault like ovl (see notes in ovl.c)*/
  647. do_rdma_config_l(module, pConfig, nonsec_switch_handle);
  648. /*in fact, dapc/port_sec will be disabled by cmdq */
  649. cmdqRecSecureEnablePortSecurity(nonsec_switch_handle,
  650. (1LL << cmdq_engine));
  651. /* cmdqRecSecureEnableDAPC(nonsec_switch_handle, (1LL << cmdq_engine)); */
  652. cmdqRecFlush(nonsec_switch_handle);
  653. cmdqRecDestroy(nonsec_switch_handle);
  654. DDPMSG("[SVP] switch rdma%d to nonsec done\n", rdma_idx);
  655. }
  656. rdma_is_sec[rdma_idx] = 0;
  657. }
  658. }
  659. return 0;
  660. }
  661. static int rdma_config_l(DISP_MODULE_ENUM module, disp_ddp_path_config *pConfig, void *handle)
  662. {
  663. if (pConfig->dst_dirty || pConfig->rdma_dirty) {
  664. setup_rdma_sec(module, pConfig, handle);
  665. do_rdma_config_l(module, pConfig, handle);
  666. }
  667. return 0;
  668. }
  669. DDP_MODULE_DRIVER ddp_driver_rdma = {
  670. .init = rdma_init,
  671. .deinit = rdma_deinit,
  672. .config = rdma_config_l,
  673. .start = rdma_start,
  674. .trigger = NULL,
  675. .stop = rdma_stop,
  676. .reset = rdma_reset,
  677. .power_on = rdma_clock_on,
  678. .power_off = rdma_clock_off,
  679. .is_idle = NULL,
  680. .is_busy = NULL,
  681. .dump_info = rdma_dump,
  682. .bypass = NULL,
  683. .build_cmdq = NULL,
  684. .set_lcm_utils = NULL,
  685. .enable_irq = rdma_enable_irq
  686. };