sde_hw_ad4.c 54 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
  4. */
  5. #include <drm/msm_drm_pp.h>
  6. #include "sde_hw_catalog.h"
  7. #include "sde_hw_util.h"
  8. #include "sde_hw_mdss.h"
  9. #include "sde_hw_lm.h"
  10. #include "sde_ad4.h"
  11. #define AD_STATE_READY(x) \
  12. (((x) & ad4_init) && \
  13. ((x) & ad4_cfg) && \
  14. ((x) & ad4_mode) && \
  15. (((x) & ad4_input) | ((x) & ad4_strength)))
  16. #define MERGE_WIDTH_RIGHT 6
  17. #define MERGE_WIDTH_LEFT 5
  18. #define AD_IPC_FRAME_COUNT 2
  19. enum ad4_ops_bitmask {
  20. ad4_init = BIT(AD_INIT),
  21. ad4_cfg = BIT(AD_CFG),
  22. ad4_mode = BIT(AD_MODE),
  23. ad4_input = BIT(AD_INPUT),
  24. ad4_strength = BIT(AD_STRENGTH),
  25. ad4_ops_max = BIT(31),
  26. };
  27. enum ad4_state {
  28. ad4_state_idle,
  29. ad4_state_startup,
  30. ad4_state_run,
  31. /* idle power collapse suspend state */
  32. ad4_state_ipcs,
  33. /* idle power collapse resume state */
  34. ad4_state_ipcr,
  35. /* manual mode state */
  36. ad4_state_manual,
  37. ad4_state_max,
  38. };
  39. struct ad4_roi_info {
  40. u32 h_start;
  41. u32 h_end;
  42. u32 v_start;
  43. u32 v_end;
  44. u32 f_in;
  45. u32 f_out;
  46. };
  47. typedef int (*ad4_prop_setup)(struct sde_hw_dspp *dspp,
  48. struct sde_ad_hw_cfg *ad);
  49. static int ad4_params_check(struct sde_hw_dspp *dspp,
  50. struct sde_ad_hw_cfg *cfg);
  51. static int ad4_no_op_setup(struct sde_hw_dspp *dspp, struct sde_ad_hw_cfg *cfg);
  52. static int ad4_setup_debug(struct sde_hw_dspp *dspp, struct sde_ad_hw_cfg *cfg);
  53. static int ad4_setup_debug_manual(struct sde_hw_dspp *dspp,
  54. struct sde_ad_hw_cfg *cfg);
  55. static int ad4_mode_setup(struct sde_hw_dspp *dspp, enum ad4_modes mode);
  56. static int ad4_mode_setup_common(struct sde_hw_dspp *dspp,
  57. struct sde_ad_hw_cfg *cfg);
  58. static int ad4_init_setup(struct sde_hw_dspp *dspp, struct sde_ad_hw_cfg *cfg);
  59. static int ad4_init_setup_idle(struct sde_hw_dspp *dspp,
  60. struct sde_ad_hw_cfg *cfg);
  61. static int ad4_init_setup_run(struct sde_hw_dspp *dspp,
  62. struct sde_ad_hw_cfg *cfg);
  63. static int ad4_init_setup_ipcr(struct sde_hw_dspp *dspp,
  64. struct sde_ad_hw_cfg *cfg);
  65. static int ad4_cfg_setup(struct sde_hw_dspp *dspp, struct sde_ad_hw_cfg *cfg);
  66. static int ad4_cfg_setup_idle(struct sde_hw_dspp *dspp,
  67. struct sde_ad_hw_cfg *cfg);
  68. static int ad4_cfg_setup_run(struct sde_hw_dspp *dspp,
  69. struct sde_ad_hw_cfg *cfg);
  70. static int ad4_cfg_setup_ipcr(struct sde_hw_dspp *dspp,
  71. struct sde_ad_hw_cfg *cfg);
  72. static int ad4_input_setup(struct sde_hw_dspp *dspp,
  73. struct sde_ad_hw_cfg *cfg);
  74. static int ad4_roi_setup(struct sde_hw_dspp *dspp, struct sde_ad_hw_cfg *cfg);
  75. static int ad4_roi_setup_ipcr(struct sde_hw_dspp *dspp,
  76. struct sde_ad_hw_cfg *cfg);
  77. static int ad4_roi_coordinate_offset(struct sde_hw_cp_cfg *hw_cfg,
  78. struct ad4_roi_info *output);
  79. static int ad4_input_setup_idle(struct sde_hw_dspp *dspp,
  80. struct sde_ad_hw_cfg *cfg);
  81. static int ad4_input_setup_ipcr(struct sde_hw_dspp *dspp,
  82. struct sde_ad_hw_cfg *cfg);
  83. static int ad4_suspend_setup(struct sde_hw_dspp *dspp,
  84. struct sde_ad_hw_cfg *cfg);
  85. static int ad4_assertive_setup(struct sde_hw_dspp *dspp,
  86. struct sde_ad_hw_cfg *cfg);
  87. static int ad4_assertive_setup_ipcr(struct sde_hw_dspp *dspp,
  88. struct sde_ad_hw_cfg *cfg);
  89. static int ad4_backlight_setup(struct sde_hw_dspp *dspp,
  90. struct sde_ad_hw_cfg *cfg);
  91. static int ad4_backlight_setup_ipcr(struct sde_hw_dspp *dspp,
  92. struct sde_ad_hw_cfg *cfg);
  93. static int ad4_strength_setup(struct sde_hw_dspp *dspp,
  94. struct sde_ad_hw_cfg *cfg);
  95. static int ad4_strength_setup_idle(struct sde_hw_dspp *dspp,
  96. struct sde_ad_hw_cfg *cfg);
  97. static int ad4_ipc_suspend_setup_run(struct sde_hw_dspp *dspp,
  98. struct sde_ad_hw_cfg *cfg);
  99. static int ad4_ipc_suspend_setup_ipcr(struct sde_hw_dspp *dspp,
  100. struct sde_ad_hw_cfg *cfg);
  101. static int ad4_ipc_resume_setup_ipcs(struct sde_hw_dspp *dspp,
  102. struct sde_ad_hw_cfg *cfg);
  103. static int ad4_ipc_reset_setup_startup(struct sde_hw_dspp *dspp,
  104. struct sde_ad_hw_cfg *cfg);
  105. static int ad4_ipc_reset_setup_ipcr(struct sde_hw_dspp *dspp,
  106. struct sde_ad_hw_cfg *cfg);
  107. static int ad4_cfg_ipc_reset(struct sde_hw_dspp *dspp,
  108. struct sde_ad_hw_cfg *cfg);
  109. static ad4_prop_setup prop_set_func[ad4_state_max][AD_PROPMAX] = {
  110. [ad4_state_idle][AD_MODE] = ad4_mode_setup_common,
  111. [ad4_state_idle][AD_INIT] = ad4_init_setup_idle,
  112. [ad4_state_idle][AD_CFG] = ad4_cfg_setup_idle,
  113. [ad4_state_idle][AD_INPUT] = ad4_input_setup_idle,
  114. [ad4_state_idle][AD_SUSPEND] = ad4_suspend_setup,
  115. [ad4_state_idle][AD_ASSERTIVE] = ad4_assertive_setup,
  116. [ad4_state_idle][AD_BACKLIGHT] = ad4_backlight_setup,
  117. [ad4_state_idle][AD_STRENGTH] = ad4_strength_setup_idle,
  118. [ad4_state_idle][AD_ROI] = ad4_roi_setup,
  119. [ad4_state_idle][AD_IPC_SUSPEND] = ad4_no_op_setup,
  120. [ad4_state_idle][AD_IPC_RESUME] = ad4_no_op_setup,
  121. [ad4_state_idle][AD_IPC_RESET] = ad4_no_op_setup,
  122. [ad4_state_startup][AD_MODE] = ad4_mode_setup_common,
  123. [ad4_state_startup][AD_INIT] = ad4_init_setup,
  124. [ad4_state_startup][AD_CFG] = ad4_cfg_setup,
  125. [ad4_state_startup][AD_INPUT] = ad4_input_setup,
  126. [ad4_state_startup][AD_SUSPEND] = ad4_suspend_setup,
  127. [ad4_state_startup][AD_ASSERTIVE] = ad4_assertive_setup,
  128. [ad4_state_startup][AD_BACKLIGHT] = ad4_backlight_setup,
  129. [ad4_state_startup][AD_IPC_SUSPEND] = ad4_no_op_setup,
  130. [ad4_state_startup][AD_STRENGTH] = ad4_no_op_setup,
  131. [ad4_state_startup][AD_ROI] = ad4_roi_setup,
  132. [ad4_state_startup][AD_IPC_RESUME] = ad4_no_op_setup,
  133. [ad4_state_startup][AD_IPC_RESET] = ad4_ipc_reset_setup_startup,
  134. [ad4_state_run][AD_MODE] = ad4_mode_setup_common,
  135. [ad4_state_run][AD_INIT] = ad4_init_setup_run,
  136. [ad4_state_run][AD_CFG] = ad4_cfg_setup_run,
  137. [ad4_state_run][AD_INPUT] = ad4_input_setup,
  138. [ad4_state_run][AD_SUSPEND] = ad4_suspend_setup,
  139. [ad4_state_run][AD_ASSERTIVE] = ad4_assertive_setup,
  140. [ad4_state_run][AD_BACKLIGHT] = ad4_backlight_setup,
  141. [ad4_state_run][AD_STRENGTH] = ad4_no_op_setup,
  142. [ad4_state_run][AD_ROI] = ad4_roi_setup,
  143. [ad4_state_run][AD_IPC_SUSPEND] = ad4_ipc_suspend_setup_run,
  144. [ad4_state_run][AD_IPC_RESUME] = ad4_no_op_setup,
  145. [ad4_state_run][AD_IPC_RESET] = ad4_setup_debug,
  146. [ad4_state_ipcs][AD_MODE] = ad4_no_op_setup,
  147. [ad4_state_ipcs][AD_INIT] = ad4_no_op_setup,
  148. [ad4_state_ipcs][AD_CFG] = ad4_no_op_setup,
  149. [ad4_state_ipcs][AD_INPUT] = ad4_no_op_setup,
  150. [ad4_state_ipcs][AD_SUSPEND] = ad4_no_op_setup,
  151. [ad4_state_ipcs][AD_ASSERTIVE] = ad4_no_op_setup,
  152. [ad4_state_ipcs][AD_BACKLIGHT] = ad4_no_op_setup,
  153. [ad4_state_ipcs][AD_STRENGTH] = ad4_no_op_setup,
  154. [ad4_state_ipcs][AD_ROI] = ad4_no_op_setup,
  155. [ad4_state_ipcs][AD_IPC_SUSPEND] = ad4_no_op_setup,
  156. [ad4_state_ipcs][AD_IPC_RESUME] = ad4_ipc_resume_setup_ipcs,
  157. [ad4_state_ipcs][AD_IPC_RESET] = ad4_no_op_setup,
  158. [ad4_state_ipcr][AD_MODE] = ad4_mode_setup_common,
  159. [ad4_state_ipcr][AD_INIT] = ad4_init_setup_ipcr,
  160. [ad4_state_ipcr][AD_CFG] = ad4_cfg_setup_ipcr,
  161. [ad4_state_ipcr][AD_INPUT] = ad4_input_setup_ipcr,
  162. [ad4_state_ipcr][AD_SUSPEND] = ad4_suspend_setup,
  163. [ad4_state_ipcr][AD_ASSERTIVE] = ad4_assertive_setup_ipcr,
  164. [ad4_state_ipcr][AD_BACKLIGHT] = ad4_backlight_setup_ipcr,
  165. [ad4_state_ipcr][AD_STRENGTH] = ad4_no_op_setup,
  166. [ad4_state_ipcr][AD_ROI] = ad4_roi_setup_ipcr,
  167. [ad4_state_ipcr][AD_IPC_SUSPEND] = ad4_ipc_suspend_setup_ipcr,
  168. [ad4_state_ipcr][AD_IPC_RESUME] = ad4_no_op_setup,
  169. [ad4_state_ipcr][AD_IPC_RESET] = ad4_ipc_reset_setup_ipcr,
  170. [ad4_state_manual][AD_MODE] = ad4_mode_setup_common,
  171. [ad4_state_manual][AD_INIT] = ad4_init_setup,
  172. [ad4_state_manual][AD_CFG] = ad4_cfg_setup,
  173. [ad4_state_manual][AD_INPUT] = ad4_no_op_setup,
  174. [ad4_state_manual][AD_SUSPEND] = ad4_no_op_setup,
  175. [ad4_state_manual][AD_ASSERTIVE] = ad4_no_op_setup,
  176. [ad4_state_manual][AD_BACKLIGHT] = ad4_no_op_setup,
  177. [ad4_state_manual][AD_STRENGTH] = ad4_strength_setup,
  178. [ad4_state_manual][AD_ROI] = ad4_roi_setup,
  179. [ad4_state_manual][AD_IPC_SUSPEND] = ad4_no_op_setup,
  180. [ad4_state_manual][AD_IPC_RESUME] = ad4_no_op_setup,
  181. [ad4_state_manual][AD_IPC_RESET] = ad4_setup_debug_manual,
  182. };
  183. struct ad4_info {
  184. enum ad4_state state;
  185. u32 completed_ops_mask;
  186. bool ad4_support;
  187. enum ad4_modes mode;
  188. bool is_master;
  189. u32 last_assertive;
  190. u32 cached_assertive;
  191. u32 last_str_inroi;
  192. u32 last_str_outroi;
  193. u64 last_als;
  194. u64 cached_als;
  195. u64 last_bl;
  196. u64 cached_bl;
  197. u32 frame_count;
  198. u32 frmt_mode;
  199. u32 irdx_control_0;
  200. u32 tf_ctrl;
  201. u32 vc_control_0;
  202. struct ad4_roi_info last_roi_cfg;
  203. struct ad4_roi_info cached_roi_cfg;
  204. };
  205. static struct ad4_info info[DSPP_MAX] = {
  206. [DSPP_0] = {ad4_state_idle, 0, true, AD4_OFF, false, 0x80, 0x80},
  207. [DSPP_1] = {ad4_state_idle, 0, true, AD4_OFF, false, 0x80, 0x80},
  208. [DSPP_2] = {ad4_state_max, 0, false, AD4_OFF, false, 0x80, 0x80},
  209. [DSPP_3] = {ad4_state_max, 0, false, AD4_OFF, false, 0x80, 0x80},
  210. };
  211. void sde_setup_dspp_ad4(struct sde_hw_dspp *dspp, void *ad_cfg)
  212. {
  213. int ret = 0;
  214. struct sde_ad_hw_cfg *cfg = ad_cfg;
  215. ret = ad4_params_check(dspp, ad_cfg);
  216. if (ret)
  217. return;
  218. ret = prop_set_func[info[dspp->idx].state][cfg->prop](dspp, ad_cfg);
  219. if (ret)
  220. DRM_ERROR("op failed %d ret %d\n", cfg->prop, ret);
  221. }
  222. int sde_validate_dspp_ad4(struct sde_hw_dspp *dspp, u32 *prop)
  223. {
  224. if (!dspp || !prop) {
  225. DRM_ERROR("invalid params dspp %pK prop %pK\n", dspp, prop);
  226. return -EINVAL;
  227. }
  228. if (*prop >= AD_PROPMAX) {
  229. DRM_ERROR("invalid prop set %d\n", *prop);
  230. return -EINVAL;
  231. }
  232. if (dspp->idx >= DSPP_MAX || !info[dspp->idx].ad4_support) {
  233. DRM_ERROR("ad4 not supported for dspp idx %d\n", dspp->idx);
  234. return -EINVAL;
  235. }
  236. return 0;
  237. }
  238. static int ad4_params_check(struct sde_hw_dspp *dspp,
  239. struct sde_ad_hw_cfg *cfg)
  240. {
  241. struct sde_hw_mixer *hw_lm;
  242. if (!dspp || !cfg || !cfg->hw_cfg) {
  243. DRM_ERROR("invalid dspp %pK cfg %pK hw_cfg %pK\n",
  244. dspp, cfg, ((cfg) ? (cfg->hw_cfg) : NULL));
  245. return -EINVAL;
  246. }
  247. if (!cfg->hw_cfg->mixer_info) {
  248. DRM_ERROR("invalid mixed info\n");
  249. return -EINVAL;
  250. }
  251. if (dspp->idx >= DSPP_MAX || !info[dspp->idx].ad4_support) {
  252. DRM_ERROR("ad4 not supported for dspp idx %d\n", dspp->idx);
  253. return -EINVAL;
  254. }
  255. if (cfg->prop >= AD_PROPMAX) {
  256. DRM_ERROR("invalid prop set %d\n", cfg->prop);
  257. return -EINVAL;
  258. }
  259. if (info[dspp->idx].state >= ad4_state_max) {
  260. DRM_ERROR("in max state for dspp idx %d\n", dspp->idx);
  261. return -EINVAL;
  262. }
  263. if (!prop_set_func[info[dspp->idx].state][cfg->prop]) {
  264. DRM_ERROR("prop set not implemented for state %d prop %d\n",
  265. info[dspp->idx].state, cfg->prop);
  266. return -EINVAL;
  267. }
  268. if (!cfg->hw_cfg->num_of_mixers ||
  269. cfg->hw_cfg->num_of_mixers > CRTC_DUAL_MIXERS) {
  270. DRM_ERROR("invalid mixer cnt %d\n",
  271. cfg->hw_cfg->num_of_mixers);
  272. return -EINVAL;
  273. }
  274. hw_lm = cfg->hw_cfg->mixer_info;
  275. if (!hw_lm) {
  276. DRM_ERROR("invalid mixer info\n");
  277. return -EINVAL;
  278. }
  279. if (cfg->hw_cfg->num_of_mixers == 1 &&
  280. hw_lm->cfg.out_height != cfg->hw_cfg->displayv &&
  281. hw_lm->cfg.out_width != cfg->hw_cfg->displayh) {
  282. DRM_ERROR("single_lm lmh %d lmw %d displayh %d displayw %d\n",
  283. hw_lm->cfg.out_height, hw_lm->cfg.out_width,
  284. cfg->hw_cfg->displayh, cfg->hw_cfg->displayv);
  285. return -EINVAL;
  286. } else if (hw_lm->cfg.out_height != cfg->hw_cfg->displayv &&
  287. hw_lm->cfg.out_width != (cfg->hw_cfg->displayh >> 1)) {
  288. DRM_ERROR("dual_lm lmh %d lmw %d displayh %d displayw %d\n",
  289. hw_lm->cfg.out_height, hw_lm->cfg.out_width,
  290. cfg->hw_cfg->displayh, cfg->hw_cfg->displayv);
  291. return -EINVAL;
  292. }
  293. return 0;
  294. }
  295. static int ad4_no_op_setup(struct sde_hw_dspp *dspp, struct sde_ad_hw_cfg *cfg)
  296. {
  297. return 0;
  298. }
  299. static int ad4_setup_debug(struct sde_hw_dspp *dspp, struct sde_ad_hw_cfg *cfg)
  300. {
  301. u32 in_str = 0, out_str = 0;
  302. struct sde_hw_mixer *hw_lm;
  303. hw_lm = cfg->hw_cfg->mixer_info;
  304. if ((cfg->hw_cfg->num_of_mixers == 2) && hw_lm->cfg.right_mixer)
  305. /* this AD core is the salve core */
  306. return 0;
  307. in_str = SDE_REG_READ(&dspp->hw, dspp->cap->sblk->ad.base + 0x4c);
  308. out_str = SDE_REG_READ(&dspp->hw, dspp->cap->sblk->ad.base + 0x50);
  309. pr_debug("%s(): AD in strength %d, out strength %d\n", __func__,
  310. in_str, out_str);
  311. return 0;
  312. }
  313. static int ad4_setup_debug_manual(struct sde_hw_dspp *dspp,
  314. struct sde_ad_hw_cfg *cfg)
  315. {
  316. u32 in_str = 0, out_str = 0;
  317. struct sde_hw_mixer *hw_lm;
  318. hw_lm = cfg->hw_cfg->mixer_info;
  319. if ((cfg->hw_cfg->num_of_mixers == 2) && hw_lm->cfg.right_mixer)
  320. /* this AD core is the salve core */
  321. return 0;
  322. in_str = SDE_REG_READ(&dspp->hw, dspp->cap->sblk->ad.base + 0x15c);
  323. out_str = SDE_REG_READ(&dspp->hw, dspp->cap->sblk->ad.base + 0x160);
  324. pr_debug("%s(): AD in strength = %d, out strength = %d in manual mode\n",
  325. __func__, in_str, out_str);
  326. return 0;
  327. }
  328. static int ad4_mode_setup(struct sde_hw_dspp *dspp, enum ad4_modes mode)
  329. {
  330. u32 blk_offset;
  331. if (mode == AD4_OFF) {
  332. blk_offset = 0x04;
  333. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
  334. 0x101);
  335. info[dspp->idx].state = ad4_state_idle;
  336. pr_debug("%s(): AD state move to idle\n", __func__);
  337. info[dspp->idx].completed_ops_mask = 0;
  338. /* reset last values to register default */
  339. info[dspp->idx].last_assertive = 0x80;
  340. info[dspp->idx].cached_assertive = U8_MAX;
  341. info[dspp->idx].last_bl = 0xFFFF;
  342. info[dspp->idx].cached_bl = U64_MAX;
  343. info[dspp->idx].last_als = 0x0;
  344. info[dspp->idx].cached_als = U64_MAX;
  345. info[dspp->idx].last_roi_cfg.h_start = 0x0;
  346. info[dspp->idx].last_roi_cfg.h_end = 0xffff;
  347. info[dspp->idx].last_roi_cfg.v_start = 0x0;
  348. info[dspp->idx].last_roi_cfg.v_end = 0xffff;
  349. info[dspp->idx].last_roi_cfg.f_in = 0x400;
  350. info[dspp->idx].last_roi_cfg.f_out = 0x400;
  351. info[dspp->idx].cached_roi_cfg.h_start = U32_MAX;
  352. info[dspp->idx].cached_roi_cfg.h_end = U32_MAX;
  353. info[dspp->idx].cached_roi_cfg.v_start = U32_MAX;
  354. info[dspp->idx].cached_roi_cfg.v_end = U32_MAX;
  355. info[dspp->idx].cached_roi_cfg.f_in = U32_MAX;
  356. info[dspp->idx].cached_roi_cfg.f_out = U32_MAX;
  357. } else {
  358. if (mode == AD4_MANUAL) {
  359. /*vc_control_0 */
  360. blk_offset = 0x138;
  361. SDE_REG_WRITE(&dspp->hw,
  362. dspp->cap->sblk->ad.base + blk_offset, 0);
  363. /* irdx_control_0 */
  364. blk_offset = 0x13c;
  365. SDE_REG_WRITE(&dspp->hw,
  366. dspp->cap->sblk->ad.base + blk_offset,
  367. info[dspp->idx].irdx_control_0);
  368. }
  369. if (info[dspp->idx].state == ad4_state_idle) {
  370. if (mode == AD4_MANUAL) {
  371. info[dspp->idx].state = ad4_state_manual;
  372. pr_debug("%s(): AD state move to manual\n",
  373. __func__);
  374. } else {
  375. info[dspp->idx].frame_count = 0;
  376. info[dspp->idx].state = ad4_state_startup;
  377. pr_debug("%s(): AD state move to startup\n",
  378. __func__);
  379. }
  380. }
  381. blk_offset = 0x04;
  382. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
  383. 0x100);
  384. }
  385. return 0;
  386. }
  387. static int ad4_init_setup(struct sde_hw_dspp *dspp, struct sde_ad_hw_cfg *cfg)
  388. {
  389. u32 frame_start, frame_end, proc_start, proc_end;
  390. struct sde_hw_mixer *hw_lm;
  391. u32 blk_offset, tile_ctl, val, i;
  392. u32 off1, off2, off3, off4, off5, off6;
  393. struct drm_msm_ad4_init *init;
  394. if (!cfg->hw_cfg->payload) {
  395. info[dspp->idx].completed_ops_mask &= ~ad4_init;
  396. return 0;
  397. }
  398. if (cfg->hw_cfg->len != sizeof(struct drm_msm_ad4_init)) {
  399. DRM_ERROR("invalid sz param exp %zd given %d cfg %pK\n",
  400. sizeof(struct drm_msm_ad4_init), cfg->hw_cfg->len,
  401. cfg->hw_cfg->payload);
  402. return -EINVAL;
  403. }
  404. hw_lm = cfg->hw_cfg->mixer_info;
  405. if (cfg->hw_cfg->num_of_mixers == 1) {
  406. frame_start = 0;
  407. frame_end = 0xffff;
  408. proc_start = 0;
  409. proc_end = 0xffff;
  410. tile_ctl = 0;
  411. info[dspp->idx].is_master = true;
  412. } else {
  413. tile_ctl = 0x5;
  414. if (hw_lm->cfg.right_mixer) {
  415. frame_start = (cfg->hw_cfg->displayh >> 1) -
  416. MERGE_WIDTH_RIGHT;
  417. frame_end = cfg->hw_cfg->displayh - 1;
  418. proc_start = (cfg->hw_cfg->displayh >> 1);
  419. proc_end = frame_end;
  420. tile_ctl |= 0x10;
  421. info[dspp->idx].is_master = false;
  422. } else {
  423. frame_start = 0;
  424. frame_end = (cfg->hw_cfg->displayh >> 1) +
  425. MERGE_WIDTH_LEFT;
  426. proc_start = 0;
  427. proc_end = (cfg->hw_cfg->displayh >> 1) - 1;
  428. tile_ctl |= 0x10;
  429. info[dspp->idx].is_master = true;
  430. }
  431. }
  432. init = cfg->hw_cfg->payload;
  433. info[dspp->idx].frmt_mode = (init->init_param_009 & (BIT(14) - 1));
  434. blk_offset = 0xc;
  435. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
  436. init->init_param_010);
  437. init->init_param_012 = cfg->hw_cfg->displayv & (BIT(17) - 1);
  438. init->init_param_011 = cfg->hw_cfg->displayh & (BIT(17) - 1);
  439. blk_offset = 0x10;
  440. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
  441. ((init->init_param_011 << 16) | init->init_param_012));
  442. blk_offset = 0x14;
  443. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
  444. tile_ctl);
  445. blk_offset = 0x44;
  446. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
  447. ((((init->init_param_013) & (BIT(17) - 1)) << 16) |
  448. (init->init_param_014 & (BIT(17) - 1))));
  449. blk_offset = 0x5c;
  450. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
  451. (init->init_param_015 & (BIT(16) - 1)));
  452. blk_offset = 0x60;
  453. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
  454. (init->init_param_016 & (BIT(8) - 1)));
  455. blk_offset = 0x64;
  456. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
  457. (init->init_param_017 & (BIT(12) - 1)));
  458. blk_offset = 0x68;
  459. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
  460. (init->init_param_018 & (BIT(12) - 1)));
  461. blk_offset = 0x6c;
  462. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
  463. (init->init_param_019 & (BIT(12) - 1)));
  464. blk_offset = 0x70;
  465. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
  466. (init->init_param_020 & (BIT(16) - 1)));
  467. blk_offset = 0x74;
  468. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
  469. (init->init_param_021 & (BIT(8) - 1)));
  470. blk_offset = 0x78;
  471. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
  472. (init->init_param_022 & (BIT(8) - 1)));
  473. blk_offset = 0x7c;
  474. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
  475. (init->init_param_023 & (BIT(16) - 1)));
  476. blk_offset = 0x80;
  477. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
  478. (((init->init_param_024 & (BIT(16) - 1)) << 16) |
  479. ((init->init_param_025 & (BIT(16) - 1)))));
  480. blk_offset = 0x84;
  481. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
  482. (((init->init_param_026 & (BIT(16) - 1)) << 16) |
  483. ((init->init_param_027 & (BIT(16) - 1)))));
  484. blk_offset = 0x90;
  485. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
  486. (init->init_param_028 & (BIT(16) - 1)));
  487. blk_offset = 0x94;
  488. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
  489. (init->init_param_029 & (BIT(16) - 1)));
  490. blk_offset = 0x98;
  491. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
  492. (((init->init_param_035 & (BIT(16) - 1)) << 16) |
  493. ((init->init_param_030 & (BIT(16) - 1)))));
  494. blk_offset = 0x9c;
  495. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
  496. (((init->init_param_032 & (BIT(16) - 1)) << 16) |
  497. ((init->init_param_031 & (BIT(16) - 1)))));
  498. blk_offset = 0xa0;
  499. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
  500. (((init->init_param_034 & (BIT(16) - 1)) << 16) |
  501. ((init->init_param_033 & (BIT(16) - 1)))));
  502. blk_offset = 0xb4;
  503. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
  504. (init->init_param_036 & (BIT(8) - 1)));
  505. blk_offset = 0xcc;
  506. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
  507. (init->init_param_037 & (BIT(8) - 1)));
  508. blk_offset = 0xc0;
  509. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
  510. (init->init_param_038 & (BIT(8) - 1)));
  511. blk_offset = 0xd8;
  512. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
  513. (init->init_param_039 & (BIT(8) - 1)));
  514. blk_offset = 0xe8;
  515. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
  516. (init->init_param_040 & (BIT(16) - 1)));
  517. blk_offset = 0xf4;
  518. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
  519. (init->init_param_041 & (BIT(8) - 1)));
  520. blk_offset = 0x100;
  521. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
  522. (init->init_param_042 & (BIT(16) - 1)));
  523. blk_offset = 0x10c;
  524. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
  525. (init->init_param_043 & (BIT(8) - 1)));
  526. blk_offset = 0x120;
  527. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
  528. (init->init_param_044 & (BIT(16) - 1)));
  529. blk_offset = 0x124;
  530. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
  531. (init->init_param_045 & (BIT(16) - 1)));
  532. blk_offset = 0x128;
  533. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
  534. (init->init_param_046 & (BIT(1) - 1)));
  535. blk_offset = 0x12c;
  536. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
  537. (init->init_param_047 & (BIT(8) - 1)));
  538. info[dspp->idx].irdx_control_0 = (init->init_param_048 & (BIT(5) - 1));
  539. blk_offset = 0x140;
  540. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
  541. (init->init_param_049 & (BIT(8) - 1)));
  542. blk_offset = 0x144;
  543. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
  544. (init->init_param_050 & (BIT(8) - 1)));
  545. blk_offset = 0x148;
  546. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
  547. (((init->init_param_051 & (BIT(8) - 1)) << 8) |
  548. ((init->init_param_052 & (BIT(8) - 1)))));
  549. blk_offset = 0x14c;
  550. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
  551. (init->init_param_053 & (BIT(10) - 1)));
  552. blk_offset = 0x150;
  553. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
  554. (init->init_param_054 & (BIT(10) - 1)));
  555. blk_offset = 0x154;
  556. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
  557. (init->init_param_055 & (BIT(8) - 1)));
  558. blk_offset = 0x158;
  559. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
  560. (init->init_param_056 & (BIT(8) - 1)));
  561. blk_offset = 0x164;
  562. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
  563. (init->init_param_057 & (BIT(8) - 1)));
  564. blk_offset = 0x168;
  565. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
  566. (init->init_param_058 & (BIT(4) - 1)));
  567. blk_offset = 0x17c;
  568. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
  569. (frame_start & (BIT(16) - 1)));
  570. blk_offset = 0x180;
  571. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
  572. (frame_end & (BIT(16) - 1)));
  573. blk_offset = 0x184;
  574. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
  575. (proc_start & (BIT(16) - 1)));
  576. blk_offset = 0x188;
  577. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
  578. (proc_end & (BIT(16) - 1)));
  579. blk_offset = 0x18c;
  580. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
  581. (init->init_param_059 & (BIT(4) - 1)));
  582. blk_offset = 0x190;
  583. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
  584. (((init->init_param_061 & (BIT(8) - 1)) << 8) |
  585. ((init->init_param_060 & (BIT(8) - 1)))));
  586. blk_offset = 0x194;
  587. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
  588. (init->init_param_062 & (BIT(10) - 1)));
  589. blk_offset = 0x1a0;
  590. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
  591. (init->init_param_063 & (BIT(10) - 1)));
  592. blk_offset = 0x1a4;
  593. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
  594. (init->init_param_064 & (BIT(10) - 1)));
  595. blk_offset = 0x1a8;
  596. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
  597. (init->init_param_065 & (BIT(10) - 1)));
  598. blk_offset = 0x1ac;
  599. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
  600. (init->init_param_066 & (BIT(8) - 1)));
  601. blk_offset = 0x1b0;
  602. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
  603. (init->init_param_067 & (BIT(8) - 1)));
  604. blk_offset = 0x1b4;
  605. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
  606. (init->init_param_068 & (BIT(6) - 1)));
  607. blk_offset = 0x460;
  608. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
  609. (init->init_param_069 & (BIT(16) - 1)));
  610. blk_offset = 0x464;
  611. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
  612. (init->init_param_070 & (BIT(10) - 1)));
  613. blk_offset = 0x468;
  614. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
  615. (init->init_param_071 & (BIT(10) - 1)));
  616. blk_offset = 0x46c;
  617. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
  618. (init->init_param_072 & (BIT(10) - 1)));
  619. blk_offset = 0x470;
  620. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
  621. (init->init_param_073 & (BIT(8) - 1)));
  622. blk_offset = 0x474;
  623. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
  624. (init->init_param_074 & (BIT(10) - 1)));
  625. blk_offset = 0x478;
  626. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
  627. (init->init_param_075 & (BIT(10) - 1)));
  628. off1 = 0x1c0;
  629. off2 = 0x210;
  630. off3 = 0x260;
  631. off4 = 0x2b0;
  632. off5 = 0x380;
  633. off6 = 0x3d0;
  634. for (i = 0; i < AD4_LUT_GRP0_SIZE - 1; i = i + 2) {
  635. val = (init->init_param_001[i] & (BIT(16) - 1));
  636. val |= ((init->init_param_001[i + 1] & (BIT(16) - 1))
  637. << 16);
  638. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + off1, val);
  639. off1 += 4;
  640. val = (init->init_param_002[i] & (BIT(16) - 1));
  641. val |= ((init->init_param_002[i + 1] & (BIT(16) - 1))
  642. << 16);
  643. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + off2, val);
  644. off2 += 4;
  645. val = (init->init_param_003[i] & (BIT(16) - 1));
  646. val |= ((init->init_param_003[i + 1] & (BIT(16) - 1))
  647. << 16);
  648. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + off3, val);
  649. off3 += 4;
  650. val = (init->init_param_004[i] & (BIT(16) - 1));
  651. val |= ((init->init_param_004[i + 1] & (BIT(16) - 1))
  652. << 16);
  653. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + off4, val);
  654. off4 += 4;
  655. val = (init->init_param_007[i] & (BIT(16) - 1));
  656. val |= ((init->init_param_007[i + 1] &
  657. (BIT(16) - 1)) << 16);
  658. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + off5, val);
  659. off5 += 4;
  660. val = (init->init_param_008[i] & (BIT(12) - 1));
  661. val |= ((init->init_param_008[i + 1] &
  662. (BIT(12) - 1)) << 16);
  663. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + off6, val);
  664. off6 += 4;
  665. }
  666. /* write last index data */
  667. i = AD4_LUT_GRP0_SIZE - 1;
  668. val = ((init->init_param_001[i] & (BIT(16) - 1)) << 16);
  669. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + off1, val);
  670. val = ((init->init_param_002[i] & (BIT(16) - 1)) << 16);
  671. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + off2, val);
  672. val = ((init->init_param_003[i] & (BIT(16) - 1)) << 16);
  673. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + off3, val);
  674. val = ((init->init_param_004[i] & (BIT(16) - 1)) << 16);
  675. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + off4, val);
  676. val = ((init->init_param_007[i] & (BIT(16) - 1)) << 16);
  677. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + off5, val);
  678. val = ((init->init_param_008[i] & (BIT(12) - 1)) << 16);
  679. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + off6, val);
  680. off1 = 0x300;
  681. off2 = 0x340;
  682. for (i = 0; i < AD4_LUT_GRP1_SIZE; i = i + 2) {
  683. val = (init->init_param_005[i] & (BIT(16) - 1));
  684. val |= ((init->init_param_005[i + 1] &
  685. (BIT(16) - 1)) << 16);
  686. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + off1, val);
  687. off1 += 4;
  688. val = (init->init_param_006[i] & (BIT(16) - 1));
  689. val |= ((init->init_param_006[i + 1] & (BIT(16) - 1))
  690. << 16);
  691. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + off2, val);
  692. off2 += 4;
  693. }
  694. return 0;
  695. }
  696. static int ad4_cfg_setup(struct sde_hw_dspp *dspp, struct sde_ad_hw_cfg *cfg)
  697. {
  698. u32 blk_offset, val;
  699. struct drm_msm_ad4_cfg *ad_cfg;
  700. if (!cfg->hw_cfg->payload) {
  701. info[dspp->idx].completed_ops_mask &= ~ad4_cfg;
  702. return 0;
  703. }
  704. if (cfg->hw_cfg->len != sizeof(struct drm_msm_ad4_cfg)) {
  705. DRM_ERROR("invalid sz param exp %zd given %d cfg %pK\n",
  706. sizeof(struct drm_msm_ad4_cfg), cfg->hw_cfg->len,
  707. cfg->hw_cfg->payload);
  708. return -EINVAL;
  709. }
  710. ad_cfg = cfg->hw_cfg->payload;
  711. blk_offset = 0x20;
  712. val = (ad_cfg->cfg_param_005 & (BIT(8) - 1));
  713. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
  714. blk_offset = 0x24;
  715. val = (ad_cfg->cfg_param_006 & (BIT(7) - 1));
  716. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
  717. info[dspp->idx].tf_ctrl = (ad_cfg->cfg_param_008 & (BIT(8) - 1));
  718. blk_offset = 0x38;
  719. val = (ad_cfg->cfg_param_009 & (BIT(10) - 1));
  720. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
  721. blk_offset = 0x3c;
  722. val = (ad_cfg->cfg_param_010 & (BIT(12) - 1));
  723. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
  724. blk_offset = 0x88;
  725. val = (ad_cfg->cfg_param_013 & (BIT(8) - 1));
  726. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
  727. blk_offset += 4;
  728. val = (ad_cfg->cfg_param_014 & (BIT(16) - 1));
  729. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
  730. blk_offset = 0xa4;
  731. val = (ad_cfg->cfg_param_015 & (BIT(16) - 1));
  732. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
  733. blk_offset += 4;
  734. val = (ad_cfg->cfg_param_016 & (BIT(10) - 1));
  735. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
  736. blk_offset += 4;
  737. val = (ad_cfg->cfg_param_017 & (BIT(16) - 1));
  738. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
  739. blk_offset += 4;
  740. val = (ad_cfg->cfg_param_018 & (BIT(16) - 1));
  741. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
  742. blk_offset = 0xc4;
  743. val = (ad_cfg->cfg_param_019 & (BIT(16) - 1));
  744. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
  745. blk_offset += 4;
  746. val = (ad_cfg->cfg_param_020 & (BIT(16) - 1));
  747. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
  748. blk_offset = 0xb8;
  749. val = (ad_cfg->cfg_param_021 & (BIT(16) - 1));
  750. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
  751. blk_offset += 4;
  752. val = (ad_cfg->cfg_param_022 & (BIT(16) - 1));
  753. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
  754. blk_offset = 0xd0;
  755. val = (ad_cfg->cfg_param_023 & (BIT(16) - 1));
  756. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
  757. blk_offset += 4;
  758. val = (ad_cfg->cfg_param_024 & (BIT(16) - 1));
  759. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
  760. blk_offset = 0xdc;
  761. val = (ad_cfg->cfg_param_025 & (BIT(16) - 1));
  762. val |= ((ad_cfg->cfg_param_026 & (BIT(16) - 1)) << 16);
  763. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
  764. blk_offset += 4;
  765. val = (ad_cfg->cfg_param_027 & (BIT(16) - 1));
  766. val |= ((ad_cfg->cfg_param_028 & (BIT(16) - 1)) << 16);
  767. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
  768. blk_offset += 4;
  769. val = (ad_cfg->cfg_param_029 & (BIT(16) - 1));
  770. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
  771. blk_offset = 0xec;
  772. val = (ad_cfg->cfg_param_030 & (BIT(16) - 1));
  773. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
  774. blk_offset += 4;
  775. val = (ad_cfg->cfg_param_031 & (BIT(12) - 1));
  776. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
  777. blk_offset = 0xf8;
  778. val = (ad_cfg->cfg_param_032 & (BIT(10) - 1));
  779. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
  780. blk_offset += 4;
  781. val = (ad_cfg->cfg_param_033 & (BIT(8) - 1));
  782. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
  783. blk_offset = 0x104;
  784. val = (ad_cfg->cfg_param_034 & (BIT(16) - 1));
  785. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
  786. blk_offset += 4;
  787. val = (ad_cfg->cfg_param_035 & (BIT(12) - 1));
  788. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
  789. blk_offset = 0x110;
  790. val = (ad_cfg->cfg_param_036 & (BIT(12) - 1));
  791. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
  792. blk_offset += 4;
  793. val = (ad_cfg->cfg_param_037 & (BIT(12) - 1));
  794. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
  795. blk_offset += 4;
  796. val = (ad_cfg->cfg_param_038 & (BIT(8) - 1));
  797. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
  798. blk_offset += 4;
  799. val = (ad_cfg->cfg_param_039 & (BIT(8) - 1));
  800. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
  801. blk_offset = 0x134;
  802. val = (ad_cfg->cfg_param_040 & (BIT(12) - 1));
  803. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
  804. info[dspp->idx].vc_control_0 = (ad_cfg->cfg_param_041 & (BIT(7) - 1));
  805. blk_offset = 0x16c;
  806. val = (ad_cfg->cfg_param_044 & (BIT(8) - 1));
  807. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
  808. blk_offset += 4;
  809. val = (ad_cfg->cfg_param_045 & (BIT(8) - 1));
  810. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
  811. blk_offset += 4;
  812. val = (ad_cfg->cfg_param_046 & (BIT(16) - 1));
  813. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
  814. return 0;
  815. }
  816. static int ad4_input_setup(struct sde_hw_dspp *dspp,
  817. struct sde_ad_hw_cfg *cfg)
  818. {
  819. u64 *val, als;
  820. u32 blk_offset;
  821. if (cfg->hw_cfg->len != sizeof(u64) && cfg->hw_cfg->payload) {
  822. DRM_ERROR("invalid sz param exp %zd given %d cfg %pK\n",
  823. sizeof(u64), cfg->hw_cfg->len, cfg->hw_cfg->payload);
  824. return -EINVAL;
  825. }
  826. blk_offset = 0x28;
  827. if (cfg->hw_cfg->payload) {
  828. val = cfg->hw_cfg->payload;
  829. } else {
  830. als = 0;
  831. val = &als;
  832. }
  833. info[dspp->idx].last_als = (*val & (BIT(16) - 1));
  834. info[dspp->idx].completed_ops_mask |= ad4_input;
  835. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
  836. info[dspp->idx].last_als);
  837. return 0;
  838. }
  839. static int ad4_roi_setup(struct sde_hw_dspp *dspp,
  840. struct sde_ad_hw_cfg *cfg)
  841. {
  842. int ret = 0;
  843. u32 blk_offset = 0, val = 0;
  844. struct ad4_roi_info roi_cfg = {};
  845. ret = ad4_roi_coordinate_offset(cfg->hw_cfg, &roi_cfg);
  846. if (ret) {
  847. DRM_ERROR("params invalid\n");
  848. return -EINVAL;
  849. }
  850. info[dspp->idx].last_roi_cfg = roi_cfg;
  851. /*roi h start and end*/
  852. blk_offset = 0x18;
  853. val = (info[dspp->idx].last_roi_cfg.h_end & (BIT(16) - 1));
  854. val |= ((info[dspp->idx].last_roi_cfg.h_start & (BIT(16) - 1)) << 16);
  855. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
  856. /*roi v start and end*/
  857. blk_offset += 4;
  858. val = (info[dspp->idx].last_roi_cfg.v_end & (BIT(16) - 1));
  859. val |= ((info[dspp->idx].last_roi_cfg.v_start & (BIT(16) - 1)) << 16);
  860. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
  861. /*roi factor in and out*/
  862. blk_offset = 0x40;
  863. val = ((info[dspp->idx].last_roi_cfg.f_in & (BIT(16) - 1)) << 16);
  864. val |= (info[dspp->idx].last_roi_cfg.f_out & (BIT(16) - 1));
  865. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
  866. return ret;
  867. }
  868. static int ad4_roi_setup_ipcr(struct sde_hw_dspp *dspp,
  869. struct sde_ad_hw_cfg *cfg)
  870. {
  871. int ret = 0;
  872. struct ad4_roi_info roi_cfg = {};
  873. ret = ad4_roi_coordinate_offset(cfg->hw_cfg, &roi_cfg);
  874. if (ret) {
  875. DRM_ERROR("params invalid\n");
  876. return -EINVAL;
  877. }
  878. info[dspp->idx].cached_roi_cfg = roi_cfg;
  879. return 0;
  880. }
  881. static int ad4_roi_coordinate_offset(struct sde_hw_cp_cfg *hw_cfg,
  882. struct ad4_roi_info *output)
  883. {
  884. struct sde_hw_mixer *hw_lm = hw_cfg->mixer_info;
  885. struct drm_msm_ad4_roi_cfg *roi = NULL;
  886. if (!hw_cfg->payload) {
  887. output->h_start = 0x0;
  888. output->h_end = hw_cfg->displayh;
  889. output->v_start = 0x0;
  890. output->v_end = hw_cfg->displayv;
  891. output->f_in = 0x400;
  892. output->f_out = 0x400;
  893. return 0;
  894. }
  895. if (hw_cfg->len != sizeof(struct drm_msm_ad4_roi_cfg)) {
  896. DRM_ERROR("invalid sz param exp %zd given %d cfg %pK\n",
  897. sizeof(struct drm_msm_ad4_roi_cfg), hw_cfg->len,
  898. hw_cfg->payload);
  899. return -EINVAL;
  900. }
  901. roi = (struct drm_msm_ad4_roi_cfg *)hw_cfg->payload;
  902. if (roi->h_x >= hw_cfg->displayh || roi->v_x >= hw_cfg->displayv) {
  903. DRM_ERROR("invalid roi=[%u,%u,%u,%u], display=[%u,%u]\n",
  904. roi->h_x, roi->h_y, roi->v_x, roi->v_y,
  905. hw_cfg->displayh, hw_cfg->displayv);
  906. return -EINVAL;
  907. }
  908. if (roi->h_x >= roi->h_y || roi->v_x >= roi->v_y) {
  909. DRM_ERROR("invalid roi=[%u,%u,%u,%u], display=[%u,%u]\n",
  910. roi->h_x, roi->h_y, roi->v_x, roi->v_y,
  911. hw_cfg->displayh, hw_cfg->displayv);
  912. return -EINVAL;
  913. }
  914. if (roi->h_y > hw_cfg->displayh)
  915. roi->h_y = hw_cfg->displayh;
  916. if (roi->v_y > hw_cfg->displayv)
  917. roi->v_y = hw_cfg->displayv;
  918. /* single dspp cfg */
  919. output->h_start = roi->h_x;
  920. output->h_end = roi->h_y;
  921. output->v_start = roi->v_x;
  922. output->v_end = roi->v_y;
  923. output->f_in = roi->factor_in;
  924. output->f_out = roi->factor_out;
  925. /* check whether dual dspp */
  926. if (hw_cfg->num_of_mixers != 2)
  927. return 0;
  928. if (roi->h_y <= hw_lm->cfg.out_width) {
  929. if (hw_lm->cfg.right_mixer) {
  930. /* the region on the left of screen, clear right info */
  931. output->h_start = 0;
  932. output->h_end = 0;
  933. output->v_start = 0;
  934. output->v_end = 0;
  935. }
  936. } else if (roi->h_x < hw_lm->cfg.out_width) {
  937. /* the region occupy both sides of screen: left and right */
  938. if (hw_lm->cfg.right_mixer) {
  939. output->h_start = 0;
  940. output->h_end -= (hw_lm->cfg.out_width -
  941. MERGE_WIDTH_RIGHT);
  942. } else {
  943. output->h_end = hw_lm->cfg.out_width;
  944. }
  945. } else {
  946. /* the region on the right of the screen*/
  947. if (hw_lm->cfg.right_mixer) {
  948. output->h_start -= (hw_lm->cfg.out_width -
  949. MERGE_WIDTH_RIGHT);
  950. output->h_end -= (hw_lm->cfg.out_width -
  951. MERGE_WIDTH_RIGHT);
  952. } else {
  953. output->h_start = 0;
  954. output->h_end = 0;
  955. output->v_start = 0;
  956. output->v_end = 0;
  957. }
  958. }
  959. return 0;
  960. }
  961. static int ad4_suspend_setup(struct sde_hw_dspp *dspp,
  962. struct sde_ad_hw_cfg *cfg)
  963. {
  964. info[dspp->idx].state = ad4_state_idle;
  965. pr_debug("%s(): AD state move to idle\n", __func__);
  966. info[dspp->idx].completed_ops_mask = 0;
  967. return 0;
  968. }
  969. static int ad4_mode_setup_common(struct sde_hw_dspp *dspp,
  970. struct sde_ad_hw_cfg *cfg)
  971. {
  972. if (cfg->hw_cfg->len != sizeof(u64) || !cfg->hw_cfg->payload) {
  973. DRM_ERROR("invalid sz param exp %zd given %d cfg %pK\n",
  974. sizeof(u64), cfg->hw_cfg->len, cfg->hw_cfg->payload);
  975. return -EINVAL;
  976. }
  977. info[dspp->idx].mode = *((enum ad4_modes *)
  978. (cfg->hw_cfg->payload));
  979. info[dspp->idx].completed_ops_mask |= ad4_mode;
  980. if (AD_STATE_READY(info[dspp->idx].completed_ops_mask) ||
  981. info[dspp->idx].mode == AD4_OFF)
  982. ad4_mode_setup(dspp, info[dspp->idx].mode);
  983. return 0;
  984. }
  985. static int ad4_init_setup_idle(struct sde_hw_dspp *dspp,
  986. struct sde_ad_hw_cfg *cfg)
  987. {
  988. int ret;
  989. u32 blk_offset;
  990. if (!cfg->hw_cfg->payload) {
  991. info[dspp->idx].completed_ops_mask &= ~ad4_init;
  992. return 0;
  993. }
  994. ret = ad4_init_setup(dspp, cfg);
  995. if (ret)
  996. return ret;
  997. /* enable memory initialization*/
  998. /* frmt mode */
  999. blk_offset = 0x8;
  1000. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
  1001. (info[dspp->idx].frmt_mode & 0x1fff));
  1002. /* memory init */
  1003. blk_offset = 0x450;
  1004. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, 0x1);
  1005. /* enforce 0 initial strength when powering up AD config */
  1006. /* irdx_control_0 */
  1007. blk_offset = 0x13c;
  1008. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, 0x6);
  1009. info[dspp->idx].completed_ops_mask |= ad4_init;
  1010. if (AD_STATE_READY(info[dspp->idx].completed_ops_mask))
  1011. ad4_mode_setup(dspp, info[dspp->idx].mode);
  1012. return 0;
  1013. }
  1014. static int ad4_init_setup_run(struct sde_hw_dspp *dspp,
  1015. struct sde_ad_hw_cfg *cfg)
  1016. {
  1017. int ret;
  1018. u32 blk_offset;
  1019. if (!cfg->hw_cfg->payload) {
  1020. info[dspp->idx].completed_ops_mask &= ~ad4_init;
  1021. return 0;
  1022. }
  1023. ret = ad4_init_setup(dspp, cfg);
  1024. if (ret)
  1025. return ret;
  1026. /* disable memory initialization*/
  1027. /* frmt mode */
  1028. blk_offset = 0x8;
  1029. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
  1030. (info[dspp->idx].frmt_mode | 0x2000));
  1031. /* no need to explicitly set memory initialization sequence,
  1032. * since AD hw were not powered off.
  1033. */
  1034. /* irdx_control_0 */
  1035. blk_offset = 0x13c;
  1036. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
  1037. info[dspp->idx].irdx_control_0);
  1038. return 0;
  1039. }
  1040. static int ad4_init_setup_ipcr(struct sde_hw_dspp *dspp,
  1041. struct sde_ad_hw_cfg *cfg)
  1042. {
  1043. int ret;
  1044. u32 blk_offset;
  1045. if (!cfg->hw_cfg->payload) {
  1046. info[dspp->idx].completed_ops_mask &= ~ad4_init;
  1047. return 0;
  1048. }
  1049. ret = ad4_init_setup(dspp, cfg);
  1050. if (ret)
  1051. return ret;
  1052. /* no need to explicitly set memory initialization sequence,
  1053. * since register reset values are the correct configuration
  1054. */
  1055. /* frmt mode */
  1056. blk_offset = 0x8;
  1057. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
  1058. (info[dspp->idx].frmt_mode | 0x2000));
  1059. /* irdx_control_0 */
  1060. blk_offset = 0x13c;
  1061. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
  1062. info[dspp->idx].irdx_control_0);
  1063. info[dspp->idx].completed_ops_mask |= ad4_init;
  1064. if (AD_STATE_READY(info[dspp->idx].completed_ops_mask))
  1065. ad4_mode_setup(dspp, info[dspp->idx].mode);
  1066. return 0;
  1067. }
  1068. static int ad4_cfg_setup_idle(struct sde_hw_dspp *dspp,
  1069. struct sde_ad_hw_cfg *cfg)
  1070. {
  1071. int ret;
  1072. u32 blk_offset;
  1073. if (!cfg->hw_cfg->payload) {
  1074. info[dspp->idx].completed_ops_mask &= ~ad4_cfg;
  1075. return 0;
  1076. }
  1077. ret = ad4_cfg_setup(dspp, cfg);
  1078. if (ret)
  1079. return ret;
  1080. /* enforce 0 initial strength when powering up AD config */
  1081. /* assertiveness */
  1082. blk_offset = 0x30;
  1083. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, 0x0);
  1084. /* tf control */
  1085. blk_offset = 0x34;
  1086. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, 0x55);
  1087. /* vc_control_0 */
  1088. blk_offset = 0x138;
  1089. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
  1090. info[dspp->idx].vc_control_0);
  1091. info[dspp->idx].completed_ops_mask |= ad4_cfg;
  1092. if (AD_STATE_READY(info[dspp->idx].completed_ops_mask))
  1093. ad4_mode_setup(dspp, info[dspp->idx].mode);
  1094. return 0;
  1095. }
  1096. static int ad4_cfg_setup_run(struct sde_hw_dspp *dspp,
  1097. struct sde_ad_hw_cfg *cfg)
  1098. {
  1099. int ret;
  1100. u32 blk_offset;
  1101. if (!cfg->hw_cfg->payload) {
  1102. info[dspp->idx].completed_ops_mask &= ~ad4_cfg;
  1103. return 0;
  1104. }
  1105. ret = ad4_cfg_setup(dspp, cfg);
  1106. if (ret)
  1107. return ret;
  1108. /* assertiveness */
  1109. blk_offset = 0x30;
  1110. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
  1111. info[dspp->idx].last_assertive);
  1112. /* tf control */
  1113. blk_offset = 0x34;
  1114. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
  1115. info[dspp->idx].tf_ctrl);
  1116. /* vc_control_0 */
  1117. blk_offset = 0x138;
  1118. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
  1119. info[dspp->idx].vc_control_0);
  1120. return 0;
  1121. }
  1122. static int ad4_cfg_setup_ipcr(struct sde_hw_dspp *dspp,
  1123. struct sde_ad_hw_cfg *cfg)
  1124. {
  1125. int ret;
  1126. u32 blk_offset;
  1127. if (!cfg->hw_cfg->payload) {
  1128. info[dspp->idx].completed_ops_mask &= ~ad4_cfg;
  1129. return 0;
  1130. }
  1131. ret = ad4_cfg_setup(dspp, cfg);
  1132. if (ret)
  1133. return ret;
  1134. /* assertiveness */
  1135. blk_offset = 0x30;
  1136. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
  1137. info[dspp->idx].last_assertive);
  1138. info[dspp->idx].completed_ops_mask |= ad4_cfg;
  1139. if (AD_STATE_READY(info[dspp->idx].completed_ops_mask))
  1140. ad4_mode_setup(dspp, info[dspp->idx].mode);
  1141. return 0;
  1142. }
  1143. static int ad4_input_setup_idle(struct sde_hw_dspp *dspp,
  1144. struct sde_ad_hw_cfg *cfg)
  1145. {
  1146. int ret;
  1147. ret = ad4_input_setup(dspp, cfg);
  1148. if (ret)
  1149. return ret;
  1150. info[dspp->idx].completed_ops_mask |= ad4_input;
  1151. if (AD_STATE_READY(info[dspp->idx].completed_ops_mask))
  1152. ad4_mode_setup(dspp, info[dspp->idx].mode);
  1153. return 0;
  1154. }
  1155. static int ad4_input_setup_ipcr(struct sde_hw_dspp *dspp,
  1156. struct sde_ad_hw_cfg *cfg)
  1157. {
  1158. u64 *val, als;
  1159. u32 blk_offset;
  1160. if (cfg->hw_cfg->len != sizeof(u64) && cfg->hw_cfg->payload) {
  1161. DRM_ERROR("invalid sz param exp %zd given %d cfg %pK\n",
  1162. sizeof(u64), cfg->hw_cfg->len, cfg->hw_cfg->payload);
  1163. return -EINVAL;
  1164. }
  1165. blk_offset = 0x28;
  1166. if (cfg->hw_cfg->payload) {
  1167. val = cfg->hw_cfg->payload;
  1168. } else {
  1169. als = 0;
  1170. val = &als;
  1171. }
  1172. info[dspp->idx].cached_als = *val & (BIT(16) - 1);
  1173. info[dspp->idx].completed_ops_mask |= ad4_input;
  1174. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
  1175. info[dspp->idx].last_als);
  1176. if (AD_STATE_READY(info[dspp->idx].completed_ops_mask))
  1177. ad4_mode_setup(dspp, info[dspp->idx].mode);
  1178. return 0;
  1179. }
  1180. static int ad4_assertive_setup(struct sde_hw_dspp *dspp,
  1181. struct sde_ad_hw_cfg *cfg)
  1182. {
  1183. u64 *val, assertive;
  1184. u32 blk_offset;
  1185. if (cfg->hw_cfg->len != sizeof(u64) && cfg->hw_cfg->payload) {
  1186. DRM_ERROR("invalid sz param exp %zd given %d cfg %pK\n",
  1187. sizeof(u64), cfg->hw_cfg->len, cfg->hw_cfg->payload);
  1188. return -EINVAL;
  1189. }
  1190. blk_offset = 0x30;
  1191. if (cfg->hw_cfg->payload) {
  1192. val = cfg->hw_cfg->payload;
  1193. } else {
  1194. assertive = 0;
  1195. val = &assertive;
  1196. }
  1197. info[dspp->idx].last_assertive = *val & (BIT(8) - 1);
  1198. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
  1199. (info[dspp->idx].last_assertive));
  1200. return 0;
  1201. }
  1202. static int ad4_assertive_setup_ipcr(struct sde_hw_dspp *dspp,
  1203. struct sde_ad_hw_cfg *cfg)
  1204. {
  1205. u64 *val, assertive;
  1206. u32 blk_offset;
  1207. if (cfg->hw_cfg->len != sizeof(u64) && cfg->hw_cfg->payload) {
  1208. DRM_ERROR("invalid sz param exp %zd given %d cfg %pK\n",
  1209. sizeof(u64), cfg->hw_cfg->len, cfg->hw_cfg->payload);
  1210. return -EINVAL;
  1211. }
  1212. blk_offset = 0x30;
  1213. if (cfg->hw_cfg->payload) {
  1214. val = cfg->hw_cfg->payload;
  1215. } else {
  1216. assertive = 0;
  1217. val = &assertive;
  1218. }
  1219. info[dspp->idx].cached_assertive = *val & (BIT(8) - 1);
  1220. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
  1221. info[dspp->idx].last_assertive);
  1222. return 0;
  1223. }
  1224. static int ad4_backlight_setup(struct sde_hw_dspp *dspp,
  1225. struct sde_ad_hw_cfg *cfg)
  1226. {
  1227. u64 *val, bl;
  1228. u32 blk_offset;
  1229. if (cfg->hw_cfg->len != sizeof(u64) && cfg->hw_cfg->payload) {
  1230. DRM_ERROR("invalid sz param exp %zd given %d cfg %pK\n",
  1231. sizeof(u64), cfg->hw_cfg->len, cfg->hw_cfg->payload);
  1232. return -EINVAL;
  1233. }
  1234. blk_offset = 0x2c;
  1235. if (cfg->hw_cfg->payload) {
  1236. val = cfg->hw_cfg->payload;
  1237. } else {
  1238. bl = 0;
  1239. val = &bl;
  1240. }
  1241. info[dspp->idx].last_bl = *val & (BIT(16) - 1);
  1242. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
  1243. info[dspp->idx].last_bl);
  1244. return 0;
  1245. }
  1246. static int ad4_backlight_setup_ipcr(struct sde_hw_dspp *dspp,
  1247. struct sde_ad_hw_cfg *cfg)
  1248. {
  1249. u64 *val, bl;
  1250. u32 blk_offset;
  1251. if (cfg->hw_cfg->len != sizeof(u64) && cfg->hw_cfg->payload) {
  1252. DRM_ERROR("invalid sz param exp %zd given %d cfg %pK\n",
  1253. sizeof(u64), cfg->hw_cfg->len, cfg->hw_cfg->payload);
  1254. return -EINVAL;
  1255. }
  1256. blk_offset = 0x2c;
  1257. if (cfg->hw_cfg->payload) {
  1258. val = cfg->hw_cfg->payload;
  1259. } else {
  1260. bl = 0;
  1261. val = &bl;
  1262. }
  1263. info[dspp->idx].cached_bl = *val & (BIT(16) - 1);
  1264. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
  1265. info[dspp->idx].last_bl);
  1266. return 0;
  1267. }
  1268. void sde_read_intr_resp_ad4(struct sde_hw_dspp *dspp, u32 event,
  1269. u32 *resp_in, u32 *resp_out)
  1270. {
  1271. if (!dspp || !resp_in || !resp_out) {
  1272. DRM_ERROR("invalid params dspp %pK resp_in %pK resp_out %pK\n",
  1273. dspp, resp_in, resp_out);
  1274. return;
  1275. }
  1276. switch (event) {
  1277. case AD4_IN_OUT_BACKLIGHT:
  1278. *resp_in = SDE_REG_READ(&dspp->hw,
  1279. dspp->cap->sblk->ad.base + 0x2c);
  1280. *resp_out = SDE_REG_READ(&dspp->hw,
  1281. dspp->cap->sblk->ad.base + 0x48);
  1282. pr_debug("%s(): AD4 input BL %u, output BL %u\n", __func__,
  1283. (*resp_in), (*resp_out));
  1284. break;
  1285. default:
  1286. break;
  1287. }
  1288. }
  1289. static int ad4_ipc_suspend_setup_run(struct sde_hw_dspp *dspp,
  1290. struct sde_ad_hw_cfg *cfg)
  1291. {
  1292. u32 in_str = 0, out_str = 0, i = 0;
  1293. struct sde_hw_mixer *hw_lm;
  1294. hw_lm = cfg->hw_cfg->mixer_info;
  1295. if ((cfg->hw_cfg->num_of_mixers == 2) && hw_lm->cfg.right_mixer) {
  1296. /* this AD core is the salve core */
  1297. for (i = DSPP_0; i < DSPP_MAX; i++) {
  1298. if (info[i].is_master) {
  1299. in_str = info[i].last_str_inroi;
  1300. out_str = info[i].last_str_outroi;
  1301. break;
  1302. }
  1303. }
  1304. } else {
  1305. in_str = SDE_REG_READ(&dspp->hw,
  1306. dspp->cap->sblk->ad.base + 0x4c);
  1307. out_str = SDE_REG_READ(&dspp->hw,
  1308. dspp->cap->sblk->ad.base + 0x50);
  1309. pr_debug("%s(): AD in strength %d, out %d\n", __func__,
  1310. in_str, out_str);
  1311. }
  1312. info[dspp->idx].last_str_inroi = in_str;
  1313. info[dspp->idx].last_str_outroi = out_str;
  1314. info[dspp->idx].state = ad4_state_ipcs;
  1315. pr_debug("%s(): AD state move to ipcs\n", __func__);
  1316. return 0;
  1317. }
  1318. static int ad4_ipc_resume_setup_ipcs(struct sde_hw_dspp *dspp,
  1319. struct sde_ad_hw_cfg *cfg)
  1320. {
  1321. u32 blk_offset, val;
  1322. info[dspp->idx].frame_count = 0;
  1323. info[dspp->idx].state = ad4_state_ipcr;
  1324. pr_debug("%s(): AD state move to ipcr\n", __func__);
  1325. /* no need to rewrite frmt_mode bit 13 and mem_init,
  1326. * since the default register values are exactly what
  1327. * we wanted.
  1328. */
  1329. /* ipc resume with manual strength */
  1330. /* tf control */
  1331. blk_offset = 0x34;
  1332. val = (0x55 & (BIT(8) - 1));
  1333. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
  1334. /* set roi config */
  1335. blk_offset = 0x18;
  1336. val = (info[dspp->idx].last_roi_cfg.h_end & (BIT(16) - 1));
  1337. val |= ((info[dspp->idx].last_roi_cfg.h_start & (BIT(16) - 1)) << 16);
  1338. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
  1339. blk_offset += 4;
  1340. val = (info[dspp->idx].last_roi_cfg.v_end & (BIT(16) - 1));
  1341. val |= ((info[dspp->idx].last_roi_cfg.v_start & (BIT(16) - 1)) << 16);
  1342. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
  1343. blk_offset = 0x40;
  1344. val = ((info[dspp->idx].last_roi_cfg.f_in & (BIT(16) - 1)) << 16);
  1345. val |= (info[dspp->idx].last_roi_cfg.f_out & (BIT(16) - 1));
  1346. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
  1347. /* set manual strength */
  1348. blk_offset = 0x15c;
  1349. val = (info[dspp->idx].last_str_inroi & (BIT(10) - 1));
  1350. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
  1351. blk_offset = 0x160;
  1352. val = (info[dspp->idx].last_str_outroi & (BIT(10) - 1));
  1353. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
  1354. /* enable manual mode */
  1355. blk_offset = 0x138;
  1356. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, 0);
  1357. return 0;
  1358. }
  1359. static int ad4_ipc_suspend_setup_ipcr(struct sde_hw_dspp *dspp,
  1360. struct sde_ad_hw_cfg *cfg)
  1361. {
  1362. info[dspp->idx].state = ad4_state_ipcs;
  1363. pr_debug("%s(): AD state move to ipcs\n", __func__);
  1364. return 0;
  1365. }
  1366. static int ad4_ipc_reset_setup_ipcr(struct sde_hw_dspp *dspp,
  1367. struct sde_ad_hw_cfg *cfg)
  1368. {
  1369. int ret;
  1370. u32 in_str = 0, out_str = 0, i = 0;
  1371. struct sde_hw_mixer *hw_lm;
  1372. /* Read AD calculator strength output during the 2 frames of manual
  1373. * strength mode, and assign the strength output to last_str
  1374. * when frame count reaches AD_IPC_FRAME_COUNT to avoid flickers
  1375. * caused by strength was not converged before entering IPC mode
  1376. */
  1377. hw_lm = cfg->hw_cfg->mixer_info;
  1378. if ((cfg->hw_cfg->num_of_mixers == 2) && hw_lm->cfg.right_mixer) {
  1379. /* this AD core is the salve core */
  1380. for (i = DSPP_0; i < DSPP_MAX; i++) {
  1381. if (info[i].is_master) {
  1382. in_str = info[i].last_str_inroi;
  1383. out_str = info[i].last_str_outroi;
  1384. break;
  1385. }
  1386. }
  1387. } else {
  1388. in_str = SDE_REG_READ(&dspp->hw,
  1389. dspp->cap->sblk->ad.base + 0x4c);
  1390. out_str = SDE_REG_READ(&dspp->hw,
  1391. dspp->cap->sblk->ad.base + 0x50);
  1392. pr_debug("%s(): AD in strength %d, out %d\n", __func__,
  1393. in_str, out_str);
  1394. }
  1395. if (info[dspp->idx].frame_count == AD_IPC_FRAME_COUNT) {
  1396. info[dspp->idx].state = ad4_state_run;
  1397. pr_debug("%s(): AD state move to run\n", __func__);
  1398. info[dspp->idx].last_str_inroi = in_str;
  1399. info[dspp->idx].last_str_outroi = out_str;
  1400. ret = ad4_cfg_ipc_reset(dspp, cfg);
  1401. if (ret)
  1402. return ret;
  1403. } else {
  1404. info[dspp->idx].frame_count++;
  1405. }
  1406. return 0;
  1407. }
  1408. static int ad4_cfg_ipc_reset(struct sde_hw_dspp *dspp,
  1409. struct sde_ad_hw_cfg *cfg)
  1410. {
  1411. u32 blk_offset, val = 0;
  1412. /* revert manual strength */
  1413. /* tf control */
  1414. blk_offset = 0x34;
  1415. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
  1416. info[dspp->idx].tf_ctrl);
  1417. /* vc_control_0 */
  1418. blk_offset = 0x138;
  1419. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
  1420. info[dspp->idx].vc_control_0);
  1421. /* reset cached ALS, backlight and assertiveness */
  1422. if (info[dspp->idx].cached_als != U64_MAX) {
  1423. SDE_REG_WRITE(&dspp->hw,
  1424. dspp->cap->sblk->ad.base + 0x28,
  1425. info[dspp->idx].cached_als);
  1426. info[dspp->idx].last_als = info[dspp->idx].cached_als;
  1427. info[dspp->idx].cached_als = U64_MAX;
  1428. }
  1429. if (info[dspp->idx].cached_bl != U64_MAX) {
  1430. SDE_REG_WRITE(&dspp->hw,
  1431. dspp->cap->sblk->ad.base + 0x2c,
  1432. info[dspp->idx].cached_bl);
  1433. info[dspp->idx].last_bl = info[dspp->idx].cached_bl;
  1434. info[dspp->idx].cached_bl = U64_MAX;
  1435. }
  1436. if (info[dspp->idx].cached_assertive != U8_MAX) {
  1437. SDE_REG_WRITE(&dspp->hw,
  1438. dspp->cap->sblk->ad.base + 0x30,
  1439. info[dspp->idx].cached_assertive);
  1440. info[dspp->idx].last_assertive =
  1441. info[dspp->idx].cached_assertive;
  1442. info[dspp->idx].cached_assertive = U8_MAX;
  1443. }
  1444. /*reset cached roi config*/
  1445. if (info[dspp->idx].cached_roi_cfg.h_start != U32_MAX) {
  1446. blk_offset = 0x18;
  1447. val = (info[dspp->idx].cached_roi_cfg.h_end & (BIT(16) - 1));
  1448. val |= ((info[dspp->idx].cached_roi_cfg.h_start &
  1449. (BIT(16) - 1)) << 16);
  1450. SDE_REG_WRITE(&dspp->hw,
  1451. dspp->cap->sblk->ad.base + blk_offset, val);
  1452. blk_offset += 4;
  1453. val = (info[dspp->idx].cached_roi_cfg.v_end & (BIT(16) - 1));
  1454. val |= ((info[dspp->idx].cached_roi_cfg.v_start &
  1455. (BIT(16) - 1)) << 16);
  1456. SDE_REG_WRITE(&dspp->hw,
  1457. dspp->cap->sblk->ad.base + blk_offset, val);
  1458. blk_offset = 0x40;
  1459. val = ((info[dspp->idx].cached_roi_cfg.f_in &
  1460. (BIT(16) - 1)) << 16);
  1461. val |= (info[dspp->idx].cached_roi_cfg.f_out & (BIT(16) - 1));
  1462. SDE_REG_WRITE(&dspp->hw,
  1463. dspp->cap->sblk->ad.base + blk_offset, val);
  1464. info[dspp->idx].last_roi_cfg = info[dspp->idx].cached_roi_cfg;
  1465. info[dspp->idx].cached_roi_cfg.h_start = U32_MAX;
  1466. info[dspp->idx].cached_roi_cfg.h_end = U32_MAX;
  1467. info[dspp->idx].cached_roi_cfg.v_start = U32_MAX;
  1468. info[dspp->idx].cached_roi_cfg.v_end = U32_MAX;
  1469. info[dspp->idx].cached_roi_cfg.f_in = U32_MAX;
  1470. info[dspp->idx].cached_roi_cfg.f_out = U32_MAX;
  1471. }
  1472. return 0;
  1473. }
  1474. static int ad4_ipc_reset_setup_startup(struct sde_hw_dspp *dspp,
  1475. struct sde_ad_hw_cfg *cfg)
  1476. {
  1477. u32 blk_offset;
  1478. if (info[dspp->idx].frame_count == AD_IPC_FRAME_COUNT) {
  1479. info[dspp->idx].state = ad4_state_run;
  1480. pr_debug("%s(): AD state move to run\n", __func__);
  1481. /* revert enforce 0 initial strength */
  1482. /* irdx_control_0 */
  1483. blk_offset = 0x13c;
  1484. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
  1485. info[dspp->idx].irdx_control_0);
  1486. /* assertiveness */
  1487. blk_offset = 0x30;
  1488. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
  1489. info[dspp->idx].last_assertive);
  1490. /* tf control */
  1491. blk_offset = 0x34;
  1492. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
  1493. info[dspp->idx].tf_ctrl);
  1494. } else {
  1495. info[dspp->idx].frame_count++;
  1496. }
  1497. return 0;
  1498. }
  1499. static int ad4_strength_setup(struct sde_hw_dspp *dspp,
  1500. struct sde_ad_hw_cfg *cfg)
  1501. {
  1502. u64 in_str = 0, out_str = 0, val;
  1503. u32 blk_offset = 0x15c;
  1504. struct drm_msm_ad4_manual_str_cfg *str_cfg = NULL;
  1505. if (cfg->hw_cfg->payload && (cfg->hw_cfg->len !=
  1506. sizeof(struct drm_msm_ad4_manual_str_cfg))) {
  1507. DRM_ERROR("invalid sz param exp %zd given %d cfg %pK\n",
  1508. sizeof(struct drm_msm_ad4_manual_str_cfg),
  1509. cfg->hw_cfg->len, cfg->hw_cfg->payload);
  1510. return -EINVAL;
  1511. }
  1512. if (cfg->hw_cfg->payload) {
  1513. str_cfg = (struct drm_msm_ad4_manual_str_cfg *)
  1514. cfg->hw_cfg->payload;
  1515. in_str = str_cfg->in_str;
  1516. out_str = str_cfg->out_str;
  1517. }
  1518. /* set manual strength */
  1519. info[dspp->idx].completed_ops_mask |= ad4_strength;
  1520. val = (in_str & (BIT(10) - 1));
  1521. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
  1522. blk_offset += 4;
  1523. val = (out_str & (BIT(10) - 1));
  1524. SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
  1525. return 0;
  1526. }
  1527. static int ad4_strength_setup_idle(struct sde_hw_dspp *dspp,
  1528. struct sde_ad_hw_cfg *cfg)
  1529. {
  1530. int ret;
  1531. ret = ad4_strength_setup(dspp, cfg);
  1532. if (ret)
  1533. return ret;
  1534. if (AD_STATE_READY(info[dspp->idx].completed_ops_mask))
  1535. ad4_mode_setup(dspp, info[dspp->idx].mode);
  1536. return 0;
  1537. }