mtk_drm_ddp_addon.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480
  1. /*
  2. * Copyright (C) 2016 MediaTek Inc.
  3. * Copyright (C) 2021 XiaoMi, Inc.
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License version 2 as
  7. * published by the Free Software Foundation.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  12. * See http://www.gnu.org/licenses/gpl-2.0.html for more details.
  13. */
  14. #include "mtk_drm_ddp_addon.h"
  15. #include "mtk_drm_drv.h"
  16. #include "mtk_rect.h"
  17. #include "mtk_dump.h"
  18. #include "mtk_drm_ddp_comp.h"
  19. #include "mtk_drm_crtc.h"
  20. static const int disp_rsz_path[] = {
  21. DDP_COMPONENT_RSZ0,
  22. };
  23. static const int disp_rsz_path_v2[] = {
  24. DDP_COMPONENT_OVL0_2L_VIRTUAL0,
  25. DDP_COMPONENT_RSZ0,
  26. };
  27. static const int dmdp_pq_with_rdma_path[] = {
  28. DDP_COMPONENT_DMDP_RDMA0, DDP_COMPONENT_DMDP_HDR0,
  29. DDP_COMPONENT_DMDP_AAL0, DDP_COMPONENT_DMDP_RSZ0,
  30. DDP_COMPONENT_DMDP_TDSHP0,
  31. };
  32. static const struct mtk_addon_path_data addon_module_path[ADDON_MODULE_NUM] = {
  33. [DISP_RSZ] = {
  34. .path = disp_rsz_path,
  35. .path_len = ARRAY_SIZE(disp_rsz_path),
  36. },
  37. [DISP_RSZ_v2] = {
  38. .path = disp_rsz_path_v2,
  39. .path_len = ARRAY_SIZE(disp_rsz_path_v2),
  40. },
  41. [DMDP_PQ_WITH_RDMA] = {
  42. .path = dmdp_pq_with_rdma_path,
  43. .path_len = ARRAY_SIZE(dmdp_pq_with_rdma_path),
  44. },
  45. };
  46. const struct mtk_addon_path_data *
  47. mtk_addon_module_get_path(enum addon_module module)
  48. {
  49. return &addon_module_path[module];
  50. }
  51. const struct mtk_addon_scenario_data *
  52. mtk_addon_get_scenario_data(const char *source, struct drm_crtc *crtc,
  53. enum addon_scenario scn)
  54. {
  55. struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
  56. if (scn < NONE || scn >= ADDON_SCN_NR)
  57. goto err;
  58. if (mtk_crtc->path_data && mtk_crtc->path_data->addon_data)
  59. return &mtk_crtc->path_data->addon_data[scn];
  60. err:
  61. DDPPR_ERR("[%s] crtc%d cannot get addon data scn[%u]\n", source,
  62. drm_crtc_index(crtc), scn);
  63. return NULL;
  64. }
  65. bool mtk_addon_scenario_support(struct drm_crtc *crtc, enum addon_scenario scn)
  66. {
  67. const struct mtk_addon_scenario_data *data =
  68. mtk_addon_get_scenario_data(__func__, crtc, scn);
  69. if (data && (data->module_num > 0 || scn == NONE))
  70. return true;
  71. return false;
  72. }
  73. static void mtk_addon_path_start(struct drm_crtc *crtc,
  74. const struct mtk_addon_path_data *path_data,
  75. struct cmdq_pkt *cmdq_handle)
  76. {
  77. int i;
  78. struct mtk_ddp_comp *add_comp = NULL;
  79. struct mtk_drm_private *priv = crtc->dev->dev_private;
  80. for (i = 0; i < path_data->path_len; i++) {
  81. if (mtk_ddp_comp_get_type(path_data->path[i])
  82. == MTK_DISP_VIRTUAL)
  83. continue;
  84. add_comp = priv->ddp_comp[path_data->path[i]];
  85. mtk_ddp_comp_start(add_comp, cmdq_handle);
  86. }
  87. }
  88. static void mtk_addon_path_stop(struct drm_crtc *crtc,
  89. const struct mtk_addon_path_data *path_data,
  90. struct cmdq_pkt *cmdq_handle)
  91. {
  92. int i;
  93. struct mtk_ddp_comp *add_comp = NULL;
  94. struct mtk_drm_private *priv = crtc->dev->dev_private;
  95. for (i = 0; i < path_data->path_len; i++) {
  96. if (mtk_ddp_comp_get_type(path_data->path[i])
  97. == MTK_DISP_VIRTUAL)
  98. continue;
  99. add_comp = priv->ddp_comp[path_data->path[i]];
  100. mtk_ddp_comp_stop(add_comp, cmdq_handle);
  101. }
  102. }
  103. static void
  104. mtk_addon_path_connect_and_add_mutex(struct drm_crtc *crtc,
  105. unsigned int ddp_mode,
  106. const struct mtk_addon_module_data *module,
  107. struct cmdq_pkt *cmdq_handle)
  108. {
  109. int i;
  110. struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
  111. int mutex_id =
  112. mtk_crtc_get_mutex_id(crtc, ddp_mode, module->attach_comp);
  113. const struct mtk_addon_path_data *path_data =
  114. mtk_addon_module_get_path(module->module);
  115. if (mutex_id < 0) {
  116. DDPPR_ERR("invalid mutex id:%d\n", mutex_id);
  117. return;
  118. }
  119. for (i = 0; i < path_data->path_len - 1; i++) {
  120. mtk_ddp_add_comp_to_path_with_cmdq(mtk_crtc, path_data->path[i],
  121. path_data->path[i + 1],
  122. cmdq_handle);
  123. mtk_disp_mutex_add_comp_with_cmdq(
  124. mtk_crtc, path_data->path[i],
  125. mtk_crtc_is_frame_trigger_mode(crtc), cmdq_handle,
  126. mutex_id);
  127. }
  128. mtk_disp_mutex_add_comp_with_cmdq(
  129. mtk_crtc, path_data->path[path_data->path_len - 1],
  130. mtk_crtc_is_frame_trigger_mode(crtc), cmdq_handle, mutex_id);
  131. }
  132. static void mtk_addon_path_disconnect_and_remove_mutex(
  133. struct drm_crtc *crtc, unsigned int ddp_mode,
  134. const struct mtk_addon_module_data *module,
  135. struct cmdq_pkt *cmdq_handle)
  136. {
  137. int i;
  138. struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
  139. int mutex_id =
  140. mtk_crtc_get_mutex_id(crtc, ddp_mode, module->attach_comp);
  141. const struct mtk_addon_path_data *path_data =
  142. mtk_addon_module_get_path(module->module);
  143. if (mutex_id < 0) {
  144. DDPPR_ERR("invalid mutex id:%d\n", mutex_id);
  145. return;
  146. }
  147. for (i = 0; i < path_data->path_len - 1; i++) {
  148. mtk_ddp_remove_comp_from_path_with_cmdq(
  149. mtk_crtc, path_data->path[i], path_data->path[i + 1],
  150. cmdq_handle);
  151. mtk_disp_mutex_remove_comp_with_cmdq(
  152. mtk_crtc, path_data->path[i], cmdq_handle, mutex_id);
  153. }
  154. mtk_disp_mutex_remove_comp_with_cmdq(
  155. mtk_crtc, path_data->path[path_data->path_len - 1], cmdq_handle,
  156. mutex_id);
  157. }
  158. void mtk_addon_connect_between(struct drm_crtc *crtc, unsigned int ddp_mode,
  159. const struct mtk_addon_module_data *module_data,
  160. union mtk_addon_config *addon_config,
  161. struct cmdq_pkt *cmdq_handle)
  162. {
  163. struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
  164. struct mtk_drm_private *priv = crtc->dev->dev_private;
  165. struct mtk_ddp_comp *comp = NULL;
  166. enum mtk_ddp_comp_id attach_comp_id, next_attach_comp_id, prev_comp_id,
  167. cur_comp_id, next_comp_id;
  168. const struct mtk_addon_path_data *path_data =
  169. mtk_addon_module_get_path(module_data->module);
  170. int i, j;
  171. unsigned int addon_idx;
  172. attach_comp_id =
  173. mtk_crtc_find_comp(crtc, ddp_mode, module_data->attach_comp);
  174. if (attach_comp_id == -1) {
  175. if (module_data->attach_comp >= 0)
  176. comp = priv->ddp_comp[module_data->attach_comp];
  177. DDPPR_ERR("Attach module:%s is not in path mode %d\n",
  178. mtk_dump_comp_str(comp), ddp_mode);
  179. return;
  180. }
  181. next_attach_comp_id = mtk_crtc_find_next_comp(crtc, ddp_mode,
  182. module_data->attach_comp);
  183. if (next_attach_comp_id == -1) {
  184. comp = priv->ddp_comp[module_data->attach_comp];
  185. DDPPR_ERR("Attach module:%s has not a next comp in path mode\n",
  186. mtk_dump_comp_str(comp));
  187. return;
  188. }
  189. /* 1. remove original path*/
  190. mtk_crtc_disconnect_path_between_component(
  191. crtc, ddp_mode, attach_comp_id, next_attach_comp_id,
  192. cmdq_handle);
  193. /* 2. connect subpath and add mutex*/
  194. mtk_addon_path_connect_and_add_mutex(crtc, ddp_mode, module_data,
  195. cmdq_handle);
  196. /* 3. add subpath to main path */
  197. mtk_ddp_add_comp_to_path_with_cmdq(mtk_crtc, attach_comp_id,
  198. path_data->path[0], cmdq_handle);
  199. mtk_ddp_add_comp_to_path_with_cmdq(
  200. mtk_crtc, path_data->path[path_data->path_len - 1],
  201. next_attach_comp_id, cmdq_handle);
  202. /* 4. config module */
  203. comp = priv->ddp_comp[attach_comp_id];
  204. prev_comp_id = mtk_crtc_find_prev_comp(crtc, ddp_mode, attach_comp_id);
  205. cur_comp_id = comp->id;
  206. next_comp_id = path_data->path[0];
  207. for (i = 0; i < path_data->path_len; i++)
  208. if (mtk_ddp_comp_get_type(path_data->path[i]) !=
  209. MTK_DISP_VIRTUAL) {
  210. next_comp_id = path_data->path[i];
  211. break;
  212. }
  213. mtk_ddp_comp_addon_config(comp, prev_comp_id, next_comp_id,
  214. addon_config, cmdq_handle);
  215. addon_idx = i;
  216. for (; i < path_data->path_len; i++) {
  217. if (mtk_ddp_comp_get_type(path_data->path[i]) ==
  218. MTK_DISP_VIRTUAL)
  219. continue;
  220. addon_idx = i;
  221. comp = priv->ddp_comp[path_data->path[i]];
  222. prev_comp_id = cur_comp_id;
  223. cur_comp_id = comp->id;
  224. for (j = i + 1; j < path_data->path_len; j++)
  225. if (mtk_ddp_comp_get_type(path_data->path[j]) !=
  226. MTK_DISP_VIRTUAL) {
  227. next_comp_id = path_data->path[j];
  228. mtk_ddp_comp_addon_config(
  229. comp, prev_comp_id, next_comp_id,
  230. addon_config, cmdq_handle);
  231. break;
  232. }
  233. }
  234. comp = priv->ddp_comp[path_data->path[addon_idx]];
  235. prev_comp_id = cur_comp_id;
  236. cur_comp_id = comp->id;
  237. next_comp_id = next_attach_comp_id;
  238. mtk_ddp_comp_addon_config(comp, prev_comp_id, next_comp_id,
  239. addon_config, cmdq_handle);
  240. comp = priv->ddp_comp[next_attach_comp_id];
  241. prev_comp_id = cur_comp_id;
  242. cur_comp_id = comp->id;
  243. next_comp_id =
  244. mtk_crtc_find_next_comp(crtc, ddp_mode, next_attach_comp_id);
  245. mtk_ddp_comp_addon_config(comp, prev_comp_id, next_comp_id,
  246. addon_config, cmdq_handle);
  247. /* 5. start addon module */
  248. mtk_addon_path_start(crtc, path_data, cmdq_handle);
  249. }
  250. void mtk_addon_disconnect_between(
  251. struct drm_crtc *crtc, unsigned int ddp_mode,
  252. const struct mtk_addon_module_data *module_data,
  253. union mtk_addon_config *addon_config, struct cmdq_pkt *cmdq_handle)
  254. {
  255. struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
  256. struct mtk_drm_private *priv = crtc->dev->dev_private;
  257. struct mtk_ddp_comp *comp = NULL;
  258. enum mtk_ddp_comp_id attach_comp_id, next_attach_comp_id, prev_comp_id,
  259. next_comp_id;
  260. const struct mtk_addon_path_data *path_data =
  261. mtk_addon_module_get_path(module_data->module);
  262. attach_comp_id =
  263. mtk_crtc_find_comp(crtc, ddp_mode, module_data->attach_comp);
  264. if (attach_comp_id == -1) {
  265. comp = priv->ddp_comp[module_data->attach_comp];
  266. DDPPR_ERR("Attach module:%s is not in path mode %d\n",
  267. mtk_dump_comp_str(comp), ddp_mode);
  268. return;
  269. }
  270. next_attach_comp_id = mtk_crtc_find_next_comp(crtc, ddp_mode,
  271. module_data->attach_comp);
  272. if (next_attach_comp_id == -1) {
  273. comp = priv->ddp_comp[module_data->attach_comp];
  274. DDPPR_ERR(
  275. "Attach module:%s has not a next comp in path mode %d\n",
  276. mtk_dump_comp_str(comp), ddp_mode);
  277. return;
  278. }
  279. /* 1. stop addon module*/
  280. mtk_addon_path_stop(crtc, path_data, cmdq_handle);
  281. /* 2. remove subpath from main path */
  282. mtk_ddp_remove_comp_from_path_with_cmdq(
  283. mtk_crtc, attach_comp_id, path_data->path[0], cmdq_handle);
  284. mtk_ddp_remove_comp_from_path_with_cmdq(
  285. mtk_crtc, path_data->path[path_data->path_len - 1],
  286. next_attach_comp_id, cmdq_handle);
  287. /* 3. disconnect subpath and remove mutex */
  288. mtk_addon_path_disconnect_and_remove_mutex(crtc, ddp_mode, module_data,
  289. cmdq_handle);
  290. /* 4. connect original path*/
  291. mtk_crtc_connect_path_between_component(crtc, ddp_mode, attach_comp_id,
  292. next_attach_comp_id,
  293. cmdq_handle);
  294. /* 5. config module*/
  295. comp = priv->ddp_comp[attach_comp_id];
  296. prev_comp_id = mtk_crtc_find_prev_comp(crtc, ddp_mode, attach_comp_id);
  297. next_comp_id = next_attach_comp_id;
  298. mtk_ddp_comp_addon_config(comp, prev_comp_id, next_comp_id,
  299. addon_config, cmdq_handle);
  300. comp = priv->ddp_comp[next_attach_comp_id];
  301. prev_comp_id = attach_comp_id;
  302. next_comp_id =
  303. mtk_crtc_find_next_comp(crtc, ddp_mode, next_attach_comp_id);
  304. mtk_ddp_comp_addon_config(comp, prev_comp_id, next_comp_id,
  305. addon_config, cmdq_handle);
  306. }
  307. void mtk_addon_connect_before(struct drm_crtc *crtc, unsigned int ddp_mode,
  308. const struct mtk_addon_module_data *module_data,
  309. union mtk_addon_config *addon_config,
  310. struct cmdq_pkt *cmdq_handle)
  311. {
  312. struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
  313. struct mtk_drm_private *priv = crtc->dev->dev_private;
  314. struct mtk_ddp_comp *comp = NULL;
  315. enum mtk_ddp_comp_id next_attach_comp_id, prev_comp_id, cur_comp_id,
  316. next_comp_id;
  317. const struct mtk_addon_path_data *path_data =
  318. mtk_addon_module_get_path(module_data->module);
  319. int i, j;
  320. unsigned int addon_idx;
  321. next_attach_comp_id =
  322. mtk_crtc_find_comp(crtc, ddp_mode, module_data->attach_comp);
  323. if (next_attach_comp_id == -1) {
  324. comp = priv->ddp_comp[module_data->attach_comp];
  325. DDPPR_ERR("Attach module:%s is not in path mode %d\n",
  326. mtk_dump_comp_str(comp), ddp_mode);
  327. return;
  328. }
  329. /* 1. connect subpath and add mutex*/
  330. mtk_addon_path_connect_and_add_mutex(crtc, ddp_mode, module_data,
  331. cmdq_handle);
  332. /* 2. add subpath to main path */
  333. mtk_ddp_add_comp_to_path_with_cmdq(
  334. mtk_crtc, path_data->path[path_data->path_len - 1],
  335. next_attach_comp_id, cmdq_handle);
  336. /* 3. config module */
  337. addon_idx = 0;
  338. cur_comp_id = -1;
  339. for (i = 0; i < path_data->path_len; i++) {
  340. if (mtk_ddp_comp_get_type(path_data->path[i]) ==
  341. MTK_DISP_VIRTUAL)
  342. continue;
  343. addon_idx = i;
  344. comp = priv->ddp_comp[path_data->path[i]];
  345. prev_comp_id = cur_comp_id;
  346. cur_comp_id = comp->id;
  347. for (j = i + 1; j < path_data->path_len; j++)
  348. if (mtk_ddp_comp_get_type(path_data->path[j]) !=
  349. MTK_DISP_VIRTUAL) {
  350. next_comp_id = path_data->path[j];
  351. mtk_ddp_comp_addon_config(
  352. comp, prev_comp_id, next_comp_id,
  353. addon_config, cmdq_handle);
  354. break;
  355. }
  356. }
  357. comp = priv->ddp_comp[path_data->path[addon_idx]];
  358. prev_comp_id = cur_comp_id;
  359. cur_comp_id = comp->id;
  360. next_comp_id = next_attach_comp_id;
  361. mtk_ddp_comp_addon_config(comp, prev_comp_id, next_comp_id,
  362. addon_config, cmdq_handle);
  363. comp = priv->ddp_comp[next_attach_comp_id];
  364. prev_comp_id = cur_comp_id;
  365. cur_comp_id = comp->id;
  366. next_comp_id =
  367. mtk_crtc_find_next_comp(crtc, ddp_mode, next_attach_comp_id);
  368. mtk_ddp_comp_addon_config(comp, prev_comp_id, next_comp_id,
  369. addon_config, cmdq_handle);
  370. /* 4. start addon module */
  371. mtk_addon_path_start(crtc, path_data, cmdq_handle);
  372. }
  373. void mtk_addon_disconnect_before(
  374. struct drm_crtc *crtc, unsigned int ddp_mode,
  375. const struct mtk_addon_module_data *module_data,
  376. union mtk_addon_config *addon_config, struct cmdq_pkt *cmdq_handle)
  377. {
  378. struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
  379. struct mtk_drm_private *priv = crtc->dev->dev_private;
  380. struct mtk_ddp_comp *comp = NULL;
  381. enum mtk_ddp_comp_id prev_comp_id, next_comp_id, next_attach_comp_id;
  382. const struct mtk_addon_path_data *path_data =
  383. mtk_addon_module_get_path(module_data->module);
  384. next_attach_comp_id =
  385. mtk_crtc_find_comp(crtc, ddp_mode, module_data->attach_comp);
  386. if (next_attach_comp_id == -1) {
  387. comp = priv->ddp_comp[module_data->attach_comp];
  388. DDPPR_ERR("Attach module:%s is not in path mode %d\n",
  389. mtk_dump_comp_str(comp), ddp_mode);
  390. return;
  391. }
  392. /* 1. stop addon module*/
  393. mtk_addon_path_stop(crtc, path_data, cmdq_handle);
  394. /* 2. remove subpath from main path */
  395. mtk_ddp_remove_comp_from_path_with_cmdq(
  396. mtk_crtc, path_data->path[path_data->path_len - 1],
  397. next_attach_comp_id, cmdq_handle);
  398. /* 3. disconnect subpath and remove mutex */
  399. mtk_addon_path_disconnect_and_remove_mutex(crtc, ddp_mode, module_data,
  400. cmdq_handle);
  401. /* 4. config module */
  402. comp = priv->ddp_comp[next_attach_comp_id];
  403. prev_comp_id =
  404. mtk_crtc_find_prev_comp(crtc, ddp_mode, next_attach_comp_id);
  405. next_comp_id =
  406. mtk_crtc_find_next_comp(crtc, ddp_mode, next_attach_comp_id);
  407. mtk_ddp_comp_addon_config(comp, prev_comp_id, next_comp_id,
  408. addon_config, cmdq_handle);
  409. }